diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | e2de64d6f1beb9e492daf5b886e19933c1fa41dd (patch) | |
tree | 9047cf9e6b5c43878d5bf82660adae77ceee097a /noatun/modules | |
download | tdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.tar.gz tdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdemultimedia@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'noatun/modules')
412 files changed, 26870 insertions, 0 deletions
diff --git a/noatun/modules/Makefile.am b/noatun/modules/Makefile.am new file mode 100644 index 00000000..90c298d3 --- /dev/null +++ b/noatun/modules/Makefile.am @@ -0,0 +1,4 @@ +SUBDIRS = artseffects \ + dcopiface excellent htmlexport infrared kaiman keyz kjofol-skin \ + marquis metatag monoscope net noatunui splitplaylist systray \ + voiceprint winskin simple diff --git a/noatun/modules/artseffects/ExtraStereo.mcopclass b/noatun/modules/artseffects/ExtraStereo.mcopclass new file mode 100644 index 00000000..7fb466ec --- /dev/null +++ b/noatun/modules/artseffects/ExtraStereo.mcopclass @@ -0,0 +1,5 @@ +Buildable=true +Interface=ExtraStereo,Arts::StereoEffect,Arts::SynthModule,Arts::Object +Language=C++ +Library=libartseffects.la +Use=directly
\ No newline at end of file diff --git a/noatun/modules/artseffects/ExtraStereoGuiFactory.mcopclass b/noatun/modules/artseffects/ExtraStereoGuiFactory.mcopclass new file mode 100644 index 00000000..5b5521ae --- /dev/null +++ b/noatun/modules/artseffects/ExtraStereoGuiFactory.mcopclass @@ -0,0 +1,5 @@ +Buildable=true +Interface=ExtraStereoGuiFactory,Arts::GuiFactory,Arts::Object +Library=libartseffects.la +Language=C++ +CanCreate=ExtraStereo diff --git a/noatun/modules/artseffects/Makefile.am b/noatun/modules/artseffects/Makefile.am new file mode 100644 index 00000000..49a5bb99 --- /dev/null +++ b/noatun/modules/artseffects/Makefile.am @@ -0,0 +1,25 @@ +INCLUDES= -I$(top_builddir)/arts/gui/common -I$(top_srcdir)/arts/gui/common -I$(kde_includes)/arts $(all_includes) +lib_LTLIBRARIES = libartseffects.la +#libartseffectsui.la + +libartseffects_la_SOURCES = artseffects.cc extrastereo_impl.cc +libartseffects_la_COMPILE_FIRST = artseffects.cc +libartseffects_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +libartseffects_la_LIBADD = $(top_builddir)/arts/gui/common/libartsgui_idl.la -lkmedia2_idl -lsoundserver_idl -lartsflow + + +artseffects.mcopclass: artseffects.h +artseffects.mcoptype: artseffects.h +artseffects.cc artseffects.h: $(srcdir)/artseffects.idl $(MCOPIDL) + $(MCOPIDL) -t -I$(top_builddir)/arts/gui/common -I$(top_srcdir)/arts/gui/common -I$(kde_includes)/arts $(srcdir)/artseffects.idl + +CLEANFILES = artsmidi.cc artsmidi.h artsmidi.mcoptype artsmidi.mcopclass + +mcoptypedir = $(libdir)/mcop +mcoptype_DATA = artseffects.mcoptype artseffects.mcopclass + +mcopclassdir = $(libdir)/mcop +mcopclass_DATA = ExtraStereo.mcopclass VoiceRemoval.mcopclass RawWriter.mcopclass ExtraStereoGuiFactory.mcopclass + +artseffects.lo: artseffects.h ../../../arts/gui/common/artsgui.h +extrastereo_impl.lo: ../../../arts/gui/common/artsgui.h artseffects.h diff --git a/noatun/modules/artseffects/RawWriter.mcopclass b/noatun/modules/artseffects/RawWriter.mcopclass new file mode 100644 index 00000000..535db20a --- /dev/null +++ b/noatun/modules/artseffects/RawWriter.mcopclass @@ -0,0 +1,4 @@ +Buildable=true +Interface=RawWriter,Arts::StereoEffect,Arts::SynthModule,Arts::Object +Language=C++ +Library=libartseffects.la diff --git a/noatun/modules/artseffects/VoiceRemoval.mcopclass b/noatun/modules/artseffects/VoiceRemoval.mcopclass new file mode 100644 index 00000000..661029bd --- /dev/null +++ b/noatun/modules/artseffects/VoiceRemoval.mcopclass @@ -0,0 +1,5 @@ +Buildable=true +Interface=VoiceRemoval,Arts::StereoEffect,Arts::SynthModule,Arts::Object +Language=C++ +Library=libartseffects.la +Use=directly diff --git a/noatun/modules/artseffects/artseffects.idl b/noatun/modules/artseffects/artseffects.idl new file mode 100644 index 00000000..86fdea16 --- /dev/null +++ b/noatun/modules/artseffects/artseffects.idl @@ -0,0 +1,17 @@ +#include <artsflow.idl> +#include <artsgui.idl> + +interface ExtraStereo : Arts::StereoEffect { + attribute float intensity; +}; + +interface VoiceRemoval : Arts::StereoEffect { +}; + +interface RawWriter : Arts::StereoEffect +{ +}; + +interface ExtraStereoGuiFactory : Arts::GuiFactory { +}; + diff --git a/noatun/modules/artseffects/effect.cpp b/noatun/modules/artseffects/effect.cpp new file mode 100644 index 00000000..8d1c8b69 --- /dev/null +++ b/noatun/modules/artseffects/effect.cpp @@ -0,0 +1 @@ + diff --git a/noatun/modules/artseffects/extrastereo_impl.cc b/noatun/modules/artseffects/extrastereo_impl.cc new file mode 100644 index 00000000..3dc92705 --- /dev/null +++ b/noatun/modules/artseffects/extrastereo_impl.cc @@ -0,0 +1,153 @@ +#include "artsgui.h" +#include "artseffects.h" +#include "stdsynthmodule.h" +#include <dynamicrequest.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <convert.h> +#include "debug.h" +#include <connect.h> +#include <cstdlib> + +using namespace Arts; + +class ExtraStereo_impl : virtual public ExtraStereo_skel, + virtual public StdSynthModule +{ + float _intensity; +// StereoEffectGUI mStereoEffectGUI; +public: + float intensity() { return _intensity; } + void intensity(float newValue) { + _intensity = newValue; +// cout << " **** INTENSITY = " << newValue << endl; + } + + ExtraStereo_impl() : _intensity(2.0) + { +// mStereoEffectGUI = DynamicCast(server.createObject("Arts::ExtraStereo")); +// DynamicRequest(mStereoEffectGUI).method("_set_effect").param(*this).invoke(); + + } + void calculateBlock(unsigned long samples) + { + unsigned long i; + + for(i = 0; i < samples; i++) + { + float average = (inleft[i] + inright[i]) / 2.0; + + float outleftnew = average + (inleft[i] - average) * _intensity; + if(outleftnew > 1.0) outleft[i] = 1.0; + else if(outleftnew < -1.0) outleft[i] = -1.0; + else outleft[i] = outleftnew; + + float outrightnew = average + (inright[i] - average) * _intensity; + if(outrightnew > 1.0) outright[i] = 1.0; + else if(outrightnew < -1.0) outright[i] = -1.0; + else outright[i] = outrightnew; + } + } +}; + + +class VoiceRemoval_impl : virtual public VoiceRemoval_skel, + virtual public StdSynthModule +{ +public: + + VoiceRemoval_impl() + { + + } + // This is based on the work of Anders Carlsson <anders.carlsson@tordata.se> + void calculateBlock(unsigned long samples) + { + for (unsigned i = 0; i < samples; i++) + { + float outleftnew=inleft[i]-inright[i]; + float outrightnew=inright[i]-inleft[i]; + + if (inleft[i] < -1.0) outleftnew = -1.0; + else if (inleft[i] > 1.0) outleftnew = 1.0; + + if (inright[i] < -1.0) outrightnew = -1.0; + else if (inright[i] > 1.0) outrightnew = 1.0; + outleft[i] = outleftnew; + outright[i] = outrightnew; + } + + } +}; + +class RawWriter_impl : virtual public RawWriter_skel, + virtual public StdSynthModule +{ + int mFd; +public: + RawWriter_impl() + { + std::string file=getenv("HOME"); + file.append("/arts-write.raw"); + mFd=::open(file.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + } + ~RawWriter_impl() + { + ::close(mFd); + } + // This is based on the work of Anders Carlsson <anders.carlsson@tordata.se> + void calculateBlock(unsigned long samples) + { + for (unsigned i = 0; i < samples; i++) + { + outleft[i]=inleft[i]; + outright[i]=inright[i]; + } + unsigned char *buffer=new unsigned char[samples*4]; + convert_stereo_2float_i16le(samples, + inleft, inright, buffer); + ::write(mFd, (const void*)buffer, samples*4); + delete [] buffer; + } +}; + +class ExtraStereoGuiFactory_impl : public ExtraStereoGuiFactory_skel +{ +public: + Widget createGui(Object object) + { + arts_return_val_if_fail(!object.isNull(), Arts::Widget::null()); + + ExtraStereo e = DynamicCast(object); + arts_return_val_if_fail(!e.isNull(), Arts::Widget::null()); + + HBox hbox; + hbox.width(80); + hbox.height(80); + hbox.show(); + + + Poti intense; + intense.caption("Intensity"); + intense.color("red"); + intense.min(0); + intense.max(5); + intense.value(e.intensity()); + intense.parent(hbox); + intense.show(); + connect(intense,"value_changed", e, "intensity"); + + hbox._addChild(intense,"intensityWidget"); + + return hbox; + } +}; + + +REGISTER_IMPLEMENTATION(ExtraStereo_impl); +REGISTER_IMPLEMENTATION(VoiceRemoval_impl); +REGISTER_IMPLEMENTATION(RawWriter_impl); +REGISTER_IMPLEMENTATION(ExtraStereoGuiFactory_impl); + + diff --git a/noatun/modules/artseffects/extrastereogui_impl.cc b/noatun/modules/artseffects/extrastereogui_impl.cc new file mode 100644 index 00000000..5952c80e --- /dev/null +++ b/noatun/modules/artseffects/extrastereogui_impl.cc @@ -0,0 +1,28 @@ +#include <qlayout.h> +#include <qslider.h> +#include "extrastereogui_impl.h" + +namespace Arts { + +ExtraStereoGUI_impl::ExtraStereoGUI_impl() : QWidget(0) +{ + (new QHBoxLayout(this))->setAutoAdd(true); + mSlider=new QSlider(0,100,10, 0, Horizontal, this); + mSlider->show(); + show(); +} + +void ExtraStereoGUI_impl::changeSlider(int v) +{ + effect.intensity((float)v/100.0); +} + +void ExtraStereoGUI_impl::setEffect(StereoEffect newEffect) +{ + effect = DynamicCast(newEffect); +} + +REGISTER_IMPLEMENTATION(ExtraStereoGUI_impl); + +}; + diff --git a/noatun/modules/artseffects/extrastereogui_impl.h b/noatun/modules/artseffects/extrastereogui_impl.h new file mode 100644 index 00000000..56104ae8 --- /dev/null +++ b/noatun/modules/artseffects/extrastereogui_impl.h @@ -0,0 +1,26 @@ +#include "artseffects.h" +#include "stdsynthmodule.h" +#include <qwidget.h> + +class QSlider; + +namespace Arts { + +class ExtraStereoGUI_impl : public QWidget, virtual public ExtraStereoGUI_skel +{ +public: + ExtraStereo effect; + + ExtraStereoGUI_impl(); + + void setEffect(StereoEffect newEffect); + +public slots: + void changeSlider(int); + +private: + QSlider *mSlider; +}; + + +}; diff --git a/noatun/modules/dcopiface/Makefile.am b/noatun/modules/dcopiface/Makefile.am new file mode 100644 index 00000000..6d55fc72 --- /dev/null +++ b/noatun/modules/dcopiface/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES= -I$(top_builddir)/noatun/library -I$(top_srcdir)/noatun/library -I$(kde_includes)/arts $(all_includes) +kde_module_LTLIBRARIES = noatun_dcopiface.la + +noatun_dcopiface_la_SOURCES = dcopiface.cpp dcopiface.skel + +noatun_dcopiface_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_dcopiface_la_LIBADD = $(LIB_KFILE) $(top_builddir)/noatun/library/libnoatun.la + +noatun_dcopiface_la_METASOURCES = AUTO + +noinst_HEADERS = dcopiface.h + +noatun_modules_dcopiface_DATA = dcopiface.plugin +noatun_modules_dcopifacedir = $(kde_datadir)/noatun + +dcopiface.lo: ../../library/noatunarts/noatunarts.h diff --git a/noatun/modules/dcopiface/dcopiface.cpp b/noatun/modules/dcopiface/dcopiface.cpp new file mode 100644 index 00000000..93ef6160 --- /dev/null +++ b/noatun/modules/dcopiface/dcopiface.cpp @@ -0,0 +1,250 @@ +#include "dcopiface.h" + +#include <noatun/player.h> +#include <noatun/app.h> +#include <noatunarts/noatunarts.h> +#include <noatun/engine.h> + +#include <dcopclient.h> + +extern "C" +{ + KDE_EXPORT NIF *create_plugin() + { + return new NIF(); + } +} + + +NIF::NIF() : Plugin(), DCOPObject("Noatun") +{ + mLastVolume = 0; +// connect(napp->player(), SIGNAL(newSong()), SLOT(newSongPlaying())); +} + +NIF::~NIF() +{ + kapp->dcopClient()->emitDCOPSignal("exiting()", QByteArray()); +} + +void NIF::toggleListView() +{ + napp->player()->toggleListView(); +} + +void NIF::handleButtons() +{ + napp->player()->handleButtons(); +} + +void NIF::removeCurrent() +{ + napp->player()->removeCurrent(); +} + +void NIF::back() +{ + napp->player()->back(); +} + +void NIF::stop() +{ + napp->player()->stop(); +} + +void NIF::play() +{ + napp->player()->play(); +} + +void NIF::playpause() +{ + napp->player()->playpause(); +} + +void NIF::forward() +{ + napp->player()->forward(); +} + +void NIF::skipTo(int msec) +{ + napp->player()->skipTo(msec); +} + +void NIF::loop() +{ + napp->player()->loop(); +} + +void NIF::setVolume(int i) +{ + napp->player()->setVolume(i); +} + +int NIF::volume() +{ + return napp->player()->volume(); +} + +void NIF::volumeUp() +{ + napp->player()->setVolume(napp->player()->volume() + 5); +} + +void NIF::volumeDown() +{ + napp->player()->setVolume(napp->player()->volume() - 5); +} + +void NIF::toggleMute() +{ + int currVol = napp->player()->volume(); + if (currVol == 0) + { + napp->player()->setVolume(mLastVolume); + } + else + { + mLastVolume = currVol; + napp->player()->setVolume(0); + } +} + +int NIF::length() // returns -1 if there's no playobject +{ + return napp->player()->getLength(); +} + +int NIF::position() // returns -1 if there's no playobject +{ + return napp->player()->getTime(); +} + +int NIF::state() +{ + if (napp->player()->isPlaying()) + return 2; + if (napp->player()->isPaused()) + return 1; + + return 0; // default to stopped +} + +QString NIF::lengthString() +{ + return napp->player()->current() ? napp->player()->current().lengthString() : ""; +} + +QString NIF::timeString() +{ + return napp->player()->lengthString(); +} + +QString NIF::title() +{ + return napp->player()->current() ? napp->player()->current().title() : ""; +} + +void NIF::setCurrentProperty(const QString &key, const QString &value) +{ + if (!napp->player()->current()) return; + + napp->player()->current().setProperty(key, value); +} + +QString NIF::currentProperty(const QString &key) +{ + if (!napp->player()->current()) return ""; + + return napp->player()->current().property(key); +} + +void NIF::clearCurrentProperty(const QString &key) +{ + if (!napp->player()->current()) return; + + return napp->player()->current().clearProperty(key); +} + + +QCString NIF::visStack() +{ + return napp->player()->engine()->visualizationStack()->toString().c_str(); +} + +QCString NIF::session() +{ + return napp->player()->engine()->session()->toString().c_str(); +} + +// adds one file to the playlist +void NIF::addFile(const QString& f, bool autoplay) +{ + napp->player()->openFile(f, false, autoplay); +} + +// Adds a bunch of files to the playlist +void NIF::addFile(const QStringList &f, bool autoplay) +{ + for (QStringList::ConstIterator it = f.begin(); it != f.end(); ++it ) + napp->player()->openFile(*it, false, autoplay); +} + +void NIF::loadPlugin(const QString &spec) +{ + napp->libraryLoader()->add(spec); +} + +QStringList NIF::availablePlugins() { + QStringList available_spec_files; + QValueList<NoatunLibraryInfo> available; + + available = napp->libraryLoader()->available(); + + QValueList<NoatunLibraryInfo>::iterator it; + for (it = available.begin();it != available.end();it++) { + available_spec_files += (*it).specfile; + } + + return available_spec_files; +} + +QStringList NIF::loadedPlugins() { + QStringList loaded_spec_files; + QValueList<NoatunLibraryInfo> loaded; + + loaded = napp->libraryLoader()->loaded(); + + QValueList<NoatunLibraryInfo>::iterator it; + for (it = loaded.begin();it != loaded.end();it++) { + loaded_spec_files += (*it).specfile; + } + + return loaded_spec_files; +} + +bool NIF::unloadPlugin(const QString &spec) +{ + return napp->libraryLoader()->remove(spec); +} + +QStringList NIF::mimeTypes() +{ + return napp->mimeTypes(); +} + +QCString NIF::version() +{ + return napp->version(); +} + +void NIF::newSongPlaying() +{ + kapp->dcopClient()->emitDCOPSignal("newFile()", QByteArray()); +} + +void NIF::clear() +{ + napp->playlist()->clear(); +} diff --git a/noatun/modules/dcopiface/dcopiface.h b/noatun/modules/dcopiface/dcopiface.h new file mode 100644 index 00000000..4b9fe5e7 --- /dev/null +++ b/noatun/modules/dcopiface/dcopiface.h @@ -0,0 +1,104 @@ +#ifndef DCOPIFACE_H +#define DCOPIFACE_H + +#include <noatun/player.h> +#include <noatun/plugin.h> + +#include <dcopobject.h> +#include <kdemacros.h> + +class KDE_EXPORT NIF : public Plugin, public DCOPObject +{ +K_DCOP + +public: + NIF(); + ~NIF(); + +private slots: + void newSongPlaying(); + +k_dcop: + void toggleListView(); + void handleButtons(); + void removeCurrent(); + + void back(); + void stop(); + void play(); + void playpause(); + void forward(); + void skipTo(int); + void loop(); + + void setVolume(int); + int volume(); + void volumeUp(); + void volumeDown(); + void toggleMute(); + + /** + * length in milliseconds + **/ + int length(); + /** + * position in milliseconds + **/ + int position(); + + /** + * 0 stopped + * 1 paused + * 2 playing + **/ + int state(); + + QString lengthString(); + QString timeString(); + + QString title(); + + /** + * set a property for the current song + **/ + void setCurrentProperty(const QString &key, const QString &value); + /** + * get a property from the current song + **/ + QString currentProperty(const QString &key); + /** + * clear a property from the current song + **/ + void clearCurrentProperty(const QString &key); + + QCString visStack(); + QCString session(); + + void addFile(const QString& f, bool autoplay); + void addFile(const QStringList &f, bool autoplay); + + void loadPlugin(const QString &specFile); + QStringList availablePlugins(); + QStringList loadedPlugins(); + bool unloadPlugin(const QString &specFile); + + QStringList mimeTypes(); + QCString version(); + + /** + * clear the playlist + **/ + void clear(); +private: + int mLastVolume; // remember volume for mute/unmute + +#ifdef DOCUMENTATION_BLEH_BLEH_DONT_TRY_COMPILING_THIS +signals: + void exiting(); + void newFile(); + +#endif +}; + +#endif + diff --git a/noatun/modules/dcopiface/dcopiface.plugin b/noatun/modules/dcopiface/dcopiface.plugin new file mode 100644 index 00000000..d98a661f --- /dev/null +++ b/noatun/modules/dcopiface/dcopiface.plugin @@ -0,0 +1,137 @@ +Filename=noatun_dcopiface.la +Author=Charles Samuels +Site=http://www.derkarl.org/noatun +Email=charles@kde.org +Type=hidden +License=Artistic +Name=DCOP Interface +Name[af]=Dcop Koppelvlak +Name[ar]=واجهة DCOP +Name[az]=DCOP Ara üzü +Name[bn]=ডিকপ ইন্টারফেস +Name[br]=Etrefas DCOP +Name[ca]=Interfície DCOP +Name[cs]=Rozhraní DCOP +Name[cy]=Rhyngwyneb DCOP +Name[da]=DCOP-grænseflade +Name[de]=DCOP-Schnittstelle +Name[el]=Διασύνδεση DCOP +Name[eo]=DCOP-interfaco +Name[es]=Interfaz de DCOP +Name[et]=DCOP liides +Name[eu]=DCOP interfazea +Name[fa]=واسط DCOP +Name[fi]=DCOP-rajapinta +Name[fr]=Interface DCOP +Name[ga]=Comhéadan DCOP +Name[gl]=Interface DCOP +Name[he]=ממשק DCOP +Name[hi]= डीकॉप इंटरफेस +Name[hr]=DCOP sučelje +Name[hu]=DCOP-felület +Name[is]=DCOP aðgangur +Name[it]=Interfaccia DCOP +Name[ja]=DCOP インターフェース +Name[kk]=DCOP интерфейсі +Name[km]=ចំណុចប្រទាក់ DCOP +Name[ko]=DCOP 인터페이스 +Name[lt]=DCOP sąsaja +Name[lv]=DCOP Starpseja +Name[mk]=Интерфејс DCOP +Name[ms]=Antaramuka DCOP +Name[mt]=Interfaċċja DCOP +Name[nb]=DCOP-grensesnitt +Name[nds]=DCOP-Koppelsteed +Name[ne]=DCOP इन्टरफेस +Name[nl]=DCOP-interface +Name[nn]=DCOP-grensesnitt +Name[pa]=DCOP ਇੰਟਰਫੇਸ +Name[pl]=Interfejs DCOP +Name[pt]=Interface do DCOP +Name[pt_BR]=Interface DCOP +Name[ro]=Interfaţă DCOP +Name[ru]=Интерфейс DCOP +Name[se]=DCOP-lakta +Name[sk]=Rozhranie DCOP +Name[sl]=Vmesnik DCOP +Name[sr]=DCOP интерфејс +Name[sr@Latn]=DCOP interfejs +Name[sv]=DCOP-gränssnitt +Name[ta]=DCOP இடைமுகம் +Name[tg]=Интерфейси DCOP +Name[th]=ส่วนติดต่อ DCOP +Name[tr]=DCOP Arayüzü +Name[uk]=Інтерфейс DCOP +Name[uz]=DCOP interfeysi +Name[uz@cyrillic]=DCOP интерфейси +Name[xh]=Ujongano lwe DCOP +Name[zh_CN]=DCOP 接口 +Name[zh_HK]=DCOP 介面 +Name[zh_TW]=DCOP 介面 +Name[zu]=Uxhumano olubhekeneyo lwe DCOP +Comment=DCOP Interface for Inter-Process Communication +Comment[af]=Dcop Koppelvlak vir Inter-Process Kommunikasie +Comment[ar]=واجهة DCOP لإستعراض تواصل عمليات النظام مع بعضها +Comment[az]=IPC üçün DCOP Ara üzü +Comment[bg]=Интерфейс за комуникация между процесите +Comment[bn]=আন্তঃপ্রক্রিয়া যোগাযোগের জন্য ডিকপ ইন্টারফেস +Comment[bs]=DCOP interfejs za međuprocesnu komunikaciju +Comment[ca]=Interfície DCOP per la comunicació entre processos +Comment[cs]=Rozhraní DCOP pro mezi procesovou komunikaci +Comment[cy]=Rhyngwyneb DCOP ar gyfer Cyfathrebu Rhyngbrosesol +Comment[da]=DCOP-grænseflade for interproceskommunikation +Comment[de]=DCOP-Schnittstelle für die Kommunikation zwischen Prozessen +Comment[el]=Διασύνδεση DCOP για επικοινωνία μεταξύ διεργασιών (IPC) +Comment[eo]=DCOP-interfaco por interproceza komunikado +Comment[es]=Interfaz de DCOP para comunicaciones entre procesos (IPC) +Comment[et]=DCOP liides protsessidevahelise ühenduse loomiseks +Comment[eu]=DCOP interfazea prozesuen arteko komunikaziorako +Comment[fa]=واسط DCOP برای ارتباط درون فرایند +Comment[fi]=DCOP-rajapinta sisäiseen kommunikointiin +Comment[fr]=Interface DCOP pour les communications entre processus +Comment[ga]=Comhéadan DCOP le haghaidh cumarsáide idirphróiseas +Comment[gl]=Interface DCOP para Comuicación Entre Procesos +Comment[he]=ממשק DCOP לתקשורת בין-תהליכית +Comment[hi]=इंटर-प्रोसेस कम्यूनिकेशन के लिए डीकॉप इंटरफेस +Comment[hr]=DCOP sučelje za komunikaciju među procesima +Comment[hu]=DCOP-felület IPC-hívásokhoz +Comment[is]=DCOP aðgangur svo ferlin geti talað saman +Comment[it]=Interfaccia DCOP per le comunicazioni tra processi (IPC) +Comment[ja]=プロセス間通信に使われる DCOP インターフェース +Comment[kk]=Процесаралық қатынаудың DCOP интерфейсі +Comment[km]=ចំណុចប្រទាក់ DCOP សម្រាប់ការទំនាក់ទំនងខាងក្នុងដំណើរការ +Comment[ko]=프로세스 사이에 통신을 주고 받을 수 있게 해주는 DCOP 인터페이스 +Comment[lt]=DCOP sąsaja tarpprocesiniam ryšiui +Comment[lv]=DCOP Starpseja Iekšējo-Procesu komunikācijām +Comment[mk]=Интерфејс DCOP за комуникација помеѓу процесите +Comment[ms]=Antaramuka DCOP untuk Komunikasi Antara Proses +Comment[mt]=Interfaċċja DCOP għal komunikazzjoni bejn proċessi (IPC) +Comment[nb]=DCOP grensesnitt for interprosesskommunikasjon +Comment[nds]=DCOP-Koppelsteed för Kommunikatschoon twischen Perzessen +Comment[ne]=आन्तरिक-प्रक्रिया सञ्चारका लागि DCOP इन्टरफेस +Comment[nl]=DCOP-interface voor interprocescommunicatie +Comment[nn]=DCOP-grensesnitt for interprosesskommunikasjon +Comment[pl]=Interfejs DCOP dla Komunikacji Międzyprocesowej (IPC) +Comment[pt]=Interface do DCOP para a comunicação entre os processos +Comment[pt_BR]=Interface DCOP para comunicações inter-processos +Comment[ro]=Interfaţă DCOP pentru comunicaţie interprocese +Comment[ru]=Интерфейс с DCOP для межпроцессного взаимодействия +Comment[se]=DCOP-lakta proseassaidgaskkasaš gulahallama dihte +Comment[sk]=Rozhranie DCOP pre komunikáciu medzi procesmi +Comment[sl]=Vmesnik DCOP za medprocesno komunikacijo +Comment[sr]=DCOP интерфејс за међупроцесну комуникацју +Comment[sr@Latn]=DCOP interfejs za međuprocesnu komunikacju +Comment[sv]=DCOP-gränssnitt för kommunikation mellan processer +Comment[ta]=செயல்களுக்கிடைப்பட்ட தகவல் பரிவர்த்தனைக்கான ODBC இடைமுகம் +Comment[tg]=Интерфейси DCOP барои Алоқаи Ҷараёни Интернет +Comment[th]=ส่วนติดต่อ DCOP สำหรับการสื่อสารระหว่างโปรเซส +Comment[tr]=IPC için DCOP Arayüzü +Comment[uk]=Інтерфейс DCOP для взаємодії процесів (IPC) +Comment[uz]=Jarayonlararo bogʻlanish uchun DCOP interfeysi +Comment[uz@cyrillic]=Жараёнлараро боғланиш учун DCOP интерфейси +Comment[ven]=DCOP Interface ya tshitenwa tsha vhudavhudzani +Comment[xh]=Ujongano lwe DCOP-lothungelwano lwangaphakathi oluqhubekayo +Comment[zh_CN]=进程间通信的 DCOP 接口 +Comment[zh_HK]=用於行程間通訊的 DCOP 介面 +Comment[zh_TW]=程序程式間通訊的 DCOP 介面 +Comment[zu]=Uxhumano olubhekene lwe DCOP-lothungelwano lwangaphakathi oluqhubekayo diff --git a/noatun/modules/excellent/Makefile.am b/noatun/modules/excellent/Makefile.am new file mode 100644 index 00000000..a2558676 --- /dev/null +++ b/noatun/modules/excellent/Makefile.am @@ -0,0 +1,18 @@ +INCLUDES= -I$(top_srcdir)/noatun/library $(all_includes) +kde_module_LTLIBRARIES = noatun_excellent.la + +noatun_excellent_la_SOURCES = noatunui.cpp\ + userinterface.cpp + +noatun_excellent_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_excellent_la_LIBADD = $(LIB_KFILE) \ + $(top_builddir)/noatun/library/libnoatun.la \ + $(top_builddir)/noatun/library/libnoatuncontrols.la \ + -lqtmcop -lkmedia2_idl -lsoundserver_idl + +noatun_excellent_la_METASOURCES = AUTO + +noinst_HEADERS = userinterface.h + +noatun_modules_excellent_DATA = excellent.plugin excellentui.rc +noatun_modules_excellentdir = $(kde_datadir)/noatun diff --git a/noatun/modules/excellent/excellent.plugin b/noatun/modules/excellent/excellent.plugin new file mode 100644 index 00000000..89f747c0 --- /dev/null +++ b/noatun/modules/excellent/excellent.plugin @@ -0,0 +1,120 @@ +Filename=noatun_excellent.la +Author=Neil Stevens +Site=http://noatun.kde.org/plugins/excellent/ +Email=neil@qualityassistant.com +Type=userinterface +License=X11-like +Name=Excellent +Name[af]=Uitstekende +Name[ar]=ممتاز +Name[az]=Mükəmməl +Name[ca]=Excel·lent +Name[cs]=Vynikající +Name[cy]=Ardderchog +Name[de]=Hervorragend +Name[el]=Έξοχο +Name[eo]=Brila +Name[es]=Excelente +Name[et]=Suurepärane +Name[eu]=Aparta +Name[fa]=عالی +Name[fi]=Erinomainen +Name[ga]=Sármhaith +Name[gl]=Excelente +Name[he]=מעולה +Name[hi]=एक्सेलेंट +Name[hr]=Odlično +Name[is]=Frábært +Name[it]=Eccellente +Name[ja]=エクセレント +Name[km]=ល្អឥតខ្ចោះ +Name[lt]=Puikus +Name[lv]=Lielisks +Name[mk]=Одличен +Name[mt]=Eċċellenti +Name[nb]=Fantastisk +Name[nds]=Goot +Name[ne]=दक्ष +Name[nn]=Fantastisk +Name[pa]=ਸਰਵੋਤਮ +Name[pl]=Doskonały +Name[pt]=Excelente +Name[pt_BR]=Excelente +Name[ro]=Excelent +Name[ru]=Превосходный +Name[sk]=Fantastický +Name[sv]=Utmärkt +Name[ta]=அற்புதம் +Name[tg]=Олиҷаноб +Name[th]=ยอดเยี่ยม +Name[tr]=Mükemmel +Name[uk]=Чудовий +Name[ven]=Zwavhudi +Name[xh]=Hle kwaphela +Name[zh_CN]=优秀的 +Name[zh_HK]=極佳的 +Name[zh_TW]=完美的 +Name[zu]=Kuhle kakhulu +Comment=A very ordinary, and therefore very usable, interface +Comment[af]='n baie gewone, en daarom baie bruikbaar, koppelvlak +Comment[ar]=واجهة استخدام عادية ، و بالتالي ممتازة +Comment[az]=Olduqca bəsit və istifadəli bir axtar üz +Comment[bg]=Обикновен и поради това много полезен интерфейс +Comment[bs]=Vrlo uobičajen i zato vrlo upotrebljiv interfejs +Comment[ca]=Una interfície molt normal, i per tant, molt usable +Comment[cs]=Velmi obvyklé, and proto velmi použitelné rozhraní +Comment[cy]=Rhyngwyneb Cyffredin iawn, ac felly defnyddiol iawn +Comment[da]=En meget ordinær, og derfor meget nyttig, grænseflade +Comment[de]=Eine ganz normale und folglich sehr brauchbare Oberfläche +Comment[el]=Ένα πολύ συνηθισμένο, και έτσι πολύ εύχρηστο περιβάλλον +Comment[eo]=Ordinara kaj do tre uzebla interfaco +Comment[es]=Una interfaz muy común y por tanto muy fácil de usar +Comment[et]=Väga tavaline ja lihtsasti kasutatav kasutajaliides +Comment[eu]=Interfaze arrunta eta oso erabilgarria +Comment[fa]=یک واسط معمولی، و بنابراین بسیار مفید +Comment[fi]=Hyvin tavallinen ja käyttökelpoinen käyttöliittymä +Comment[fr]=Une interface très ordinaire et donc très utilisable +Comment[ga]=Comhéadan an-choitianta, agus dá bharr sin, an-inúsáidte +Comment[gl]=Unha interface moi usual e polo tanto moi usábel +Comment[he]=ממשק מאוד פשוט, ועל כן מאוד שימושי +Comment[hi]=एक बहुत साधारण, अतः बहुत उपयोगी इंटरफेस +Comment[hr]=Vrlo obično, i prema tome vrlo upotrebljivo, sučelje +Comment[hu]=Egy jól ismert, ezért jól használható felület +Comment[is]=Mjög venjulegt og notanlegt viðmót +Comment[it]=Un'interfaccia molto ordinaria e molto usabile +Comment[ja]=非常にありふれているが、だからこそ使いやすいインターフェース +Comment[kk]=Ең кәдімгі, сондықтан жиі қолданылатын интерфейс +Comment[km]=ចំណុចប្រទាក់សាមញ្ញបំផុត ហើយក៏ងាយស្រួលប្រើដែរ +Comment[ko]=아주 평범하고 쓸만한 인터페이스 +Comment[lt]=Labai paprasta ir dėlto labai naudinga sąsaja +Comment[lv]=Ļoti vienkārša, un tādēļ ļoti izmantojama, starpseja +Comment[mk]=Мошне обичен, и според тоа мошне корисен интерфејс +Comment[ms]=Antaramuka yang sangat biasa tetapi berguna +Comment[mt]=Interfaċċja ordijarja ħafna u għalhekk utli ħafna +Comment[nb]=Et svært vanlig og brukervennlig grensesnitt +Comment[nds]=En bannig normaal un dorüm bannig eenfach to bruken Böversiet +Comment[ne]=साधारण भएकोले धेरै उपयोगि इन्टरफेस +Comment[nl]=Een heel gewone, en daarom erg bruikbare, interface +Comment[nn]=Eit svært normalt og difor lettbruka grensesnitt +Comment[pl]=Bardzo zwyczajny, ale przez to bardzo użyteczny motyw +Comment[pt]=Uma interface básica e, por isso, muito fácil de usar +Comment[pt_BR]=Uma interface bem ordinária e portanto muito utilizável +Comment[ro]=O interfaţă foarte simplă şi foarte utilă +Comment[ru]=Самый обычный, а потому и очень полезный интерфейс +Comment[se]=Hui dábálaš ja dannege geavahahtti lakta +Comment[sk]=Veľmi obyčajné, a preto použiteľné, rozhranie +Comment[sl]=Zelo običajen in zato zelo uporaben vmesnik +Comment[sr]=Веома обичан, стога и веома лак за коришћење, интерфејс +Comment[sr@Latn]=Veoma običan, stoga i veoma lak za korišćenje, interfejs +Comment[sv]=Ett väldigt vanligt och därför väldigt användbart gränssnitt +Comment[ta]=மிக எளிய, பயனுள்ள இடைமுகம் +Comment[tg]=Интерфейси хеле содда ва бинобар бисёр фоиданок +Comment[th]=ส่วนติดต่อแบบง่ายๆ และด้วยเหตุนั้นก็เลยมีประโยชน์อย่างมาก +Comment[tr]=Oldukça basit ve kullanışlı bir arayüz +Comment[uk]=Дуже звичний, і тому дуже зручний, інтерфейс +Comment[ven]=Zwithu zwazwo, zwo ralo zwa vhuthogwa, interface +Comment[xh]=Eqheleke kakhulu, neluncedo kakhulu, injongano +Comment[zh_CN]=非常普通,因而也非常有用的接口 +Comment[zh_HK]=非常普通但是很實用的介面 +Comment[zh_TW]=非常普通但是很實用的介面 +Comment[zu]=Ejwayelekile ngakhoke esebenzisekayo,uxhumano olubhekeneyo diff --git a/noatun/modules/excellent/excellentui.rc b/noatun/modules/excellent/excellentui.rc new file mode 100644 index 00000000..f9c43c70 --- /dev/null +++ b/noatun/modules/excellent/excellentui.rc @@ -0,0 +1,45 @@ +<!DOCTYPE kpartgui> +<!-- +vim: syntax=xml +--> +<kpartgui name="noatunexcellent" version="4"> +<MenuBar> + <Menu name="file" noMerge="1"><text>&File</text> + <Action name="file_open"/> + <Separator lineSeparator="true"/> + <Action name="file_quit"/> + </Menu> + <Menu name="go_music" noMerge="1"><text>&Go</text> + <Action name="back"/> + <Action name="stop"/> + <Action name="play"/> + <Action name="pause"/> + <Action name="forward"/> + </Menu> + <Menu name="settings" noMerge="1"><text>&Settings</text> + <Merge name="StandardToolBarMenuHandler" /> + <Action name="options_show_toolbar"/> + <Action name="options_show_menubar"/> + <Action name="show_playlist"/> + <Action name="show_volumecontrol"/> + <Separator lineSeparator="true"/> + <Action name="effects"/> + <Action name="equalizer"/> + <Action name="loop_style"/> + <Separator lineSeparator="true"/> + <Action name="options_configure"/> + </Menu> +</MenuBar> +<Toolbar name="main"><text>Main Toolbar</text> + <Action name="back"/> + <Action name="stop"/> + <Action name="play"/> + <Action name="pause"/> + <Action name="forward"/> + <Separator lineSeparator="true"/> + <Action name="file_open"/> + <Action name="show_playlist"/> + <Separator lineSeparator="true"/> + <Action name="loop_style"/> +</Toolbar> +</kpartgui> diff --git a/noatun/modules/excellent/noatunui.cpp b/noatun/modules/excellent/noatunui.cpp new file mode 100644 index 00000000..a103268d --- /dev/null +++ b/noatun/modules/excellent/noatunui.cpp @@ -0,0 +1,32 @@ +// noatunui.cpp +// +// Copyright (C) 2000 Neil Stevens <multivac@fcmail.com> +// Copyright (C) 1999 Charles Samuels <charles@kde.org> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name(s) of the author(s) shall not be +// used in advertising or otherwise to promote the sale, use or other dealings +// in this Software without prior written authorization from the author(s). + +#include "userinterface.h" + +extern "C" KDE_EXPORT Plugin *create_plugin() +{ + return new Excellent(); +} diff --git a/noatun/modules/excellent/userinterface.cpp b/noatun/modules/excellent/userinterface.cpp new file mode 100644 index 00000000..7f218e98 --- /dev/null +++ b/noatun/modules/excellent/userinterface.cpp @@ -0,0 +1,394 @@ +// userinterface.cpp +// +// Copyright (C) 2001 Neil Stevens <neil@qualityassistant.com> +// Copyright (C) 1999 Charles Samuels <charles@kde.org> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name(s) of the author(s) shall not be +// used in advertising or otherwise to promote the sale, use or other dealings +// in this Software without prior written authorization from the author(s). + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <noatun/effects.h> +#include <noatun/app.h> +#include <noatun/controls.h> +#include <noatun/pref.h> +#include <noatun/player.h> + +#include "userinterface.h" + +#include <kbuttonbox.h> +#include <kconfig.h> +#include <kfiledialog.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kmenubar.h> +#include <kmessagebox.h> +#include <kpixmapeffect.h> +#include <kpopupmenu.h> +#include <kstatusbar.h> +#include <kstdaction.h> +#include <kwin.h> +#include <kurldrag.h> + +#include <qbitmap.h> +#include <qdragobject.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qobjectlist.h> +#include <qobjectdict.h> +#include <qpushbutton.h> +#include <qtooltip.h> +#include <qvbox.h> + +Excellent::Excellent() + : KMainWindow(0, "NoatunExcellent") + , UserInterface() +{ + setAcceptDrops(true); + + KStdAction::quit(napp, SLOT(quit()), actionCollection()); + KStdAction::open(napp, SLOT(fileOpen()), actionCollection()); + setStandardToolBarMenuEnabled(true); + + menubarAction = KStdAction::showMenubar(this, SLOT(showMenubar()), actionCollection()); + KStdAction::preferences(napp, SLOT(preferences()), actionCollection()); + + // buttons + NoatunStdAction::back(actionCollection(), "back"); + NoatunStdAction::stop(actionCollection(), "stop"); + NoatunStdAction::play(actionCollection(), "play"); + NoatunStdAction::pause(actionCollection(), "pause"); + NoatunStdAction::forward(actionCollection(), "forward"); + NoatunStdAction::playlist(actionCollection(), "show_playlist"); + + volumeAction = new KToggleAction(i18n("Show &Volume Control"), 0, this, SLOT(showVolumeControl()), actionCollection(), "show_volumecontrol"); + volumeAction->setCheckedState(i18n("Hide &Volume Control")); + NoatunStdAction::effects(actionCollection(), "effects"); + NoatunStdAction::equalizer(actionCollection(), "equalizer"); + + NoatunStdAction::loop(actionCollection(), "loop_style"); + + createGUI("excellentui.rc"); + + napp->pluginActionMenu()->plug(menuBar(),3); + toolBar("mainToolBar")->hide(); + + // Who needs Qt Designer? + mainFrame = new QHBox(this); + mainFrame->setSpacing(KDialog::spacingHint()); + mainFrame->setMargin(0); + slider = new L33tSlider(0, 1000, 10, 0, L33tSlider::Horizontal, mainFrame); + slider->setTickmarks(QSlider::NoMarks); + + elapsed = new QLabel(mainFrame); + QFont labelFont = elapsed->font(); + labelFont.setPointSize(24); + labelFont.setBold(true); + QFontMetrics labelFontMetrics = labelFont; + elapsed->setFont(labelFont); + elapsed->setAlignment(AlignCenter | AlignVCenter | ExpandTabs); + elapsed->setText("--:--"); + elapsed->setFixedHeight(labelFontMetrics.height()); + elapsed->setMinimumWidth(elapsed->sizeHint().width()); + + // Doing this makes the slider the same heigh as the font. This is just plain wrong... + //slider->setFixedHeight(labelFontMetrics.height()); + + setCentralWidget(mainFrame); + + total = new QLabel(statusBar()); + labelFont = total->font(); + labelFont.setBold(true); + total->setFont(labelFont); + total->setAlignment(AlignCenter | AlignVCenter | ExpandTabs); + total->setText("--:--"); + total->setMinimumWidth(total->sizeHint().width()); + total->setText(""); + + statusBar()->addWidget(total, 0, true); + statusBar()->show(); + + connect( napp, SIGNAL(hideYourself()), this, SLOT(hide()) ); + connect( napp, SIGNAL(showYourself()), this, SLOT(show()) ); + + connect(napp->player(), SIGNAL(playing()), this, SLOT(slotPlaying())); + connect(napp->player(), SIGNAL(stopped()), this, SLOT(slotStopped())); + connect(napp->player(), SIGNAL(paused()), this, SLOT(slotPaused())); + napp->player()->handleButtons(); + + connect(napp->player(), SIGNAL(timeout()), this, SLOT(slotTimeout())); + connect(napp->player(), SIGNAL(loopTypeChange(int)), this, SLOT(slotLoopTypeChanged(int))); + + /* This skipToWrapper is needed to pass milliseconds to Player() as everybody + * below the GUI is based on milliseconds instead of some unprecise thingy + * like seconds or mille */ + connect(slider, SIGNAL(userChanged(int)), this, SLOT(skipToWrapper(int))); + connect(this, SIGNAL(skipTo(int)), napp->player(), SLOT(skipTo(int))); + + connect(slider, SIGNAL(sliderMoved(int)), SLOT(sliderMoved(int))); + + setCaption("Noatun"); + setIcon(SmallIcon("noatun")); + //slotLoopTypeChanged(Player::None); + changeStatusbar(); + handleLengthString("--:--/--:--"); + + setMinimumWidth(250); + resize(300, 75); + + KConfig &config = *KGlobal::config(); + + toolBar("main")->applySettings(&config, "Excellent main"); + + config.setGroup("excellent"); + + volumeSlider = 0; + volumeAction->setChecked( config.readBoolEntry("volumeShown", false) ); + showVolumeControl(); + + menubarAction->setChecked( config.readBoolEntry("menuShown", true) ); + showMenubar(); + + applyMainWindowSettings(&config, "excellent"); + + switch((NET::MappingState)config.readNumEntry("mappingState", (int)NET::Visible)) + { + case NET::Visible: + showNormal(); + break; + case NET::Withdrawn: + if (napp->libraryLoader()->isLoaded("systray.plugin")) + hide(); + break; + case NET::Iconic: + showMinimized(); + break; + } + + for (QPtrListIterator<QObject> i(*children()); i.current(); ++i) + (*i)->installEventFilter(this); +} + +Excellent::~Excellent() +{ + KConfig &config = *KGlobal::config(); + saveMainWindowSettings(&config, "excellent"); + toolBar("main")->saveSettings(&config, "Excellent main"); + config.setGroup("excellent"); + config.writeEntry("volumeShown", volumeAction->isChecked()); + config.writeEntry("menuShown", menubarAction->isChecked()); + config.writeEntry("width", width()); + config.writeEntry("height", height()); + config.sync(); +} + +void Excellent::showEvent(QShowEvent *e) +{ + KConfig *config = KGlobal::config(); + config->setGroup("excellent"); + config->writeEntry("mappingState", NET::Visible); + config->sync(); + + KMainWindow::showEvent(e); +} + +void Excellent::hideEvent(QHideEvent *e) +{ + KConfig *config = KGlobal::config(); + config->setGroup("excellent"); + config->writeEntry("mappingState", NET::Withdrawn); + config->sync(); + + KMainWindow::hideEvent(e); +} + +void Excellent::closeEvent(QCloseEvent *) +{ + unload(); +} + +void Excellent::dragEnterEvent(QDragEnterEvent *event) +{ + // accept uri drops only + event->accept(KURLDrag::canDecode(event)); +} + +void Excellent::dropEvent(QDropEvent *event) +{ + KURL::List uri; + if (KURLDrag::decode(event, uri)) + { + for (KURL::List::Iterator i = uri.begin(); i != uri.end(); ++i) + napp->player()->openFile(*i, false); + } +} + +bool Excellent::eventFilter(QObject *o, QEvent *e) +{ + if (e->type() == QEvent::Wheel) + { + wheelEvent(static_cast<QWheelEvent*>(e)); + return true; + } + return QWidget::eventFilter(o, e); +} + +void Excellent::wheelEvent(QWheelEvent *e) +{ + int delta=e->delta(); + napp->player()->setVolume(napp->player()->volume() + delta/120*2); +} + +void Excellent::slotPlaying() +{ + slider->setEnabled(true); + changeStatusbar(); +} + +void Excellent::slotStopped() +{ + slider->setEnabled(false); + if(!napp->player()->current()) return; + changeStatusbar(); + slider->setValue(0); + handleLengthString("--:--/--:--"); +} + +void Excellent::slotPaused() +{ + slider->setEnabled(true); + changeStatusbar(); +} + +void Excellent::slotTimeout() +{ + if(volumeSlider) volumeSlider->setValue(100 - napp->player()->volume()); + + if (!slider->currentlyPressed()) + handleLengthString(napp->player()->lengthString()); + + if(!napp->player()->current()) return; + if(slider->currentlyPressed()) return; + + slider->setRange(0, (int)napp->player()->getLength() / 1000 ); + slider->setValue((int)napp->player()->getTime() / 1000 ); + + changeStatusbar(); +} + +void Excellent::sliderMoved(int seconds) +{ + if(napp->player()->current()) + handleLengthString(napp->player()->lengthString(seconds * 1000)); +} + +void Excellent::skipToWrapper(int second) // wrap int to int _and_ seconds to mseconds +{ + emit skipTo((int)(second*1000)); +} + +void Excellent::slotLoopTypeChanged(int type) +{ + static const int time = 2000; + switch (type) + { + case Player::None: + statusBar()->message(i18n("No looping"), time); + break; + case Player::Song: + statusBar()->message(i18n("Song looping"), time); + break; + case Player::Playlist: + statusBar()->message(i18n("Playlist looping"), time); + break; + case Player::Random: + statusBar()->message(i18n("Random play"), time); + } +} + +void Excellent::showMenubar(void) +{ + if(menubarAction->isChecked()) + { + menuBar()->show(); + } + else + { + KMessageBox::information(this, i18n("<qt>Press %1 to show the menubar.</qt>").arg(menubarAction->shortcut().toString()), QString::null, "Hide Menu warning"); + menuBar()->hide(); + } +} + +void Excellent::showVolumeControl(void) +{ + if(volumeAction->isChecked()) + growVolumeControl(); + else + shrinkVolumeControl(); +} + +void Excellent::changeStatusbar(void) +{ + if(!napp->player()->current().isNull()) + statusBar()->message(napp->player()->current().title()); +} + +void Excellent::handleLengthString(const QString &text) +{ + if(text.right(5) == "00:00" && text.left(5) == "00:00") + { + elapsed->setText("--:--"); + total->setText("--:--"); + } + else + { + // Split the length string in to "current" and "elapsed" + QStringList tokens = QStringList::split("/", text); + + elapsed->setText(tokens[0]); + total->setText(tokens[1]); + } +} + +void Excellent::growVolumeControl(void) +{ + volumeSlider = new L33tSlider(0, 100, 10, 0, Vertical, mainFrame); + volumeSlider->setValue(100 - napp->player()->volume()); + volumeSlider->show(); + connect(volumeSlider, SIGNAL(sliderMoved(int)), SLOT(changeVolume(int))); + connect(volumeSlider, SIGNAL(userChanged(int)), SLOT(changeVolume(int))); +} + +void Excellent::shrinkVolumeControl(void) +{ + delete volumeSlider; + volumeSlider = 0; +} + +void Excellent::changeVolume(int slider) +{ + napp->player()->setVolume(100 - slider); +} + +#include "userinterface.moc" diff --git a/noatun/modules/excellent/userinterface.h b/noatun/modules/excellent/userinterface.h new file mode 100644 index 00000000..588db6e4 --- /dev/null +++ b/noatun/modules/excellent/userinterface.h @@ -0,0 +1,101 @@ +// userinterface.h +// +// Copyright (C) 2000, 2001 Neil Stevens <multivac@fcmail.com> +// Copyright (C) 1999 Charles Samuels <charles@kde.org> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name(s) of the author(s) shall not be +// used in advertising or otherwise to promote the sale, use or other dealings +// in this Software without prior written authorization from the author(s). + +#ifndef USERINTERFACE_H +#define USERINTERFACE_H + +#include <noatun/plugin.h> +#include <noatun/app.h> +#include <noatun/stdaction.h> +#include <kmainwindow.h> + +class KAction; +class KPopupMenu; +class KStatusBar; +class Player; +class QHBox; +class QLabel; +class QSlider; +class L33tSlider; +class KToggleAction; + +/** + * @short Main window class + * @author Neil Stevens <multivac@fcmail.com> + * @author Charles Samuels <charles@kde.org> + */ +class Excellent : public KMainWindow, public UserInterface +{ +Q_OBJECT + +public: + Excellent(); + virtual ~Excellent(); + void load(const QString& url); + +protected: + virtual void showEvent(QShowEvent *); + virtual void hideEvent(QHideEvent *); + virtual void closeEvent(QCloseEvent *); + virtual void dragEnterEvent(QDragEnterEvent *); + virtual void dropEvent(QDropEvent *); + void wheelEvent(QWheelEvent *e); + bool eventFilter(QObject *o, QEvent *e); + +public slots: + void slotPlaying(); + void slotStopped(); + void slotPaused(); + + void slotTimeout(); + void sliderMoved(int seconds); + void slotLoopTypeChanged(int type); + void skipToWrapper(int second); + +signals: + // emitted by skipToWrapper() + void skipTo(int); + +private slots: + void showVolumeControl(void); + void showMenubar(void); + void changeStatusbar(void); + void changeVolume(int); + + void handleLengthString(const QString &text); + +private: + void growVolumeControl(void); + void shrinkVolumeControl(void); + + QHBox *mainFrame; + + KToggleAction *volumeAction, *menubarAction; + L33tSlider *volumeSlider, *slider; + QLabel *elapsed, *total; +}; + +#endif diff --git a/noatun/modules/htmlexport/Makefile.am b/noatun/modules/htmlexport/Makefile.am new file mode 100644 index 00000000..bbea16ab --- /dev/null +++ b/noatun/modules/htmlexport/Makefile.am @@ -0,0 +1,16 @@ + +INCLUDES= -I$(top_srcdir)/noatun/library $(all_includes) +kde_module_LTLIBRARIES = noatun_htmlexport.la + +noatun_htmlexport_la_SOURCES = htmlexport.cpp +noinst_HEADERS = htmlexport.h + +noatun_htmlexport_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_htmlexport_la_LIBADD = $(LIB_KFILE) $(top_builddir)/noatun/library/libnoatun.la \ + -lqtmcop -lkmedia2_idl -lsoundserver_idl + +noatun_htmlexport_la_METASOURCES = AUTO + + +noatun_modules_htmlexport_DATA = htmlexport.plugin +noatun_modules_htmlexportdir = $(kde_datadir)/noatun diff --git a/noatun/modules/htmlexport/TODO b/noatun/modules/htmlexport/TODO new file mode 100644 index 00000000..6f97ad78 --- /dev/null +++ b/noatun/modules/htmlexport/TODO @@ -0,0 +1,3 @@ +Most important TODO items: +* Read tags before writing the file +* Clean up the configure dialog and fix remaining issues diff --git a/noatun/modules/htmlexport/htmlexport.cpp b/noatun/modules/htmlexport/htmlexport.cpp new file mode 100644 index 00000000..dc48fd8f --- /dev/null +++ b/noatun/modules/htmlexport/htmlexport.cpp @@ -0,0 +1,308 @@ +#include <klocale.h> +#include <qregexp.h> +#include <qtextcodec.h> +#include <kaction.h> +#include <noatun/stdaction.h> +#include "htmlexport.h" + +extern "C" +{ + KDE_EXPORT Plugin *create_plugin() + { + return new HTMLExport(); + } +} + +HTMLExport::HTMLExport(): QObject(0, "HTMLExport"), Plugin() +{ + NOATUNPLUGINC(HTMLExport); + + mAction = new KAction(i18n("&Export Playlist..."), "filesaveas", 0, + this, SLOT(slotExport()), this, "exportlist"); + napp->pluginActionMenu()->insert(mAction); + + new Prefs(this); + config = KGlobal::config(); +} + +HTMLExport::~HTMLExport() +{ + napp->pluginActionMenu()->remove(mAction); +} + +void HTMLExport::slotExport() +{ + // init readConfig + config->setGroup("HTMLExport"); + + // get output target + KURL url = KFileDialog::getSaveURL(QString::null, + "text/html", + 0, + i18n("Export Playlist")); + + // write into tempfile + KTempFile temp; + temp.setAutoDelete(true); + QFile file(temp.name()); + file.open(IO_WriteOnly); + QTextStream str(&file); + str.setCodec(QTextCodec::codecForName("utf8")); + + str << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl; + str << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">" << endl; + str << "<!-- Generated by Noatun " << NOATUN_MAJOR << "." << NOATUN_MINOR << "." << NOATUN_PATCHLEVEL << " -->" << endl; + + str << endl; + + str << "<html>" << endl; + str << "<head>" << endl; + str << "\t<title>" << i18n("Noatun Playlist") << "</title>" << endl; + + str << "\t<style type=\"text/css\">" << endl; + str << "\t\t<!--" << endl; + // Set the heading color + str << "\t\th1 { color:#"<< getColorByEntry("headColor")<<"; }" << endl; + + // Optionally set the background image + if (!config->readPathEntry( "bgImgPath" ).stripWhiteSpace().isEmpty()) { + // Image + str << "\t\tp,li { color:#"<< getColorByEntry("txtColor") << "; }" << endl; + str << "\t\tbody { background-image: url(\"" << config->readPathEntry( "bgImgPath" ) << "\"); }" << endl; + } + else { + // Color + str << "\t\tp,li,body { color:#"<< getColorByEntry("txtColor"); + str << "; background-color:#" << getColorByEntry( "bgColor" ) << "; }" << endl; + } + + // Links are text colored, too + str << "\t\ta { color:#" << getColorByEntry("txtColor") << "; }" << endl; + if (getColorByEntry("hoverColor") != getColorByEntry("txtColor")) + str << "\t\ta:hover { color:#"<< getColorByEntry("hoverColor")<<"; }"<< endl; + + str << "\t\t-->" << endl; + str << "\t</style>" << endl; + + str << "</head>" << endl; + str << endl; + str << "<body>" << endl; + str << "\t<h1>" << i18n("Noatun Playlist") << "</h1>" << endl; + + // Cache the config settings used in the big loop + bool link_entries = config->readBoolEntry( "linkEntries" ); + bool number_entries = config->readBoolEntry( "numberEntries" ); + + if (number_entries) + str << "\t\t<ol>" << endl; + else + str << "\t\t<p>" << endl; + + + for (PlaylistItem item = napp->playlist()->getFirst();item;item = napp->playlist()->getAfter(item)) { + str << "\t\t\t"; + + if (number_entries) + str << "<li>"; + + if (link_entries) + str << "<a href=\"" << htmlEscape(item.file()) << "\">"; + + str << htmlEscape(item.title()); + + if (link_entries) + str << "</a>"; + + if (number_entries) + str << "</li>" << endl; + else + str << "<br />" << endl; + } + + if (number_entries) + str << "\t\t</ol>" << endl; + else + str << "\t\t</p>" << endl; + + str << "\t</body>" << endl; + str << "</html>" << endl; + + file.close(); + // tempfile -> userdefined file + KIO::NetAccess::upload(temp.name(), url, 0); +} + +QString HTMLExport::htmlEscape(const QString &source) { + // Escape characters that need to be escaped + QString temp = source; + + temp.replace( QRegExp("&"), "&" ); + temp.replace( QRegExp("<"), "<" ); + temp.replace( QRegExp(">"), ">" ); + + return temp; +} + +QString HTMLExport::getColorByEntry(QString s) +{ + QString res; + QString tmp; + QColor c; + + // init readConfig + + config->setGroup("HTMLExport"); + + c = config->readColorEntry( s ); + tmp = QString::number( c.red(), 16); + if (tmp.length()==1) tmp="0"+tmp; + res = tmp; + + tmp = QString::number( c.green(), 16); + if (tmp.length()==1) tmp="0"+tmp; + res += tmp; + + tmp = QString::number( c.blue(), 16); + if (tmp.length()==1) tmp="0"+tmp; + res += tmp; + + return res; + +} +//////////////////////////////////// Settings //////////////////////////////////// + +Prefs::Prefs(QObject *parent) + : CModule(i18n("Playlist Export"), i18n("Colors & Settings for HTML Export"), "html", parent) +{ + + // Init Config + KConfig *config = KGlobal::config(); + config->setGroup("HTMLExport"); + + // Set default values + if ( !config->hasKey( "headColor" ) ) + config->writeEntry( "headColor", QColor( black ) ) ; + + if ( !config->hasKey( "hoverColor" ) ) + config->writeEntry( "hoverColor", QColor( black ) ); + + if ( !config->hasKey( "bgColor" ) ) + config->writeEntry( "bgColor", QColor( white ) ) ; + + if ( !config->hasKey( "txtColor" ) ) + config->writeEntry( "txtColor", QColor( black ) ); + + config->sync(); + + // Draw Stuff and insert Settings + QVBoxLayout *top = new QVBoxLayout(this, KDialog::marginHint(), + KDialog::spacingHint() ); + + colorBox = new QGroupBox( i18n( "HTML Color Settings" ), this, "colorBox" ); + + bgcolorLabel = new QGridLayout( colorBox, 2, 5, + KDialog::marginHint(), KDialog::spacingHint() ); + + headColorSelect = new KColorButton( colorBox, "headColorSelect" ); + + hoverColorSelect = new KColorButton( colorBox, "hoverColorSelect" ); + + bgColorSelect = new KColorButton( colorBox, "bgColorSelect" ); + + txtColorSelect = new KColorButton( colorBox, "txtColorSelect" ); + + txtColorLabel = new QLabel( colorBox, "txtColorLabel" ); + txtColorLabel->setText( i18n( "Text:" ) ); + txtColorLabel->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) ); + + bgColorLabel = new QLabel( colorBox, "bgColorLabel" ); + bgColorLabel->setText( i18n( "Background:" ) ); + bgColorLabel->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) ); + + headColorLabel = new QLabel( colorBox, "headColorLabel" ); + headColorLabel->setText( i18n( "Heading:" ) ); + headColorLabel->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) ); + + hoverColorLabel = new QLabel( colorBox, "hoverColorLabel" ); + hoverColorLabel->setText( i18n( "Link hover:" ) ); + hoverColorLabel->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) ); + + bgcolorLabel->setRowStretch(0, 1); + + // Makes the spacing nice + bgcolorLabel->setColStretch(1, 2); + bgcolorLabel->setColStretch(2, 1); + bgcolorLabel->setColStretch(4, 2); + + bgcolorLabel->addWidget( txtColorLabel, 0, 0 ); + bgcolorLabel->addWidget( txtColorSelect, 0, 1 ); + bgcolorLabel->addWidget( headColorLabel, 1, 0 ); + bgcolorLabel->addWidget( headColorSelect, 1, 1 ); + bgcolorLabel->addWidget( bgColorLabel, 0, 3 ); + bgcolorLabel->addWidget( bgColorSelect, 0, 4 ); + bgcolorLabel->addWidget( hoverColorLabel, 1, 3 ); + bgcolorLabel->addWidget( hoverColorSelect, 1, 4 ); + + + // Set up the Background Image frame + bgPicBox = new QHGroupBox( i18n( "Background Image"), this, "bgPicBox" ); + + // Set up the URL requestor + bgPicPath = new KURLRequester ( bgPicBox, "bgPicPath" ); + bgPicPath->setShowLocalProtocol(true); + + // Set up the URL requestor's file dialog + bgPicPath->setMode(KFile::File | KFile::ExistingOnly); + bgPicPath->setFilter("image/gif image/jpeg image/gif image/png image/svg+xml image/tiff"); + + linkEntries = new QCheckBox( this, "linkEntries" ); + linkEntries->setText( i18n( "Hyper&link playlist entries to their URL" ) ); + linkEntries->setTristate( false ); + + numberEntries = new QCheckBox( this, "numberEntries" ); + numberEntries->setText( i18n( "&Number playlist entries" ) ); + numberEntries->setTristate( false ); + + top->addWidget( colorBox ); + top->addWidget( bgPicBox ); + top->addWidget( linkEntries ); + top->addWidget( numberEntries ); + + top->addStretch(); + + reopen(); +} + +void Prefs::save() +{ + KConfig *config = KGlobal::config(); + + QString bgRealURL = bgPicPath->url(); + + if (bgRealURL[0] == '/') + bgRealURL = "file:" + bgRealURL; + + config->setGroup( "HTMLExport" ); + config->writeEntry( "bgColor", bgColorSelect->color() ); + config->writeEntry( "txtColor", txtColorSelect->color() ); + config->writeEntry( "headColor", headColorSelect->color() ); + config->writeEntry( "hoverColor", hoverColorSelect->color() ); + config->writePathEntry( "bgImgPath", bgRealURL ); + config->writeEntry( "linkEntries", linkEntries->isChecked() ); + config->writeEntry( "numberEntries", numberEntries->isChecked() ); + config->sync(); +} + +void Prefs::reopen() +{ + KConfig *config = KGlobal::config(); + headColorSelect->setColor(config->readColorEntry( "headColor" ) ); + hoverColorSelect->setColor( config->readColorEntry( "hoverColor" ) ); + bgColorSelect->setColor( config->readColorEntry( "bgColor" ) ); + txtColorSelect->setColor( config->readColorEntry( "txtColor" ) ); + bgPicPath->setURL( config->readPathEntry( "bgImgPath" ) ); + numberEntries->setChecked( config->readBoolEntry( "numberEntries" ) ); + linkEntries->setChecked( config->readBoolEntry( "linkEntries" ) ); +} +#include "htmlexport.moc" + diff --git a/noatun/modules/htmlexport/htmlexport.h b/noatun/modules/htmlexport/htmlexport.h new file mode 100644 index 00000000..a909a5cb --- /dev/null +++ b/noatun/modules/htmlexport/htmlexport.h @@ -0,0 +1,89 @@ + +#ifndef _HTMLEXPORT_H_ +#define _HTMLEXPORT_H_ + +#include <qfile.h> +#include <qtextstream.h> +#include <qlabel.h> +#include <qhgroupbox.h> +#include <qlineedit.h> +#include <qcheckbox.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +#include <klocale.h> +#include <kpopupmenu.h> +#include <kfiledialog.h> +#include <ktempfile.h> +#include <kcolorbutton.h> +#include <kio/netaccess.h> +#include <kconfig.h> +#include <kurlrequester.h> + +//#include <kdebug.h> + +#include <noatun/app.h> +#include <noatun/playlist.h> +#include <noatun/pref.h> +#include <noatun/plugin.h> + +class KAction; + +class HTMLExport : public QObject, public Plugin +{ +Q_OBJECT +NOATUNPLUGIND +public: + HTMLExport(); + ~HTMLExport(); + + +private: + QString htmlEscape(const QString &source); + QString getColorByEntry(QString s); + KConfig *config; + KAction *mAction; + +private slots: + void slotExport(); + +}; + +class Prefs : public CModule +{ +Q_OBJECT +public: + Prefs(QObject *parent); + virtual void save(); + virtual void reopen(); + + QGroupBox* colorBox; + + KColorButton* headColorSelect; + KColorButton* hoverColorSelect; + KColorButton* bgColorSelect; + KColorButton* txtColorSelect; + + QLabel* bgColorLabel; + QLabel* txtColorLabel; + QLabel* headColorLabel; + QLabel* hoverColorLabel; + + QCheckBox* linkEntries; + QCheckBox* numberEntries; + + QGroupBox* bgPicBox; + KURLRequester* bgPicPath; + +protected: + QGridLayout* bgcolorLabel; + + +signals: + void saved(); +}; + +#endif + diff --git a/noatun/modules/htmlexport/htmlexport.plugin b/noatun/modules/htmlexport/htmlexport.plugin new file mode 100644 index 00000000..97a10fb9 --- /dev/null +++ b/noatun/modules/htmlexport/htmlexport.plugin @@ -0,0 +1,124 @@ +Filename=noatun_htmlexport.la +Author=Malte Starostik +Email=malte@kde.org +Type=other +License=Artistic +Name=HTML Playlist Export +Name[bn]=এইচ-টি-এম-এল সঙ্গীত-তালিকা রপ্তানি +Name[br]=Ezporzh ar roll tonioù e HTML +Name[bs]=Izvoz liste numera u HTML +Name[ca]=Exportació del repertori en HTML +Name[cs]=Export seznamu skladeb do HTML +Name[cy]=Allforio Rhestr Chwarae HTML +Name[da]=HTML-spilleliste-eksport +Name[de]=Export von Wiedergabelisten in HTML +Name[el]=Εξαγωγή λίστας αναπαραγωγής HTML +Name[eo]=HTML-ludlisteksporto +Name[es]=Exportador de listas de reproducción HTML +Name[et]=Esitusnimekirja eksport HTML-i +Name[eu]=HTML erreprodukzio-zerrendaren esportazioa +Name[fa]=صادرات فهرست پخش زنگام +Name[fi]=HTML-soittolistan vienti +Name[fr]=Export en HTML des listes de lecture +Name[ga]=Easpórtáil Seinmliosta mar HTML +Name[gl]=Exportación de Lista de Reprodución a HTML +Name[he]=ייצוא לרשימת ניגון בתבנית HTML +Name[hu]=Lejátszási lista exportálása HTML-fájlba +Name[is]=Útflutningur á HTML lagalista +Name[it]=Esportazione HTML delle playlist +Name[ja]=HTML プレイリストのエクスポート +Name[kk]=Орындау тізімін HTML-экспорттау +Name[km]=នាំចេញបញ្ជីចាក់ HTML +Name[ko]=HTML 재생 목록 내보내기 +Name[lt]=HTML gaidaraščio eksportas +Name[mk]=Испраќање на листа со нумери како HTML +Name[nb]=Eksport av HTML-spilleliste +Name[nds]=Afspeellist-Export na HTML +Name[ne]=HTML बजाउने सूची निर्यात +Name[nl]=HTML-afspeellijst-export +Name[nn]=Eksport av HTML-speleliste +Name[pa]=HTML ਸੰਗੀਤ-ਸੂਚੀ ਨਿਰਯਾਤ +Name[pl]=Eksport listy utworów do formatu HTML +Name[pt]=Exportação de Listas de Músicas em HTML +Name[pt_BR]=Exportação de listas de reprodução em HTML +Name[ro]=Exportare HTML listă de redare +Name[ru]=Экспорт списка песен в HTML +Name[sk]=Export playlistu do HTML +Name[sl]=Izvoz predvajalnega seznama v HTML +Name[sr]=Извожење листе нумера у HTML +Name[sr@Latn]=Izvoženje liste numera u HTML +Name[sv]=HTML-spellistexport +Name[ta]=HTML பாடல் பட்டியல் ஏற்றுமதி +Name[th]=ส่งออกรายการเล่นเป็น HTML +Name[tr]=HTML Çalma Listesi Dışarı Aktarma +Name[uk]=Експорт списку композицій до HTML +Name[zh_CN]=HTML 播放列表导出 +Name[zh_HK]=HTML 播放清單匯出 +Name[zh_TW]=HTML 播放清單匯出 +Comment=Creates a HTML file from the playlist +Comment[af]=Skep 'n Html lêer van die liedjielys +Comment[ar]=ينشئ ملف HTML من لائحة التشغيل +Comment[az]=Çalma siyahısından bir HTML faylı yarat +Comment[bg]=Експортиране на списък за изпълнение във файл от тип HTML +Comment[bn]=সঙ্গীত-তালিকা থেকে একটি এইচ-টি-এম-এল ফাইল তৈরি করে +Comment[br]=Krouiñ ur restr HTML eus ar roll tonioù +Comment[bs]=Pravi HTML dokument od liste numera +Comment[ca]=Crea un fitxer HTML d'una selecció de peces +Comment[cs]=Vytváří ze seznamu skladeb HTML soubor +Comment[cy]=Creu ffeil HTML o'r rhestr chwarae +Comment[da]=Opretter en HTML-fil fra spillelisten +Comment[de]=Erstellt eine HTML-Datei aus einer Wiedergabeliste +Comment[el]=Δημιουργεί ένα αρχείο HTML από τη λίστα αναπαραγωγής +Comment[en_GB]=Creates an HTML file from the playlist +Comment[eo]=Kreas HTML-dosieron el la ludlisto +Comment[es]=Crea un archivo HTML a partir de la lista de reproducción +Comment[et]=HTML-faili loomine nimekirjast +Comment[eu]=HTML fitxategia erreprodukzio-zerrendatik sortzen du +Comment[fa]=از فهرست پخش یک پروندۀ زنگام ایجاد میکند +Comment[fi]=Luo HTML-tiedoston soittolistasta +Comment[fr]=Crée un fichier HTML à partir de la liste de lecture +Comment[ga]=Cruthaigh comhad HTML ón seinmliosta +Comment[gl]=Crea un ficheiro HTML a partires da lista de reprodución +Comment[he]=יצירת קובץ HTML מתוך רשימת הניגון +Comment[hi]=प्लेलिस्ट से एचटीएमएल फ़ाइल बनाता है +Comment[hr]=Stvara od liste pjesama HTML datoteku +Comment[hu]=Lejátszási lista exportálása HTML-ben +Comment[is]=Býr til HTML skrá úr lagalistanum +Comment[it]=Crea un file HTML dalla playlist +Comment[ja]=プレイリストから HTML を作成 +Comment[kk]=Орындау тізімін HTML-пішімді файлға жазу +Comment[km]=បង្កើតបញ្ជីឯកសារ HTML ពីបញ្ជីចាក់ +Comment[ko]=재생 목록에서 HTML 파일 만들기 +Comment[lt]=Sukuria HTML failą iš gaidaraščio +Comment[lv]=Izveido HTML failu no plejlista +Comment[mk]=Креира датотека HTML од листата со нумери +Comment[ms]=Bina fail HTML untuk senarai main +Comment[mt]=Joħloq fajl HTML mill-playlist +Comment[nb]=Lager en HTML-fil fra spillelisten +Comment[nds]=Stellt ut de Afspeellist en HTML-Datei op +Comment[ne]=बजाउने सूचीबाट HTML फाइल सिर्जना गर्दछ +Comment[nl]=Maakt een HTML-bestand aan op basis van de speellijst +Comment[nn]=Lagar ei HTML-fil frå spelelista +Comment[pa]=ਸੰਗੀਤ-ਸੂਚੀ ਤੋਂ ਇੱਕ HTML ਫਾਇਲ ਬਣਾਓ +Comment[pl]=Tworzy plik HTML z listy nagrań +Comment[pt]=Cria um ficheiro HTML a partir de uma lista de músicas +Comment[pt_BR]=Cria um arquivo HTML a partir da lista de reprodução +Comment[ro]=Creează un fişier HTML dintr-o listă de redare +Comment[ru]=Создание HTML-файла из списка песен +Comment[se]=Ráhkada HTML-fiilla čuojahanlisttus +Comment[sk]=Vytvorí HTML súbor z playlistu +Comment[sl]=Ustvari datoteko HTML iz predvajalnega seznama +Comment[sr]=Прави HTML фајл на основу листе нумера +Comment[sr@Latn]=Pravi HTML fajl na osnovu liste numera +Comment[sv]=Skapar en HTML-fil av en spellista +Comment[ta]=பாடல் பட்டியலிலிருந்து HTML ஆவணமொன்றை உருவாக்கின்றது +Comment[tg]=Аз рӯйхати бозикуниҳо файли HTML-ро офарид +Comment[th]=สร้างแฟ้ม HTML สำหรับรายการเล่น +Comment[tr]=Çalma listesinden bir HTML dosyası oluşturur +Comment[uk]=Створює файл HTML зі списку композицій +Comment[ven]=Itani faela ya HTML u bva kha mutevhe wa tshitambi +Comment[xh]=Yenza ifayile ye HTML kuluhlu lomdlalo +Comment[zh_CN]=从播放列表创建 HTML 文件 +Comment[zh_HK]=從播放清單建立 HTML 檔案 +Comment[zh_TW]=從播放清單建立 HTML 文件檔案 +Comment[zu]=Yenza ifayela ye HTML kuluhlu lomdlalo diff --git a/noatun/modules/infrared/Makefile.am b/noatun/modules/infrared/Makefile.am new file mode 100644 index 00000000..bf8a7212 --- /dev/null +++ b/noatun/modules/infrared/Makefile.am @@ -0,0 +1,16 @@ + +INCLUDES= -I$(top_srcdir)/noatun/library $(all_includes) +kde_module_LTLIBRARIES = noatun_infrared.la + +noatun_infrared_la_SOURCES = infrared.cpp lirc.cpp irprefs.cpp +noinst_HEADERS = infrared.h lirc.h irprefs.h + +noatun_infrared_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_infrared_la_LIBADD = $(LIB_KFILE) $(top_builddir)/noatun/library/libnoatun.la \ + -lqtmcop -lkmedia2_idl -lsoundserver_idl + +noatun_infrared_la_METASOURCES = AUTO + + +noatun_modules_infrared_DATA = infrared.plugin +noatun_modules_infrareddir = $(kde_datadir)/noatun diff --git a/noatun/modules/infrared/README b/noatun/modules/infrared/README new file mode 100644 index 00000000..b3fda334 --- /dev/null +++ b/noatun/modules/infrared/README @@ -0,0 +1,3 @@ +This plugin enables Noatun to be controlled with an IR remote control. +You'll need lirc (http://fsinfo.cs.uni-sb.de/~columbus/lirc/) and +an IR receiver supported by lirc. diff --git a/noatun/modules/infrared/infrared.cpp b/noatun/modules/infrared/infrared.cpp new file mode 100644 index 00000000..60ea145c --- /dev/null +++ b/noatun/modules/infrared/infrared.cpp @@ -0,0 +1,120 @@ + +#include <stdio.h> + +#include <unistd.h> +#include <noatun/player.h> +#include <noatun/app.h> + +#include <klocale.h> +#include <qtimer.h> + +#include "infrared.h" +#include "lirc.h" +#include "irprefs.h" + +extern "C" +{ + KDE_EXPORT Plugin *create_plugin() + { + return new InfraRed(); + } +} + + +InfraRed::InfraRed() + : QObject(), + Plugin() +{ + NOATUNPLUGINC(InfraRed); + m_lirc = new Lirc(this); + connect(m_lirc, + SIGNAL(commandReceived(const QString &, const QString &, int)), + SLOT(slotCommand(const QString &, const QString &, int))); + + IRPrefs::s_lirc = m_lirc; + volume=0; + QTimer::singleShot(0, this, SLOT(start())); +} + +InfraRed::~InfraRed() +{ +} + +void InfraRed::start() +{ + new IRPrefs(this); +} + +void InfraRed::slotCommand(const QString &remote, const QString &button, int repeat) +{ + switch (IRPrefs::actionFor(remote, button, repeat)) + { + case IRPrefs::None: + break; + + case IRPrefs::Play: + napp->player()->play(); + break; + + case IRPrefs::Stop: + napp->player()->stop(); + break; + + case IRPrefs::Pause: + napp->player()->playpause(); + break; + + case IRPrefs::Mute: + if (napp->player()->volume()) + { + volume=napp->player()->volume(); + napp->player()->setVolume(0); + } + else + { + napp->player()->setVolume(volume); + } + break; + + case IRPrefs::Previous: + napp->player()->back(); + break; + + case IRPrefs::Next: + napp->player()->forward(); + break; + + case IRPrefs::VolumeDown: + napp->player()->setVolume(napp->player()->volume() - 4); + break; + + case IRPrefs::VolumeUp: + napp->player()->setVolume(napp->player()->volume() + 4); + break; + + case IRPrefs::SeekBackward: // - 3 seconds + napp->player()->skipTo( QMAX(0, napp->player()->getTime() - 3000) ); + break; + + case IRPrefs::SeekForward: // + 3 seconds + napp->player()->skipTo( QMIN(napp->player()->getLength(), + napp->player()->getTime() + 3000) ); + break; + case IRPrefs::ShowPlaylist: + napp->player()->toggleListView(); + break; + case IRPrefs::NextSection: + // This and the next case theoretically shouldn't bypass player() + // but I'm making this change as inobtrusive as possible. That + // means restricting the change to infrared and not messing around + // in libnoatun -- Neil + napp->playlist()->nextSection(); + break; + case IRPrefs::PreviousSection: + napp->playlist()->previousSection(); + break; + } +} + +#include "infrared.moc" + diff --git a/noatun/modules/infrared/infrared.h b/noatun/modules/infrared/infrared.h new file mode 100644 index 00000000..37e97735 --- /dev/null +++ b/noatun/modules/infrared/infrared.h @@ -0,0 +1,30 @@ + +#ifndef _INFRARED_H_ +#define _INFRARED_H_ + +#include <noatun/player.h> +#include <noatun/plugin.h> + +class NoatunPreferences; +class Lirc; + +class InfraRed : public QObject, public Plugin +{ +Q_OBJECT +NOATUNPLUGIND +public: + InfraRed(); + ~InfraRed(); + +private slots: + void slotCommand(const QString &, const QString &, int); + + void start(); + +private: + Lirc *m_lirc; + int volume; +}; + +#endif + diff --git a/noatun/modules/infrared/infrared.plugin b/noatun/modules/infrared/infrared.plugin new file mode 100644 index 00000000..dab20149 --- /dev/null +++ b/noatun/modules/infrared/infrared.plugin @@ -0,0 +1,120 @@ +Filename=noatun_infrared.la +Author=Malte Starostik +Email=malte@kde.org +Type=other +License=Artistic +Name=Infrared Control +Name[af]=Infrared Kontrole +Name[ar]=تحكم بالأشعة تحت الحمراء +Name[az]=İnfra Qırmızı İdarə +Name[bn]=ইনফ্রা-রেড নিয়ন্ত্রণ +Name[bs]=Infrared kontrola +Name[ca]=Control per infraroigs +Name[cs]=Dálkové ovládání +Name[cy]=Rheolaeth Isgoch +Name[da]=Infrarød kontrol +Name[de]=Infrarot-Fernbedienung +Name[el]=Έλεγχος μέσω υπέρυθρων +Name[eo]=INfraruĝstirilo +Name[es]=Control por infrarrojos +Name[et]=Infrapunaliidese kaudu juhtimine +Name[eu]=Kontrol infragorria +Name[fa]= کنترل مادون قرمز +Name[fi]=Infrapunahallinta +Name[fr]=Contrôleur infrarouge +Name[ga]=Rialú Infridhearg +Name[gl]=Control por Infravermellos +Name[he]=שליטה בעזרת אינפרא־אדום +Name[hi]=इन्फ्रारेड नियंत्रण +Name[hr]=Infra-crvena kontrola +Name[hu]=Távirányító +Name[id]=Kontrol infra merah +Name[is]=Innrauð stýring +Name[it]=Controllo a infrarossi +Name[ja]=赤外線コントロール +Name[kk]=ИҚ тұтқасымен басқару +Name[km]=ឧបករណ៍ Infrared +Name[ko]=적외선 제어 +Name[lt]=Infraraudonųjų spindulių valdymas +Name[lv]=Infrasarkanā Vadība +Name[mk]=Инфрацрвена контрола +Name[mt]=Kontroll Infrared +Name[nb]=Infrarød kontroll +Name[nds]=Infraroot-Feernbedenen +Name[ne]=इन्फ्रारेड नियन्त्रण +Name[nl]=Infraroodbediening +Name[nn]=Infraraud kontroll +Name[pa]=ਇੰਫਰਾਰੈੱਡ ਕੰਟਰੋਲ +Name[pl]=Sterowanie przez podczerwień +Name[pt]=Controlo de Infra-Vermelhos +Name[pt_BR]=Controle de Infravermelho +Name[ro]=Control în infraroşu +Name[ru]=ИК пульт +Name[se]=Infrarukses stivrran +Name[sk]=Diaľkové ovládanie +Name[sl]=Infrardeči nadzor +Name[sr]=Инфрацрвена контрола +Name[sr@Latn]=Infracrvena kontrola +Name[sv]=Infraröd fjärrkontroll +Name[ta]=செங்கீழ்க்கதிர்க் கட்டுப்பாடு +Name[tg]=Идоракунии Инфрасурх +Name[th]=ตัวควบคุมแบบอินฟราเรด +Name[tr]=Kızılötesi Kontrol +Name[uk]=Керуванням інфрачервоним зв'язком +Name[ven]=Vhulanguli ha Infrared +Name[xh]=Ulawulo olwakhelwe ngezantsi +Name[zh_CN]=红外线控制 +Name[zh_HK]=紅外線控制 +Name[zh_TW]=紅外線控制 +Name[zu]=Ulawulo Olunokubomvu +Comment=Control Noatun with your IR remote +Comment[bg]=Управление на Noatun с помощта на инфрачервено, дистанционно управление +Comment[bn]=আপনার ইনফ্রা-রেড রিমোট ব্যবহার করে নোটান নিয়ন্ত্রণ করুন +Comment[bs]=Kontrolišite Noatun vašim infracrvenim daljinskim upravljačem +Comment[ca]=Controla Noatun amb el comandament a distància +Comment[cs]=Ovládejte Noatun svým dálkovým ovladačem +Comment[cy]=Rheoli Noatun efo'ch Rheolydd Isgoch +Comment[da]=Kontrollér Noatun med din fjernbetjening +Comment[de]=Kontrollieren Sie Noatun mit Ihrer Infrarot-Fernbedienung +Comment[el]=Έλεγχος του Noatun με το IR τηλεκοντρόλ σας +Comment[eo]=Stiru Noatun per via infraruĝstirilo +Comment[es]=Controle Noatun con su mando a distancia +Comment[et]=Noatun juhtimine IR puldi abil +Comment[eu]=Kontrolatu Noatun urruneko infragorriekin +Comment[fa]=کنترل Noatun با IR دور شما +Comment[fi]=Hallitse Noatunia infrapunakauko-ohjaimella +Comment[fr]=Contrôlez Noatun avec votre télécommande infrarouge +Comment[ga]=Rialaigh Noatun le do cianrialtán infridhearg +Comment[gl]=Controlar Noatun co seu IR remoto +Comment[he]=שליטה ב-Noatun באמצעות שלט אינפרא־אדום +Comment[hu]=A Noatun kezelése távirányítóval +Comment[is]=Stjórnaðu Nóatún með fjarstýringunni þinni +Comment[it]=Controlla Noatun con il tuo telecomando +Comment[ja]=赤外線リモコンで Noatun をコントロール +Comment[kk]=Noatun-ды ИҚ тұтқасымен басқару +Comment[km]=បញ្ជា Noatun ដោយប្រើ IR របស់អ្នកពីចម្ងាយ +Comment[ko]=적외선 리모콘으로 Noatun 조정하기 +Comment[lt]=Valdykite Noatun pasitelkdami nuotolinį pultą +Comment[mk]=Го контролира Noatun со вашиот инфрацрвен далечински управувач +Comment[nb]=Styr Noatun med en infrerød fjernkontroll +Comment[nds]=Noatun mit Dien Infraroot-Feernbedenen stüern +Comment[ne]=तपाईँको IR टाढाकोसँग नियन्त्रण नोवटुन +Comment[nl]=Bedien Noatun met uw infrarood afstandbediening +Comment[nn]=Styr Noatun med ein infraraud fjernkontroll +Comment[pl]=Sterowanie Noatun za pomocą pilota podczerwieni +Comment[pt]=Controle o Noatun com um comando à distância +Comment[pt_BR]=Controlar o Noatun com seu controle-remoto infravermelho +Comment[ro]=Controlează Noatun cu telecomanda în infraroşu +Comment[ru]=Управление Noatun с помощью инфракрасного пульта +Comment[sk]=Ovládajte Noatun vaším diaľkovým ovládačom +Comment[sl]=Nadzorujte Noatun z vašim infrardečim daljinskim upravljalcem +Comment[sr]=Контролишите Noatun вашим ИЦ даљинским управљачем +Comment[sr@Latn]=Kontrolišite Noatun vašim IC daljinskim upravljačem +Comment[sv]=Styr Noatun med en infraröd fjärrkontroll +Comment[ta]=உங்கள் IR கருவியால் Noatun இனைக் கட்டுப்படுத்தவும் +Comment[th]=ควบคุม Noatun ด้วยตัวรีโมทอินฟราเรดของคุณ +Comment[tr]=Kızılötesi Uzaktan Kumanda ile Noatun'u Kontrol Edin +Comment[uk]=Керує Noatun з віддаленого інфрачервоного пульта керування +Comment[zh_CN]=使用红外线遥控 Noatun +Comment[zh_HK]=使用紅外線遙控控制 Noatun +Comment[zh_TW]=使用 Noatun 透過紅外線遙控 diff --git a/noatun/modules/infrared/irprefs.cpp b/noatun/modules/infrared/irprefs.cpp new file mode 100644 index 00000000..409fa94e --- /dev/null +++ b/noatun/modules/infrared/irprefs.cpp @@ -0,0 +1,311 @@ + +#include <qlayout.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <noatun/app.h> + +#include <kdialog.h> +#include <klocale.h> +#include <kconfig.h> +#include <klistview.h> +#include <kcombobox.h> +#include <knuminput.h> + +#include "irprefs.h" +#include "lirc.h" + +class CommandItem : public QListViewItem +{ +public: + CommandItem(QListViewItem *remote, const QString &name, + IRPrefs::Action action, int interval) + : QListViewItem(remote, name, IRPrefs::actionName(action), + interval ? QString().setNum(interval) : QString::null), + m_name(remote->text(0) + "::" + name), + m_action(action), + m_interval(interval) + { + } + + const QString &name() const { return m_name; } + IRPrefs::Action action() const { return m_action; } + int interval() const { return m_interval; } + void setAction(IRPrefs::Action action) + { + setText(1, IRPrefs::actionName(action)); + m_action = action; + } + void setInterval(int interval) + { + setText(2, interval ? QString().setNum(interval) : QString::null); + m_interval = interval; + } + +private: + QString m_name; + IRPrefs::Action m_action; + int m_interval; +}; + +Lirc *IRPrefs::s_lirc = 0; +bool IRPrefs::s_configRead = false; +QMap<QString, IRPrefs::Command> IRPrefs::s_commands; + +IRPrefs::IRPrefs(QObject *parent) + : CModule(i18n("Infrared Control"), i18n("Configure Infrared Commands"), "remote", parent) +{ + QGridLayout *layout = new QGridLayout(this, 3, 5, KDialog::marginHint(), KDialog::spacingHint()); + layout->setColStretch(1, 1); + + QLabel *label = new QLabel(i18n("Remote control &commands:"), this); + layout->addMultiCellWidget(label, 0, 0, 0, 4); + + label->setBuddy(m_commands = new KListView(this)); + layout->addMultiCellWidget(m_commands, 1, 1, 0, 4); + + label = new QLabel(i18n("&Action:"), this); + layout->addWidget(label, 2, 0); + + label->setBuddy(m_action = new KComboBox(this)); + m_action->setEnabled(false); + layout->addWidget(m_action, 2, 1); + + m_repeat = new QCheckBox(i18n("&Repeat"), this); + m_repeat->setEnabled(false); + layout->addWidget(m_repeat, 2, 2); + + label = new QLabel(i18n("&Interval:"), this); + layout->addWidget(label, 2, 3); + + label->setBuddy(m_interval = new KIntSpinBox(this)); + m_interval->setMinValue(1); + m_interval->setMaxValue(0xff); + m_interval->setValue(10); + m_interval->setEnabled(false); + layout->addWidget(m_interval, 2, 4); + + connect(s_lirc, SIGNAL(remotesRead()), SLOT(reopen())); + connect(m_commands, + SIGNAL(selectionChanged(QListViewItem *)), + SLOT(slotCommandSelected(QListViewItem *))); + connect(m_action, + SIGNAL(activated(int)), + SLOT(slotActionActivated(int))); + connect(m_repeat, + SIGNAL(toggled(bool)), + SLOT(slotRepeatToggled(bool))); + connect(m_interval, + SIGNAL(valueChanged(int)), + SLOT(slotIntervalChanged(int))); + + reopen(); +} + +void IRPrefs::save() +{ + KConfig *c = kapp->config(); + KConfigGroupSaver groupSaver(c, "Infrared"); + c->writeEntry("CommandCount", s_commands.count()); + int i = 1; + for (QMap<QString, Command>::ConstIterator it = s_commands.begin(); it != s_commands.end(); ++it) + { + c->writePathEntry(QString("Command_%1").arg(i), it.key()); + c->writeEntry(QString("Action_%1").arg(i), (int)((*it).action)); + c->writeEntry(QString("Interval_%1").arg(i), (*it).interval); + ++i; + } +} + +void IRPrefs::reopen() +{ + readConfig(); + + QStringList remotes = s_lirc->remotes(); + m_commands->clear(); + while (m_commands->columns()) m_commands->removeColumn(0); + if (!remotes.count()) + { + m_commands->addColumn(i18n("Sorry")); + m_commands->setSorting(-1); + if (s_lirc->isConnected()) + { + new QListViewItem(m_commands, i18n("You do not have any remote control configured.")); + new QListViewItem(m_commands, i18n("Please make sure lirc is setup correctly.")); + } + else + { + new QListViewItem(m_commands, i18n("Connection could not be established.")); + new QListViewItem(m_commands, i18n("Please make sure lirc is setup correctly and lircd is running.")); + } + m_commands->setEnabled(false); + return; + } + m_commands->setEnabled(true); + m_commands->addColumn(i18n("Button")); + m_commands->addColumn(i18n("Action")); + m_commands->addColumn(i18n("Interval")); + m_commands->setSorting(0); + for (QStringList::ConstIterator it = remotes.begin(); it != remotes.end(); ++it) + { + QListViewItem *remote = new QListViewItem(m_commands, *it); + const QStringList &buttons = s_lirc->buttons(*it); + for (QStringList::ConstIterator btn = buttons.begin(); btn != buttons.end(); ++btn) + { + QString key = *it + "::" + *btn; + if (s_commands.contains(key)) + new CommandItem(remote, *btn, s_commands[key].action, s_commands[key].interval); + else + new CommandItem(remote, *btn, None, 0); + } + remote->setOpen(true); + } + + m_action->clear(); + for (int i = 0; ; ++i) + { + QString action = actionName((Action)i); + if (action.isNull()) + break; + if (action.isEmpty()) + m_action->insertItem(i18n("None")); + else + m_action->insertItem(action); + } + + +} + +void IRPrefs::slotCommandSelected(QListViewItem *item) +{ + CommandItem *cmd = dynamic_cast<CommandItem *>(item); + if (cmd) + { + m_action->setCurrentItem((int)(cmd->action())); + m_repeat->setChecked(cmd->interval()); + if (cmd->interval()) + m_interval->setValue(cmd->interval()); + else + { + m_interval->setValue(10); + cmd->setInterval(0); // HACKHACKHACK + } + m_action->setEnabled(true); + m_repeat->setEnabled(cmd->action() != None); + m_interval->setEnabled(cmd->interval()); + } + else + { + m_action->setEnabled(false); + m_repeat->setEnabled(false); + m_interval->setEnabled(false); + } +} + +void IRPrefs::slotActionActivated(int action) +{ + CommandItem *cmd = dynamic_cast<CommandItem *>(m_commands->currentItem()); + if (!cmd) + return; // Shouldn't happen + cmd->setAction((Action)action); + if (cmd->action() == None) + { + cmd->setInterval(0); + m_repeat->setChecked(false); + m_repeat->setEnabled(false); + m_interval->setEnabled(false); + } + else + { + m_repeat->setEnabled(true); + m_interval->setEnabled(cmd->interval()); + } + s_commands[cmd->name()].action = cmd->action(); + s_commands[cmd->name()].interval = 0; +} + +void IRPrefs::slotRepeatToggled(bool value) +{ + CommandItem *cmd = dynamic_cast<CommandItem *>(m_commands->currentItem()); + if (!cmd) + return; // Shouldn't happen + cmd->setInterval(value ? 10 : 0); + s_commands[cmd->name()].interval = cmd->interval(); + m_interval->setEnabled(value); +} + +void IRPrefs::slotIntervalChanged(int value) +{ + CommandItem *cmd = dynamic_cast<CommandItem *>(m_commands->currentItem()); + if (!cmd) + return; // Shouldn't happen + cmd->setInterval(value); + s_commands[cmd->name()].interval = cmd->interval(); +} + +const QString IRPrefs::actionName(Action action) +{ + switch (action) + { + case None: + return QString(""); + case Play: + return i18n("Play"); + case Stop: + return i18n("Stop"); + case Previous: + return i18n("Back"); + case Next: + return i18n("Next"); + case VolumeDown: + return i18n("Volume Down"); + case VolumeUp: + return i18n("Volume Up"); + case Mute: + return i18n("Mute"); + case Pause: + return i18n("Pause"); + case SeekBackward: + return i18n("Seek Backward"); + case SeekForward: + return i18n("Seek Forward"); + case ShowPlaylist: + return i18n("Show Playlist"); + case NextSection: + return i18n("Next Section"); + case PreviousSection: + return i18n("Previous Section"); + } + return QString::null; +} + +void IRPrefs::readConfig() +{ + if (s_configRead) + return; + KConfig *c = kapp->config(); + KConfigGroupSaver groupSaver(c, "Infrared"); + int count = c->readNumEntry("CommandCount"); + for (int i = 1; i <= count; ++i) + { + Command cmd; + cmd.action = (Action)(c->readNumEntry(QString("Action_%1").arg(i))); + cmd.interval = c->readNumEntry(QString("Interval_%1").arg(i)); + s_commands.insert(c->readPathEntry(QString("Command_%1").arg(i)), cmd); + } + s_configRead = true; +} + +IRPrefs::Action IRPrefs::actionFor(const QString &remote, const QString &button, int repeat) +{ + readConfig(); + Command cmd = s_commands[remote + "::" + button]; + if ((cmd.interval == 0 && repeat == 0) + || (cmd.interval != 0 && repeat % cmd.interval == 0)) + return cmd.action; + else + return None; +} + +#include "irprefs.moc" + + diff --git a/noatun/modules/infrared/irprefs.h b/noatun/modules/infrared/irprefs.h new file mode 100644 index 00000000..7f813ac8 --- /dev/null +++ b/noatun/modules/infrared/irprefs.h @@ -0,0 +1,62 @@ + +#ifndef _IRPREFS_H_ +#define _IRPREFS_H_ + +#include <qmap.h> +#include <noatun/pref.h> + +class QCheckBox; +class QListViewItem; +class KListView; +class KComboBox; +class KIntSpinBox; +class Lirc; + +class IRPrefs : public CModule +{ +Q_OBJECT +public: + enum Action + { + None, Play, Stop, Pause, Mute, + Previous, Next, VolumeDown, VolumeUp, + SeekBackward, SeekForward, ShowPlaylist, + NextSection, PreviousSection + }; + + IRPrefs(QObject *parent); + + virtual void save(); + + static const QString actionName(Action); + static Action actionFor(const QString &, const QString &, int); + +public slots: + static Lirc *s_lirc; + +private slots: + virtual void reopen(); + void slotCommandSelected(QListViewItem *); + void slotActionActivated(int); + void slotRepeatToggled(bool); + void slotIntervalChanged(int); + +private: + static void readConfig(); + + KListView *m_commands; + KComboBox *m_action; + QCheckBox *m_repeat; + KIntSpinBox *m_interval; + + struct Command + { + Action action; + int interval; + }; + static bool s_configRead; + static QMap<QString, Command> s_commands; +}; + +#endif + diff --git a/noatun/modules/infrared/lirc.cpp b/noatun/modules/infrared/lirc.cpp new file mode 100644 index 00000000..857c07e2 --- /dev/null +++ b/noatun/modules/infrared/lirc.cpp @@ -0,0 +1,173 @@ + +#include <unistd.h> +#include <sys/un.h> +#include <sys/socket.h> +#include <errno.h> + +#include <qsocket.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include "lirc.h" + +Lirc::Lirc(QObject *parent) + : QObject(parent), + m_socket(0) +{ + int sock = ::socket(PF_UNIX, SOCK_STREAM, 0); + if (sock == -1) + { + KMessageBox::sorry(0, i18n("Could not create a socket to receive infrared signals. The error is:\n") + strerror(errno)); + return; + } + sockaddr_un addr; + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, "/dev/lircd"); + if (::connect(sock, (struct sockaddr *)(&addr), sizeof(addr)) == -1) + { + KMessageBox::sorry(0, i18n("Could not establish a connection to receive infrared signals. The error is:\n") + strerror(errno)); + ::close(sock); + return; + } + + m_socket = new QSocket; + m_socket->setSocket(sock); + connect(m_socket, SIGNAL(readyRead()), SLOT(slotRead())); + update(); +} + +Lirc::~Lirc() +{ + delete m_socket; +} + +const QStringList Lirc::remotes() const +{ + QStringList result; + for (Remotes::ConstIterator it = m_remotes.begin(); it != m_remotes.end(); ++it) + result.append(it.key()); + result.sort(); + return result; +} + +void Lirc::slotRead() +{ + while (m_socket->bytesAvailable()) + { + QString line = readLine(); + if (line == "BEGIN") + { + // BEGIN + // <command> + // [SUCCESS|ERROR] + // [DATA + // n + // n lines of data] + // END + line = readLine(); + if (line == "SIGHUP") + { + // Configuration changed + do line = readLine(); + while (!line.isEmpty() && line != "END"); + update(); + return; + } + else if (line == "LIST") + { + // remote control list + if (readLine() != "SUCCESS" || readLine() != "DATA") + { + do line = readLine(); + while (!line.isEmpty() && line != "END"); + return; + } + QStringList remotes; + int count = readLine().toInt(); + for (int i = 0; i < count; ++i) + remotes.append(readLine()); + do line = readLine(); + while (!line.isEmpty() && line != "END"); + if (line.isEmpty()) + return; // abort on corrupt data + for (QStringList::ConstIterator it = remotes.begin(); it != remotes.end(); ++it) + sendCommand("LIST " + *it); + return; + } + else if (line.left(4) == "LIST") + { + // button list + if (readLine() != "SUCCESS" || readLine() != "DATA") + { + do line = readLine(); + while (!line.isEmpty() && line != "END"); + return; + } + QString remote = line.mid(5); + QStringList buttons; + int count = readLine().toInt(); + for (int i = 0; i < count; ++i) + { + // <code> <name> + QString btn = readLine(); + buttons.append(btn.mid(17)); + } + m_remotes.insert(remote, buttons); + } + do line = readLine(); + while (!line.isEmpty() && line != "END"); + emit remotesRead(); + } + else + { + // <code> <repeat> <button name> <remote control name> + line.remove(0, 17); // strip code + int pos = line.find(' '); + if (pos < 0) + return; + bool ok; + int repeat = line.left(pos).toInt(&ok, 16); + if (!ok) + return; + line.remove(0, pos + 1); + + pos = line.find(' '); + if (pos < 0) + return; + QString btn = line.left(pos); + line.remove(0, pos + 1); + + emit commandReceived(line, btn, repeat); + } + } +} + +void Lirc::update() +{ + m_remotes.clear(); + sendCommand("LIST"); +} + +const QString Lirc::readLine() +{ + if (!m_socket->bytesAvailable()) + return QString::null; + + QString line = m_socket->readLine(); + if (line.isEmpty()) + return QString::null; + + line.remove(line.length() - 1, 1); + return line; +} + +void Lirc::sendCommand(const QString &command) +{ + QString cmd = command + "\n"; + m_socket->writeBlock(cmd.latin1(), cmd.length()); +} + +#include "lirc.moc" + diff --git a/noatun/modules/infrared/lirc.h b/noatun/modules/infrared/lirc.h new file mode 100644 index 00000000..e5380c5c --- /dev/null +++ b/noatun/modules/infrared/lirc.h @@ -0,0 +1,75 @@ + +#ifndef _LIRC_H_ +#define _LIRC_H_ + +#include <qobject.h> +#include <qstringlist.h> +#include <qmap.h> + +class QSocket; + +typedef QMap<QString, QStringList> Remotes; + +class Lirc : public QObject +{ +Q_OBJECT +public: + /** + * Constructor + */ + Lirc(QObject *parent); + /** + * Destructor + */ + virtual ~Lirc(); + + /** + * Returns true if the connection to lircd is operational + */ + bool isConnected() const { return m_socket; } + /** + * The names of the remote configured controls + */ + const QStringList remotes() const; + /** + * The names of the buttons for the specified + * remote control + */ + const QStringList buttons(const QString &remote) const + { + return m_remotes[remote]; + } + +signals: + /** + * Emitted when the list of controls / buttons was cmpletely read + */ + void remotesRead(); + /** + * Emitted when a IR command was received + * + * The arguments are the name of the remote control used, + * the name of the button pressed and the repeat counter. + * + * The signal is emitted repeatedly as long as the button + * on the remote control remains pressed. + * The repeat counter starts with 0 and increases + * every time this signal is emitted. + */ + void commandReceived(const QString &, const QString &, int); + +private slots: + void slotRead(); + +private: + void update(); + const QString readLine(); + void sendCommand(const QString &); + +private: + QSocket *m_socket; + Remotes m_remotes; +}; + +#endif + diff --git a/noatun/modules/kaiman/Makefile.am b/noatun/modules/kaiman/Makefile.am new file mode 100644 index 00000000..a8205a59 --- /dev/null +++ b/noatun/modules/kaiman/Makefile.am @@ -0,0 +1,23 @@ +SUBDIRS = skins +INCLUDES= -I$(top_srcdir)/noatun/library $(all_includes) +kde_module_LTLIBRARIES = noatun_kaiman.la + +noatun_kaiman_la_SOURCES = \ + noatunui.cpp \ + style.cpp \ + userinterface.cpp \ + pref.cpp + +noatun_kaiman_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_kaiman_la_LIBADD = $(LIB_KFILE) $(top_builddir)/noatun/library/libnoatun.la \ + -lqtmcop -lkmedia2_idl -lsoundserver_idl + +noatun_kaiman_la_METASOURCES = AUTO + +noinst_HEADERS = \ + userinterface.h \ + style.h \ + pref.h + +noatun_modules_kaiman_DATA = kaiman.plugin kaimanui.rc +noatun_modules_kaimandir = $(kde_datadir)/noatun diff --git a/noatun/modules/kaiman/README b/noatun/modules/kaiman/README new file mode 100644 index 00000000..4c24a3ae --- /dev/null +++ b/noatun/modules/kaiman/README @@ -0,0 +1,3 @@ +kaiman - Media player for KDE2.0 + + diff --git a/noatun/modules/kaiman/SKIN-SPECS b/noatun/modules/kaiman/SKIN-SPECS new file mode 100644 index 00000000..bc3533ad --- /dev/null +++ b/noatun/modules/kaiman/SKIN-SPECS @@ -0,0 +1,518 @@ + ############ GQmpeg skin specifications file. ############ + + (A quick reference of what is required in the image files + for each widget type is located at the end of this document ) + +Skins are simply a directory which contain image files and +a skindata file (named skindata). + +All skin features are configured in the skindata file. + +Note: when using an alternate skin, it's specs go into a file named +skindata_alt, it uses the same format as the skindata file. Pressing +the Alt_Skin_Button button switches between the two skins. +(each skin must contain an Alt_Skin_Button if you want the alternate +skin feature to work) + +Any line can be made into a comment by prefacing it with a '#' symbol. + +All image files can be any size, GQmpeg will calculate the drawing data +for you. Skins can have any size buttons, display items, digits, +fonts, etc. The files can be of any type supported by gdk-pixbuf (xpm, png, +jpeg, gif, etc.) The recommended file format is png. + +Prelights are optional on all items that support them. A prelight is an +alternate image that is displayed when the mouse is over a pressable +item (button, slider, dial). For example, the default skin includes prelights +for all buttons, notice the buttons 'brighten' when the mouse moves over +them. + +Every image within a file must have the same width and height, for example +if the play button was 30 by 20, the resulting image file would be +180 by 20. (6 button states total, including status lights and prelights) + + Addendum: If the above button was specified with the status light and + prelight options as false, the resulting image file would be + 60 by 20. (2 button states total, 1 for normal, 1 for pressed) + +Note that images for buttons and numbers contain the items horizontally, +the images for items contain the items vertically, the image for a font +contains 3 rows of 32 items, and the slider contains the background and +handle horizontally or vertically (depending if a slider is horizontal +or verticle, respectivley). + +Only the background image is required, all other elements are optional +(although it would be nice to always have a play button :) +If you do not want an item displayed, comment out the line with +a '#' symbol. + +IMPORTANT: +Slots enclosed in "[]" are optional, but are so only to retain backward +compatibility of skins. Please specify all options for each type as in the +future the options enclosed in "[]" may no longer be "optional". Please +separate each option with a single space, and do not add extra characters +at the end of the line, as the extra info may be mistaken for expanded +options in the event that options are added to the skin spec in the future. + +PROPER TRANSPARENCY: +The main background image uses a threshold of 1 (out of 256 levels) for the +window shape, the rest is used for partially overwiting the background when +the Transparency option is true. + +Portions of items, buttons, sliders, numbers, and text that never change and +are the same as the background image should be set transparent so that the +'force transparent' option works properly. + + ############# skindata file format ################# + +Note: For an example skindata file see the file skindata-template. + +x and y are always the position in the window (use the -skinhelp command line +option to have GQmpeg print out the mouse coordinates as the mouse moves) + +And finally, to what is available: + +========================== + Main options +========================== + +Background: filename + + filename + The background image file, the window will be the same size as this image. + Add transparency to this image for shaped skins, the cutoff threshold for + transparency is 1 on images with muli-level alpha (like in png). + +Transparency: flag + + flag + True or False, this specifies if the background image (above) has a multiple + level alpha channel (as in png files) to apply when overwriting the root + window's background. + +Mask: filename + +(this is DEPRECATED!, for transparent skins just add transparency to the + Background image, Mask remains merely for backwards compatibility) + filename + The mask image file, only needed for skins which are shaped windows (not + rectangular). Contains a transparency mask for the main window. + +========================== + Text display +========================== + +Title/Album/Artist/Genre: filename length [extended] x y + + filename + Should contain a fixed font. With 3 or 6 lines of 32 characters each, + these are the characters, they are listed in three rows so you can copy + and past them into you graphics program. (first character in the top line + is a space) + + !"#$%&'()*+,-./0123456789:;<=>? + @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ + `abcdefghijklmnopqrstuvwxyz{|}~ + + When extended is TRUE these are the 3 addition lines of international chars + + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + XXXXXXX FIXME! TO DO! XXXXXXXXXX + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + + length + Maximum number of characters to display in window. + + extended + (optional, absence defaults to FALSE) + When TRUE, the image contains 3 additional lines for internation + characters. The result is 6 lines of 32 characters each. + +========================== + Buttons (that optionally include an 'active' mode) +========================== + +Play/Pause/Stop/Shuffle/Repeat/ + Time_Remaining/Time_Total_Button: filename prelight status_light x y [clip_filename] + + filename + Image file. Contains the buttons horizontally in this order: + normal, normal pressed, normal active, normal active pressed, prelit, prelit active + (the actual number of images may vary, see next two options) + + prelight + TRUE or FALSE, specifies whether or not prelight buttons are available, If + FALSE, do not include the last two prelight buttons in the image file. + + status_light + TRUE or FALSE, specifies whether or not button lights are available. If FALSE, + do not include the 'lit up', 'lit down', and 'prelight lit up' buttons in the + image file. + + clip_filename (optional) + When specified, defines an image with transparency to be used as the button's + draw clip mask. The clip mask is placed at location x, y The transparency is used to + indicate the portions of the button that should be visible (drawn) and respond to + mouse clicks. If the image contains a multiple level alpha channel, the mask is reduced + such that levels above 50% are visible and those below 50% are not visible. + +========================== + Buttons (standard) +========================== + +Next/Prev/FF/RW/Playlist/Config/Iconify/Mixer/Exit/Alt_Skin/Volume_Up/Volume_Down/ + Balance_Left/Balance_Right_Button: filename prelight x y [clip_filename] +Preset_1_/.../Preset_10_Button: filename prelight x y [clip_filename] + + filename + Image file. Contains the buttons horizontally in this order: + normal, normal pressed, prelit + (the actual number of images may vary, see next option) + + prelight + TRUE or FALSE, specifies whether or not prelight buttons are available. If + FALSE, do not include the last prelight button in the image file. + + clip_filename (optional) + When specified, defines an image with transparency to be used as the button's + draw clip mask. The clip mask is placed at location x, y The transparency is used to + indicate the portions of the button that should be visible (drawn) and respond to + mouse clicks. If the image contains a multiple level alpha channel, the mask is reduced + such that levels above 50% are visible and those below 50% are not visible. + + +========================== + Items (with fixed number sections) +========================== + +Stereo/Shuffle/Repeat/Mpegversion/Mpeglayer/Mpegmode/Status/ + Minus/Total_Item: filename x y + + filename + Image file. Contains the items vertically in the order below: + + Stereo_Item: blank, mono , stereo + Shuffle_Item: off, on + Repeat_Item: off, on + Mpegversion_Item: blank, 1, 2 + Mpeglayer_Item: blank, 1, 2, 3 + Mpegmode_Item: blank, stereo, joint-stereo, dual-channel, single-channel + Status_Item: stop, pause, play + Minus_Item: time counts up, time counts down + Total_Item: time refers to current song only, to total playlist, to live + +========================== + Items (animation oriented) +========================== + +Load_Item: filename sections x y + + filename + Image file. Contains animations for the following items: + + Load_Item: Animation for loading playlist in background. + + sections + The total number of sections in the image file. The first section is always + blank (animation is off), the subsequent images are cycled through to create + the animation. This number is a total count, so it will be 1 (first is always + blank) plus the number of animation frames. + +========================== + Items (value oriented) +========================== + +Position/Volume/Balance_Item: filename sections x y + + filename + Image file. Contains images vertically in the order representing the lowest to + highest values. + + sections + The number of images within the file, recommended number of images is 16 to 32. + The most possible usable images is 101 for volume and blance (from volume=0% + to volume = 100%). + + Note: + These items must be listed before their respective sliders: + (see Position/Volume/Balance_Slider). + +========================== + Digit placeholder (for convenience, less memory usage with many similar numbers) +========================== + +Digit_Large/Digit_Small_Default: filename + + filename + Image file. Contains digits horizontally from 0 to 9, and a blank space. + + These two digits are a convenience function, if you want to use a digit more than + once it is quicker to load it into on of these two slots. Then when using the digit + in the number item type below, use the words 'Large' or 'Small' in place of the + filename. + +========================== + Numbers +========================== + +Hour/Minute/Second/Song/Total/In_Rate/In_Hz/Out_Bits/Out_Hz/ + Song_Minute/Song_Second/Frame/Frame_Total/CPU/ + Hour_Total/Minute_Total/Second_Total_Number: filename [length center] x y + + filename + Image file for the number's digit, or the word 'Large' or 'Small' (see above). + If a filename is specified, the image should contain the digits horizontally + from 0 to 9, and a blank space. + + length (optional) + The number of digits to display, if not present the default is assumed. + + center (optional, but if specified length is required too) + TRUE or FALSE, specify to center the number. + +========================== + Sliders +========================== + +Position/Volume/Balance_Slider: filename prelight [verticle reversed] length x y + + filename + Image file. Contains images horizontally in this order: + slider background, handle normal, handle pressed, handle prelit + (handles must have the same dimensions) + + prelight + TRUE or FALSE, specifies whether or not a prelight handle is available, if FALSE, + do not include a 'handle prelit' in the image file. + + verticle + TRUE or FALSE. If false the slider is horizontal, if true, verticle. + + reversed + TRUE or FALSE. If true, the slider works opposite than normal. For example + when false the slider moves from left to right, when true the slider moves + from right to left. On a verticle slider and reversed is false, the slider + moves from top to bottom. + + length + The width of the slider's background, this is the complete width the slider will + be in the window, and must match the length of the 'slider background' in the + image file. + +========================== + Dials (AKA knobs) +========================== + +Position/Volume/Balance_Dial: filename has_press_image has_prelight_image reversed + angle_start angle_end handle_offset_x handle_offset_y center_x center_y + x y w h [clip_filename] + + filename + Image file. Contains images for the dial's handle vertically in this order: + normal + pressed (being dragged with mouse, optional) + prelit (mouse over highlight, optional) + + has_press_image + TRUE or FALSE, specifies whether or not handle has a pressed image (above) + + has_prelight_image + TRUE or FALSE, specifies whether or not handle has a pressed image (above) + + reversed + TRUE of FALSE, normally a dial works clockwise with angle_start being the + lowest (zero) value and angle_end being the highest value. When TRUE the dial + works counter-clockwise with angle_end being the lowest (zero) value to + angle_start being the highest position. + + angle_start + angle_end + The start and end angles define the end points of the dial's rotation in integer + degrees, the degrees count from 0 located right of center axis increasing clockwise + to a value of 359. (360 is equivelent to 0, but the only accepted numbers are 0 - 359. + This (admittedly poor) figure might help: + + + 270 ____ center axis + _|_ / + / / + / / \ + 180 -| + |- 0 (360) + \ / + \_ _/ + | + 90 + + handle_offset_x + handle_offset_y + The x and y coordinates into the handle image that represents the handle center + of rotation (pivot point), this does not have to actually be within the image size. + + center_x + center_y + The x and y coordinates on the skin image for the handle center of rotation. + + x, y, width, height: + Marks the clipping region to draw the dial, basically the handle is not drawn + outside this region. (width and height will be ignored if a clip mask image + is specified (see next option). + + clip_filename (optional) + When specified, defines an image with transparency to be used as the dial's + draw clip mask. The clip mask is placed at x, y (above) and the image's dimensions + are used in place of width, height (above). The transparency is used to indicate the + portions of the dial that should be visible (drawn) and respond to mouse clicks. + If the image contains a multiple level alpha channel, the mask is reduced such that + levels above 50% are visible and those below 50% are not visible. + +============================================================================== + ************ Quick reference tables ************** +============================================================================== + +Note: All example values below set (*)coordinates x=1 and y=1, and filename to fn.png. + (*) Except Dials. + +-------------------------- + Buttons (all button images contained horizontally) +-------------------------- + +Play/Pause/Stop/Shuffle/Repeat_Button: filename prelight status_light x y +Time_Remaining/Time_Total_Button: filename prelight status_light x y + +Option line: | # images | Normal | Pressed | Lit | Lit | Prelit | Prelit | + | total | | | Normal | Pressed | Normal | Lit Normal | +-----------------------+----------+--------+---------+--------+---------+--------+------------+ + fn.png TRUE TRUE 1 1 | 6 | X | X | X | X | X | X | + fn.png TRUE FALSE 1 1 | 3 | X | X | | | X | | + fn.png FALSE TRUE 1 1 | 4 | X | X | X | X | | | + fn.png FALSE FALSE 1 1| 2 | X | X | | | | | + +Next/Prev/FF/RW/Playlist/Config/Iconify/Mixer/Exit/Alt_Skin_Button: filename prelight x y +Volume_Up/Volume_Down/Balance_Left/Balance_Right_Button: filename prelight x y + +Option line: | # images | Normal | Pressed | Prelit | + | total | | | Normal | +-----------------------+----------+--------+---------+--------+ + fn.png TRUE 1 1 | 3 | X | X | X | + fn.png FALSE 1 1 | 2 | X | X | | + + +-------------------------- + Items (all item images contained vertically) +-------------------------- + +Stereo/Shuffle/Repeat/Mpegversion/Mpeglayer/Mpegmode/Status/Minus/Total_Item: filename x y + +Item: | # images | Image 1 | Image 2 | Image 3 | Image 4 | Image 5 | + | total | | | | | | +-----------------------+----------+---------+---------+---------+---------+---------+ + Stereo_Item | 3 | blank | mono | stereo | | | + Shuffle_Item | 2 | off | on | | | | + Repeat_Item | 2 | off | on | | | | + Mpegversion_Item | 3 | blank | ver 1 | ver 2 | | | + Mpeglayer_Item | 4 | blank | layer 1 | layer 2 | layer 3 | | + Mpegmode_Item | 5 | blank | stereo | j-stereo| dual-ch |single-ch| + Status_Item | 3 | stop | pause | play | | | + Minus_Item | 2 | normal |remaining| | | | + Total_Item | 2 | normal | total | live | | | + + +Load_Item: filename section_count x y + +(These are special Animation items, any number of sections can be included) + +Option line: | # images | Image 1 | Image 2 | ....... | Last Image | + | total | | | | | +-------------------+----------+---------+---------+---------+------------+ + fn.png 8 1 1 | 8 | blank | Frame 1 | F2...F6 | Frame 7 | + fn.png 4 1 1 | 4 | blank | Frame 1 | Frame 2 | Frame 3 | + + +Position/Volume/Balance_Item: filename sections x y + +Option Line: (*) | # images | 1st Image | middle Image | Last Image | + | total | | | | +----------------------------+----------+-----------+--------------+---------------+ + Volume_Item fn.png 17 1 1 | 17 | 1 - 0% vol| 9 - 50 % vol | 17 - 100% vol | + Volume_Item fn.png 31 1 1 | 31 | 1 - 0% vol| 16 - 50 % vol| 31 - 100% vol | + Balance_Item fn.png 17 1 1 | 17 | 1 - Left | 9 - middle | 17 - Right | + Balance_Item fn.png 13 1 1 | 13 | 1 - Left | 6 - middle | 13 - Right | + + (*)note: The values (17, 31, 17, 13) above are only examples, any number of images + can be specified. + + +-------------------------- + Sliders (all slider images contained horizontally) +-------------------------- + +Position/Volume/Balance_Slider: filename prelight [verticle reversed] length x y + +Option line: | # images | Background | Normal | Pressed | Prelit | + | total | width | | | Normal | +-----------------------------------+----------+-------------+--------+---------+--------+ + fn.png TRUE FALSE FALSE 32 1 1 | 4 | 32 pixels | X | X | X | + fn.png FALSE FALSE FALSE 250 1 1 | 3 | 250 pixels | X | X | | + + +-------------------------- + Dials (can be confusing, see detailed description, above) +-------------------------- + +Position/Volume/Balance_Dial: filename has_press_image has_prelight_image reversed + angle_start angle_end handle_offset_x handle_offset_y center_x center_y + x y w h [clip_filename] + +Option line: | # images | Normal | Pressed | Prelit | + | total | | | Normal | +----------------------------------------------------------+----------+--------+---------+--------+ + fn.png TRUE TRUE TRUE 0 180 16 16 200 100 140 40 80 80 | 3 | X | X | X | + fn.png FALSE TRUE TRUE 0 180 16 16 200 100 140 40 80 80 | 2 | X | | X | + fn.png FALSE FALSE TRUE 0 180 16 16 200 100 140 40 80 80 | 1 | X | | | + +-------------------------- + Numbers (all number images contained horizontally) +-------------------------- + +*_Number: filename [length centered] x y + +Option line: | # images | Images in order (left to right) | + | total | | +---------------------+----------+------------------------------------------------+ + fn.png 1 1 | 11 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " "(blank space) | + fn.png 3 FALSE 1 1 | 11 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " "(blank space) | + + +-------------------------- + Fonts (all font images contained in 3 or 6 rows of 32 columns) +-------------------------- + +Title/Album/Artist/Genre: filename length [extended] x y + +Option line: | # images | Images in order | + | total | | +------------------------+----------+--------------------+ + fn.png 16 1 1 | 96 | see grid 1 (below) | + fn.png 16 FALSE 1 1 | 96 | see grid 1 (below) | + fn.png 16 TRUE 1 1 | 192 | see grid 2 (below) | + + +------------------------------------+ +character grid 1: | | +(standard) | !"#$%&'()*+,-./0123456789:;<=>? | + | @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ | + | `abcdefghijklmnopqrstuvwxyz{|}~ | + | | + +------------------------------------+ + + +------------------------------------+ +character grid 2: | | +(international | !"#$%&'()*+,-./0123456789:;<=>? | + extended) | @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ | + | `abcdefghijklmnopqrstuvwxyz{|}~ | + | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | + | XXXXXXX FIXME! TO DO! XXXXXXXXXX | + | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | + | | + +------------------------------------+ + +################################# diff --git a/noatun/modules/kaiman/kaiman.plugin b/noatun/modules/kaiman/kaiman.plugin new file mode 100644 index 00000000..1b345de3 --- /dev/null +++ b/noatun/modules/kaiman/kaiman.plugin @@ -0,0 +1,132 @@ +Filename=noatun_kaiman.la +Author=Stefan Schimanski +Site=http://www.derkarl.org/noatun +Email=schimmi@kde.org +Type=userinterface +License=GPL +Name=Kaiman Interface +Name[af]=Kaiman Koppelvlak +Name[ar]=واجهة Kaiman +Name[az]=Kaiman Ara üzü +Name[bn]=কাইমান ইন্টারফেস +Name[br]=Etrefas Kaiman +Name[ca]=Interfície Kaiman +Name[cs]=Rozhraní Kaimana +Name[cy]=Rhyngwyneb Kaiman +Name[da]=Kaiman-grænseflade +Name[de]=Kaiman-Oberfläche +Name[el]=Περιβάλλον Kaiman +Name[eo]=Kajmaninterfaco +Name[es]=Interfaz de Kaiman +Name[et]=Kaiman kasutajaliides +Name[eu]=Kaiman interfazea +Name[fa]=واسط Kaiman +Name[fi]=Kaiman-käyttöliittymä +Name[fr]=Interface de Kaiman +Name[ga]=Comhéadan Kaiman +Name[gl]=Interface Kayman +Name[he]=ממשק Kaiman +Name[hi]= काईमेन इंटरफेस +Name[hr]=Kaiman sučelje +Name[hu]=Kaiman felület +Name[is]=Kaiman aðgangur +Name[it]=Interfaccia Kaiman +Name[ja]=Kaiman インターフェース +Name[kk]=Kaiman интерфейсі +Name[km]=ចំណុចប្រទាក់ Kaiman +Name[ko]=Kaiman 인터페이스 +Name[lt]=Kaiman sąsaja +Name[lv]=Kaiman Starpseja +Name[mk]=Интерфејс Kaiman +Name[mt]=Interfaċċja Kaiman +Name[nb]=Kaiman grensesnitt +Name[nds]=Kaiman-Böversiet +Name[ne]=काइम्यान इन्टरफेस +Name[nl]=Kaiman interface +Name[nn]=Kaiman-grensesnitt +Name[pl]=Motyw Kaimana +Name[pt]=Interface do Kaiman +Name[pt_BR]=Interface do Kaiman +Name[ro]=Interfaţă Kaiman +Name[ru]=Интерфейс Кайман +Name[se]=Kaiman-lakta +Name[sk]=Rozhranie Kaimana +Name[sl]=Vmesnik Kaiman +Name[sr]=Kaiman интерфејс +Name[sr@Latn]=Kaiman interfejs +Name[sv]=Kaiman-gränssnitt +Name[ta]=Kaiman இடைமுகம் +Name[tg]=Интерфейси Kaiman +Name[th]=ส่วนติดต่อ Kaiman +Name[tr]=Kaiman Arayüzü +Name[uk]=Інтерфейс Kaiman +Name[uz]=Kaiman interfeysi +Name[uz@cyrillic]=Kaiman интерфейси +Name[ven]=Interface ya Kaiman +Name[xh]=Ujongano lwe Kaiman +Name[zh_CN]=Kaiman 接口 +Name[zh_HK]=Kaiman 介面 +Name[zh_TW]=Kaiman 介面 +Name[zu]=Uxhumano olubhekeneyo lwe Kaiman +Comment=A GQMpeg skin interface ported from Kaiman +Comment[af]='n Gqmpeg vel koppelvlak oorgedra van Kaiman +Comment[ar]=واجهة GQMpeg مأخوذة من Kaiman +Comment[az]=Kaiman'dan alınan GQMpeg dekorsiya axtar üzü +Comment[bg]=Интерфейс за GQMpeg прехвърлен за Kaiman +Comment[bs]=GQMpeg skin interface prebačen sa Kaiman-a +Comment[ca]=Una aparença d'interfície GQMpeg portada de Kaiman +Comment[cs]=Motiv rozhraní GQMpegu přenesený z Kaimana +Comment[cy]=Rhyngwyneb croen GQMpeg wedi'i droi o Kaiman +Comment[da]=En GQMpeg-forsidegrænseflade overført fra Kaiman +Comment[de]=Eine Schnittstelle zur GQMpeg-Optik, aus Kaiman übernommen +Comment[el]=Μια διασύνδεση βασισμένη στο θέμα GQMpeg προσαρμοσμένο από το Kaiman +Comment[eo]=GQMpeg-etosinterfaco portita de Kajmano +Comment[es]=Una interfaz de pieles GQMpeg portado de Kaiman +Comment[et]=Kaimanist porditud GQMpeg skinnide toetus +Comment[eu]=GQMpeg azal interfazea Kaiman-etik ekarria +Comment[fa]=یک واسط GQMpeg skin که از Kaiman آورده شده است +Comment[fi]=GQMpeg-käyttöliittymärajapinta Kaimanille +Comment[fr]=Un revêtement à la GQMpeg importé de Kaiman +Comment[gl]=Unha pel para a interface GQMPeg importada de Kaiman +Comment[he]=ממשק Skin של GQMpeg שיובא מתוך Kaiman +Comment[hi]=काईमेन से पोर्टेड जीक्यू-एमपीईजी इंटरफेस +Comment[hr]=GQMpeg sučelje za kože uvezeno iz Kaiman-a +Comment[hu]=A Kaimanban használt GQMpeg kinézet átültetett változata +Comment[is]=GQMpeg skinn frá Kaiman +Comment[it]=Una skin per GQMpeg convertita da Kaiman +Comment[ja]=Kaiman から移植した GQMpeg スキンインターフェース +Comment[kk]=Kaiman-нан аударылған GQMpeg тыстарының интерфейсі +Comment[km]=ចំណុចប្រទាក់ស្បែក GQMpeg ដែលបានបញ្ចូលពី Kaiman +Comment[ko]=Kaiman에서 이식된 GQMpeg 스킨 +Comment[lt]=GQMpeg pavidalų sąsaja, pritaikyta nuo Kaiman +Comment[lv]=GQMpeg ādu starpseja pārcelta no Kaimana +Comment[mk]=Интерфејс GQMpeg за маски пренесен од Kaiman +Comment[ms]=Kulit antaramuka GQMpeg dari Kaiman +Comment[mt]=Interfaċċja għal faċċati GQMpeg portata minn Kaiman +Comment[nb]=Et GQMpeg ham-grensesnitt tatt fra Kaiman +Comment[nds]=En GQMpeg-Böversiet, vun Kaiman överdragen +Comment[ne]=काइम्यानबाट परिमार्जन गरिएको GQMpeg स्किन इन्टरफेस +Comment[nl]=Een GQMpeg-skin-interface, overgedragen van Kaiman +Comment[nn]=Eit GQMpeg-skalgrensesnitt porta frå Kaiman +Comment[pl]=Motyw skór GQMpeg przeniesiony z Kaimana +Comment[pt]=A interface de aspectos do GQMpeg transposta para o Kaiman +Comment[pt_BR]=Uma interface de aparência (skin) GQMpeg portada do Kaiman +Comment[ro]=O interfaţă GQMpeg portată de la Kaiman +Comment[ru]=Интерфейс образов GQMpeg, перенесенный из Каймана +Comment[se]=GQMpeg-náhkkelakta portejuvvon Kaimanas +Comment[sk]=Téma rozhrania GQMpeq prenesená z Kaimana +Comment[sl]=Vmesnik preobleke GQMpeg, prenesen iz Kaimana +Comment[sr]=GQMpeg интерфејс скинова пренесен са из Kaiman-а +Comment[sr@Latn]=GQMpeg interfejs skinova prenesen sa iz Kaiman-a +Comment[sv]=Gqmpeg-skalgränssnitt överfört från Kaiman +Comment[ta]=GQMpeg தோல் இடைமுகம் காய்மானில் இருந்து இறக்கப்பட்டது +Comment[tg]=Намуди интерфейси GQMpeg, ки аз Kaiman даргоҳбандӣ шудааст +Comment[th]=ส่วนติดต่อหน้ากาก GQMpeg ที่ข้ามระบบมาให้ใช้กับ Kaiman +Comment[tr]=Kaiman'dan alınan GQMpeg dekor arayüzü +Comment[uk]=Інтерфейс жупанів GQMpeg, перенесено з Kaiman +Comment[ven]=Lukanda lwa GQMpeg lu vhonwaho kha Kaiman +Comment[xh]=GQMpeg wojongano nolusu olunezibuko olusuka kwi Kaiman +Comment[zh_CN]=从 Kaiman 移植的 GQMpeg 外观 +Comment[zh_HK]=從 Kaiman 移植的 GQMpeg 外貌主題 +Comment[zh_TW]=從 Kaiman 移植的 GQMpeg 外表 +Comment[zu]=A GQMpeg uxhumano lwesikhumba ported from Kaiman diff --git a/noatun/modules/kaiman/kaimanui.rc b/noatun/modules/kaiman/kaimanui.rc new file mode 100644 index 00000000..fb2696ff --- /dev/null +++ b/noatun/modules/kaiman/kaimanui.rc @@ -0,0 +1,45 @@ +<!DOCTYPE kpartgui> +<kpartgui name="noatunkaiman" version="1"> +<ActionProperties> + <Action name="play" icon="noatunplay"/> + <Action name="stop" icon="noatunstop"/> + <Action name="back" icon="noatunback"/> + <Action name="forward" icon="noatunforward"/> + <Action name="show_playlist" icon="noatunplaylist"/> +</ActionProperties> +<MenuBar> + <Menu name="file" noMerge="1"><text>&File</text> + <Action name="file_open"/> + <Separator lineSeparator="true"/> + <Action name="file_quit"/> + </Menu> + <Menu name="go_music" noMerge="1"><text>&Go</text> + <Action name="back"/> + <Action name="stop"/> + <Action name="play"/> + <Action name="forward"/> + </Menu> + <Menu name="settings" noMerge="1"><text>&Settings</text> + <Action name="options_show_toolbar"/> + <Action name="show_playlist"/> + <Separator lineSeparator="true"/> + <Action name="options_configure"/> + <Action name="effects"/> + <Separator lineSeparator="true"/> + <Action name="loop_style"/> + </Menu> +</MenuBar> +<Toolbar name="main"><text>Main Toolbar</text> + <Action name="file_quit"/> + <Separator lineSeparator="true"/> + <Action name="back"/> + <Action name="stop"/> + <Action name="play"/> + <Action name="forward"/> + <Separator lineSeparator="true"/> + <Action name="file_open"/> + <Action name="show_playlist"/> + <Separator lineSeparator="true"/> + <Action name="loop_style"/> +</Toolbar> +</kpartgui> diff --git a/noatun/modules/kaiman/noatunui.cpp b/noatun/modules/kaiman/noatunui.cpp new file mode 100644 index 00000000..bc1bceb0 --- /dev/null +++ b/noatun/modules/kaiman/noatunui.cpp @@ -0,0 +1,9 @@ +#include "userinterface.h" + +extern "C" +{ + KDE_EXPORT Plugin *create_plugin() + { + return new Kaiman(); + } +} diff --git a/noatun/modules/kaiman/pref.cpp b/noatun/modules/kaiman/pref.cpp new file mode 100644 index 00000000..892435fc --- /dev/null +++ b/noatun/modules/kaiman/pref.cpp @@ -0,0 +1,122 @@ +/* + Copyright (c) 1999-2000 Stefan Schimanski <1Stein@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <klocale.h> +#include <qlayout.h> +#include <qlabel.h> +#include <klistbox.h> +#include <qdir.h> +#include <qfileinfo.h> +#include <kglobal.h> +#include <kdebug.h> +#include <kstandarddirs.h> +#include <kconfig.h> + +#include "pref.h" +#include "userinterface.h" + + +KaimanPrefDlg::KaimanPrefDlg(QObject *parent ) + : CModule(i18n("Kaiman Skins"), i18n("Skin Selection for the Kaiman Plugin"), "style", parent) +{ + // create widgets + QVBoxLayout *topLayout = new QVBoxLayout( this, 6, 11 ); + QLabel *label = new QLabel( i18n("Kaiman Skins"), this, "label" ); + topLayout->addWidget( label ); + + _skinList = new KListBox( this, "skinList" ); + topLayout->addWidget( _skinList, 1 ); + reopen(); +} + + +KaimanPrefDlg::~KaimanPrefDlg() +{ +} + + +void KaimanPrefDlg::save() +{ + KConfig *config=KGlobal::config(); + config->setGroup("Kaiman"); + config->writeEntry("SkinResource", skin() ); + config->sync(); + + Kaiman *l=Kaiman::kaiman; + if ( l ) { + l->changeStyle( skin() ); + } +} + +void KaimanPrefDlg::reopen() +{ + _skinList->clear(); + // fill with available skins + KGlobal::dirs()->addResourceType("skins", KStandardDirs::kde_default("data") + "noatun/skins/kaiman/"); + QStringList list = KGlobal::dirs()->resourceDirs("skins"); + for (QStringList::ConstIterator it = list.begin(); it != list.end(); it++) + readSkinDir(*it); + + // load current config + KConfig *config=KGlobal::config(); + config->setGroup("Kaiman"); + QString skin = config->readEntry( "SkinResource", Kaiman::DEFAULT_SKIN ); + QListBoxItem *item = _skinList->findItem( skin ); + if ( item ) + _skinList->setCurrentItem( item ); + else + _skinList->setCurrentItem( 0 ); +} + + +void KaimanPrefDlg::setSkin( QString skin ) +{ + _skinList->setCurrentItem( _skinList->findItem( skin ) ); +} + + +QString KaimanPrefDlg::skin() +{ + return _skinList->currentText(); +} + + +void KaimanPrefDlg::readSkinDir( const QString &dir ) +{ + kdDebug() << "readSkinDir " << dir << endl; + + QDir directory( dir ); + if (!directory.exists()) + return; + + const QFileInfoList *list = directory.entryInfoList(); + QFileInfoListIterator it(*list); + + while ( it.current() ) { + kdDebug() << it.current()->absFilePath() << endl; + QFileInfo skindata( it.current()->absFilePath()+"/skindata" ); + + if ( skindata.exists() ) { + _skinList->insertItem( it.current()->baseName() ); + } + + ++it; + } +} + +#include "pref.moc" diff --git a/noatun/modules/kaiman/pref.h b/noatun/modules/kaiman/pref.h new file mode 100644 index 00000000..551dd16a --- /dev/null +++ b/noatun/modules/kaiman/pref.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 1999-2000 Stefan Schimanski <1Stein@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef PREF_H_INCLUDED +#define PREF_H_INCLUDED + +#include <noatun/pref.h> + +class KListBox; +class QLabel; + +class KaimanPrefDlg : public CModule +{ + Q_OBJECT + public: + KaimanPrefDlg( QObject *parent ); + virtual ~KaimanPrefDlg(); + + virtual void save(); + virtual void reopen(); + + public slots: + void setSkin( QString skin ); + QString skin(); + + private: + void readSkinDir( const QString &dir ); + + KListBox *_skinList; +}; + +#endif + diff --git a/noatun/modules/kaiman/skins/Makefile.am b/noatun/modules/kaiman/skins/Makefile.am new file mode 100644 index 00000000..0d3d6687 --- /dev/null +++ b/noatun/modules/kaiman/skins/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = k9 car-preset circle + +skinsdir = $(kde_datadir)/Skins diff --git a/noatun/modules/kaiman/skins/car-preset/Makefile.am b/noatun/modules/kaiman/skins/car-preset/Makefile.am new file mode 100644 index 00000000..646898d0 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/Makefile.am @@ -0,0 +1,10 @@ +skin_DATA = btn_p1.png btn_play.png digbig.png random.png \ + btn_p2.png btn_prev.png digmed.png repeat.png \ +btn_exit.png btn_p3.png btn_sml.png letters.png skindata \ +btn_iconify.png btn_p4.png btn_stop.png main.png status.png \ +btn_list.png btn_p5.png btn_voldn.png monoster.png volume.png \ +btn_next.png btn_p6.png btn_volup.png posbar.png + +skindir = $(kde_datadir)/noatun/skins/kaiman/car-preset + +EXTRA_DIST = $(skin_DATA) diff --git a/noatun/modules/kaiman/skins/car-preset/README b/noatun/modules/kaiman/skins/car-preset/README new file mode 100644 index 00000000..fedefaaa --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/README @@ -0,0 +1,22 @@ +GQmpeg skin directory: car-preset +Author: Johne Ellis <gqview@geocities.ocm> +Released: October 25, 1998 +Version: 1.0 +URL: +Comment: Skin similar to an automotive stereo, complete + with presets. +Note: For the presets and volume controls to work, GQmpeg + 0.3.6 is required. Previous versions will work, + except for these functions. + +To use this skin with GQmpeg, use the command line: + + gqmpeg -skin:car-preset + +Or when editing skin data, point GQmpeg to this skin with: + + gqmpeg -skin:../car-preset + +or to allow the skin to be the default skin copy this directory +to 'HOME/.gqmpeg/skins/car-preset' and specify 'car-preset' as the +skin on the skin tab of the config dialog. diff --git a/noatun/modules/kaiman/skins/car-preset/btn_exit.png b/noatun/modules/kaiman/skins/car-preset/btn_exit.png Binary files differnew file mode 100644 index 00000000..5bac9d23 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_exit.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_iconify.png b/noatun/modules/kaiman/skins/car-preset/btn_iconify.png Binary files differnew file mode 100644 index 00000000..81b2859a --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_iconify.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_list.png b/noatun/modules/kaiman/skins/car-preset/btn_list.png Binary files differnew file mode 100644 index 00000000..1bea110e --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_list.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_next.png b/noatun/modules/kaiman/skins/car-preset/btn_next.png Binary files differnew file mode 100644 index 00000000..67a3db2a --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_next.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_p1.png b/noatun/modules/kaiman/skins/car-preset/btn_p1.png Binary files differnew file mode 100644 index 00000000..4877b86e --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_p1.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_p2.png b/noatun/modules/kaiman/skins/car-preset/btn_p2.png Binary files differnew file mode 100644 index 00000000..1f6b1f41 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_p2.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_p3.png b/noatun/modules/kaiman/skins/car-preset/btn_p3.png Binary files differnew file mode 100644 index 00000000..d3ec7ab5 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_p3.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_p4.png b/noatun/modules/kaiman/skins/car-preset/btn_p4.png Binary files differnew file mode 100644 index 00000000..16b57b7c --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_p4.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_p5.png b/noatun/modules/kaiman/skins/car-preset/btn_p5.png Binary files differnew file mode 100644 index 00000000..18d65172 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_p5.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_p6.png b/noatun/modules/kaiman/skins/car-preset/btn_p6.png Binary files differnew file mode 100644 index 00000000..2b0eba96 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_p6.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_play.png b/noatun/modules/kaiman/skins/car-preset/btn_play.png Binary files differnew file mode 100644 index 00000000..814cbbf9 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_play.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_prev.png b/noatun/modules/kaiman/skins/car-preset/btn_prev.png Binary files differnew file mode 100644 index 00000000..ffdc59a5 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_prev.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_sml.png b/noatun/modules/kaiman/skins/car-preset/btn_sml.png Binary files differnew file mode 100644 index 00000000..a2acff28 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_sml.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_stop.png b/noatun/modules/kaiman/skins/car-preset/btn_stop.png Binary files differnew file mode 100644 index 00000000..faca588f --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_stop.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_voldn.png b/noatun/modules/kaiman/skins/car-preset/btn_voldn.png Binary files differnew file mode 100644 index 00000000..15e40697 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_voldn.png diff --git a/noatun/modules/kaiman/skins/car-preset/btn_volup.png b/noatun/modules/kaiman/skins/car-preset/btn_volup.png Binary files differnew file mode 100644 index 00000000..9e6c8964 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/btn_volup.png diff --git a/noatun/modules/kaiman/skins/car-preset/digbig.png b/noatun/modules/kaiman/skins/car-preset/digbig.png Binary files differnew file mode 100644 index 00000000..44ea6a9d --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/digbig.png diff --git a/noatun/modules/kaiman/skins/car-preset/digmed.png b/noatun/modules/kaiman/skins/car-preset/digmed.png Binary files differnew file mode 100644 index 00000000..55a43732 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/digmed.png diff --git a/noatun/modules/kaiman/skins/car-preset/letters.png b/noatun/modules/kaiman/skins/car-preset/letters.png Binary files differnew file mode 100644 index 00000000..7f59af69 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/letters.png diff --git a/noatun/modules/kaiman/skins/car-preset/main.png b/noatun/modules/kaiman/skins/car-preset/main.png Binary files differnew file mode 100644 index 00000000..2601e03b --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/main.png diff --git a/noatun/modules/kaiman/skins/car-preset/monoster.png b/noatun/modules/kaiman/skins/car-preset/monoster.png Binary files differnew file mode 100644 index 00000000..fe8129b7 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/monoster.png diff --git a/noatun/modules/kaiman/skins/car-preset/posbar.png b/noatun/modules/kaiman/skins/car-preset/posbar.png Binary files differnew file mode 100644 index 00000000..3d6eb8e8 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/posbar.png diff --git a/noatun/modules/kaiman/skins/car-preset/random.png b/noatun/modules/kaiman/skins/car-preset/random.png Binary files differnew file mode 100644 index 00000000..30b99726 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/random.png diff --git a/noatun/modules/kaiman/skins/car-preset/repeat.png b/noatun/modules/kaiman/skins/car-preset/repeat.png Binary files differnew file mode 100644 index 00000000..022648fd --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/repeat.png diff --git a/noatun/modules/kaiman/skins/car-preset/skindata b/noatun/modules/kaiman/skins/car-preset/skindata new file mode 100644 index 00000000..7a9651e0 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/skindata @@ -0,0 +1,71 @@ +#GQmpeg skin data file + +#Title: Car faceplate with presets +#Version: 1 +#Released: October 25, 1998 +#Author: John Ellis <gqview@geocities.com> +#URL: +#Comments: Skin similar to an automotive stereo, complete +# with presets. + +#run 'gqmpeg -skinhelp' for help with coordinates. +#simply comment out items you do not want to display +#only Background is required. +Background: main.png + +#Title: filename length x y +Title: letters.png 16 60 18 + +#Play/Pause/Stop/Shuffle/Repeat_Button: filename prelight status_light x y +Play_Button: btn_play.png FALSE FALSE 25 32 +Stop_Button: btn_stop.png FALSE FALSE 4 32 +Shuffle_Button: btn_sml.png FALSE FALSE 265 41 +Repeat_Button: btn_sml.png FALSE FALSE 283 41 + +#Next/Prev/FF/RW/Playlist/Config/ +# Iconify/Mixer/Exit/Alt_Skin_Button: prelight x y +Next_Button: btn_next.png FALSE 7 18 +Prev_Button: btn_prev.png FALSE 7 51 +Playlist_Button: btn_list.png FALSE 11 66 +Config_Button: btn_sml.png FALSE 283 23 +Iconify_Button: btn_iconify.png FALSE 263 4 +Exit_Button: btn_exit.png FALSE 280 4 + +#Stereo/Shuffle/Repeat/Mpegver/Mpeglayer/Mpegmode/Status_Item: filename x y +Stereo_Item: monoster.png 161 49 +Shuffle_Item: random.png 161 38 +Repeat_Item: repeat.png 205 38 +Status_Item: status.png 57 39 + +#you can define one or both of these first: +Digit_Large_Default: digbig.png +Digit_Small_Default: digmed.png +#then use Large or Small as the filename in *_Number below (convenience feature) + +#Minute/Second/Song/Total/In_Rate/In_Hz/Out_Bits/Out_Hz/Frame/CPU_Number: filename x y +Minute_Number: Large 65 38 +Second_Number: Large 97 38 +Song_Number: Small 129 44 +CPU_Number: Small 236 44 + +#Volume/Balance_Item: filename sections x y +# (these 2 items must be before their respective Volume/Balance_Sliders) +Volume_Item: volume.png 17 181 48 + +#Volume_Up/Volume_Down/Balance_Left/Balance_Right_Button: filename prelight x y +Volume_Up_Button: btn_volup.png FALSE 261 60 +Volume_Down_Button: btn_voldn.png FALSE 279 60 + +#Position/Volume/Balance_Slider: filename prelight length x y +Position_Slider: posbar.png FALSE 195 58 5 + +#Preset_1_ ... Preset_10_Button: filename prelight x y +Preset_1_Button: btn_p1.png FALSE 58 66 +Preset_2_Button: btn_p2.png FALSE 91 66 +Preset_3_Button: btn_p3.png FALSE 124 66 +Preset_4_Button: btn_p4.png FALSE 157 66 +Preset_5_Button: btn_p5.png FALSE 190 66 +Preset_6_Button: btn_p6.png FALSE 223 66 + +# end + diff --git a/noatun/modules/kaiman/skins/car-preset/status.png b/noatun/modules/kaiman/skins/car-preset/status.png Binary files differnew file mode 100644 index 00000000..05ceed86 --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/status.png diff --git a/noatun/modules/kaiman/skins/car-preset/volume.png b/noatun/modules/kaiman/skins/car-preset/volume.png Binary files differnew file mode 100644 index 00000000..f690e79d --- /dev/null +++ b/noatun/modules/kaiman/skins/car-preset/volume.png diff --git a/noatun/modules/kaiman/skins/circle/Makefile.am b/noatun/modules/kaiman/skins/circle/Makefile.am new file mode 100644 index 00000000..6c8ae5f2 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/Makefile.am @@ -0,0 +1,13 @@ +skin_DATA = btn_exit.png btn_repeat.png btn_sm_stop.png \ + btn_iconify.png btn_shuffle.png btn_stop.png \ +back.png btn_list.png btn_sm_exit.png dig.png \ +back_mask.png btn_mode.png btn_sm_iconify.png digsml.png \ +back_sm.png btn_next.png btn_sm_mode.png letters.png \ +back_sm_mask.png btn_play.png btn_sm_next.png skindata \ +bar_pos.png btn_pref.png btn_sm_play.png \ +bar_vol.png btn_prev.png btn_sm_prev.png status.png + + +skindir = $(kde_datadir)/noatun/skins/kaiman/circle + +EXTRA_DIST = $(skin_DATA) diff --git a/noatun/modules/kaiman/skins/circle/README b/noatun/modules/kaiman/skins/circle/README new file mode 100644 index 00000000..d80082af --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/README @@ -0,0 +1,22 @@ +GQmpeg skin directory: circle +Author: Johne Ellis <gqview@geocities.ocm> +Released: November 25, 1998 +Version: 1.0 +URL: http://www.geocities.com/SiliconValley/Haven/5235 +Comments: Skin with a doughnut shape to test shaped windows. + (skins with a shape mask) + +Note: For transparency to work, GQmpeg 0.4.2 is required. + Previous versions will work, but will be _ugly_. + +To use this skin with GQmpeg, use the command line: + + gqmpeg -skin:circle + +Or when editing skin data, point GQmpeg to this skin with: + + gqmpeg -skin:../circle + +or to allow the skin to be the default skin copy this directory +to 'HOME/.gqmpeg/skins/circle' and specify 'circle' as the +skin on the skin tab of the config dialog. diff --git a/noatun/modules/kaiman/skins/circle/back.png b/noatun/modules/kaiman/skins/circle/back.png Binary files differnew file mode 100644 index 00000000..83758a14 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/back.png diff --git a/noatun/modules/kaiman/skins/circle/back_mask.png b/noatun/modules/kaiman/skins/circle/back_mask.png Binary files differnew file mode 100644 index 00000000..de54ddef --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/back_mask.png diff --git a/noatun/modules/kaiman/skins/circle/back_sm.png b/noatun/modules/kaiman/skins/circle/back_sm.png Binary files differnew file mode 100644 index 00000000..3263c2db --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/back_sm.png diff --git a/noatun/modules/kaiman/skins/circle/back_sm_mask.png b/noatun/modules/kaiman/skins/circle/back_sm_mask.png Binary files differnew file mode 100644 index 00000000..315d88bf --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/back_sm_mask.png diff --git a/noatun/modules/kaiman/skins/circle/bar_pos.png b/noatun/modules/kaiman/skins/circle/bar_pos.png Binary files differnew file mode 100644 index 00000000..e6ac85a3 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/bar_pos.png diff --git a/noatun/modules/kaiman/skins/circle/bar_vol.png b/noatun/modules/kaiman/skins/circle/bar_vol.png Binary files differnew file mode 100644 index 00000000..88f88651 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/bar_vol.png diff --git a/noatun/modules/kaiman/skins/circle/btn_exit.png b/noatun/modules/kaiman/skins/circle/btn_exit.png Binary files differnew file mode 100644 index 00000000..cd36d2fd --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_exit.png diff --git a/noatun/modules/kaiman/skins/circle/btn_iconify.png b/noatun/modules/kaiman/skins/circle/btn_iconify.png Binary files differnew file mode 100644 index 00000000..20647819 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_iconify.png diff --git a/noatun/modules/kaiman/skins/circle/btn_list.png b/noatun/modules/kaiman/skins/circle/btn_list.png Binary files differnew file mode 100644 index 00000000..f51e322b --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_list.png diff --git a/noatun/modules/kaiman/skins/circle/btn_mode.png b/noatun/modules/kaiman/skins/circle/btn_mode.png Binary files differnew file mode 100644 index 00000000..4c6db0e1 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_mode.png diff --git a/noatun/modules/kaiman/skins/circle/btn_next.png b/noatun/modules/kaiman/skins/circle/btn_next.png Binary files differnew file mode 100644 index 00000000..4ae8ee71 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_next.png diff --git a/noatun/modules/kaiman/skins/circle/btn_play.png b/noatun/modules/kaiman/skins/circle/btn_play.png Binary files differnew file mode 100644 index 00000000..f21d287e --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_play.png diff --git a/noatun/modules/kaiman/skins/circle/btn_pref.png b/noatun/modules/kaiman/skins/circle/btn_pref.png Binary files differnew file mode 100644 index 00000000..9337e704 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_pref.png diff --git a/noatun/modules/kaiman/skins/circle/btn_prev.png b/noatun/modules/kaiman/skins/circle/btn_prev.png Binary files differnew file mode 100644 index 00000000..c65a9298 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_prev.png diff --git a/noatun/modules/kaiman/skins/circle/btn_repeat.png b/noatun/modules/kaiman/skins/circle/btn_repeat.png Binary files differnew file mode 100644 index 00000000..48b12a90 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_repeat.png diff --git a/noatun/modules/kaiman/skins/circle/btn_shuffle.png b/noatun/modules/kaiman/skins/circle/btn_shuffle.png Binary files differnew file mode 100644 index 00000000..75ad39f9 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_shuffle.png diff --git a/noatun/modules/kaiman/skins/circle/btn_sm_exit.png b/noatun/modules/kaiman/skins/circle/btn_sm_exit.png Binary files differnew file mode 100644 index 00000000..f14752f8 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_sm_exit.png diff --git a/noatun/modules/kaiman/skins/circle/btn_sm_iconify.png b/noatun/modules/kaiman/skins/circle/btn_sm_iconify.png Binary files differnew file mode 100644 index 00000000..69b9332c --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_sm_iconify.png diff --git a/noatun/modules/kaiman/skins/circle/btn_sm_mode.png b/noatun/modules/kaiman/skins/circle/btn_sm_mode.png Binary files differnew file mode 100644 index 00000000..79b4c5a0 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_sm_mode.png diff --git a/noatun/modules/kaiman/skins/circle/btn_sm_next.png b/noatun/modules/kaiman/skins/circle/btn_sm_next.png Binary files differnew file mode 100644 index 00000000..66c01ddb --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_sm_next.png diff --git a/noatun/modules/kaiman/skins/circle/btn_sm_play.png b/noatun/modules/kaiman/skins/circle/btn_sm_play.png Binary files differnew file mode 100644 index 00000000..191551eb --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_sm_play.png diff --git a/noatun/modules/kaiman/skins/circle/btn_sm_prev.png b/noatun/modules/kaiman/skins/circle/btn_sm_prev.png Binary files differnew file mode 100644 index 00000000..d70dbb53 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_sm_prev.png diff --git a/noatun/modules/kaiman/skins/circle/btn_sm_stop.png b/noatun/modules/kaiman/skins/circle/btn_sm_stop.png Binary files differnew file mode 100644 index 00000000..0d0841d7 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_sm_stop.png diff --git a/noatun/modules/kaiman/skins/circle/btn_stop.png b/noatun/modules/kaiman/skins/circle/btn_stop.png Binary files differnew file mode 100644 index 00000000..2563dbc0 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/btn_stop.png diff --git a/noatun/modules/kaiman/skins/circle/dig.png b/noatun/modules/kaiman/skins/circle/dig.png Binary files differnew file mode 100644 index 00000000..c417de15 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/dig.png diff --git a/noatun/modules/kaiman/skins/circle/digsml.png b/noatun/modules/kaiman/skins/circle/digsml.png Binary files differnew file mode 100644 index 00000000..29f2ed43 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/digsml.png diff --git a/noatun/modules/kaiman/skins/circle/letters.png b/noatun/modules/kaiman/skins/circle/letters.png Binary files differnew file mode 100644 index 00000000..b4322d62 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/letters.png diff --git a/noatun/modules/kaiman/skins/circle/skindata b/noatun/modules/kaiman/skins/circle/skindata new file mode 100644 index 00000000..25268d22 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/skindata @@ -0,0 +1,58 @@ +#GQmpeg skin data file +#tested on version 0.4.2 + +#Title: circle +#Version: 1 +#Released: November 25, 1998 +#Author: John Ellis <gqview@geocities.com> +#URL: http://www.geocities.com/SiliconValley/Haven/5235/ +#Comments: Skin with a doughnut shape to test shaped windows. +# (skins with a shape mask) + +#run 'gqmpeg -skinhelp' for help with coordinates. +#simply comment out items you do not want to display +#only Background is required. +Background: back.png + +#Mask is an image with transparency used to define a shaped window +Mask: back_mask.png + +#Title: filename length x y +Title: letters.png 23 32 86 + +#Play/Pause/Stop/Shuffle/Repeat_Button: filename prelight status_light x y +Play_Button: btn_play.png TRUE TRUE 125 160 +Stop_Button: btn_stop.png TRUE TRUE 44 160 +Shuffle_Button: btn_shuffle.png TRUE TRUE 151 29 +Repeat_Button: btn_repeat.png TRUE TRUE 164 49 + +#Next/Prev/FF/RW/Playlist/Config/ +# Iconify/Mixer/Exit/Alt_Skin_Button: prelight x y +Next_Button: btn_next.png TRUE 125 10 +Prev_Button: btn_prev.png TRUE 44 10 +Playlist_Button: btn_list.png TRUE 158 130 +Config_Button: btn_pref.png TRUE 13 130 +Iconify_Button: btn_iconify.png TRUE 3 69 +Exit_Button: btn_exit.png TRUE 13 40 +Alt_Skin_Button: btn_mode.png TRUE 3 103 + +#Stereo/Shuffle/Repeat/Mpegver/Mpeglayer/Mpegmode/Status_Item: filename x y +#Stereo_Item: stereo.png 280 26 +Status_Item: status.png 82 20 + +#you can define one or both of these first: +Digit_Large_Default: dig.png +#then use Large or Small as the filename in *_Number below (convenience feature) + +#Minute/Second/Song/Total/In_Rate/In_Hz/Out_Bits/Out_Hz/Frame/CPU_Number: filename x y +Minute_Number: Large 79 176 +Second_Number: Large 102 176 +Song_Number: Large 91 7 +CPU_Number: digsml.png 78 8 + +#Position/Volume/Balance_Slider: filename prelight verticle reversed length x y +Position_Slider: bar_pos.png TRUE FALSE FALSE 142 30 103 +Volume_Slider: bar_vol.png TRUE TRUE TRUE 46 175 77 + +# end + diff --git a/noatun/modules/kaiman/skins/circle/skindata_alt b/noatun/modules/kaiman/skins/circle/skindata_alt new file mode 100644 index 00000000..fb3e97f5 --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/skindata_alt @@ -0,0 +1,44 @@ +#GQmpeg skin data file +#tested on version 0.4.2 + +#Title: circle +#Version: 1 +#Released: November 25, 1998 +#Author: John Ellis <gqview@geocities.com> +#URL: http://www.geocities.com/SiliconValley/Haven/5235/ +#Comments: Skin with a doughnut shape to test shaped windows. +# (skins with a shape mask) + +#run 'gqmpeg -skinhelp' for help with coordinates. +#simply comment out items you do not want to display +#only Background is required. +Background: back_sm.png + +#Mask is an image with transparency used to define a shaped window +Mask: back_sm_mask.png + +#Title: filename length x y +Title: letters.png 21 8 4 + +#Play/Pause/Stop/Shuffle/Repeat_Button: filename prelight status_light x y +Play_Button: btn_sm_play.png TRUE TRUE 21 21 +Stop_Button: btn_sm_stop.png TRUE TRUE 4 21 + +#Next/Prev/FF/RW/Playlist/Config/ +# Iconify/Mixer/Exit/Alt_Skin_Button: prelight x y +Next_Button: btn_sm_next.png TRUE 87 21 +Prev_Button: btn_sm_prev.png TRUE 70 21 +Iconify_Button: btn_sm_iconify.png TRUE 120 29 +Exit_Button: btn_sm_exit.png TRUE 120 21 +Alt_Skin_Button: btn_sm_mode.png TRUE 104 21 + +#you can define one or both of these first: +Digit_Small_Default: digsml.png +#then use Large or Small as the filename in *_Number below (convenience feature) + +#Minute/Second/Song/Total/In_Rate/In_Hz/Out_Bits/Out_Hz/Frame/CPU_Number: filename x y +Minute_Number: Small 41 24 +Second_Number: Small 55 24 + +# end + diff --git a/noatun/modules/kaiman/skins/circle/status.png b/noatun/modules/kaiman/skins/circle/status.png Binary files differnew file mode 100644 index 00000000..b29e075c --- /dev/null +++ b/noatun/modules/kaiman/skins/circle/status.png diff --git a/noatun/modules/kaiman/skins/k9/Makefile.am b/noatun/modules/kaiman/skins/k9/Makefile.am new file mode 100644 index 00000000..bac3bd84 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/Makefile.am @@ -0,0 +1,11 @@ +skin_DATA = README skindata conf.jpg conf.png eject.jpg icon.jpg icon.png \ + kill.jpg kill.png knine-nfont.jpg knine-nfont.png knine-nfont2.jpg \ + knine-nfont2.png knine-normal2.jpg knine-normal2.png knine-vfont.jpg \ + knine-vfont.png long2.jpg mask.png newtext.jpg newtext.png next.jpg \ + pause.jpg play.jpg pos_item.jpg repeat.jpg repeat.png reverse.jpg \ + shuffle.jpg shuffle.png small-k.jpg small-k.png square.jpg square.png \ + status.jpg status.png stop.jpg trans-pos.png trans-slide.png + +skindir = $(kde_datadir)/noatun/skins/kaiman/k9 + +EXTRA_DIST = $(skin_DATA) diff --git a/noatun/modules/kaiman/skins/k9/README b/noatun/modules/kaiman/skins/k9/README new file mode 100644 index 00000000..8425d0c3 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/README @@ -0,0 +1,24 @@ + +This skin is totally (c) 1999 to Morgan aka."Splif" Thomas / +the Aegis Corporation.
Please don't rip, sell, use in public +without the author's acceptation. Thanks.
But you are +totally free to distribute it all around the universe. +_____________________________________________________________ +Ported by Me, 'cuz "A skin like this belongs under +Enlightenment, not windows." + DNAspark99 +Contact: jedeye_one@hotmail.com +check out: http://www3.bc.sympatico.ca/desperados + +Notes: I reversed the iris, so it "closes" as volume increases. +If ya wanna try it the default way, edit the "Volume_Item" line in +the skindata file and change it to "long" instead of "long2" + + & Too bad GQmpeg doesn't have fancy playlist customization like those +"other" mp3 players......this skin has a "kill" one of those too... +----------------------------------------------------- --- -- +origional artist: +Contact: Splif@Aegis-Corp.org +Home: http://www.Aegis-Corp.org/Splif/ + +____________________________________________________________ diff --git a/noatun/modules/kaiman/skins/k9/conf.jpg b/noatun/modules/kaiman/skins/k9/conf.jpg Binary files differnew file mode 100644 index 00000000..91be54d1 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/conf.jpg diff --git a/noatun/modules/kaiman/skins/k9/conf.png b/noatun/modules/kaiman/skins/k9/conf.png Binary files differnew file mode 100644 index 00000000..56860e00 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/conf.png diff --git a/noatun/modules/kaiman/skins/k9/eject.jpg b/noatun/modules/kaiman/skins/k9/eject.jpg Binary files differnew file mode 100644 index 00000000..f1d00f09 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/eject.jpg diff --git a/noatun/modules/kaiman/skins/k9/icon.jpg b/noatun/modules/kaiman/skins/k9/icon.jpg Binary files differnew file mode 100644 index 00000000..3740549b --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/icon.jpg diff --git a/noatun/modules/kaiman/skins/k9/icon.png b/noatun/modules/kaiman/skins/k9/icon.png Binary files differnew file mode 100644 index 00000000..e9057671 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/icon.png diff --git a/noatun/modules/kaiman/skins/k9/kill.jpg b/noatun/modules/kaiman/skins/k9/kill.jpg Binary files differnew file mode 100644 index 00000000..8d52aa86 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/kill.jpg diff --git a/noatun/modules/kaiman/skins/k9/kill.png b/noatun/modules/kaiman/skins/k9/kill.png Binary files differnew file mode 100644 index 00000000..8ec851dd --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/kill.png diff --git a/noatun/modules/kaiman/skins/k9/knine-nfont.jpg b/noatun/modules/kaiman/skins/k9/knine-nfont.jpg Binary files differnew file mode 100644 index 00000000..5010b881 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/knine-nfont.jpg diff --git a/noatun/modules/kaiman/skins/k9/knine-nfont.png b/noatun/modules/kaiman/skins/k9/knine-nfont.png Binary files differnew file mode 100644 index 00000000..2e166ee1 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/knine-nfont.png diff --git a/noatun/modules/kaiman/skins/k9/knine-nfont2.jpg b/noatun/modules/kaiman/skins/k9/knine-nfont2.jpg Binary files differnew file mode 100644 index 00000000..7511230a --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/knine-nfont2.jpg diff --git a/noatun/modules/kaiman/skins/k9/knine-nfont2.png b/noatun/modules/kaiman/skins/k9/knine-nfont2.png Binary files differnew file mode 100644 index 00000000..63e45974 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/knine-nfont2.png diff --git a/noatun/modules/kaiman/skins/k9/knine-normal2.jpg b/noatun/modules/kaiman/skins/k9/knine-normal2.jpg Binary files differnew file mode 100644 index 00000000..b744ac82 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/knine-normal2.jpg diff --git a/noatun/modules/kaiman/skins/k9/knine-normal2.png b/noatun/modules/kaiman/skins/k9/knine-normal2.png Binary files differnew file mode 100644 index 00000000..e0d95dc8 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/knine-normal2.png diff --git a/noatun/modules/kaiman/skins/k9/knine-vfont.jpg b/noatun/modules/kaiman/skins/k9/knine-vfont.jpg Binary files differnew file mode 100644 index 00000000..a7c27bbf --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/knine-vfont.jpg diff --git a/noatun/modules/kaiman/skins/k9/knine-vfont.png b/noatun/modules/kaiman/skins/k9/knine-vfont.png Binary files differnew file mode 100644 index 00000000..e8692e80 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/knine-vfont.png diff --git a/noatun/modules/kaiman/skins/k9/long2.jpg b/noatun/modules/kaiman/skins/k9/long2.jpg Binary files differnew file mode 100644 index 00000000..321c121a --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/long2.jpg diff --git a/noatun/modules/kaiman/skins/k9/mask.png b/noatun/modules/kaiman/skins/k9/mask.png Binary files differnew file mode 100644 index 00000000..9ea57d2b --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/mask.png diff --git a/noatun/modules/kaiman/skins/k9/newtext.jpg b/noatun/modules/kaiman/skins/k9/newtext.jpg Binary files differnew file mode 100644 index 00000000..69c437f2 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/newtext.jpg diff --git a/noatun/modules/kaiman/skins/k9/newtext.png b/noatun/modules/kaiman/skins/k9/newtext.png Binary files differnew file mode 100644 index 00000000..e8f25356 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/newtext.png diff --git a/noatun/modules/kaiman/skins/k9/next.jpg b/noatun/modules/kaiman/skins/k9/next.jpg Binary files differnew file mode 100644 index 00000000..0a0e5267 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/next.jpg diff --git a/noatun/modules/kaiman/skins/k9/pause.jpg b/noatun/modules/kaiman/skins/k9/pause.jpg Binary files differnew file mode 100644 index 00000000..1144e70d --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/pause.jpg diff --git a/noatun/modules/kaiman/skins/k9/play.jpg b/noatun/modules/kaiman/skins/k9/play.jpg Binary files differnew file mode 100644 index 00000000..dbfe446f --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/play.jpg diff --git a/noatun/modules/kaiman/skins/k9/pos_item.jpg b/noatun/modules/kaiman/skins/k9/pos_item.jpg Binary files differnew file mode 100644 index 00000000..0ba2f333 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/pos_item.jpg diff --git a/noatun/modules/kaiman/skins/k9/repeat.jpg b/noatun/modules/kaiman/skins/k9/repeat.jpg Binary files differnew file mode 100644 index 00000000..774e0804 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/repeat.jpg diff --git a/noatun/modules/kaiman/skins/k9/repeat.png b/noatun/modules/kaiman/skins/k9/repeat.png Binary files differnew file mode 100644 index 00000000..84810e5b --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/repeat.png diff --git a/noatun/modules/kaiman/skins/k9/reverse.jpg b/noatun/modules/kaiman/skins/k9/reverse.jpg Binary files differnew file mode 100644 index 00000000..a9b74366 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/reverse.jpg diff --git a/noatun/modules/kaiman/skins/k9/shuffle.jpg b/noatun/modules/kaiman/skins/k9/shuffle.jpg Binary files differnew file mode 100644 index 00000000..1d52ac9b --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/shuffle.jpg diff --git a/noatun/modules/kaiman/skins/k9/shuffle.png b/noatun/modules/kaiman/skins/k9/shuffle.png Binary files differnew file mode 100644 index 00000000..a3e22250 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/shuffle.png diff --git a/noatun/modules/kaiman/skins/k9/skindata b/noatun/modules/kaiman/skins/k9/skindata new file mode 100644 index 00000000..1fdc4320 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/skindata @@ -0,0 +1,73 @@ +# +# port of K-Nine skin for K-Jofol +# original art done by Morgan aka. "Splif" Thomas / the Aegis Corp. +# +# "'cuz a skin like this belongs under Enlightenment" +# +# DNAspark99 +# +# +###################################################### + +Background: knine-normal2.jpg +Mask: mask.png + +Play_Button: play.jpg FALSE FALSE 55 133 89 166 +Stop_Button: stop.jpg FALSE FALSE 28 124 52 145 +Pause_Button: pause.jpg FALSE 91 148 116 173 +Prev_Button: reverse.jpg FALSE 13 108 32 127 +Next_Button: next.jpg FALSE 122 154 141 173 +Repeat_Button: repeat.jpg FALSE TRUE 50 114 63 128 +Shuffle_Button: shuffle.jpg FALSE TRUE 102 134 118 147 +Playlist_Button: eject.jpg FALSE 78 106 104 +Mixer_Button: square.jpg FALSE 294 110 310 126 +Exit_Button: kill.jpg FALSE 282 57 295 69 +Iconify_Button: icon.jpg FALSE 292 85 304 96 + +Config_Button: conf.jpg FALSE 222 163 242 181 + +Alt_Skin_Button: small-k.jpg FALSE 287 138 299 153 + + +Minute_Number: knine-nfont2.jpg 69 64 +Second_Number: knine-nfont2.jpg 91 64 + +In_Rate_Number: knine-vfont.jpg 123 59 +In_Hz_Number: knine-vfont.jpg 132 50 + +Song_Number: knine-vfont.jpg 113 50 + +Status_Item: status.jpg 113 68 + +CPU_Number: knine-vfont.jpg 80 50 + +Digit_Large: knine-vfont.jpg 113 40 +Digit_Small_Default: knine-vfont.jpg + +Title: newtext.jpg 26 19 87 + +#RW_Button: back.jpg FALSE 35 192 +#FF_Button: ff.jpg FALSE 51 214 + +#Preset_1_Button: list_1.jpg TRUE 70 70 +#Preset_2_Button: list_2.jpg TRUE 77 70 +#Preset_3_Button: list_3.jpg TRUE 84 70 +#Preset_4_Button: list_4.jpg TRUE 91 70 +#Preset_5_Button: list_5.jpg TRUE 98 70 +#Preset_6_Button: list_6.jpg TRUE 70 80 +#Preset_7_Button: list_7.jpg TRUE 77 80 +#Preset_8_Button: list_8.jpg TRUE 84 80 +#Preset_9_Button: list_9.jpg TRUE 91 80 +#Preset_10_Button: list_10.jpg TRUE 98 80 + + +Volume_Item: long2.jpg 27 199 76 +Volume_Slider: trans-slide.png FALSE FALSE FALSE 71 205 76 210 + +Position_Item: pos_item.jpg 32 128 2 30 +Position_Slider: trans-pos.png FALSE FALSE FALSE 140 128 2 70 + +#Balance_Item: balance.jpg FALSE FALSE FALSE 10 156 95 +#Balance_Slider: knine-pitchbtn.jpg 57 156 95 + +# END diff --git a/noatun/modules/kaiman/skins/k9/small-k.jpg b/noatun/modules/kaiman/skins/k9/small-k.jpg Binary files differnew file mode 100644 index 00000000..219ebb05 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/small-k.jpg diff --git a/noatun/modules/kaiman/skins/k9/small-k.png b/noatun/modules/kaiman/skins/k9/small-k.png Binary files differnew file mode 100644 index 00000000..2a43a4a8 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/small-k.png diff --git a/noatun/modules/kaiman/skins/k9/square.jpg b/noatun/modules/kaiman/skins/k9/square.jpg Binary files differnew file mode 100644 index 00000000..c13b1644 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/square.jpg diff --git a/noatun/modules/kaiman/skins/k9/square.png b/noatun/modules/kaiman/skins/k9/square.png Binary files differnew file mode 100644 index 00000000..d77de4ef --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/square.png diff --git a/noatun/modules/kaiman/skins/k9/status.jpg b/noatun/modules/kaiman/skins/k9/status.jpg Binary files differnew file mode 100644 index 00000000..db6c61a1 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/status.jpg diff --git a/noatun/modules/kaiman/skins/k9/status.png b/noatun/modules/kaiman/skins/k9/status.png Binary files differnew file mode 100644 index 00000000..682d01b4 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/status.png diff --git a/noatun/modules/kaiman/skins/k9/stop.jpg b/noatun/modules/kaiman/skins/k9/stop.jpg Binary files differnew file mode 100644 index 00000000..0ca261e3 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/stop.jpg diff --git a/noatun/modules/kaiman/skins/k9/trans-pos.png b/noatun/modules/kaiman/skins/k9/trans-pos.png Binary files differnew file mode 100644 index 00000000..0eecf3bb --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/trans-pos.png diff --git a/noatun/modules/kaiman/skins/k9/trans-slide.png b/noatun/modules/kaiman/skins/k9/trans-slide.png Binary files differnew file mode 100644 index 00000000..76aa00d7 --- /dev/null +++ b/noatun/modules/kaiman/skins/k9/trans-slide.png diff --git a/noatun/modules/kaiman/style.cpp b/noatun/modules/kaiman/style.cpp new file mode 100644 index 00000000..d42ed45f --- /dev/null +++ b/noatun/modules/kaiman/style.cpp @@ -0,0 +1,1504 @@ +/* + Copyright (c) 2000 Stefan Schimanski (1Stein@gmx.de) + 1999-2000 Christian Esken (esken@kde.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#include <kapplication.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qpainter.h> +#include <qdropsite.h> +#include <kdebug.h> +#include <klocale.h> +#include <kurldrag.h> +#include <qtimer.h> + +#include <stdlib.h> +#include <unistd.h> + +#include "style.h" +#include "userinterface.h" +#include <noatun/app.h> +#include <noatun/stdaction.h> + +const bool KaimanStyleSlider::optionVertical = 1; +const bool KaimanStyleSlider::optionReversed = 2; +const bool KaimanStyleText::optionExtended = 1; + +KaimanStyleElement::KaimanStyleElement(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + // Initialize everything to default values + filename = ""; + element = ""; + upperLeft.setX(0); + upperLeft.setY(0); + dimension.setWidth(0); + dimension.setHeight(0); + optionPrelight = optionStatuslight = false; + options[0] = options[1] = options[2] = false; + _currentPixmap = 0; + digits = -1; + pixmapLines = 1; + pixmapColumns = 1; + + setAcceptDrops(true); + pixmaps.setAutoDelete(true); + + setBackgroundMode( NoBackground ); +} + + +KaimanStyleElement::~KaimanStyleElement() +{ +} + + +void KaimanStyleElement::loadPixmaps(QString &val_s_filename) +{ + QPixmap pixmap; + + bool i_b_ret = pixmap.load(val_s_filename); + pixmapNum = pixmapLines*pixmapColumns; + + pixmaps.resize(pixmapNum); + + if ( i_b_ret ) { + if(pixmapNum) { + int firstWidth, firstHeight, width, height, sourcex = 0, sourcey = 0; + + // first bitmap may be with different size + if ( dimension.width()!=0 ) + { + firstWidth = dimension.width(); + if ( pixmapColumns>1 ) + width = (pixmap.width()-firstWidth) / (pixmapColumns-1); + else + width = 0; + } else + firstWidth = width = pixmap.width() / pixmapColumns; + + if ( dimension.height()!=0 ) + { + firstHeight = dimension.height(); + if ( pixmapLines>1 ) + height = (pixmap.height()-firstHeight) / (pixmapLines-1); + else + height = 0; + } else + firstHeight = height = pixmap.height() / pixmapLines; + + // create single pixmaps + int i=0; + sourcey = 0; + for( int y=0; y<pixmapLines; y++ ) + { + int h = (y==0) ? firstHeight : height; + sourcex = 0; + + for( int x=0; x<pixmapColumns; x++ ) + { + int w = (x==0) ? firstWidth : width; + + QPixmap *part = new QPixmap(w,h,pixmap.depth()); + part->fill(Qt::black); + bitBlt(part,0,0,&pixmap,sourcex,sourcey,w,h); + pixmaps.insert(i,part); + + if(pixmap.mask()) + { + QBitmap maskpart(w,h); + bitBlt(&maskpart,0,0,pixmap.mask(),sourcex,sourcey,w,h); + part->setMask(maskpart); + } + + i++; + sourcex += w; + } + + sourcey += h; + } + } + } else { + kdDebug() << "Cannot load pixmap " << val_s_filename << endl; + + for ( int i=0; i<pixmapNum; i++ ) + { + QPixmap *pm = new QPixmap(10, 10); + pm->fill(Qt::black); + pixmaps.insert( i, pm ); + } + } + + if ( dimension.width()==0 ) dimension.setWidth( pixmaps[0]->width() ); + if ( dimension.height()==0 ) dimension.setHeight( pixmaps[0]->height() ); + setGeometry( QRect(upperLeft, dimension) ); +} + +void KaimanStyleElement::setPixmap( int num ) +{ + if ( num!=_currentPixmap ) + { + if ( num>pixmapNum-1 ) num = pixmapNum-1; + if ( num<0 ) num = 0; + + _currentPixmap = num; + repaint( FALSE ); + } +} + +void KaimanStyleElement::paintEvent ( QPaintEvent */*qpe*/ ) +{ + QPixmap *pm = pixmaps[_currentPixmap]; + if ( pm ) + bitBlt(this, 0, 0, pm ); + else + kdDebug() << "Invalid pixmap" << endl; + +/* QPainter p( this ); + p.setBrush( NoBrush ); + p.setPen( QColor(255,255,255) ); + p.drawRect( 0, 0, width(), height() ); + p.drawText( 2, 16, name() ); */ +} + +void KaimanStyleElement::dragEnterEvent( QDragEnterEvent *event ) +{ + event->accept( KURLDrag::canDecode(event) ); +} + +void KaimanStyleElement::dropEvent( QDropEvent *event ) +{ + ((Kaiman*)(parentWidget()->parentWidget()))->doDropEvent(event); +} + +/***************************************************************************/ + + +KaimanStyleButton::KaimanStyleButton(QWidget *parent, const char *name) + : KaimanStyleMasked(parent, name) +{ + i_b_lit = i_b_prelit = i_b_down = false; + i_i_currentState = NormalUp; + + I_pmIndex.resize( StateListEND ); + + for (int i=0; i<StateListEND; i++) { + // Set pixmap index of all states to 0 (the default pixmap) + I_pmIndex.insert( i, new int(0)); + } +} + +KaimanStyleButton::~KaimanStyleButton() +{ +} + +void KaimanStyleButton::mousePressEvent(QMouseEvent *qme) +{ + // We deactivate prelight, because the user presses the button. + // So it is now down, but there is no PrelitDown icon (BTW: would + // make no real sense anyhow). + setPrelight(false); + setDown(true); + grabMouse(); + + KaimanStyleMasked::mousePressEvent( qme ); +} + +void KaimanStyleButton::mouseReleaseEvent(QMouseEvent *qme) +{ + releaseMouse (); + + if (down()) + { + setDown(false); + emit clicked(); + } + + KaimanStyleMasked::mouseReleaseEvent( qme ); +} + + +/* paint prelight */ +void KaimanStyleButton::enterEvent ( QEvent * e ) +{ + if ( !down() ) + setPrelight(true); + + KaimanStyleMasked::enterEvent( e ); +} + +/* unpaint prelight */ +void KaimanStyleButton::leaveEvent ( QEvent * e ) +{ + if (!down()) + setPrelight(false); + + KaimanStyleMasked::leaveEvent( e ); +} + +bool KaimanStyleButton::lit() +{ + return i_b_lit; +} + +void KaimanStyleButton::setLit(bool val_b_lit) +{ + i_b_lit = val_b_lit; + updateButtonState(); +} + +bool KaimanStyleButton::prelit() +{ + return i_b_prelit; +} + +void KaimanStyleButton::setPrelight(bool val_b_prelit) +{ + i_b_prelit = val_b_prelit; + updateButtonState(); +} + +bool KaimanStyleButton::down() +{ + return i_b_down; +} + +void KaimanStyleButton::setDown(bool val_b_down) +{ + i_b_down = val_b_down; + updateButtonState(); +} + +void KaimanStyleButton::updateButtonState() { + + if ( i_b_prelit ) { + if ( i_b_lit ) { + // Prelit and Lit + i_i_currentState = PrelightLitUp; + } + else { + // Prelit and not Lit + i_i_currentState = PrelightUp; + } + } + + else if ( i_b_lit ) { + if ( i_b_down ) { + // Lit and Down + i_i_currentState = LitDown; + } else { + // Lit and not Down + i_i_currentState = LitUp; + } + } + else { + if ( i_b_down ) { + // Normal and Down + i_i_currentState = NormalDown; + } + else { + // Normal and not Down + i_i_currentState = NormalUp; + } + } + + setPixmap( *I_pmIndex[i_i_currentState] ); + repaint(); +} + + +/***********************************************************************/ + +KaimanStyleSlider::KaimanStyleSlider(int min, int max, QWidget *parent, const char *name) + : KaimanStyleMasked( parent, name ) +{ + _min = min; + _max = max; + _down = false; + _lit = false; + + setValue( _min ); +} + + +KaimanStyleSlider::~KaimanStyleSlider() +{ +} + + +void KaimanStyleSlider::setValue( int value ) +{ + if (value>_max) value=_max; + if (value<_min) value=_min; + _value = value; + repaint(); +} + + +void KaimanStyleSlider::setValue( int value, int min, int max ) +{ + if ( value!=_value || min!=_min || max!=_max ) { + _min = min; + _max = max; + setValue( value ); + repaint(); + } +} + +int KaimanStyleSlider::pos2value( int x, int y ) +{ + int p; + int v; + if ( options[optionVertical] ) { + p = y; + v = p*(_max-_min)/height(); + } else { + p = x; + v = p*(_max-_min)/width(); + } + + if ( options[optionReversed] ) v = (_max-_min) - v; + return _min + v; +} + + +void KaimanStyleSlider::mouseMoveEvent(QMouseEvent *qme) +{ + KaimanStyleMasked::mouseMoveEvent( qme ); + + if ( _down ) + { + setValue( pos2value(qme->x(), qme->y()) ); + emit newValue( value() ); + } +} + +void KaimanStyleSlider::mousePressEvent(QMouseEvent *qme) +{ + if ( !_down ) + { + grabMouse(); + _down = true; + + setValue( pos2value(qme->x(), qme->y()) ); + emit newValueDrag( value() ); + emit newValue( value() ); + } + + KaimanStyleMasked::mousePressEvent( qme ); +} + + +void KaimanStyleSlider::mouseReleaseEvent(QMouseEvent *qme) +{ + if ( _down ) + { + _down = false; + releaseMouse(); + repaint(); + + setValue( pos2value(qme->x(), qme->y()) ); + emit newValue( value() ); + emit newValueDrop( value() ); + } + + KaimanStyleMasked::mouseReleaseEvent( qme ); +} + + +void KaimanStyleSlider::paintEvent(QPaintEvent */*qpe*/) +{ + // draw background + bitBlt( this, 0, 0, pixmaps[0] ); + + // draw optional handle + QPixmap *handle; + if ( _down ) + handle = pixmaps[2]; + else + { + if ( _lit && optionPrelight ) + handle = pixmaps[3]; + else + handle = pixmaps[1]; + } + + if ( handle && handle->width() ) + { + int x = 0; + int y = 0; + + if ( _max-_min ) { + int v = _value-_min; + if ( options[optionReversed] ) v = (_max-_min) - v; + + if ( options[optionVertical] ) + y = ( height()-handle->height() ) * v / (_max-_min); + else + x = ( width()-handle->width() ) * v / (_max-_min); + } + + bitBlt( this, x, y, handle ); + } +} + +void KaimanStyleSlider::enterEvent ( QEvent * e ) +{ + if ( !_lit && optionPrelight ) + { + _lit = true; + repaint(); + } + + KaimanStyleMasked::enterEvent( e ); +} + +void KaimanStyleSlider::leaveEvent ( QEvent * e ) +{ + if ( _lit ) + { + _lit = false; + repaint(); + } + + KaimanStyleMasked::leaveEvent( e ); +} + + +/***********************************************************************/ + + +KaimanStyleBackground::KaimanStyleBackground(QWidget *parent, const char *name) + : KaimanStyleMasked( parent, name ) +{ + i_b_move = false; +} + +KaimanStyleBackground::~KaimanStyleBackground() +{ +} + +void KaimanStyleBackground::mouseReleaseEvent(QMouseEvent *qme) +{ + i_b_move = false; + KaimanStyleMasked::mouseReleaseEvent( qme ); +} + +void KaimanStyleBackground::mouseMoveEvent(QMouseEvent *qme) +{ + QPoint diff = qme->globalPos() - i_point_lastPos; + if ( abs(diff.x()) > 10 || abs(diff.y()) > 10) { + // Moving starts only, when passing a drag border + i_b_move = true; + } + + if ( i_b_move ) { + QWidget *p = parentWidget()->parentWidget(); + if ( !p ) p = parentWidget(); + + p->move( qme->globalPos() - i_point_dragStart ); + } + + KaimanStyleMasked::mouseMoveEvent( qme ); +} + +void KaimanStyleBackground::mousePressEvent(QMouseEvent *qme) +{ + // On the background we move the shaped toplevel around + if (!i_b_move) { + i_point_dragStart = qme->pos(); + i_point_lastPos = qme->globalPos(); + } + + KaimanStyleMasked::mousePressEvent( qme ); +} + +/***********************************************************************/ + +KaimanStyleValue::KaimanStyleValue(int min, int max, QWidget *parent, const char *name) + : KaimanStyleMasked( parent, name ) +{ + _min = min; + _max = max; + _value = _min; + + setPixmap( 0 ); +} + +KaimanStyleValue::~KaimanStyleValue() +{ +} + +void KaimanStyleValue::setValue( int value ) +{ + if (value>_max) value=_max; + if (value<_min) value=_min; + _value = value; + + int len = _max-_min; + if ( len ) + setPixmap( (_value-_min)*pixmapNum/len ); + else + setPixmap( 0 ); +} + +void KaimanStyleValue::setValue( int value, int min, int max ) +{ + _min = min; + _max = max; + + setValue( value ); +} + + +/***********************************************************************/ + +KaimanStyleNumber::KaimanStyleNumber(QWidget *parent, const char *name) + : KaimanStyleElement( parent, name ) +{ + //kdDebug(66666) << k_funcinfo << "name = '" << name << "'" << endl; + _value = 0; + if (QCString(name) == "In_Rate_Number") + digits = 3; + else + digits = 2; +} + +KaimanStyleNumber::~KaimanStyleNumber() +{ +} + + +void KaimanStyleNumber::loadPixmaps(QString &val_s_filename) +{ + KaimanStyleElement::loadPixmaps( val_s_filename ); + resize( digits*pixmaps[0]->width(),pixmaps[0]->height() ); +} + + +void KaimanStyleNumber::setValue( int value ) +{ + if ( _value!=value ) + { + _value = value; + repaint(); + } +} + +void KaimanStyleNumber::paintEvent(QPaintEvent */*qpe*/) +{ + // check for overflow + int v = _value; + for ( int i=digits; i>0 && v>0; i-- ) + v /= 10; + + if ( v!=0 ) + v = 999999999; // overflow + else + v = _value; + + // draw number + int x = width(); + do { + x -= pixmaps[0]->width(); + bitBlt(this, x, 0, pixmaps[v%10] ); + + v /= 10; + } while ( v>0 ); + + // draw right free space + while ( x>0 ) + { + x -= pixmaps[0]->width(); + bitBlt(this, x, 0, pixmaps[0] ); + } +/* + QPainter p( this ); + p.setBrush( NoBrush ); + p.setPen( QColor(255,255,255) ); + p.drawRect( 0, 0, width(), height() ); + p.drawText( 2, 16, name() );*/ +} + +/***********************************************************************/ + +KaimanStyleText::KaimanStyleText(QWidget *parent, const char *name) + : KaimanStyleElement( parent, name ) +{ + _pos = 0; + _timer = new QTimer( this ); + _delay = 500; + connect( _timer, SIGNAL(timeout()), this, SLOT(timeout()) ); +} + +KaimanStyleText::~KaimanStyleText() +{ +} + + +void KaimanStyleText::loadPixmaps(QString &val_s_filename) +{ + KaimanStyleElement::loadPixmaps( val_s_filename ); + resize( digits*pixmaps[0]->width(), pixmaps[0]->height() ); +} + + +void KaimanStyleText::setValue( QString value ) +{ + if ( value!=_value ) { + _pos = 0; + _direction = 1; + _value = value; + repaint(); + } +} + + +void KaimanStyleText::startAnimation( int delay ) +{ + _pos = 0; + _direction = 1; + _delay = delay; + _timer->start( _delay, TRUE ); +} + + +void KaimanStyleText::stopAnimation() +{ + _pos = 0; + _timer->stop(); +} + + +void KaimanStyleText::timeout() +{ + // reflect + if ( _pos+_direction<0 || (int)_value.length()-(_pos+_direction)<digits ) { + _direction = -_direction; + _timer->start( _delay*5, TRUE ); + } else { + // check new position + if ( _pos+_direction>=0 && (int)_value.length()-(_pos+_direction)>=digits ) { + _pos += _direction; + repaint(); + } + + _timer->start( _delay, TRUE ); + } + + +} + + +void KaimanStyleText::paintEvent(QPaintEvent */*qpe*/) +{ + // draw number + int p; + for (p=0; p<digits && p<(int)_value.length()-_pos; p++ ) + { + int pmNum = _value[p+_pos].latin1() - ' ' ; + if ( pmNum>=96 ) pmNum = '?' - ' '; + if ( pmNum<0 ) pmNum = '?' - ' '; + + QPixmap *pm = pixmaps[pmNum]; + if ( pm ) bitBlt(this, p*pixmaps[0]->width(), 0, pm ); + } + + QPixmap *pm = pixmaps[0]; + for ( ; p<digits; p++ ) + bitBlt(this, p*pixmaps[0]->width(), 0, pm ); + +/* QPainter pnt( this ); + pnt.setBrush( NoBrush ); + pnt.setPen( QColor(255,255,255) ); + pnt.drawRect( 0, 0, width(), height() ); + pnt.drawText( 2, 16, name() );*/ +} + +/***********************************************************************/ + +KaimanStyleAnimation::KaimanStyleAnimation(int delay, QWidget *parent, const char *name) + : KaimanStyleMasked( parent, name ) +{ + _delay = delay; + _frame = 0; + _timer = new QTimer( this ); + connect( _timer, SIGNAL(timeout()), this, SLOT(timeout()) ); +} + +KaimanStyleAnimation::~KaimanStyleAnimation() +{ +} + +void KaimanStyleAnimation::start() +{ + _timer->start( _delay, FALSE ); +} + +void KaimanStyleAnimation::pause() +{ + _timer->stop(); +} + +void KaimanStyleAnimation::stop() +{ + _timer->stop(); + _frame = 0; + setPixmap( _frame ); +} + +void KaimanStyleAnimation::timeout() +{ + _frame++; + if ( _frame>=pixmapNum ) _frame = 1; + setPixmap( _frame ); +} + +/***********************************************************************/ + +KaimanStyleState::KaimanStyleState(QWidget *parent, const char *name) + : KaimanStyleMasked( parent, name ) +{ + _value = 0; +} + +KaimanStyleState::~KaimanStyleState() +{ +} + +void KaimanStyleState::setValue( int value ) +{ + _value = value; + setPixmap( _value ); +} + +void KaimanStyleState::mousePressEvent(QMouseEvent *qme) +{ + emit clicked(); + KaimanStyleMasked::mouseReleaseEvent( qme ); +} + +/***********************************************************************/ + + +KaimanStyle::KaimanStyle( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + i_qw_parent = parent; + i_eventSemaphore = false; +} + + +KaimanStyle::~KaimanStyle() +{ +} + + +int KaimanStyle::parseStyleFile(QString &l_s_tmpName) +{ + int l_i_ret = false; + + QStringList l_s_tokens; + + QFile l_fd(l_s_tmpName); + if ( l_fd.open(IO_ReadOnly) ) { + // file opened successfully + QTextStream l_ts_line( &l_fd ); + QString l_s_textLine, l_s_token; + while ( !l_ts_line.eof() ) { + // Clear list of tokens (we are going to fill them now) + l_s_tokens.clear(); + + // Read a line + l_s_textLine = l_ts_line.readLine(); + l_s_textLine = l_s_textLine.simplifyWhiteSpace(); + + if ( l_s_textLine.left(1) != "#" ) { + // OK, this is not a comment line + if ( l_s_textLine.isNull()) + l_s_textLine = ""; + while ( !l_s_textLine.isEmpty() ) { + l_s_token = getToken(l_s_textLine, ' '); + if ( ! l_s_token.isEmpty() ) { + // OK. There is a useful token. It is not NULL + if ( l_s_token.right(1) == ":" ) + l_s_tokens.append(l_s_token.left(l_s_token.length() -1 )); + else + l_s_tokens.append(l_s_token); + } // -<- if it is a not-empty token + } // -<- while there are tokens available + + interpretTokens(l_s_tokens); + + } // -<- if is not comment line + } // -<- While not EOF on file + + l_i_ret = 0; + } // -<- if file could be opened + + else { + l_i_ret = KaimanStyle::FileNotFound; + } + return l_i_ret; +} + + + +/* + This function gets a list of tokens and inserts a new + KaimanStyleElement in I_styleElem. */ +void KaimanStyle::interpretTokens(QStringList& ref_s_tokens) +{ + if ( ref_s_tokens.count() < 1 ) { + // A list with less than 1 item is useless to us + return; + } + + QString l_s_tokenTypes; + const QString &l_s_elem = ref_s_tokens.first(); + bool l_vertPixmaps = false; + int l_i_pmIndex[KaimanStyleButton::StateListEND]; + for (int i=0; i<KaimanStyleButton::StateListEND; i++) l_i_pmIndex[i]=0; + + enum { UnknownElement, BackgroundElement, MaskElement, ButtonElement, SliderElement, + ValueElement, AnimationElement, StateElement, DigitElement, NumberElement, + TextElement } l_elementType = UnknownElement; + + // Now determine the meaning of the following tokens + // l_s_tokenTypes stores the meaning (e.g. x-Position, filename, ...) + if ( l_s_elem == "Background" ) { + l_s_tokenTypes = "f"; + l_elementType = BackgroundElement; + } + // --- + else if ( l_s_elem == "Mask" ) { + l_s_tokenTypes = "f"; + l_elementType = MaskElement; + } else if ( l_s_elem=="Digit_Small" || l_s_elem=="Digit_Small_Default" ) { + i_smallFont = ref_s_tokens[1]; + return; + } else if ( l_s_elem=="Digit_Large" || l_s_elem=="Digit_Large_Default" ) { + i_largeFont = ref_s_tokens[1]; + return; + } + // --- + else if ( l_s_elem == "Title" || + l_s_elem == "Album" || + l_s_elem == "Artist" || + l_s_elem == "Genre" ) { + // You can have an OPTIONAL argument, so lets see if it is there. + if (ref_s_tokens.count() == 6 ) + l_s_tokenTypes = "fd1xy"; + else + l_s_tokenTypes = "fdxy"; + l_elementType = TextElement; + } + // --- + else if ( l_s_elem == "Play_Button" || + l_s_elem == "Pause_Button" || + l_s_elem == "Stop_Button" || + l_s_elem == "Shuffle_Button" || + l_s_elem == "Repeat_Button" ) { + l_s_tokenTypes = "fPSxy"; + l_i_pmIndex[KaimanStyleButton::NormalUp] = 0; + l_i_pmIndex[KaimanStyleButton::NormalDown] = 1; + l_i_pmIndex[KaimanStyleButton::LitUp] = 2; + l_i_pmIndex[KaimanStyleButton::LitDown] = 3; + l_i_pmIndex[KaimanStyleButton::PrelightUp] = 4; + l_i_pmIndex[KaimanStyleButton::PrelightLitUp] = 5; + l_elementType = ButtonElement; + } + // --- + else if ( l_s_elem == "Next_Button" || + l_s_elem == "Prev_Button" || + l_s_elem == "FF" || + l_s_elem == "RW" || + l_s_elem == "Playlist_Button" || + l_s_elem == "Config_Button" || + l_s_elem == "Iconify_Button" || + l_s_elem == "Mixer_Button" || + l_s_elem == "Exit_Button" || + l_s_elem == "Alt_Skin_Button" || + l_s_elem == "Volume_Up_Button" || + l_s_elem == "Volume_Down_Button" || + l_s_elem == "Balance_Left_Button" || + l_s_elem == "Balance_Right_Button" ) { + l_i_pmIndex[KaimanStyleButton::NormalUp] = 0; + l_i_pmIndex[KaimanStyleButton::NormalDown] = 1; + l_i_pmIndex[KaimanStyleButton::PrelightUp] = 2; + l_s_tokenTypes = "fPxy"; + l_elementType = ButtonElement; + } + // --- + else if ( l_s_elem == "Stereo_Item" || + l_s_elem == "Shuffle_Item" || + l_s_elem == "Repeat_Item" || + l_s_elem == "Mpegversion_Item" || + l_s_elem == "Mpeglayer_Item" || + l_s_elem == "Mpegmode_Item" || + l_s_elem == "Status_Item" ) { + l_s_tokenTypes = "Vfxy"; + l_elementType = StateElement; + } + // --- + else if ( l_s_elem == "Hour_Number" || + l_s_elem == "Minute_Number" || + l_s_elem == "Second_Number" || + l_s_elem == "Song_Number" || + l_s_elem == "Total_Number" || + l_s_elem == "In_Rate_Number" || + l_s_elem == "In_Hz_Number" || + l_s_elem == "Out_Bits" || + l_s_elem == "Out_Hz" || + l_s_elem == "Song_Minute" || + l_s_elem == "Song_Second" || + l_s_elem == "Frame" || + l_s_elem == "Frame_Total" || + l_s_elem == "CPU_Number" || + l_s_elem == "Hour_Total" || + l_s_elem == "Minute_Total" || + l_s_elem == "Second_Total_Number" ) { + // You can have an OPTIONAL argument, so lets see if it is there. + if (ref_s_tokens.count() == 6 ) + l_s_tokenTypes = "fd1xy"; + else if (ref_s_tokens.count() == 5 ) + l_s_tokenTypes = "fdxy"; + else + l_s_tokenTypes = "fxy"; + + l_elementType = NumberElement; + } + // --- + else if ( l_s_elem == "Position_Item" || + l_s_elem == "Volume_Item" || + l_s_elem == "Balance_Item" ) { + l_s_tokenTypes = "Vflxy"; + l_elementType = ValueElement; + } + // --- + else if ( l_s_elem == "Load_Item" ) { + l_s_tokenTypes = "Vflxy"; + l_elementType = AnimationElement; + } + // --- + else if ( l_s_elem == "Position_Slider" || + l_s_elem == "Volume_Slider" || + l_s_elem == "Balance_Slider" ) { + + if ( ref_s_tokens.count()==10 ) + l_s_tokenTypes = "VfP12wxyh"; + else + l_s_tokenTypes = "VfP12sxy"; + l_elementType = SliderElement; + } + else { + kdDebug() << l_s_elem << " not handled yet." << endl; + l_s_tokenTypes = "f"; + } + + /* The above lines decode the meanings of the tokens. The rules for + this are the SKIN-SPECS. So the decoder implements a syntactic + analyser (parser). + + I now do know the type of each tokens, whether it represents a + filename, the prelight parameter, the x position or what else. This + information resides in l_s_tokenTypes, and will help in creating + the kaiman style elements. + + I will now do two things: + 1) Create a new KaimanStyle*, that is inserted into I_styleElem. + 2) Fill the KaimanStyleElement structure, by interpreting the tokens. + */ + QStringList::Iterator li_s_tokens = ref_s_tokens.begin(); + ++ li_s_tokens; // Skip the name of the element + + // 1) Create a new KaimanStyleElement, that is inserted into I_styleElem. + KaimanStyleElement *l_kse_elem = 0; + KaimanStyleButton *but = 0; + + switch ( l_elementType ) + { + case BackgroundElement: + l_kse_elem = new KaimanStyleBackground(this, l_s_elem.latin1()); + l_kse_elem->show(); + break; + + case MaskElement: + l_kse_elem = new KaimanStyleElement(this, l_s_elem.latin1()); + l_kse_elem->hide(); + break; + + case ButtonElement: + l_kse_elem = new KaimanStyleButton(this, l_s_elem.latin1()); + but = static_cast<KaimanStyleButton*>(l_kse_elem); + l_kse_elem->show(); + break; + + case SliderElement: + l_kse_elem = new KaimanStyleSlider(0, 100, this, l_s_elem.latin1()); + i_sliders.append(l_kse_elem); + l_kse_elem->show(); + break; + + case ValueElement: + l_kse_elem = new KaimanStyleValue(0, 100, this, l_s_elem.latin1()); + break; + + case AnimationElement: + l_kse_elem = new KaimanStyleAnimation(30, this, l_s_elem.latin1()); + break; + + case StateElement: + l_kse_elem = new KaimanStyleState(this, l_s_elem.latin1()); + break; + + case NumberElement: + l_kse_elem = new KaimanStyleNumber(this, l_s_elem.latin1()); + break; + + case TextElement: + l_kse_elem = new KaimanStyleText(this, l_s_elem.latin1()); + break; + + default: + break; + } + + if ( !l_kse_elem ) + { + kdDebug() << "Ignoring style element " << l_s_elem << endl; + return; + } + + // insert element into element list + uint l_i_size = I_styleElem.size(); + I_styleElem.resize(l_i_size + 1); + I_styleElem.insert(l_i_size, l_kse_elem); + l_kse_elem->installEventFilter( this ); + + // initialize element parameters + l_kse_elem->element = l_s_elem; + + if ( l_s_tokenTypes.left(1) == "V" ) { + // Vertical flag + l_vertPixmaps = true; + l_s_tokenTypes = l_s_tokenTypes.mid(1); + } + + // initialize button parameters + if ( but ) + { + for (int i=0; i<KaimanStyleButton::StateListEND; i++) + but->I_pmIndex.insert(i, new int(l_i_pmIndex[i]) ); + } + + // 2) Fill the KaimanStyleElement structure, by interpreting the tokens. + while ( l_s_tokenTypes.length() != 0 ) { + /* The skindata format allows omitting arguments if the parser + can reconstruct without problems what you mean. This is taken + into account when writing the l_s_tokenTypes sting. + + Unfortunately, several skins do ship with a broken skindata file. + Most common problem is that width and height is also given. + + Even worse examples leave out specified parametes and add others. + For instance, the pause line is specified as "fPSxy". But in k9 + + + the line looks like + + Pause_Button: pause.jpg FALSE 91 148 116 173 + + So the actual parameters are fPxywh. The parser has to be pretty + smart now. It should "see" that S (status light) is not present, + since that should be either TRUE or FALSE, and distribute the + others accordingly. */ + + bool skipOne; + + do { + skipOne = false; + + // Take the first item from the l_s_tokenTypes; + char l_c_type = (l_s_tokenTypes[0]).latin1(); + l_s_tokenTypes = l_s_tokenTypes.mid(1); + QString l_s_token = *li_s_tokens; + switch(l_c_type) { + case 'f': + // filename + l_kse_elem->filename = l_s_token; + break; + case 'P': + // Prelight + if ( l_s_token.upper() == "TRUE" ) + l_kse_elem->optionPrelight = true; + else + { + l_kse_elem->optionPrelight = false; + + // was that token really there? + skipOne = ( l_s_token.upper() != "FALSE" ); + } + break; + case 'S': + // Statuslight + if ( l_s_token.upper() == "TRUE" ) + l_kse_elem->optionStatuslight = true; + else + { + l_kse_elem->optionStatuslight = false; + + // was that token really there? + skipOne = ( l_s_token.upper() != "FALSE" ); + } + break; + case '1': + // parameter 1 + if ( l_s_token.upper() == "TRUE" ) + l_kse_elem->options[0] = true; + else + { + l_kse_elem->options[0] = false; + + // was that token really there? + skipOne = ( l_s_token.upper() != "FALSE" ); + } + break; + case '2': + // parameter 2 + if ( l_s_token.upper() == "TRUE" ) + l_kse_elem->options[1] = true; + else + { + l_kse_elem->options[1] = false; + + // was that token really there? + skipOne = ( l_s_token.upper() != "FALSE" ); + } + break; + case '3': + // parameter 3 + if ( l_s_token.upper() == "TRUE" ) + l_kse_elem->options[2] = true; + else + { + l_kse_elem->options[2] = false; + + // was that token really there? + skipOne = ( l_s_token.upper() != "FALSE" ); + } + break; + case 'l': + // length + if ( l_vertPixmaps ) + l_kse_elem->pixmapLines = l_s_token.toInt(); + else + l_kse_elem->pixmapColumns = l_s_token.toInt(); + break; + case 'x': + // x Position + l_kse_elem->upperLeft.setX(l_s_token.toInt()); + break; + case 'y': + // y Position + l_kse_elem->upperLeft.setY(l_s_token.toInt()); + break; + case 's': + // dimension + if ( l_kse_elem->options[KaimanStyleSlider::optionVertical] ) + l_kse_elem->dimension.setHeight(l_s_token.toInt()); + else + l_kse_elem->dimension.setWidth(l_s_token.toInt()); + break; + case 'w': + // width + l_kse_elem->dimension.setWidth(l_s_token.toInt()); + break; + case 'h': + // height + l_kse_elem->dimension.setHeight(l_s_token.toInt()); + break; + case 'd': + // number of digits + l_kse_elem->digits = l_s_token.toInt(); + break; + + default: + kdDebug() << "Element type '" << l_c_type << "' unknown" << endl; + } + + if(skipOne) { + kdDebug() << "Skipped one element '" << l_c_type << "'" << endl; + } + } while(skipOne && l_s_tokenTypes.length() != 0); + + // Next token. + ++li_s_tokens; + if (li_s_tokens == ref_s_tokens.end() ) { + // End of token list + break; + } + } + + /* Do some post-processing */ + + if( l_elementType==ButtonElement ) { + // <Normal button> + if(but->optionPrelight) { + // --- Has Prelight --- + if(but->optionStatuslight) + but->pixmapColumns = 6; + else { + but->pixmapColumns = 3; + but->I_pmIndex.insert( KaimanStyleButton::LitUp, + new int( *(but->I_pmIndex[KaimanStyleButton::NormalUp]))); + but->I_pmIndex.insert( KaimanStyleButton::LitDown, + new int( *(but->I_pmIndex[KaimanStyleButton::NormalDown]))); + } + } else { + // --- Has No Prelight --- + but->I_pmIndex.insert( KaimanStyleButton::PrelightUp, + new int( *(but->I_pmIndex[KaimanStyleButton::NormalUp]))); + but->I_pmIndex.insert( KaimanStyleButton::PrelightLitUp, + new int( *(but->I_pmIndex[KaimanStyleButton::LitUp]))); + if(l_kse_elem->optionStatuslight) + but->pixmapColumns = 4; + else { + but->pixmapColumns = 2; + but->I_pmIndex.insert( KaimanStyleButton::LitUp, + new int( *(but->I_pmIndex[KaimanStyleButton::NormalUp]))); + but->I_pmIndex.insert( KaimanStyleButton::LitDown, + new int( *(but->I_pmIndex[KaimanStyleButton::NormalDown]))); + but->I_pmIndex.insert( KaimanStyleButton::PrelightLitUp, + new int( *(but->I_pmIndex[KaimanStyleButton::NormalUp]))); + } + } + } else if( l_elementType==NumberElement ) { + // number items + l_kse_elem->pixmapColumns = 11; + if ( l_kse_elem->filename=="Small" ) l_kse_elem->filename = i_smallFont; + else if ( l_kse_elem->filename=="Large" ) l_kse_elem->filename = i_largeFont; + } else if( l_elementType==SliderElement ) { + // slider items + if ( l_kse_elem->options[KaimanStyleSlider::optionVertical] ) + l_kse_elem->pixmapLines = l_kse_elem->optionPrelight ? 4 : 3; + else + l_kse_elem->pixmapColumns = l_kse_elem->optionPrelight ? 4 : 3; + } else if( l_elementType==TextElement ) { + // text items + l_kse_elem->pixmapColumns = 32; + l_kse_elem->pixmapLines = l_kse_elem->options[KaimanStyleText::optionExtended] ? 6 : 3; + } else { + // <Not standard element> + if(l_s_elem == "Stereo_Item") + l_kse_elem->pixmapLines = 3; + else if(l_s_elem == "Shuffle_Item") + l_kse_elem->pixmapLines = 2; + else if(l_s_elem == "Repeat_Item") + l_kse_elem->pixmapLines = 2; + else if(l_s_elem == "Mpegversion_Item") + l_kse_elem->pixmapLines = 3; + else if(l_s_elem == "Mpegversion_Item") + l_kse_elem->pixmapLines = 4; + else if(l_s_elem == "Mpegmode_Item") + l_kse_elem->pixmapLines = 5; + else if(l_s_elem == "Status_Item") + l_kse_elem->pixmapLines = 3; + } // </Not normal button> +} + + +QString KaimanStyle::getToken(QString &val_s_string, char val_c_separator) +{ + int l_i_pos; + QString l_s_token; + + // Find the first occurrence of the separator + l_i_pos = val_s_string.find(val_c_separator, 0, false); + if ( l_i_pos == -1 ) { + // No sparator! Then the whole string is the token + l_s_token = val_s_string; + val_s_string = ""; + } + else { + // Separator found: Split the string at the separator position + l_s_token = val_s_string.left(l_i_pos); + val_s_string.remove(0,l_i_pos); + } + val_s_string = val_s_string.simplifyWhiteSpace(); + + // Return the first token + return l_s_token; +} + + + +bool KaimanStyle::loadStyle(const QString &styleName, const QString &descFile) +{ + bool l_b_ret = true; + int l_i_ret = 0; + QString l_s_tmpName; + + i_skinName = styleName; + this->i_s_styleName = styleName; + i_s_styleBase = QString("skins/kaiman/") + i_s_styleName + QString("/"); + + l_s_tmpName = locate("appdata", i_s_styleBase + descFile ); + if ( l_s_tmpName.isNull() ) { + l_b_ret = false; + } + + if ( l_b_ret) { + // Skin description found. Now parse StyleFile. + l_i_ret = parseStyleFile(l_s_tmpName); + if (l_i_ret == 0) { + // If parsiing OK, load the referenced pixmaps + l_b_ret = loadPixmaps(); + + kdDebug(66666) << "Found " << I_styleElem.count() << " elements." << endl; + } + else { + if ( l_i_ret == KaimanStyle::FileNotFound ) { + // File not found + KMessageBox::error( 0, i18n("Cannot load style. Style not installed.") ); + } + else { + // Parsing not OK: Notify user + KMessageBox::error( 0, i18n("Cannot load style. Unsupported or faulty style description.") ); + } + } + } + + return l_b_ret; +} + +bool KaimanStyle::eventFilter( QObject *o, QEvent *e ) +{ + /* HACK! HACK! HACK! */ + if ( !i_eventSemaphore ) + if ( e->type()==QEvent::MouseMove || e->type()==QEvent::MouseButtonPress || + e->type()==QEvent::MouseButtonRelease ) + { + QMouseEvent *m = (QMouseEvent*)e; + + // handle noatun context menu + if (m->button()==RightButton) { + NoatunStdAction::ContextMenu::showContextMenu(); + return true; + } + + QPoint mousePos( m->x()+static_cast<QWidget *>(o)->x(), + m->y()+static_cast<QWidget *>(o)->y() ); + QWidget *slider = 0; + + /* find slider that is under the mouse position */ + for ( QWidget *s = i_sliders.first(); s!=0; s=i_sliders.next() ) + { + QRect sliderRect( s->pos(), s->size() ); + if ( sliderRect.contains(mousePos) ) slider = s; + } + + /* the slider the mouse events instead of the visible widget */ + if ( slider ) + { + QMouseEvent newMouseEvent( m->type(), mousePos-slider->pos(), + m->globalPos(), m->button(), m->state() ); + + i_eventSemaphore = true; + bool ret = QApplication::sendEvent( slider, &newMouseEvent ); + i_eventSemaphore = false; + return ret; + } + } + + return QWidget::eventFilter( o, e ); // standard event processing +} + +bool KaimanStyle::loadPixmaps() +{ + QString l_s_tmpName; + QPixmap *l_pixmap_Background = 0, *l_pixmap_Mask = 0; + KaimanStyleElement *l_kse_elem; + + for ( uint l_i_elem = 0; l_i_elem<I_styleElem.count(); l_i_elem++) { + l_kse_elem = I_styleElem[l_i_elem]; + + l_s_tmpName = locate("appdata", i_s_styleBase + l_kse_elem->filename ); + l_kse_elem->loadPixmaps(l_s_tmpName); + } + + l_kse_elem = this->find("Background"); + if ( l_kse_elem != 0 ) { + l_pixmap_Background = l_kse_elem->pixmaps[0]; + } + l_kse_elem = this->find("Mask"); + if ( l_kse_elem != 0 ) { + l_pixmap_Mask = l_kse_elem->pixmaps[0]; + } + + if ( (l_pixmap_Background != 0) && (l_pixmap_Mask != 0) ) { + + // OK, background and mask are defined. So now I can calculate the shape + int l_i_width_Mask = l_pixmap_Mask->width(); + int l_i_height_Mask = l_pixmap_Mask->height(); + + QImage l_image_MaskOrig = l_pixmap_Mask->convertToImage(); + + QImage l_image_Mask(l_i_width_Mask,l_i_height_Mask, 1, 2, QImage::LittleEndian); + l_image_Mask.setColor( 0, 0x00ffffff ); + l_image_Mask.setColor( 1, 0 ); + l_image_Mask.fill( 0xff ); + + uchar *l_c_pixel; + uint l_qcol_white = qRgb(255,255,255); + + for (int l_i_x=0; l_i_x<l_i_width_Mask; l_i_x++) { + for (int l_i_y=0; l_i_y < l_i_height_Mask; l_i_y++) { + if ( ((*((QRgb*) l_image_MaskOrig.scanLine(l_i_y)+l_i_x) & 0x00ffffff)) != (l_qcol_white & 0x00ffffff) ) { + l_c_pixel = (uchar *)l_image_Mask.scanLine(l_i_y); + *(l_c_pixel + (l_i_x>>3) ) &= ~(1 << (l_i_x & 7)); + } + } + } + + i_bitmap_Mask.convertFromImage(l_image_Mask); + // l_pixmap_Background.setMask(i_bitmap_Mask); + } + + return true; +} + + +QBitmap* KaimanStyle::Mask() +{ + return &i_bitmap_Mask; +} + +KaimanStyleElement* KaimanStyle::find(const char *val_s_elemName) +{ + for (uint i=0; i< I_styleElem.count(); i++) { + if ( I_styleElem[i]->element == QString(val_s_elemName)) { + return I_styleElem[i]; + } + } + return 0; +} +#include "style.moc" diff --git a/noatun/modules/kaiman/style.h b/noatun/modules/kaiman/style.h new file mode 100644 index 00000000..0c1a6d81 --- /dev/null +++ b/noatun/modules/kaiman/style.h @@ -0,0 +1,356 @@ +// -*- C++ -*- +/* + Copyright (c) 2000 Stefan Schimanski (1Stein@gmx.de) + 1999-2000 Christian Esken (esken@kde.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef KaimanStyle_H +#define KaimanStyle_H + +#include <qstring.h> +#include <qwidget.h> +#include <qpixmap.h> +#include <qbitmap.h> +#include <qimage.h> +#include <qevent.h> +#include <qptrvector.h> + +class KaimanStyleElement : public QWidget +{ + Q_OBJECT +public: + KaimanStyleElement(QWidget *parent, const char *name=0); + ~KaimanStyleElement(); + + virtual void loadPixmaps(QString &val_s_filename); + + QString element; + QString filename; + QPoint upperLeft; + QSize dimension; + + bool options[3]; + int digits; + + bool optionPrelight; + bool optionStatuslight; + + int pixmapLines; + int pixmapColumns; + + QPtrVector<QPixmap> pixmaps; + +public slots: + void setPixmap( int num ); + +protected: + void paintEvent(QPaintEvent *qpe); + void dropEvent( QDropEvent *event ); + void dragEnterEvent( QDragEnterEvent *event ); + + int pixmapNum; + +private: + int _currentPixmap; +}; + + +class KaimanStyleMasked : public KaimanStyleElement +{ + Q_OBJECT +public: + KaimanStyleMasked(QWidget *parent, const char *name=0) + : KaimanStyleElement( parent, name ) {}; + + virtual void loadPixmaps(QString &val_s_filename) + { + KaimanStyleElement::loadPixmaps( val_s_filename ); + if(pixmaps[0]->mask()) + setMask(*pixmaps[0]->mask()); + }; +}; + + +class KaimanStyleButton : public KaimanStyleMasked +{ + Q_OBJECT +public: + KaimanStyleButton(QWidget *parent, const char *name=0); + ~KaimanStyleButton(); + + // Button states. + enum { NormalUp=0, NormalDown, LitUp, LitDown, PrelightUp, PrelightLitUp, StateListEND }; + + QPtrVector<int> I_pmIndex; + + void setLit(bool); + void setPrelight(bool); + void setDown(bool); + bool lit(); + bool prelit(); + bool down(); + void updateButtonState(); + +signals: + void clicked(); + +protected: + void mousePressEvent(QMouseEvent *qme); + void mouseReleaseEvent(QMouseEvent *qme); + void enterEvent(QEvent * ); + void leaveEvent ( QEvent * ); + +private: + int i_i_currentState; + bool i_b_lit; + bool i_b_prelit; + bool i_b_down; +}; + + +class KaimanStyleSlider : public KaimanStyleMasked +{ + Q_OBJECT +public: + KaimanStyleSlider(int min, int max, QWidget *parent, const char *name=0); + ~KaimanStyleSlider(); + + int value() { return _value; }; + + static const bool optionVertical; + static const bool optionReversed; + +public slots: + void setValue( int value ); + void setValue( int value, int min, int max ); + +signals: + void newValue( int value ); + void newValueDrag( int value ); + void newValueDrop( int value ); + +protected: + void mouseMoveEvent(QMouseEvent *qme); + void mousePressEvent(QMouseEvent *qme); + void mouseReleaseEvent(QMouseEvent *qme); + void paintEvent(QPaintEvent *qpe); + void enterEvent(QEvent * ); + void leaveEvent ( QEvent * ); + + int pos2value( int x, int y ); + + bool _down; + bool _lit; + int _value; + int _min, _max; +}; + + +class KaimanStyleBackground : public KaimanStyleMasked +{ + Q_OBJECT +public: + KaimanStyleBackground(QWidget *parent, const char *name=0); + ~KaimanStyleBackground(); + +protected: + void mousePressEvent(QMouseEvent *qme); + void mouseReleaseEvent(QMouseEvent *qme); + void mouseMoveEvent(QMouseEvent *qme); + +private: + bool i_b_move; + QPoint i_point_dragStart; + QPoint i_point_lastPos; +}; + + +class KaimanStyleValue : public KaimanStyleMasked +{ + Q_OBJECT +public: + KaimanStyleValue(int min, int max, QWidget *parent, const char *name=0); + ~KaimanStyleValue(); + + int value() { return _value; }; + +public slots: + void setValue( int value ); + void setValue( int value, int min, int max ); + +private: + int _min, _max, _value; +}; + + +class KaimanStyleState : public KaimanStyleMasked +{ + Q_OBJECT +public: + KaimanStyleState(QWidget *parent, const char *name=0); + ~KaimanStyleState(); + + int value() { return _value; }; + +public slots: + void setValue( int value ); + +signals: + void clicked(); + +protected: + void mousePressEvent(QMouseEvent *qme); + +private: + int _value; +}; + + +class KaimanStyleNumber : public KaimanStyleElement +{ + Q_OBJECT +public: + KaimanStyleNumber(QWidget *parent, const char *name=0); + ~KaimanStyleNumber(); + + virtual void loadPixmaps(QString &val_s_filename); + + static const bool optionCentered = 1; + + int value() { return _value; }; + +public slots: + void setValue( int value ); + +protected: + void paintEvent(QPaintEvent *qpe); + +private: + int _value; +}; + + +class KaimanStyleText : public KaimanStyleElement +{ + Q_OBJECT +public: + KaimanStyleText(QWidget *parent, const char *name=0); + ~KaimanStyleText(); + + virtual void loadPixmaps(QString &val_s_filename); + + static const bool optionExtended; + + QString value() { return _value; }; + + void startAnimation( int delay ); + void stopAnimation(); + +public slots: + void setValue( QString value ); + +protected: + void paintEvent(QPaintEvent *qpe); + +protected slots: + void timeout(); + +private: + QString _value; + int _pos; + int _direction; + int _delay; + QTimer *_timer; +}; + + +class KaimanStyleAnimation : public KaimanStyleMasked +{ + Q_OBJECT +public: + KaimanStyleAnimation(int delay, QWidget *parent, const char *name=0); + ~KaimanStyleAnimation(); + +public slots: + void start(); + void pause(); + void stop(); + +protected: + void timeout(); + +private: + int _delay,_frame; + QTimer *_timer; +}; + +class KaimanStyle : public QWidget +{ + Q_OBJECT +public: + KaimanStyle(QWidget *parent, const char *name=0); + ~KaimanStyle(); + + enum { background, mask, play_Button, stop_Button, pause_Button, prev_Button, next_Button, repeat_Button, shuffle_Button, playlist_Button, mixer_Button, exit_Button, Iconify_Button, Config_Button, Alt_Skin_Button, Minute_Number, Second_Number, in_Rate_Number, in_Hz_Number, song_Number, status_Item, cPU_Number, digit_Large, digit_Small_Default, title, volume_Item, volume_Slider, position_Item, position_Slider }; + + enum { ParsingError=1, FileNotFound }; + + /// Finds a style element, according to it's name. Returns 0 when element is not available. + KaimanStyleElement* find(const char* val_s_elemName); + + /// Tries to load the given style and returns success (true) or failure (false) + bool loadStyle(const QString &styleName, const QString &descFile="skindata" ); + QString skinName() { return i_skinName; }; + + /// Returns the mask + QBitmap* Mask(); + + virtual bool eventFilter( QObject *o, QEvent *e ); + +private: + // Parses the "skindata" file and returns success (true) or failure (false) + int parseStyleFile(QString &l_s_tmpName); + QString getToken(QString &val_s_string, char val_c_separator); + void interpretTokens(QStringList& ref_s_tokens); + bool loadPixmaps(); + + /// The name of the style, e.g. "k9" + QString i_s_styleName; + /// The base directory, where the style is found. For example + /// "/opt/kde/share/apps/kaiman/Skins/k9/" or "/opt/kde/share/apps/kaiman/Skins/k9.tgz" + QString i_s_styleBase; + + + // The mask of the complete style. Used for doing shaped windows + QBitmap i_bitmap_Mask; + + /// All style elements are stored here. + QPtrVector<KaimanStyleElement> I_styleElem; + + // The parent window. In other words: The container that holds all the KaimanStyleElement's + QWidget* i_qw_parent; + + QPtrList<QWidget> i_sliders; + bool i_eventSemaphore; + + QString i_smallFont; + QString i_largeFont; + QString i_skinName; +}; + + +#endif diff --git a/noatun/modules/kaiman/userinterface.cpp b/noatun/modules/kaiman/userinterface.cpp new file mode 100644 index 00000000..31db0e09 --- /dev/null +++ b/noatun/modules/kaiman/userinterface.cpp @@ -0,0 +1,562 @@ +/* + Copyright (c) 2000 Stefan Schimanski <1Stein@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + aint with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <unistd.h> + +#include <noatun/effects.h> +#include <noatun/app.h> +#include <noatun/player.h> +#include <noatun/pref.h> +#include "userinterface.h" +#include "pref.h" + +#include <qcursor.h> +#include <qpixmap.h> +#include <qbitmap.h> +#include <qimage.h> +#include <qdropsite.h> +#include <qdragobject.h> +#include <qtimer.h> + +#include <kfiledialog.h> +#include <kdebug.h> +#include <kapplication.h> +#include <kwin.h> +#include <kglobal.h> +#include <klocale.h> +#include <kconfig.h> +#include <kpopupmenu.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> +#include <kio/netaccess.h> +#include <kurldrag.h> + +#include <sys/types.h> +#include <sys/wait.h> +#include <errno.h> + +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/extensions/shape.h> + +Kaiman* Kaiman::kaiman=0; +const char Kaiman::DEFAULT_SKIN[]="car-preset"; + +Kaiman::Kaiman() + : KMainWindow(0, "NoatunKaiman"), UserInterface() +{ + NOATUNPLUGINC(Kaiman); + kaiman=this; + + //setCaption( i18n("Kaiman") ); + KWin::setType( this->winId(), NET::Override ); + setBackgroundMode( NoBackground ); + setAcceptDrops(true); + + _style = 0; + _seeking = false; + _altSkin = false; + + // init config + KConfig *config=KGlobal::config(); + config->setGroup("Kaiman"); + + // load skin + QString skinName = config->readEntry( "SkinResource", DEFAULT_SKIN ); + + if ( !changeStyle(skinName, "skindata") ) + { + KMessageBox::sorry( this, i18n("Cannot load skin %1. Switching to default skin.").arg(skinName) ); + if ( !changeStyle( DEFAULT_SKIN, "skindata" ) ) + { + KMessageBox::error( this, i18n("Cannot load default skin %1.").arg(DEFAULT_SKIN) ); + QTimer::singleShot( 0, this, SLOT(close()) ); + return; + } + } + + // global connects + connect( napp, SIGNAL(hideYourself()), this, SLOT(hide()) ); + connect( napp, SIGNAL(showYourself()), this, SLOT(show()) ); + + connect( napp->player(), SIGNAL(playing()), this, SLOT(updateMode())); + connect( napp->player(), SIGNAL(stopped()), this, SLOT(updateMode())); + connect( napp->player(), SIGNAL(paused()), this, SLOT(updateMode())); + connect( napp->player(), SIGNAL(timeout()), this, SLOT(timeout())); + connect( napp->player(), SIGNAL(loopTypeChange(int)), this, SLOT(loopTypeChange(int))); + connect( napp->player(), SIGNAL(newSongLen(int,int)), this, SLOT(newSongLen(int,int))); + connect( napp->player(), SIGNAL(newSong()), this, SLOT(newSong())); + + if( napp->player()->isPlaying() ) + newSong(); + + new KaimanPrefDlg(this); + + show(); +} + + +Kaiman::~Kaiman() +{ +} + + +bool Kaiman::changeStyle( const QString &style, const QString &desc ) +{ + QString ldesc = desc; + if ( ldesc.isEmpty() ) + ldesc = _altSkin ? "alt_skindata" : "skindata"; + + bool vis = isVisible(); + if ( vis ) + hide(); + + bool ret = loadStyle( style, ldesc ); + + newSongLen(0,0); + timeout(); + loopTypeChange(0); + updateMode(); + + if ( vis ) + show(); + return ret; +} + + +bool Kaiman::loadStyle( const QString &style, const QString &desc ) +{ + if ( _style ) delete _style; + _style = new KaimanStyle(this); + if ( !_style->loadStyle( style, desc ) ) + { + delete _style; + _style = 0; + return false; + } + + if ( _style->Mask() != 0 ) + { + // Set the shaped window form + XShapeCombineMask( qt_xdisplay(), winId(), ShapeBounding, 0,0, + _style->Mask()->handle(), ShapeSet ); + } + + KaimanStyleElement* item = _style->find("Background"); + setBackgroundMode(QWidget::NoBackground); + if ( item!=0 ) + { + _style->resize( item->width(), item->height()); + resize( item->width(), item->height()); + setFixedSize( item->width(), item->height()); + } + + item = _style->find("Playlist_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), napp->player(), SLOT(toggleListView()) ); + + item = _style->find("Play_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), napp->player(), SLOT(playpause()) ); + + item = _style->find("Pause_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), napp->player(), SLOT(playpause()) ); + + item = _style->find("Stop_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), napp->player(), SLOT(stop()) ); + + item = _style->find("Next_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), napp->player(), SLOT(forward()) ); + + item = _style->find("Prev_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), napp->player(), SLOT(back()) ); + + item = _style->find("Exit_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), this, SLOT(close()) ); + + item = _style->find("Mixer_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), this, SLOT(execMixer()) ); + + item = _style->find("Iconify_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), this, SLOT(showMinimized()) ); + + item = _style->find("Alt_Skin_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), this, SLOT(toggleSkin()) ); + + item = _style->find("Repeat_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), this, SLOT(toggleLoop()) ); + + item = _style->find("Shuffle_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), this, SLOT(toggleShuffle()) ); + + item = _style->find("Config_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), napp, SLOT(preferences()) ); + + item = _style->find("Volume_Up_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), this,SLOT(volumeUp())); + + item = _style->find("Volume_Down_Button"); + if( item!=0 ) connect( item, SIGNAL(clicked()), this,SLOT(volumeDown())); + + KaimanStyleSlider* slider = + static_cast<KaimanStyleSlider*>(_style->find("Position_Slider")); + if( slider!=0 ) + { + connect( slider, SIGNAL(newValueDrag(int)), this, SLOT(seekStart(int)) ); + connect( slider, SIGNAL(newValue(int)), this, SLOT(seekDrag(int)) ); + connect( slider, SIGNAL(newValueDrop(int)), this, SLOT(seekStop(int)) ); + slider->setValue( 0, 0, 1000 ); + } + + slider = static_cast<KaimanStyleSlider*>(_style->find("Volume_Slider")); + if ( slider!=0 ) + { + connect(slider, SIGNAL(newValue(int)), this, SLOT(setVolume(int))); + slider->setValue( napp->player()->volume(), 0, 100 ); + } + + KaimanStyleValue* volItem = static_cast<KaimanStyleValue*>(_style->find("Volume_Item")); + if ( volItem ) + volItem->setValue( napp->player()->volume(), 0, 100 ); + + KaimanStyleText* titleItem = static_cast<KaimanStyleText*>(_style->find("Title")); + if ( titleItem ) + titleItem->startAnimation( 300 ); + + return true; +} + + +void Kaiman::closeEvent(QCloseEvent*) +{ + unload(); +} + + +void Kaiman::dragEnterEvent( QDragEnterEvent *event ) +{ + event->accept( KURLDrag::canDecode(event) ); +} + + +void Kaiman::dropEvent( QDropEvent *event ) +{ + doDropEvent(event); +} + + +void Kaiman::doDropEvent(QDropEvent *event) +{ + KURL::List uri; + if (KURLDrag::decode(event, uri)) + { + for (KURL::List::Iterator i = uri.begin(); i != uri.end(); ++i) + napp->player()->openFile(*i, false); + } +} + + +void Kaiman::seekStart( int ) +{ + _seeking = true; +} + + +void Kaiman::seekDrag( int value ) +{ + int length = napp->player()->getLength()/1000; + if ( length < 0) + length = 0; + + if ( !_style ) return; + + KaimanStyleValue* posItem = + static_cast<KaimanStyleValue*>(_style->find("Position_Item")); + if ( posItem ) + posItem->setValue( value, 0, length ); + + KaimanStyleSlider* posSlider = + static_cast<KaimanStyleSlider*>(_style->find("Position_Slider")); + if ( posSlider ) + posSlider->setValue( value, 0, length ); + + // update time + + KaimanStyleNumber* numItem = + static_cast<KaimanStyleNumber*>(_style->find("Minute_Number")); + if ( numItem ) + numItem->setValue( value/60%60 ); + + numItem = static_cast<KaimanStyleNumber*>(_style->find("Second_Number")); + if ( numItem ) + numItem->setValue( value % 60 ); +} + + +void Kaiman::seekStop( int value ) +{ + seek( value ); + _seeking = false; +} + + +void Kaiman::seek( int value ) +{ + napp->player()->skipTo( value*1000 ); // skipTo() takes milliseconds +} + + +void Kaiman::toggleSkin() +{ + _altSkin = !_altSkin; + + QString skinName = _style->skinName(); + + QString oldDesc, newDesc; + if ( _altSkin ) + { + oldDesc = QString::fromLatin1("skindata"); + newDesc = QString::fromLatin1("alt_skindata"); + } + else + { + newDesc = QString::fromLatin1("skindata"); + oldDesc = QString::fromLatin1("alt_skindata"); + } + + if ( !changeStyle(skinName, newDesc) ) + changeStyle(skinName, oldDesc); +} + + +void Kaiman::setVolume( int vol ) +{ + if ( vol<0 ) vol=0; + if ( vol>=100 ) vol=100; + + napp->player()->setVolume( vol ); +} + + +void Kaiman::volumeUp() +{ + setVolume( napp->player()->volume()+10 ); +} + + +void Kaiman::volumeDown() +{ + setVolume( napp->player()->volume()-10 ); +} + + +void Kaiman::execMixer() +{ + kapp->startServiceByDesktopName ( QString::fromLatin1("kmix"), QString::null ); +} + + +void Kaiman::timeout() +{ + if ( !_style ) return; + + if (!napp->player()->current()) + return; + + // update volume + KaimanStyleSlider* l_elem_volslider = static_cast<KaimanStyleSlider*>(_style->find("Volume_Slider")); + KaimanStyleValue* l_elem_volitem = static_cast<KaimanStyleValue*>(_style->find("Volume_Item")); + if ( l_elem_volslider!=0 ) + l_elem_volslider->setValue( napp->player()->volume(), 0, 100 ); + if ( l_elem_volitem!=0 ) + l_elem_volitem->setValue( napp->player()->volume(), 0, 100 ); + + // update position + if ( !_seeking ) + { + int sec = napp->player()->getTime()/1000; + if ( sec < 0 ) + sec = 0; + + KaimanStyleValue* posItem = + static_cast<KaimanStyleValue*>(_style->find("Position_Item")); + if ( posItem ) posItem->setValue( sec, 0, napp->player()->getLength()/1000 ); + + KaimanStyleSlider* posSlider = + static_cast<KaimanStyleSlider*>(_style->find("Position_Slider")); + if ( posSlider ) posSlider->setValue( sec, 0, napp->player()->getLength()/1000 ); + + // update time + KaimanStyleNumber* numItem = + static_cast<KaimanStyleNumber*>(_style->find("Minute_Number")); + if ( numItem ) + numItem->setValue( sec/60%60 ); + + numItem = static_cast<KaimanStyleNumber*>(_style->find("Second_Number")); + if ( numItem ) + numItem->setValue( sec%60 ); + } + + const PlaylistItem &item = napp->playlist()->current(); + KaimanStyleNumber* numItem = 0; + + numItem = static_cast<KaimanStyleNumber*>(_style->find("In_Rate_Number")); + if ( numItem ) + numItem->setValue(item.property("bitrate").toInt()); + + QString hzString = item.property("samplerate"); + hzString.truncate(2); + + numItem = static_cast<KaimanStyleNumber*>(_style->find("In_Hz_Number")); + if ( numItem ) + numItem->setValue(hzString.toInt()); +} + + +void Kaiman::updateMode() +{ + if ( !_style ) return; + + KaimanStyleButton* pause = + static_cast<KaimanStyleButton*>(_style->find("Pause_Button")); + KaimanStyleButton* play = + static_cast<KaimanStyleButton*>(_style->find("Play_Button")); + KaimanStyleState* status = + static_cast<KaimanStyleState*>(_style->find("Status_Item")); + + if (napp->player()->isStopped() ) + { + if ( pause ) pause->setLit( false ); + if ( play ) play->setLit( false ); + if ( status ) status->setValue( 0 ); + } + else if ( napp->player()->isPlaying() ) + { + if ( pause ) pause->setLit( false ); + if ( play ) play->setLit( true ); + if ( status ) status->setValue( 2 ); + } + else if ( napp->player()->isPaused() ) + { + if ( pause ) pause->setLit( true ); + if ( play ) play->setLit( false ); + if ( status ) status->setValue( 1 ); + } +} + + +void Kaiman::loopTypeChange( int ) +{ + if ( !_style ) return; + + KaimanStyleState* rep = static_cast<KaimanStyleState*>(_style->find("Repeat_Item")); + if ( rep ) + rep->setValue( napp->player()->loopStyle() ); +} + + +void Kaiman::newSongLen( int, int ) +{ + if ( !_style ) + return; + + int len = napp->player()->getLength()/1000; // convert milliseconds -> seconds + if ( len < 0 ) // getLength returns -1 if there's no Playobject + len = 0; + + // update time + KaimanStyleNumber* numItem = + static_cast<KaimanStyleNumber*>(_style->find("Minute_Total_Number")); + if ( numItem ) + numItem->setValue( len/60%60 ); + + numItem = static_cast<KaimanStyleNumber*>(_style->find("Second_Total_Number")); + if ( numItem ) + numItem->setValue( len%60 ); + + numItem = static_cast<KaimanStyleNumber*>(_style->find("Song_Minute_Number")); + if ( numItem ) + numItem->setValue( len/60%60 ); + + numItem = static_cast<KaimanStyleNumber*>(_style->find("Second_Minute_Number")); + if ( numItem ) + numItem->setValue( len%60 ); + + newSong(); +} + + +void Kaiman::newSong() +{ + if ( !_style ) return; + + KaimanStyleText* titleItem = static_cast<KaimanStyleText*>(_style->find("Title")); + if ( titleItem ) + { + QString title = i18n("Noatun"); + if ( napp->player()->current() ) + { + title = napp->player()->current().title(); + if ( title.isEmpty() ) + title = napp->player()->current().file(); + + title = i18n("TITLE (LENGTH)", "%1 (%2)").arg(title, + napp->player()->current().lengthString()); + } + titleItem->setValue( title ); + } +} + + +#undef None +void Kaiman::toggleLoop() +{ + KPopupMenu *loopMenu = new KPopupMenu(this, "loopMenu"); + int selectedItem = 0; + + loopMenu->setCheckable(true); + loopMenu->insertTitle(i18n("Loop Style")); + loopMenu->insertItem(i18n("&None"), + (int)Player::None); + loopMenu->insertItem(i18n("&Song"), + (int)Player::Song); + loopMenu->insertItem(i18n("&Playlist"), + (int)(Player::Playlist)); + loopMenu->insertItem(i18n("&Random"), + (int)(Player::Random)); + + loopMenu->setItemChecked((int)napp->player()->loopStyle(), true); // select current loopstyle in menu + selectedItem = loopMenu->exec(QCursor::pos()); + if (selectedItem != -1) + napp->player()->loop(selectedItem); // set new loopstyle + + delete loopMenu; +} + + +void Kaiman::toggleShuffle() +{ + napp->player()->loop(Player::Random); // set loopstyle to be random +} + +#include "userinterface.moc" diff --git a/noatun/modules/kaiman/userinterface.h b/noatun/modules/kaiman/userinterface.h new file mode 100644 index 00000000..2fb46184 --- /dev/null +++ b/noatun/modules/kaiman/userinterface.h @@ -0,0 +1,85 @@ +/* + Copyright (c) 2000 Stefan Schimanski <1Stein@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + aint with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef USERINTERFACE_H +#define USERINTERFACE_H + +#include <noatun/plugin.h> +#include <noatun/app.h> +#include <kmainwindow.h> +#include "style.h" + + +class Player; + +/** + * @short Main window class + * @author Stefan Schimanski <1Stein@gmx.de> + * @version 0.1 + */ +class Kaiman : public KMainWindow, public UserInterface +{ +Q_OBJECT + public: + Kaiman(); + virtual ~Kaiman(); + + bool changeStyle( const QString &style, const QString &desc=QString::null ); + public slots: + void dropEvent( QDropEvent * ); + void doDropEvent( QDropEvent * ); + void dragEnterEvent( QDragEnterEvent * ); + void closeEvent(QCloseEvent*); + + protected slots: + void seekStart( int ); + void seekDrag( int ); + void seekStop( int ); + void seek( int ); + void toggleSkin(); + + void setVolume( int vol ); + void volumeUp(); + void volumeDown(); + + void execMixer(); + + + void timeout(); + void loopTypeChange( int t ); + void newSongLen( int mins, int sec ); + void newSong(); + void updateMode(); + void toggleLoop(); + void toggleShuffle(); + + public: + static const char DEFAULT_SKIN[]; + static Kaiman *kaiman; + + protected: + bool loadStyle( const QString &style, const QString &desc ); + + + bool _seeking; + bool _altSkin; + KaimanStyle *_style; +}; + + +#endif diff --git a/noatun/modules/keyz/Makefile.am b/noatun/modules/keyz/Makefile.am new file mode 100644 index 00000000..61c9f1bd --- /dev/null +++ b/noatun/modules/keyz/Makefile.am @@ -0,0 +1,14 @@ +INCLUDES= -I$(top_srcdir)/noatun/library -I$(kde_includes)/arts $(all_includes) +kde_module_LTLIBRARIES = noatun_keyz.la + +noatun_keyz_la_SOURCES = keyz.cpp + +noatun_keyz_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_keyz_la_LIBADD = $(LIB_KFILE) $(top_builddir)/noatun/library/libnoatun.la + +noatun_keyz_la_METASOURCES = AUTO + +noinst_HEADERS = keyz.h + +noatun_modules_keyz_DATA = keyz.plugin +noatun_modules_keyzdir = $(kde_datadir)/noatun diff --git a/noatun/modules/keyz/keyz.cpp b/noatun/modules/keyz/keyz.cpp new file mode 100644 index 00000000..7b32cf98 --- /dev/null +++ b/noatun/modules/keyz/keyz.cpp @@ -0,0 +1,189 @@ +#include <noatun/engine.h> +#include <noatun/player.h> +#include <noatun/app.h> +#include <noatun/playlist.h> + +#include <qlayout.h> + +#include <kglobalaccel.h> +#include <kkeydialog.h> +#include <klocale.h> +#include <qclipboard.h> + +#include "keyz.h" + +extern "C" +{ + KDE_EXPORT Plugin *create_plugin() + { + return new Keyz(); + } +} + +KGlobalAccel * Keyz::s_accel = 0L; + +Keyz::Keyz() : QObject( 0L, "Keyz" ), Plugin(), preMuteVol(0) +{ + NOATUNPLUGINC(Keyz); + Player *player = napp->player(); + + if ( !s_accel ) + { + s_accel = new KGlobalAccel( this, "noatunglobalaccel" ); + s_accel->insert( "PlayPause", i18n("Play/Pause"), QString::null, + CTRL+ALT+Key_P, KKey::QtWIN+CTRL+Key_P, + player, SLOT( playpause() )); + s_accel->insert( "Stop", i18n("Stop Playing"), QString::null, + CTRL+ALT+Key_S, KKey::QtWIN+CTRL+Key_S, + player, SLOT( stop() )); + s_accel->insert( "Back", i18n("Back"), QString::null, + CTRL+ALT+Key_Left, KKey::QtWIN+CTRL+Key_Left, + player, SLOT( back() )); + s_accel->insert( "Forward", i18n("Forward"), QString::null, + CTRL+ALT+Key_Right, KKey::QtWIN+CTRL+Key_Right, + player, SLOT( forward() )); + s_accel->insert( "Playlist", i18n("Show/Hide Playlist"), QString::null, + CTRL+ALT+Key_L, KKey::QtWIN+CTRL+Key_L, + player, SLOT( toggleListView() )); + s_accel->insert( "OpenFile", i18n("Open File to Play"), QString::null, + CTRL+ALT+Key_O, KKey::QtWIN+CTRL+Key_O, + napp, SLOT( fileOpen() )); + s_accel->insert( "Effects", i18n("Effects Configuration"), QString::null, + CTRL+ALT+Key_E, KKey::QtWIN+CTRL+Key_E, + napp, SLOT( effectView() )); + s_accel->insert( "Preferences", i18n("Preferences"), QString::null, + CTRL+ALT+Key_F, KKey::QtWIN+CTRL+Key_F, + napp, SLOT( preferences() )); + s_accel->insert( "VolumeUp", i18n("Volume Up"), QString::null, + CTRL+ALT+SHIFT+Key_Up, KKey::QtWIN+CTRL+SHIFT+Key_Up, + this, SLOT( slotVolumeUp() )); + s_accel->insert( "VolumeDown", i18n("Volume Down"), QString::null, + CTRL+ALT+SHIFT+Key_Down, KKey::QtWIN+CTRL+SHIFT+Key_Down, + this, SLOT( slotVolumeDown() )); + s_accel->insert( "Mute", i18n("Mute"), QString::null, + CTRL+ALT+Key_M, KKey::QtWIN+CTRL+Key_M, + this, SLOT( slotMute() )); + s_accel->insert( "SeekForward", i18n("Seek Forward"), QString::null, + CTRL+ALT+SHIFT+Key_Right, KKey::QtWIN+CTRL+SHIFT+Key_Right, + this, SLOT( slotForward() )); + s_accel->insert( "SeekBackward", i18n("Seek Backward"), QString::null, + CTRL+ALT+SHIFT+Key_Left, KKey::QtWIN+CTRL+SHIFT+Key_Left, + this, SLOT( slotBackward() )); + s_accel->insert( "NextSection", i18n("Next Section"), QString::null, + 0, 0, + this, SLOT( slotNextSection() )); + s_accel->insert( "PrevSection", i18n("Previous Section"), QString::null, + 0, 0, + this, SLOT( slotPrevSection() )); + s_accel->insert( "CopyTitle", i18n("Copy Song Title to Clipboard"), QString::null, + CTRL+ALT+Key_C, KKey::QtWIN+CTRL+Key_C, + this, SLOT( slotCopyTitle() )); + + s_accel->insert( "ToggleGUI", i18n("Show/Hide Main Window"), QString::null, + CTRL+ALT+Key_W, KKey::QtWIN+CTRL+Key_W, + napp, SLOT( toggleInterfaces() )); + + s_accel->readSettings(); + s_accel->updateConnections(); + } + + new KeyzPrefs(this); +} + +Keyz::~Keyz() +{ + delete s_accel; + s_accel = 0L; +} + +void Keyz::slotVolumeUp() +{ + int vol = napp->player()->volume(); + if ( vol >= 100 ) + return; + + napp->player()->setVolume( vol + 4 ); +} + +void Keyz::slotVolumeDown() +{ + int vol = napp->player()->volume(); + if ( vol <= 0 ) + return; + + napp->player()->setVolume( vol - 4 ); +} + +void Keyz::slotForward() +{ + napp->player()->skipTo( QMIN(napp->player()->getLength(), napp->player()->getTime() + 3000) ); // + 3 seconds +} + +void Keyz::slotBackward() +{ + napp->player()->skipTo( QMAX( 0, napp->player()->getTime() - 3000 )); // - 3 seconds +} + +void Keyz::slotNextSection() +{ + Playlist *list = napp->playlist(); + if ( list ) { + PlaylistItem item = list->nextSection(); + if ( !item.isNull() ) + napp->player()->play( item ); + } +} + +void Keyz::slotPrevSection() +{ + Playlist *list = napp->playlist(); + if ( list ) { + PlaylistItem item = list->previousSection(); + if ( !item.isNull() ) + napp->player()->play( item ); + } +} + +void Keyz::slotCopyTitle() +{ + if (napp->player()->current()) + KApplication::kApplication()->clipboard()->setText(napp->player()->current().title()); +} + + +void Keyz::slotMute() +{ + int vol = napp->player()->volume(); + + if ( vol <= 0 ) // already muted + { + vol = preMuteVol; + } + else // we should mute + { + preMuteVol = vol; + vol = 0; + } + + napp->player()->setVolume( vol ); +} + +/////////////////////////////////////////////////////////////////// + +KeyzPrefs::KeyzPrefs( QObject *parent ) : + CModule( i18n("Keyz"), i18n("Shortcut Configuration"), "key_bindings", + parent ) +{ + QVBoxLayout *layout = new QVBoxLayout( this ); + m_chooser = new KKeyChooser( Keyz::accel(), this ); + layout->addWidget( m_chooser ); +} + +void KeyzPrefs::save() +{ + m_chooser->commitChanges(); + Keyz::accel()->updateConnections(); + Keyz::accel()->writeSettings(); +} + +#include "keyz.moc" diff --git a/noatun/modules/keyz/keyz.h b/noatun/modules/keyz/keyz.h new file mode 100644 index 00000000..929e6c67 --- /dev/null +++ b/noatun/modules/keyz/keyz.h @@ -0,0 +1,48 @@ +#ifndef KEYZ_H +#define KEYZ_H + +#include <noatun/pref.h> +#include <noatun/plugin.h> + +class Keyz : public QObject, public Plugin +{ + Q_OBJECT + NOATUNPLUGIND + +public: + Keyz(); + ~Keyz(); + + static KGlobalAccel *accel() { return s_accel; } + +public slots: +void slotVolumeUp(); + void slotVolumeDown(); + void slotMute(); + + void slotForward(); + void slotBackward(); + void slotNextSection(); + void slotPrevSection(); + void slotCopyTitle(); + +private: + static KGlobalAccel *s_accel; + int preMuteVol; +}; + + +class KeyzPrefs : public CModule +{ + Q_OBJECT + +public: + KeyzPrefs( QObject *parent ); + virtual void save(); + +private: + class KKeyChooser* m_chooser; + +}; + +#endif // KEYZ_H diff --git a/noatun/modules/keyz/keyz.plugin b/noatun/modules/keyz/keyz.plugin new file mode 100644 index 00000000..41560e86 --- /dev/null +++ b/noatun/modules/keyz/keyz.plugin @@ -0,0 +1,69 @@ +Filename=noatun_keyz.la +Author=Carsten Pfeiffer +Site=http://noatun.kde.org/ +Email=pfeiffer@kde.org +Type=other +License=Artistic +Name=Keyz +Name[af]=Keys +Name[cs]=Klávesy +Name[de]=Tasten +Name[eo]=Klavkombinoj +Name[he]=מקשים +Name[hi]=के-ईवायज़ेड +Name[nds]=Tasten +Name[ru]=Клавишки +Name[sv]=Tangentisar +Name[ta]=விசைகள் +Name[xh]=Izitshixo +Name[zu]=Izikhiye +Comment=Global shortcuts for most operations +Comment[bg]=Управление чрез бързи клавиши на повечето операции +Comment[bs]=Globalne kratice za većinu operacija +Comment[ca]=Dreceres globals per a la majoria d'operacions +Comment[cs]=Globální zkratky pro většinu operací +Comment[cy]=Byrlwybrau Eang i'r rhan fwyaf o weithredoedd +Comment[da]=Globale genveje til de fleste operationer +Comment[de]=Globale Kurzbefehle für die meisten Vorgänge +Comment[el]=Καθολικές συντομεύσεις για τις περισσότερες λειτουργίες +Comment[eo]=Mallokaj klavkombinoj por multaj operacioj +Comment[es]=Accesos directos globales para la mayoría de las operaciones +Comment[et]=Enamiku tegevuste globaalsed kiirklahvid +Comment[eu]=Laisterbide globalak eragiketa gehienetarako +Comment[fa]=میانبرهای سراسری برای اغلب عملیاتها +Comment[fi]=Yleiset pikavalinnat lähes kaikille toiminnoille +Comment[fr]=Raccourcis pour l'essentiel des opérations +Comment[ga]=Aicearraí comhchoiteanna d'fhormhór na n-oibríochtaí +Comment[gl]=Atallos globais para a maioría das operacións +Comment[he]=קיצורי דרך גלובליים לרוב הפעולות +Comment[hu]=Globális billentyűparancsok a legtöbb művelethez +Comment[is]=Altækir flýtilyklar fyrir flest allt +Comment[it]=Scorciatoie globali per le operazioni comuni +Comment[ja]=ほとんどの操作に使われるグローバルショートカット +Comment[kk]=Көп операциялардың жалпы-жүйелік перне тірсесімдері +Comment[km]=ផ្លូវកាត់សកលសម្រាប់ប្រតិបត្តិការភាគច្រើន +Comment[ko]=대부분 작업에 대한 전역 단축키 +Comment[lt]=Bendri spartieji klavišai daugumai operacijų +Comment[mk]=Глобални кратенки за повеќето операции +Comment[nb]=Globale snarveier for de fleste operasjoner +Comment[nds]=Globaal Tastkombinatschonen för de mehrsten Akschonen +Comment[ne]=धेरै सञ्चालनका लागि विश्वव्यापी सर्टकट +Comment[nl]=Globale snelkoppelingen voor de meeste handelingen +Comment[nn]=Globale snøggtastar for dei fleste operasjonar +Comment[pl]=Globalne skróty dla większości operacji +Comment[pt]=Atalhos globais para a maioria das operações +Comment[pt_BR]=Atalhos globais para a maioria das operações +Comment[ro]=Acceleratori globali pentru operaţii uzuale +Comment[ru]=Привязки клавиш для большинства действий +Comment[sk]=Globálne skratky pre väčšinu operácií +Comment[sl]=Globalne bližnjice za večino operacij +Comment[sr]=Глобалне пречице за већину операција +Comment[sr@Latn]=Globalne prečice za većinu operacija +Comment[sv]=Globala snabbtangenter för de flesta operationerna +Comment[ta]=பல செயலுகளுக்கான உலகளாவிய குறுக்குவழிகள் +Comment[th]=ปุ่มพิมพ์ลัดส่วนกลางสำหรับปฏิบัติการส่วนใหญ่ +Comment[tr]=Pek çok İşlemler için Genel Kısayollar +Comment[uk]=Глобальні скорочення для більшості дій +Comment[zh_CN]=大多数操作的全局快捷键 +Comment[zh_HK]=大部分操作的通用捷徑 +Comment[zh_TW]=給一般大部分操作使用的全域快速鍵 diff --git a/noatun/modules/kjofol-skin/ChangeLog b/noatun/modules/kjofol-skin/ChangeLog new file mode 100644 index 00000000..537de012 --- /dev/null +++ b/noatun/modules/kjofol-skin/ChangeLog @@ -0,0 +1,111 @@ +ChangeLog (only lists MY changes) +----------------------------------------------------------------------------------- + +2003-01-09 Stefan Gehn <sgehn@gmx.net> +* Allow use of system fonts instead of skin-supplied pixmap-fonts, user + has to take care for choosing an appropriate font and font-color + +2003-01-19 Stefan Gehn <sgehn@gmx.net> +* Equalizer support +* Ignore unsupported buttons for spectrum/oscilloscope, won't work with default skin anyway +* Display about-lines in skinselector + +2002-04-04 Stefan Gehn <sgehn@gmx.net> +* Started work on config-dialog, this will unhide most things you can now only + set by clicking on widgets (i.e. time counting mode) + +2002-01-21 Stefan Gehn <sgehn@gmx.net> +* Actually read counting-mode of time-display from config + +2002-01-20 Stefan Gehn <sgehn@gmx.net> +* Fix ugly crash on Startup related to Time-Display +* less debug + +2002-01-06 Stefan Gehn <sgehn@gmx.net> +* Made Playlist-button show if playlist-window is open even after loading a new skin +* Added Tooltips for text-displays +* usual removal of old debug-messages and adding new ones :) + +2002-01-04 Stefan Gehn <sgehn@gmx.net> +* changed scrolling-text behaviour (scrolls 1/2 char every 400ms now) +* playlist-button is a state-button, i.e. shows if playlist-window is open or not +* commented or removed some more unused debug-messages + +2001-12-14 Stefan Gehn <sgehn@gmx.net> +* slightly changed skin-installer (creates dirs without archive extension) +* code cleanups, removed debug-messages + +2001-12-12 Stefan Gehn <sgehn@gmx.net> +* finally made font-spacing between characters working (no garbage inside space) +* textfields with more space than needed for the string to display now get centered text + (take a look at volumetext or pitchtext to see the centere-effect) +* Noatun is not shown in taskbar if in dockmode as it's no normal window in that mode +* take care if Playlist is shown/hidden and update the playlistbutton +* using kdDebug(66666) for debugmessages instead of stderr-output + +2001-10-04 Stefan Gehn <sgehn@gmx.net> +* Still fighting with analyzer and osci visualizations, + now both are buffered and flicker-free +* fixed stupid bug in isGray(qRgb), now RGB(0,0,0) is treated as gray again :) +* commented out (hopefully) unneded debug-messages +* added splash-screen for skins supporting it (only skin I know of: K-Nine) + +2001-09-30 Stefan Gehn <sgehn@gmx.net> +* ignore alpha-channel of loaded files, they break applying masks to QPixmaps, + result of this is text without transparency + (this happened for two skins: adagio and xbs) + +2001-09-28 Stefan Gehn <sgehn@gmx.net> +* analyzer-like scope is now drawn using a gradient instead of exactly one boring color +* removed KJLoader::fixSkin() as Njaard deleted the script doing all the work, I assume + that this is not needed anymore (guess: maybe QT3 now handles + most fileformats in a proper way?) + +2001-09-22 Stefan Gehn <sgehn@gmx.net> +* isGray(qRgb) is more tolerant, colors like rgb(162,163,162) are treated as gray too + This fixes some volume/pitch-sliders and makes using them a lot easier +* made titletext move again (works with and without transparent text) + +2001-09-16 Stefan Gehn <sgehn@gmx.net> +* Made it compile with QT3 and stopped using Njaard's hack to load PNGs + +2001-09-04 Stefan Gehn <sgehn@gmx.net> +* added support for transparent fonts (a skin named steelforged still got problems though) + for the moment this disables moving of titletext, + I have to find a new way to move it (bitblt on a masked QPixmap is tricky) + +2001-09-03 Stefan Gehn <sgehn@gmx.net> +* added support for pitch-slider and its textlabel + kjfol now depends on libartsmodules because of pitch-support +* finished splitting up kjloader.cpp into several files. + Now almost every class has its own file + also took care that compiling with --enable-final works + +2001-09-02 Stefan Gehn <sgehn@gmx.net> +* started splitting up kjloader.cpp into several files + +Before 2001-09-02 Stefan Gehn <sgehn@gmx.net> + +I should have started a ChangeLog earlier :/ +Never thought I would change THAT much +(it all started with small noatun-bugfixes) + +I'll now try to list the tons of changes done before (totally unordered) + +* fixed seeker to work with long files + (I've got a 330min mp3, seeking did not work behind about 120min) +* made the repeat-button work, it switches between no-looping and song-looping +* made the forward/backward-buttons work, they will skip 10 seconds +* added dockmode-support, in this mode kjfol will dock to the currently active window + the window's behaviour looks like this mode needs some more work +* added support for textlabels showing current volume +* added a skininstaller, it still needs proper widgets showing + the actions going on (unpacking, moving files, deleting files on uninstall) +* tweaked builtin visualizations, both now try to fit into any possible skin + last activated vis is remembered on restart +* vis honors "AnalyzerColor" and defaults to white if that key is missing in the skin.rc +* support for buttons with "DARKEN"-flag (normally "BMPsomenumber" is used) +* made kjofol parse the skin.rc in lowercase only, now it's fully case-insensitve +* many many tests for existence of keys, 99% of former crashes were caused by not making + sure a certain key really exists. Many places now assume "default"-values if keys are + missing, this leads to MUCH better compatibility diff --git a/noatun/modules/kjofol-skin/Makefile.am b/noatun/modules/kjofol-skin/Makefile.am new file mode 100644 index 00000000..17ff1162 --- /dev/null +++ b/noatun/modules/kjofol-skin/Makefile.am @@ -0,0 +1,41 @@ +INCLUDES = -I$(top_srcdir)/noatun/library \ + -I$(top_builddir)/noatun/library \ + -I$(top_builddir)/arts/modules \ + -I$(top_builddir)/arts/midi \ + -I$(top_builddir)/arts/modules/synth \ + -I$(top_builddir)/arts/modules/common \ + -I$(top_builddir)/arts/modules/effects \ + -I$(top_builddir)/arts/modules/mixers \ + -I$(top_builddir)/arts/gui/common \ + -I$(kde_includes)/kio \ + -I$(kde_includes)/arts \ + $(all_includes) + +kde_module_LTLIBRARIES = noatun_kjofol.la +SUBDIRS= . skins +METASOURCES = AUTO + +noatun_kjofol_la_SOURCES = kjloader.cpp kjwidget.cpp kjbutton.cpp kjseeker.cpp \ + kjsliders.cpp kjfont.cpp kjtextdisplay.cpp \ + kjvis.cpp kjequalizer.cpp kjbackground.cpp \ + noatunui.cpp parser.cpp \ + kjprefs.cpp \ + kjskinselectorwidget.ui kjguisettingswidget.ui + +noatun_kjofol_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_kjofol_la_LIBADD = $(LIB_KFILE) $(top_builddir)/noatun/library/libnoatun.la \ + $(LIB_KIO) -lm \ + $(top_builddir)/arts/modules/libartsmodules.la + +noinst_HEADERS = kjloader.h kjwidget.h kjbutton.h kjseeker.h \ + kjsliders.h kjfont.h kjtextdisplay.h \ + kjvis.h kjequalizer.h kjbackground.h \ + parser.h kjprefs.h \ + kjskinselectorwidget.h kjguisettingswidget.h + +noatun_modules_kjofol_DATA = kjofolui.plugin +noatun_modules_kjofoldir = $(kde_datadir)/noatun + +kjloader.lo: ../../../arts/modules/artsmodules.h ../../../arts/midi/artsmidi.h ../../../arts/gui/common/artsgui.h ../../../arts/modules/common/artsmodulescommon.h ../../../arts/modules/synth/artsmodulessynth.h ../../../arts/modules/effects/artsmoduleseffects.h ../../../arts/modules/mixers/artsmodulesmixers.h ../../library/noatunarts/noatunarts.h +kjsliders.lo: ../../../arts/modules/artsmodules.h ../../../arts/midi/artsmidi.h ../../../arts/gui/common/artsgui.h ../../../arts/modules/common/artsmodulescommon.h ../../../arts/modules/synth/artsmodulessynth.h ../../../arts/modules/effects/artsmoduleseffects.h ../../../arts/modules/mixers/artsmodulesmixers.h +kjtextdisplay.lo: ../../../arts/modules/artsmodules.h ../../../arts/midi/artsmidi.h ../../../arts/gui/common/artsgui.h ../../../arts/modules/common/artsmodulescommon.h ../../../arts/modules/synth/artsmodulessynth.h ../../../arts/modules/effects/artsmoduleseffects.h ../../../arts/modules/mixers/artsmodulesmixers.h diff --git a/noatun/modules/kjofol-skin/helpers.cpp b/noatun/modules/kjofol-skin/helpers.cpp new file mode 100644 index 00000000..b38822a6 --- /dev/null +++ b/noatun/modules/kjofol-skin/helpers.cpp @@ -0,0 +1,64 @@ +/*************************************************************************** + helpers.cpp + Just a few functions needed in several Kjofol-classes + --------------------------------------------- + Maintainer: Charles Samuels <charles@kde.org> + + ***************************************************************************/ + +#ifndef KJHELPERS_CPP +#define KJHELPERS_CPP + +static int grayRgb(QRgb r) +{ + return qGray(qRed(r), qGreen(r), qBlue(r)); +} + +static int isGray(QRgb r) +{ +// this is more tolerant than the old version +// i.e. RGB 162 163 162 is treated as gray too +// too many broken skins around having such colors + +// cerr << "r("<<qRed(r)<<","<<qGreen(r)<<","<<qBlue(r)<<")"<<endl; + + if ( (qRed(r)==qGreen(r)) || (qRed(r)+1==qGreen(r)) || (qRed(r)-1==qGreen(r))) + { + if ( (qRed(r)==qBlue(r)) || (qRed(r)+1==qBlue(r)) || (qRed(r)-1==qBlue(r))) + { + // looks a bit like gray, so return true + return (1); + } + } + // well, it's not gray + return(0); + +/* + // mETz: wrong braces in the code below ?? + return (qRed(r)==qGreen(r)) && (qRed(r) == qBlue(r)); +*/ +} + +// only works little endian +// UPDATE: should work on both little and big endian now (haven't tested that!) +// this code is taken from the QT-docu and I hope that this example +// is one of the working ones ;) +inline void setPixel1BPP(QImage &image, int x, int y, bool value) +{ + if ( image.bitOrder() == QImage::LittleEndian ) + { + if (value) + *(image.scanLine(y) + (x >> 3)) |= 1 << (x & 7); + else + *(image.scanLine(y) + (x >> 3)) &= ~(1 << (x & 7)); + } + else + { + if (value) + *(image.scanLine(y) + (x >> 3)) |= 1 << (7-(x & 7)); + else + *(image.scanLine(y) + (x >> 3)) &= ~(1 << (7-(x & 7))); + } +} + +#endif diff --git a/noatun/modules/kjofol-skin/kjbackground.cpp b/noatun/modules/kjofol-skin/kjbackground.cpp new file mode 100644 index 00000000..83c19ace --- /dev/null +++ b/noatun/modules/kjofol-skin/kjbackground.cpp @@ -0,0 +1,29 @@ +/*************************************************************************** + kjbackground.cpp + -------------------------------------- + Just draws the main-pixmap of a KJfol-Skin + -------------------------------------- + Maintainer: Stefan Gehn <sgehn@gmx.net> + + ***************************************************************************/ + +#include "kjbackground.h" + +KJBackground::KJBackground(KJLoader *parent) + : KJWidget(parent) +{ + QImage ibackground; + + mBackground = parent->pixmap(parser()["backgroundimage"][1]); + ibackground = parent->image(parser()["backgroundimage"][1]); + + parent->setMask( getMask(ibackground) ); + parent->setFixedSize ( QSize(mBackground.width(), mBackground.height()) ); + + setRect(0,0,parent->width(),parent->height()); +} + +void KJBackground::paint(QPainter *painter, const QRect &rect) +{ + bitBlt(painter->device(), rect.topLeft(), &mBackground, rect, Qt::CopyROP); +} diff --git a/noatun/modules/kjofol-skin/kjbackground.h b/noatun/modules/kjofol-skin/kjbackground.h new file mode 100644 index 00000000..502611c5 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjbackground.h @@ -0,0 +1,21 @@ +#ifndef KJBACKGROUND_H +#define KJBACKGROUND_H + +#include "kjwidget.h" +//#include "kjloader.h" +class KJLoader; + +#include <qpainter.h> + +class KJBackground : public KJWidget +{ +public: + KJBackground(KJLoader *); + virtual void paint(QPainter *, const QRect &rect); + virtual bool mousePress(const QPoint &) {return false;} + virtual void mouseRelease(const QPoint &, bool) {} + +private: + QPixmap mBackground; +}; +#endif diff --git a/noatun/modules/kjofol-skin/kjbutton.cpp b/noatun/modules/kjofol-skin/kjbutton.cpp new file mode 100644 index 00000000..403ea61e --- /dev/null +++ b/noatun/modules/kjofol-skin/kjbutton.cpp @@ -0,0 +1,301 @@ +/*************************************************************************** + kjbutton.cpp + -------------------------------------- + Handles all ordinary Buttons like stop, play, pause, etc. + -------------------------------------- + Maintainer: Stefan Gehn <sgehn@gmx.net> + + ***************************************************************************/ + +#include "kjbutton.h" +#include "kjbutton.moc" +#include "kjloader.h" +#include "kjprefs.h" + +#include <noatun/pref.h> +#include <noatun/player.h> +#include <noatun/vequalizer.h> + +#include <qcursor.h> +#include <kdebug.h> +#include <klocale.h> +#include <kpixmap.h> +#include <kpixmapeffect.h> +#include <kurl.h> +#include <kfiledialog.h> +#include <khelpmenu.h> +#include <kpopupmenu.h> + +/******************************************* + * KJButton + *******************************************/ + +KJButton::KJButton(const QStringList &i, KJLoader *parent) + : QObject(0), KJWidget(parent), mTitle(i[0]), mShowPressed(false) +{ +// kdDebug(66666) << k_funcinfo << "new button: " << i[0].latin1() << endl; + mPushedPixmap = (i.count() >= 7); + + // get the rectangle + int x, y, xs, ys; + x=i[1].toInt(); + y=i[2].toInt(); + xs=i[3].toInt()-x; // width + ys=i[4].toInt()-y; // height + setRect ( x, y, xs, ys ); + + QStringList temp = i; + + // search for selected button-type + // can be either BMPx where x is a number representing one + // of the background-images + // or darken which means just darken the button on click + bool gotBack = false; // in case any of these keys is duplicated + for(QStringList::Iterator it = temp.begin(); it != temp.end(); ++it) + { + if((*it).contains("bmp")) + { + QString pressedTmp = backgroundPressed((*it)); + if(!pressedTmp.isEmpty()) + { + mPressed = parent->pixmap(pressedTmp); + gotBack = true; + } + } + else if((*it) == "darken") + { + // take background and darken the buttons rectangle + // FIXME: what KPixmapEffect causes the desired effect? + // intensity is the wrong one + KPixmap temp = parent->pixmap(parser()["backgroundimage"][1]); + mPressed = (QPixmap)KPixmapEffect::intensity ( temp, 1.2f ); + gotBack = true; + } + if(gotBack) + break; + } + + if(!gotBack) + { + kdDebug(66666) << k_funcinfo << "Couldn't find valid background for button '" << + mTitle << "', dafulting to backgroundimage" << endl; + mPressed = parent->pixmap(parser()["backgroundimage"][1]); + } + + // playlistbutton has to show if playlistwindow is open + // right after the button appears on screen + if (mTitle=="playlistbutton") + { + mShowPressed = napp->playlist()->listVisible(); + connect( napp->player(), SIGNAL(playlistShown()), this, SLOT(slotPlaylistShown()) ); + connect( napp->player(), SIGNAL(playlistHidden()), this, SLOT(slotPlaylistHidden()) ); + } + else if ( mTitle=="equalizeroffbutton") // same goes for EQ buttons + { + mShowPressed = (!napp->vequalizer()->isEnabled()); + connect( napp->vequalizer(), SIGNAL(enabled(bool)), SLOT(slotEqEnabled(bool))); + } + else if (mTitle=="equalizeronbutton") + { + mShowPressed = napp->vequalizer()->isEnabled(); + connect( napp->vequalizer(), SIGNAL(enabled(bool)), SLOT(slotEqEnabled(bool))); + } +} + +QString KJButton::tip() +{ + QString str; + if (mTitle=="closebutton") + str=i18n("Close"); + else if (mTitle=="minimizebutton") + str=i18n("Minimize"); + else if (mTitle=="aboutbutton") + str=i18n("About"); + else if (mTitle=="stopbutton") + str=i18n("Stop"); + else if (mTitle=="playbutton") + str=i18n("Play"); + else if (mTitle=="pausebutton") + str=i18n("Pause"); + else if (mTitle=="openfilebutton") + str=i18n("Open"); + else if (mTitle=="playlistbutton") + str=i18n("Playlist"); + else if (mTitle=="repeatbutton") + str=i18n("Loop"); + else if (mTitle=="equalizerbutton") + str=i18n("Show Equalizer Window"); + else if (mTitle=="equalizeronbutton") + str=i18n("Turn on Equalizer"); + else if (mTitle=="equalizeroffbutton") + str=i18n("Turn off Equalizer"); + else if (mTitle=="equalizerresetbutton") + str=i18n("Reset Equalizer"); + else if (mTitle=="nextsongbutton") + str=i18n("Next"); + else if (mTitle=="previoussongbutton") + str=i18n("Previous"); + else if (mTitle=="forwardbutton") + str=i18n("Forward"); + else if (mTitle=="rewindbutton") + str=i18n("Rewind"); + else if (mTitle=="preferencesbutton") + str=i18n("K-Jöfol Preferences"); + else if (mTitle=="dockmodebutton") + str=i18n("Switch to dockmode"); + else if (mTitle=="undockmodebutton") + str=i18n("Return from dockmode"); + + return str; +} + +void KJButton::paint(QPainter *, const QRect &) +{ + if (mShowPressed) + bitBlt(KJWidget::parent(), rect().topLeft(), &mPressed, rect(), Qt::CopyROP); +} + +bool KJButton::mousePress(const QPoint &) +{ + bitBlt(KJWidget::parent(), rect().topLeft(), &mPressed, rect(), Qt::CopyROP); + return true; +} + +void KJButton::showPressed(bool b) +{ + mShowPressed = b; + if ( mShowPressed ) + repaint(true); // repaint with selected image + else + repaint(false); // repaint with default image (player-background) +} + +void KJButton::slotPlaylistShown(void) +{ +// kdDebug(66666) << "KJButton::slotPlaylistShown()" << endl; + showPressed(true); +} + +void KJButton::slotPlaylistHidden(void) +{ +// kdDebug(66666) << "KJButton::slotPlaylistHidden()" << endl; + showPressed(false); +} + +void KJButton::slotEqEnabled(bool on) +{ +// kdDebug(66666) << "KJButton::slotEqEnabled(" << on << ") for " << mTitle << endl; + if (mTitle=="equalizeronbutton") + showPressed(on); + else if (mTitle=="equalizeroffbutton") + showPressed(!on); +} + +void KJButton::mouseRelease(const QPoint &, bool in) +{ + // repaint with default image (player-background) + repaint(false); + + if (!in) // only do something if users is still inside the button + return; + + // now, find what widget I am and do the proper action + if (mTitle=="closebutton") + KJWidget::parent()->close(); + else if (mTitle=="minimizebutton") + KJWidget::parent()->minimize(); + else if (mTitle=="aboutbutton") + KJWidget::parent()->helpMenu()->aboutApplication(); + else if (mTitle=="stopbutton") + napp->player()->stop(); + else if (mTitle=="playbutton") + napp->player()->play(); + else if (mTitle=="pausebutton") + napp->player()->playpause(); + else if (mTitle=="openfilebutton") + { + KURL file(KFileDialog::getOpenURL(0, napp->mimeTypes(), KJWidget::parent(), i18n("Select File to Play"))); + if (file.isValid()) + napp->player()->openFile(file); + } + else if (mTitle=="playlistbutton") + napp->player()->toggleListView(); + else if (mTitle=="repeatbutton") + { + KPopupMenu *loopMenu = new KPopupMenu(KJWidget::parent(),"loopMenu"); + int selectedItem = 0; + + loopMenu->setCheckable(true); + loopMenu->insertTitle(i18n("Loop Style")); + loopMenu->insertItem(i18n("&None"), static_cast<int>(Player::None)); + loopMenu->insertItem(i18n("&Song"), static_cast<int>(Player::Song)); + loopMenu->insertItem(i18n("&Playlist"), static_cast<int>(Player::Playlist)); + loopMenu->insertItem(i18n("&Random"), static_cast<int>(Player::Random)); + + loopMenu->setItemChecked(static_cast<int>(napp->player()->loopStyle()), true); // select current loopstyle in menu + selectedItem = loopMenu->exec(QCursor::pos()); + if (selectedItem != -1) + napp->player()->loop(selectedItem); // set new loopstyle + + delete loopMenu; + +/* + if ( napp->player()->loopStyle() == 1) + { +// kdDebug(66666) << "loop song is OFF" << endl; + +// bah, xlib.h already defined None +#undef None + napp->player()->loop( Player::None ); + showPressed( false ); + } + else + { +// kdDebug(66666) << "loop song is ON" << endl; + napp->player()->loop( Player::Song ); + showPressed ( true ); + } +*/ + } + else if (mTitle=="equalizerbutton") + { + napp->equalizerView(); + } + else if (mTitle=="equalizeronbutton") + { + if (!napp->vequalizer()->isEnabled()) + napp->vequalizer()->enable(); + } + else if (mTitle=="equalizeroffbutton") + { + if (napp->vequalizer()->isEnabled()) + napp->vequalizer()->disable(); + } + else if (mTitle=="equalizerresetbutton") + { + for (int band=0; band<napp->vequalizer()->bands(); band++) + napp->vequalizer()->band(band).setLevel(0); + /* + // That preset resets to 6 bands, that's not what we want + VPreset set = napp->vequalizer()->presetByName("Zero"); + if (set) // tests if that preset is valid + set.load(); + */ + } + else if (mTitle=="nextsongbutton") + napp->player()->forward(); + else if (mTitle=="previoussongbutton") + napp->player()->back(); + else if (mTitle=="forwardbutton") + napp->player()->skipTo(napp->player()->getTime()+10000); // TODO: make +- 10 secs configurable + else if (mTitle=="rewindbutton") + napp->player()->skipTo(napp->player()->getTime()-10000); + else if (mTitle=="preferencesbutton") + napp->preferencesBox()->show(static_cast<CModule *>(KJWidget::parent()->prefs())); + else if (mTitle=="dockmodebutton") + KJWidget::parent()->switchToDockmode(); + else if (mTitle=="undockmodebutton") + KJWidget::parent()->returnFromDockmode(); + else + kdDebug(66666) << "unknown buttontype: " << mTitle.latin1() << endl; +} diff --git a/noatun/modules/kjofol-skin/kjbutton.h b/noatun/modules/kjofol-skin/kjbutton.h new file mode 100644 index 00000000..4af4fcb0 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjbutton.h @@ -0,0 +1,34 @@ +#ifndef KJBUTTON_H +#define KJBUTTON_H + +#include "kjwidget.h" +#include <qobject.h> +class KJLoader; + +class KJButton : public QObject, public KJWidget +{ +Q_OBJECT +public: + KJButton(const QStringList&, KJLoader *); + + virtual void paint(QPainter *, const QRect &rect); + virtual bool mousePress(const QPoint &pos); + virtual void mouseRelease(const QPoint &pos, bool); + virtual void showPressed(bool b=true); + + virtual QString tip(); + +private slots: + void slotPlaylistShown(void); + void slotPlaylistHidden(void); + void slotEqEnabled(bool on); + +private: + QPixmap mBackground; + bool mPushedPixmap; + QPixmap mPressed; + QString mTitle; + bool mShowPressed; +}; + +#endif diff --git a/noatun/modules/kjofol-skin/kjequalizer.cpp b/noatun/modules/kjofol-skin/kjequalizer.cpp new file mode 100644 index 00000000..3f0716e4 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjequalizer.cpp @@ -0,0 +1,129 @@ +/*************************************************************************** + kjequalizer.cpp - links noatun VEqualizer and KJofol + -------------------------------------- + Maintainer: Stefan Gehn <sgehn@gmx.net> + + ***************************************************************************/ + +#include "kjequalizer.h" +#include "kjequalizer.moc" + +#include <qpainter.h> +#include <qtimer.h> + +#include <kdebug.h> +#include <kpixmap.h> + +#include <noatun/vequalizer.h> + +KJEqualizer::KJEqualizer(const QStringList &l, KJLoader *p) + : QObject(0), KJWidget(p), mBack(0), mView(0), mInterpEq(0) +{ + int x=l[1].toInt(); + int y=l[2].toInt(); + int xs=l[3].toInt()-x; + int ys=l[4].toInt()-y; + setRect(x,y,xs,ys); + + mBars = p->pixmap(parser()["equalizerbmp"][3]); + + mBands = l[6].toInt(); + mXSpace = l[7].toInt(); + + // background under equalizer + // needed to only blit onto screen ONCE and not for every band + QPixmap tmp = p->pixmap(p->item("backgroundimage")[1]); + mBack = new KPixmap ( QSize(xs,ys) ); + bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP ); + + // buffer for view + mView = new QPixmap ( xs, ys ); + + mBandWidth=parser()["EqualizerBmp"][1].toInt(); + mBandHalfHeight=parser()["EqualizerBmp"][2].toInt(); + + kdDebug(66666) << "[KJEqualizer] mBands=" << mBands << ", mXSpace=" << mXSpace << ", mBandWidth=" << mBandWidth << ", mBandHalfHeight=" << mBandHalfHeight << "." << endl; + + kdDebug(66666) << "[KJEqualizer] creating VInterpolation for " << mBands << " bands..." << endl; + mInterpEq = new VInterpolation(mBands); +// napp->vequalizer()->setBands(mBands); // FIXME: hack because spline sucks :P + connect(napp->vequalizer(), SIGNAL(changed()), this, SLOT(slotUpdateBuffer())); + + slotUpdateBuffer(); // fill mView pixmap with valid data +} + +KJEqualizer::~KJEqualizer(void) +{ + delete mInterpEq; + delete mView; + delete mBack; +} + +int KJEqualizer::barNum(const QPoint &pos) const +{ + int x = pos.x(); + x = x / mXSpace; + return mInterpEq->bands() * x / mBands; +} + +int KJEqualizer::level(const QPoint &pos) const +{ + int y = ((-pos.y()) + mBandHalfHeight+1) * (200/mBandHalfHeight); + return y; +} + +void KJEqualizer::paint(QPainter *p, const QRect &) +{ + QPixmap temp(rect().width(), rect().height()); + // draw background into buffer + bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP ); + // draw band sliders into buffer + bitBlt( &temp, 0, 0, mView, 0, 0, rect().width(), rect().height(), Qt::CopyROP); + // and draw it on screen + bitBlt(p->device(), rect().topLeft(), &temp, QRect(0,0,-1,-1), Qt::CopyROP); +} + +void KJEqualizer::slotUpdateBuffer() +{ +// kdDebug(66666) << "[KJEqualizer] slotUpdateBuffer() called." << endl; + + QBitmap regionMask( rect().width(), rect().height(), true); // fully transparent mask + QPainter mask( ®ionMask ); + + QPoint destX = QPoint(0, 0); + + for (int band=0; band<mBands; band++) + { + int level = mInterpEq->level(band); + if (level>200) level=200; + if (level<-200) level=-200; + int picNum = ((int)(level+200)*(mBandHalfHeight-1) / 400) + 1; + int xPos = (picNum * mBandWidth) - mBandWidth; + +// kdDebug(66666) << "[KJEqualizer] band=" << band << ", level=" << level << ", picNum=" << picNum << " @ xpos=" << xPos << "." << endl; + + bitBlt(mView, destX, &mBars, QRect(xPos,0,mBandWidth,rect().height()), Qt::CopyROP); + // make slider opaque in mask so you see something on screen + mask.fillRect ( destX.x(), 0, mBandWidth, rect().height(), Qt::color1 ); + destX += QPoint(mXSpace,0); + + } // for() + // whole thingy has been drawn, now set the mask + mView->setMask( regionMask ); + repaint(); +} + +void KJEqualizer::mouseMove(const QPoint &p, bool in) +{ + if (!in) return; + mousePress(p); +} + +bool KJEqualizer::mousePress(const QPoint &p) +{ + kdDebug(66666) << "[KJEqualizer] setting band " << mBands << "/" << barNum(p)+1 << " to level " << level(p) << endl; + VBand b = mInterpEq->band( barNum(p) ); + b.setLevel( level(p) ); +// mouseMove(p, true); + return true; +} diff --git a/noatun/modules/kjofol-skin/kjequalizer.h b/noatun/modules/kjofol-skin/kjequalizer.h new file mode 100644 index 00000000..f3f13bd5 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjequalizer.h @@ -0,0 +1,39 @@ +#ifndef KJEQUALIZER_H +#define KJEQUALIZER_H + +#include "kjwidget.h" +//#include "kjloader.h" +class KJLoader; +class VInterpolation; + +#include <qobject.h> + +class KJEqualizer : public QObject, public KJWidget +{ +Q_OBJECT +public: + KJEqualizer(const QStringList &, KJLoader *parent); + ~KJEqualizer(void); + + virtual void mouseMove(const QPoint &pos, bool); + virtual bool mousePress(const QPoint&); + virtual void paint(QPainter *p, const QRect &rect); + int barNum(const QPoint &pos) const; + int level(const QPoint &pos) const; + +public slots: + void slotUpdateBuffer(); + +private: + int mBands; + int mXSpace; + + int mBandWidth; + int mBandHalfHeight; + QPixmap mBars; // holds all slider images + QPixmap *mBack; // holds background of EQ for easy repaint + QPixmap *mView; // holds prepared img of all sliders + VInterpolation *mInterpEq; +}; + +#endif diff --git a/noatun/modules/kjofol-skin/kjfont.cpp b/noatun/modules/kjofol-skin/kjfont.cpp new file mode 100644 index 00000000..df2abed3 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjfont.cpp @@ -0,0 +1,290 @@ +/*************************************************************************** + kjfont.cpp + -------------------------------------- + Font-Handling of KJfol + Creates pixmaps of strings using the supplied font-pixmap + -------------------------------------- + Maintainer: Stefan Gehn <sgehn@gmx.net> + + ***************************************************************************/ + +#include "kjfont.h" +#include "kjloader.h" +#include "kjwidget.h" +#include "kjprefs.h" + +#include <kdebug.h> +#include <kglobalsettings.h> + +#include <qimage.h> +#include <qpainter.h> + +/******************************************* + * KJFont + *******************************************/ + +KJFont::KJFont(const QString &prefix, KJLoader *parent) : mTextMask(0), mTransparentRGB(0) +{ +// kdDebug(66666) << "KJFont::KJFont(const QString &prefix, KJLoader *parent)" << prefix.latin1() << endl; + + if (prefix=="timefont") + { + mString[0]="0123456789: "; + mString[1]=mString[2]=""; + mNullChar=' '; + } + else if ( (prefix=="volumefont") || (prefix=="pitchfont") ) + { + mString[0]="0123456789% "; + mString[1]=mString[2]=""; + mNullChar=' '; + } + else + { + mString[0]="abcdefghijklmnopqrstuvwxyz\"@"; + mString[1]="0123456789;_:()-'!_+\\/[]*&%.=$#"; + mString[2]="?*, "; + mNullChar=' '; + } + + mText = parent->pixmap(parent->item(prefix+"image")[1]); + + if ( parent->exist(prefix+"size") ) + { + mWidth = parent->item(prefix+"size")[1].toInt(); + mHeight = parent->item(prefix+"size")[2].toInt(); + } + else // try to load the font even we are missing important settings + { // this still can cause crashes! + kdDebug(66666) << "font height/width missing, this skin might crash noatun!" << endl; + + mWidth = mText.width() / strlen(mString[0]); + + if ( (prefix=="timefont") || (prefix=="volumefont") || (prefix=="pitchfont") ) + mHeight = mText.height(); + else + mHeight = mText.height()/3; + } + +// kdDebug(66666) << prefix << " h: " << mHeight << " w: " << mWidth << endl; + + // fix for wrong numbers in rc (a skin named steelforged needs that) + if ( mHeight > mText.height() ) + mHeight = mText.height(); + + // Stupid Skin authors tend to forget keys :/ + if ( parent->exist(prefix+"spacing") ) + mSpacing = parent->item(prefix+"spacing")[1].toInt(); + else + mSpacing = 0; // FIXME: What's default for this in kjfol??? + + if ( parent->exist(prefix+"transparent") ) + mTransparent = (bool)parent->item(prefix+"transparent")[1].toInt(); + else + mTransparent = true; // transparency seems to be default in kjfol + + // define color in font that will be transparent later on + if ( mTransparent ) + { + QImage ibackground = mText.convertToImage(); + mTransparentRGB = ibackground.pixel( ibackground.width()-1, ibackground.height()-1 ); +// kdDebug(66666) << "color (" << qRed(mTransparentRGB) << "," << qGreen(mTransparentRGB) << "," << qBlue(mTransparentRGB) << ") will be transparent for " << prefix.latin1() << endl; + mTextMask = KJWidget::getMask(ibackground,mTransparentRGB); + } + + mUseSysFont = KJLoader::kjofol->prefs()->useSysFont(); + sysFontMetrics = 0L; + if (mUseSysFont) + recalcSysFont(); +} + +void KJFont::recalcSysFont(void) +{ +// kdDebug(66666) << k_funcinfo << "called." << endl; + + mUseSysFont = KJLoader::kjofol->prefs()->useSysFont(); + if (!mUseSysFont) + return; + sysFont = QFont(KJLoader::kjofol->prefs()->sysFont()); + sysFont.setStyleStrategy( QFont::NoAntialias ); + if ( sysFontMetrics ) + delete sysFontMetrics; + sysFontColor = KJLoader::kjofol->prefs()->sysFontColor(); + +// kdDebug(66666) << "mHeight=" << mHeight << endl; + + int fSize; + for(fSize = mHeight; fSize>=4; fSize--) + { + sysFont.setPixelSize ( fSize ); + sysFontMetrics = new QFontMetrics(sysFont); +// kdDebug(66666) << "wanted fSize=" << fSize << ", metric h=" << sysFontMetrics->height() << endl; + // either found a small enough font or found no proper font at all + if ( sysFontMetrics->height() <= mHeight || fSize==4 ) + { +// kdDebug(66666) << "stopping @ fSize=" << fSize << ", metric h=" << sysFontMetrics->height() << endl; + return; + } + delete sysFontMetrics; + } +} + +QPixmap KJFont::draw(const QCString &str, int wide, const QPoint &pos) const +{ + if ( mUseSysFont ) + return drawSysFont(str,wide,pos); + else + return drawPixmapFont(str,wide,pos); +} + +QPixmap KJFont::drawSysFont(const QCString &s, int wide, const QPoint &pos) const +{ +// kdDebug(66666) << k_funcinfo << "BEGIN, s='" << s << "'" << endl; + QPoint to(pos); + QString string(s); + + int stringWidth = sysFontMetrics->width( string ); +// kdDebug(66666) << "final metrics; w=" << stringWidth << ", h=" << sysFontMetrics->height() << endl; + + QPixmap region( + (stringWidth > wide ? stringWidth : wide), + mHeight); + QPainter rp(®ion); // region painter + + QBitmap regionMask( + (stringWidth > wide ? stringWidth : wide), + mHeight, true); // fully transparent mask + QPainter mp(®ionMask); // mask painter + +// kdDebug(66666) << "region; w=" << region.width() << ", h=" << region.height() << endl; + + int freeSpace=0; + // center string into pixmap if its chars won't fill the whole pixmap + if ( stringWidth < wide ) + { + freeSpace = wide - stringWidth; + mp.fillRect ( to.x(), 0, (freeSpace/2), mHeight, Qt::color0 ); + to += QPoint ( (freeSpace/2), 0 ); +// kdDebug(66666) << "centering text, freeSpace=" << freeSpace << endl; + } + + rp.setFont(sysFont); + rp.setPen(sysFontColor); + rp.drawText(to.x(), to.y(), region.width()-freeSpace, mHeight, Qt::AlignLeft|Qt::AlignTop, string); + + mp.setFont(sysFont); + mp.setPen(Qt::color1); + mp.drawText(to.x(), to.y(), region.width()-freeSpace, mHeight, Qt::AlignLeft|Qt::AlignTop, string); + + to += QPoint(region.width()-freeSpace,0); +// kdDebug(66666) << "text width=" << region.width()-freeSpace << endl; + + if (freeSpace > 0) + { + mp.fillRect ( to.x(), 0, (freeSpace/2), mHeight, Qt::color0 ); + to += QPoint ( (freeSpace/2), 0 ); +// kdDebug(66666) << "centering text, freeSpace=" << freeSpace << endl; + } + + region.setMask( regionMask ); +// kdDebug(66666) << "width: " << wide << "|end after drawing: " << to.x() << endl; +// kdDebug(66666) << k_funcinfo << "END" << endl << endl; + return region; +} + +QPixmap KJFont::drawPixmapFont(const QCString &str, int wide, const QPoint &pos) const +{ +// kdDebug(66666) << k_funcinfo << "BEGIN" << endl; + QPoint to(pos); + + QCString string = str.lower(); + QPixmap region( + (string.length()*mWidth+string.length()*mSpacing > (unsigned int)wide + ? string.length()*mWidth+string.length()*mSpacing : wide), + mHeight); + + QBitmap regionMask( + (string.length()*mWidth+string.length()*mSpacing > (unsigned int)wide + ? string.length()*mWidth+string.length()*mSpacing : wide), + mHeight, true); // fully transparent mask + QPainter mask( ®ionMask ); + +// kdDebug(66666) << "draw: {" << str << "}" << endl; + + int freeSpace=0; + // center string into pixmap if its chars won't fill the whole pixmap + if ( string.length()*mWidth+string.length()*mSpacing < (unsigned int)wide ) + { + freeSpace = wide - string.length()*mWidth+string.length()*mSpacing; + mask.fillRect ( to.x(), 0, (freeSpace/2), mHeight, Qt::color0 ); + to += QPoint ( (freeSpace/2), 0 ); + } + +// kdDebug(66666) << k_funcinfo << "pixmap width=" << region.width() << endl; + + // draw every char and add spacing in between these chars if defined + unsigned int stringLength(string.length()); + for ( unsigned int charPos=0; charPos < stringLength; charPos++ ) + { + char c = string[charPos]; // the character to be drawn next + + drawCharacter(®ion, ®ionMask, to, c); + to += QPoint(mWidth, 0); + + // draw according to "spacing" + if ( (charPos < string.length()-1) && mSpacing > 0 ) + { // make the spacing-area transparent + mask.fillRect ( to.x(), 0, mSpacing, mHeight, Qt::color0 ); + to += QPoint ( mSpacing, 0 ); + } + } + + if (freeSpace > 0) + { + mask.fillRect ( to.x(), 0, (freeSpace/2), mHeight, Qt::color0 ); + to += QPoint ( (freeSpace/2), 0 ); + } + + region.setMask( regionMask ); +// kdDebug(66666) << "width: " << wide << "|end after drawing: " << to.x() << endl; + return region; +} + +void KJFont::drawCharacter(QPixmap *dev, QBitmap *devMask, const QPoint &to, char c) const +{ + QPoint src=charSource(c); + int x=src.x(); + int y=src.y(); + int xs=mWidth; + int ys=mHeight; + + bitBlt(dev, to, &mText, QRect(x,y,xs,ys), Qt::CopyROP); + + // bitBlt mask for transparency + if ( mTransparent ) + { + bitBlt(devMask, to, &mTextMask, QRect(x,y,xs,ys), Qt::OrROP); + } + else // fill mask + { + QPainter tempPainter (devMask); + tempPainter.fillRect ( to.x(), 0, xs,ys, Qt::color1 ); + } +} + +// needed for strchr +#include <string.h> + +// searches for top/left coordinate of a given character inside the font-pixmap +QPoint KJFont::charSource(char c) const +{ + for (int i=0; i<3; i++) + { + const char *pos = strchr(mString[i], c); + + if (!pos) continue; + return QPoint(mWidth*((int)(pos-mString[i])), mHeight*i); + } + + return charSource(mNullChar); +} diff --git a/noatun/modules/kjofol-skin/kjfont.h b/noatun/modules/kjofol-skin/kjfont.h new file mode 100644 index 00000000..4ea5319b --- /dev/null +++ b/noatun/modules/kjofol-skin/kjfont.h @@ -0,0 +1,50 @@ +#ifndef KJFONT_H +#define KJFONT_H + +#include <qstring.h> +#include <qpixmap.h> +#include <qbitmap.h> +#include <qfont.h> + +class KJLoader; + +class KJFont +{ +public: + KJFont(const QString &prefix, KJLoader *parent); + // draw the string str to dev at position pos, within rectangle limit in relation to pos + QPixmap draw(const QCString &str, int wide, const QPoint &pt=QPoint(0,0)) const; + QPixmap draw(const QString &str, int wide, const QPoint &pt=QPoint(0,0)) const + { return draw(QCString(str.latin1()), wide, pt); } + + int fontHeight() const {return mHeight;} + int fontWidth() const {return mWidth;} + int fontSpacing() const {return mSpacing;} + bool isTransparent() const {return mTransparent;} + + // !!! Call if you changed the systemfont !!! + void recalcSysFont(void); + +protected: + QPixmap drawSysFont(const QCString &s, int wide, const QPoint &pos=QPoint(0,0)) const; + QPixmap drawPixmapFont(const QCString &, int, const QPoint &pos=QPoint(0,0)) const; + + void drawCharacter(QPixmap *dev, QBitmap *devMask, const QPoint &to, char c) const; + QPoint charSource(char c) const; + +private: + QPixmap mText; + QBitmap mTextMask; + QRgb mTransparentRGB; // this color will be transparent + int mSpacing; + int mWidth, mHeight; + bool mTransparent; // indicates wether there's transparency + const char *mString[3]; + char mNullChar; + QFontMetrics *sysFontMetrics; + QFont sysFont; + QColor sysFontColor; + bool mUseSysFont; +}; + +#endif diff --git a/noatun/modules/kjofol-skin/kjguisettingswidget.ui b/noatun/modules/kjofol-skin/kjguisettingswidget.ui new file mode 100644 index 00000000..e2b4f784 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjguisettingswidget.ui @@ -0,0 +1,465 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>KJGuiSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KJGuiSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>690</width> + <height>454</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>Layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>ButtonGroup1</cstring> + </property> + <property name="title"> + <string>Visualization</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>visScope</cstring> + </property> + <property name="text"> + <string>Oscillo&scope</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>visAnalyzer</cstring> + </property> + <property name="text"> + <string>&Analyzer</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>visNone</cstring> + </property> + <property name="text"> + <string>&None</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel1_3</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>U&pdate every:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>visTimerValue</cstring> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>visTimerValue</cstring> + </property> + <property name="value"> + <number>30</number> + </property> + <property name="minValue"> + <number>20</number> + </property> + <property name="maxValue"> + <number>1000</number> + </property> + <property name="suffix"> + <string>ms</string> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>GroupBox1</cstring> + </property> + <property name="title"> + <string>Pitch</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel1_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Lower limit:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>minPitch</cstring> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>minPitch</cstring> + </property> + <property name="value"> + <number>50</number> + </property> + <property name="minValue"> + <number>50</number> + </property> + <property name="maxValue"> + <number>98</number> + </property> + <property name="suffix"> + <string>%</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel1_2_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Upper limit:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>maxPitch</cstring> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>maxPitch</cstring> + </property> + <property name="value"> + <number>200</number> + </property> + <property name="minValue"> + <number>102</number> + </property> + <property name="maxValue"> + <number>200</number> + </property> + <property name="suffix"> + <string>%</string> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + </hbox> + </widget> + <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>displayTooltips</cstring> + </property> + <property name="text"> + <string>Display &tooltips</string> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>displaySplash</cstring> + </property> + <property name="text"> + <string>Display splash sc&reen</string> + </property> + </widget> + <spacer row="5" column="0"> + <property name="name"> + <cstring>Spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>60</height> + </size> + </property> + </spacer> + <widget class="QLayoutWidget" row="4" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>Layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel1</cstring> + </property> + <property name="text"> + <string>T&itle display scrolling speed:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>titleScrollSpeed</cstring> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel2</cstring> + </property> + <property name="text"> + <string>Slow</string> + </property> + </widget> + <widget class="QSlider"> + <property name="name"> + <cstring>titleScrollSpeed</cstring> + </property> + <property name="minimumSize"> + <size> + <width>80</width> + <height>0</height> + </size> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="maxValue"> + <number>3</number> + </property> + <property name="pageStep"> + <number>1</number> + </property> + <property name="value"> + <number>2</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="tickmarks"> + <enum>NoMarks</enum> + </property> + <property name="tickInterval"> + <number>1</number> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel3</cstring> + </property> + <property name="text"> + <string>Fast</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QGroupBox" row="3" column="0"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>System Font</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KColorCombo" row="2" column="1"> + <property name="name"> + <cstring>cmbSysFontColor</cstring> + </property> + <property name="color"> + <color> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>txtFontColor</cstring> + </property> + <property name="text"> + <string>Color:</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>txtFont</cstring> + </property> + <property name="text"> + <string>Font:</string> + </property> + </widget> + <widget class="KFontCombo" row="1" column="1"> + <property name="name"> + <cstring>cmbSysFont</cstring> + </property> + <property name="urlDropsEnabled" stdset="0"> + <bool>false</bool> + </property> + <property name="editable" stdset="0"> + <bool>false</bool> + </property> + </widget> + <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>useSysFont</cstring> + </property> + <property name="text"> + <string>Use system font</string> + </property> + </widget> + </grid> + </widget> + <spacer row="3" column="1"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>140</width> + <height>21</height> + </size> + </property> + </spacer> + </grid> +</widget> +<customwidgets> +</customwidgets> +<tabstops> + <tabstop>visScope</tabstop> + <tabstop>visAnalyzer</tabstop> + <tabstop>visNone</tabstop> + <tabstop>visTimerValue</tabstop> + <tabstop>minPitch</tabstop> + <tabstop>maxPitch</tabstop> + <tabstop>displayTooltips</tabstop> + <tabstop>displaySplash</tabstop> + <tabstop>useSysFont</tabstop> + <tabstop>cmbSysFont</tabstop> + <tabstop>cmbSysFontColor</tabstop> + <tabstop>titleScrollSpeed</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>kcolorcombo.h</includehint> + <includehint>kfontcombo.h</includehint> + <includehint>klineedit.h</includehint> +</includehints> +</UI> diff --git a/noatun/modules/kjofol-skin/kjloader.cpp b/noatun/modules/kjofol-skin/kjloader.cpp new file mode 100644 index 00000000..11f96b7a --- /dev/null +++ b/noatun/modules/kjofol-skin/kjloader.cpp @@ -0,0 +1,832 @@ +/*************************************************************************** + kjloader.cpp - The KJfol-GUI itself + -------------------------------------- + Maintainer: Stefan Gehn <sgehn@gmx.net> + + ***************************************************************************/ + +// local includes +#include "kjloader.h" +#include "kjloader.moc" +#include "kjwidget.h" +#include "kjbackground.h" +#include "kjbutton.h" +#include "kjfont.h" +#include "kjseeker.h" +#include "kjsliders.h" +#include "kjtextdisplay.h" +#include "kjvis.h" +#include "kjprefs.h" +#include "kjequalizer.h" + +#include "helpers.cpp" + +// arts-includes, needed for pitch +#include <artsmodules.h> +#include <reference.h> +#include <soundserver.h> +#include <kmedia2.h> + +// noatun-specific includes +#include <noatun/engine.h> +#include <noatunarts/noatunarts.h> +#include <noatun/stdaction.h> +#include <noatun/app.h> +#include <noatun/player.h> +#include <noatun/vequalizer.h> + +// system includes +#include <string.h> +#include <math.h> +#include <stdlib.h> +#include <unistd.h> + +#include <qdragobject.h> +#include <qimage.h> +#include <qbitmap.h> +#include <qpixmap.h> +#include <qcursor.h> +#include <qpainter.h> +#include <qtooltip.h> +#include <qptrvector.h> +#include <qvbox.h> +#include <qlabel.h> + +#include <kaction.h> +#include <kdebug.h> +#include <kfiledialog.h> +#include <khelpmenu.h> +#include <kstdaction.h> +#include <kpopupmenu.h> +#include <klocale.h> +#include <kglobalsettings.h> +#include <kglobal.h> +#include <kstandarddirs.h> +#include <knotifyclient.h> +#include <kpixmapeffect.h> +#include <kurldrag.h> + +#include <kwin.h> +#include <kiconloader.h> + +class KJToolTip : public QToolTip +{ +public: + KJToolTip(KJLoader *parent) + : QToolTip(parent), mParent(parent) + {} + +protected: + virtual void maybeTip(const QPoint &p) + { + if ( !mParent->prefs()->displayTooltips() ) + return; + + QPtrList<KJWidget> things=mParent->widgetsAt(p); + for (KJWidget *i=things.first(); i!=0; i=things.next()) + { + QString string=i->tip(); + if (string.length()) + { + tip(i->rect(), string); + return; + } + } + } + +private: + KJLoader *mParent; +}; + + +KJLoader *KJLoader::kjofol=0; + + +KJLoader::KJLoader() + : QWidget(0, "NoatunKJLoader", + WType_TopLevel | WStyle_NoBorder | WRepaintNoErase ), + UserInterface(), + moving(false), + mClickedIn(0), + mText(0), + mNumbers(0), + mVolumeFont(0), + mPitchFont(0), + splashScreen(0) +{ + kjofol = this; + + mTooltips = new KJToolTip(this); + + // Windowname and Icon + setCaption(i18n("Noatun")); + setIcon(SmallIcon("noatun")); + setAcceptDrops(true); + + // We're going to draw over everything, there is no point in drawing the grey background first + setBackgroundMode(NoBackground); + + // used for dockmode + mWin = new KWinModule(); + + subwidgets.setAutoDelete(true); + + mPrefs = new KJPrefs(this); + connect ( mPrefs, SIGNAL(configChanged()), this, SLOT(readConfig()) ); + + QString skin = mPrefs->skin(); + if ( QFile(skin).exists() ) + { + loadSkin(skin); + } + else + { + KNotifyClient::event(winId(), "warning", + i18n("There was trouble loading skin %1. Please select another skin file.").arg(skin)); + napp->preferences(); + } + + mHelpMenu = new KHelpMenu(this, kapp->aboutData()); + connect(napp->player(), SIGNAL(timeout()), SLOT(timeUpdate())); + connect(napp->player(), SIGNAL(stopped()), SLOT(timeUpdate())); + connect(napp->player(), SIGNAL(newSong()), SLOT(newSong())); + + connect(napp, SIGNAL(hideYourself()), SLOT(hide())); + connect(napp, SIGNAL(showYourself()), SLOT(show())); +// KStdAction::quit(napp, SLOT(quit()), actionCollection()); + + QApplication::restoreOverrideCursor(); +// newSong(); +} + +QPtrList<KJWidget> KJLoader::widgetsAt(const QPoint &pt) const +{ + QPtrList<KJWidget> things; + for ( QPtrListIterator<KJWidget> i(subwidgets); i.current(); ++i ) + if ( (*i)->rect().contains(pt) ) + things.append((*i)); + + return things; +} + +void KJLoader::removeChild(KJWidget *c) +{ + if ( mClickedIn == c ) + mClickedIn = 0; + if (subwidgets.findRef(c) != -1) + subwidgets.take(); +} + +void KJLoader::addChild(KJWidget *c) +{ + subwidgets.append(c); +} + +// The BIG one ;) +// this methode does all the hard work on loading these weird skins +void KJLoader::loadSkin(const QString &file) +{ +// kdDebug(66666) << "<KJLoader::loadSkin(const QString &file)>" << endl; +// kdDebug(66666) << " file = " << file.latin1() << endl; + + if ( file == mCurrentSkin ) // we don't load the same skin again + return; + + mCurrentSkin = file; + + // don't overwrite path to *.rc when we are loading dock- or winshade-mode + if ( (file != mCurrentWinshadeModeSkin) && (file != mCurrentDockModeSkin) ) + { + mCurrentDefaultSkin = file; +// kdDebug(66666) << " setting mCurrentDefaultSkin: '" << file.latin1() << "'" << endl; + } + unloadSkin(); + + Parser::open( filenameNoCase(file) ); + + KJPitchText *pitchText=0; + KJVolumeText *volumeText=0; + mText = 0; + mNumbers = 0; + mVolumeFont = 0; + mPitchFont = 0; + + if ( exist("splashscreen") && mPrefs->displaySplash() ) + showSplash(); + + if ( (file != mCurrentWinshadeModeSkin) && (file != mCurrentDockModeSkin) ) + { + if ( exist("dockmodercfile") ) + { + // set path to dockmode rc-file (its not always skinname.dck) + mCurrentDockModeSkin = file.left(file.findRev("/")+1) + (item("dockmodercfile")[1]); + mDockPosition = item("dockmodeposition")[1].toInt(); + mDockPositionX = item("dockmodepositionxy")[1].toInt(); + mDockPositionY = item("dockmodepositionxy")[2].toInt(); + } + else // NO DockMode + mCurrentDockModeSkin=""; + + if ( exist("winshademodercfile") ) + mCurrentWinshadeModeSkin = file.left(file.findRev("/")+1) + (item("winshademodercfile")[1]); + else // no WinshadeMode + mCurrentWinshadeModeSkin=""; + } + + // Font-loading + if ( exist("fontimage") ) + mText = new KJFont("font", this); + + if ( exist("timefontimage") ) + mNumbers = new KJFont("timefont", this); + + if (exist("volumefontimage")) + mVolumeFont = new KJFont("volumefont", this); + + // our skin-background, There has to be one so no check with exist() + subwidgets.append( new KJBackground(this) ); + + if ( exist("pitchtext") ) + { + if (exist("pitchfontimage")) + { + mPitchFont = new KJFont("pitchfont", this); + } + else + { + mPitchFont = mNumbers; + kdDebug(66666) << "no pitchfont but pitchtext!" << endl; + kdDebug(66666) << "replacing pitchfont with timefont" << endl; + } + subwidgets.append( pitchText=new KJPitchText(item("pitchtext"), this) ); + } + + if (exist("volumetext")) + subwidgets.append(volumeText=new KJVolumeText(item("volumetext"), this)); + + if ( exist("volumecontroltype") ) + { + if ( item("volumecontroltype")[1] == "bmp" ) + { + KJVolumeBMP *b; + subwidgets.append(b=new KJVolumeBMP(item("volumecontrolbutton"), this)); + b->setText(volumeText); + } + else if ( item("volumecontroltype")[1] == "bar" ) + { + KJVolumeBar *b; + subwidgets.append(b=new KJVolumeBar(item("volumecontrolbutton"), this)); + b->setText(volumeText); + } +/* else + { + kdDebug(66666) << "unknown volumecontrol: " << item("volumecontroltype")[1].latin1() << endl; + } */ + } + else + { + kdDebug(66666) << "guessing type of volumecontrol" << endl; + if (exist("volumecontrolbutton") && + exist("volumecontrolimage") && + exist("volumecontrolimagexsize") && + exist("volumecontrolimageposition") && + exist("volumecontrolimagenb") ) + { + KJVolumeBMP *b; + subwidgets.append(b=new KJVolumeBMP(item("volumecontrolbutton"), this)); + b->setText(volumeText); + } + else if (exist("volumecontrolimage") && + exist("volumecontrolbutton") ) + { + KJVolumeBar *b; + subwidgets.append(b=new KJVolumeBar(item("volumecontrolbutton"), this)); + b->setText(volumeText); + } +/* else + { + kdDebug(66666) << " no volumecontrol" << endl; + } */ + } + + if (exist("pitchcontrolbutton") && + exist("pitchcontrolimage") && + exist("pitchcontrolimagexsize") && + exist("pitchcontrolimageposition") && + exist("pitchcontrolimagenb") ) + { +// kdDebug(66666) << "added KJPitchBMP" << endl; + KJPitchBMP *b; + subwidgets.append(b=new KJPitchBMP(item("pitchcontrolbutton"), this)); + b->setText(pitchText); + } + else + { + // make sure we reset speed to 100% as the user won't be able + // to reset it without a pitchcontrol + Arts::PlayObject playobject = napp->player()->engine()->playObject(); + Arts::PitchablePlayObject pitchable = Arts::DynamicCast(playobject); + + if ( !pitchable.isNull() ) + { + if ( pitchable.speed() > 1.0f ) + pitchable.speed(1.0f); + } + } + + if (exist("filenamewindow")) + subwidgets.append(new KJFilename(item("filenamewindow"), this)); + + if (exist("mp3timewindow")) + subwidgets.append(new KJTime(item("mp3timewindow"), this)); + + if (exist("mp3kbpswindow")) + subwidgets.append(new KJFileInfo(item("mp3kbpswindow"), this)); + + if (exist("mp3khzwindow")) + subwidgets.append(new KJFileInfo(item("mp3khzwindow"), this)); + + if (exist("analyzerwindow")) + { + int vistype = mPrefs->visType(); + switch ( vistype ) + { + case KJVisScope::Null: + subwidgets.append(new KJNullScope(item("analyzerwindow"), this)); + break; + case KJVisScope::FFT: + subwidgets.append(new KJFFT(item("analyzerwindow"), this)); + break; + case KJVisScope::StereoFFT: + subwidgets.append(new KJStereoFFT(item("analyzerwindow"), this)); + break; + case KJVisScope::Mono: + subwidgets.append(new KJScope(item("analyzerwindow"), this)); + break; + } + } + + if (exist("EqualizerWindow")) + subwidgets.append(new KJEqualizer(item("EqualizerWindow"), this)); + + // I cant believe it, there are skins without a seeker, now THATS stupid :) + if (exist("seekregion")) + QTimer::singleShot(0, this, SLOT(loadSeeker())); + + // all the regular buttons + for (QDictIterator<QStringList> i(*this); i.current(); ++i) + { + QString d=i.currentKey(); + if(d.contains("button") && + !d.startsWith("playlistwindow") && // don't add buttons that belong to the playlistwindow + d != "pitchcontrolbutton" && // both already handled above as they aren't buttons but sliders + d != "volumecontrolbutton" && + d != "spectrumanalyzerbutton" && // FIXME: unsupported button + d != "oscilloscopebutton" && // FIXME: unsupported button + i.count() >= 7 ) + { + subwidgets.append(new KJButton(*(*i), this)); + } + } + + show(); + conserveMemory(); + + repaint(); + + // update displays if we are already playing + // This happens while changing skins + if (napp->player()->isPlaying()) + newSong(); + +// kdDebug(66666) << "</KJLoader::loadSkin(const QString &file)>" << endl; +} + +void KJLoader::loadSeeker() +{ + subwidgets.append(new KJSeeker(item("seekregion"), this)); +} + +void KJLoader::unloadSkin() +{ +// kdDebug(66666) << "<KJLoader::unloadSkin()>" << endl; + + KWin::clearState(winId(), NET::SkipTaskbar); + +// kdDebug(66666) << " freeing subwidgets" << endl; + subwidgets.clear(); + + // This is special because mPitchfont can also point to mNumbers + // as some skins use the NumberFont for pitchtext + if ( mPitchFont && mPitchFont != mNumbers ) + { +// kdDebug(66666) << " freeing mPitchFont" << endl; + delete mPitchFont; + } + + if ( mText ) + { +// kdDebug(66666) << " freeing mText" << endl; + delete mText; + } + + if ( mNumbers ) + { +// kdDebug(66666) << " freeing mNumbers" << endl; + delete mNumbers; + } + + if ( mVolumeFont ) + { +// kdDebug(66666) << " freeing mVolumeFont" << endl; + delete mVolumeFont; + } + +// kdDebug(66666) << "</KJLoader::unloadSkin()>" << endl; +} + +void KJLoader::minimize() +{ +// kdDebug(66666) << "KJLoader::minimize()" << endl; + showMinimized(); +} + +void KJLoader::closeEvent(QCloseEvent*) +{ +// kdDebug(66666) << "KJLoader::closeEvent(QCloseEvent*)" << endl; + unload(); +} + +void KJLoader::dragEnterEvent(QDragEnterEvent *event) +{ + // accept uri drops only + event->accept(KURLDrag::canDecode(event)); +} + +void KJLoader::dropEvent(QDropEvent *event) +{ + KURL::List urls; + if ( KURLDrag::decode(event,urls) ) + { + for ( KURL::List::iterator it = urls.begin(); it != urls.end(); ++it ) + napp->player()->openFile((*it), false); + } +} + +void KJLoader::wheelEvent(QWheelEvent *e) +{ // from QT-Docu: delta() is 120 for one step + if (e->state() & ControlButton) + napp->player()->setVolume ( napp->player()->volume() + (e->delta()/8) ); // 15% volumechange + else + napp->player()->setVolume ( napp->player()->volume() + (e->delta()/24) ); // 5% volumechange +} + +// now for some dockmode stuff +void KJLoader::switchToDockmode() +{ +// kdDebug(66666) << "KJLoader::switchToDockmode()" << endl; + loadSkin( mCurrentDockModeSkin ); + + connect(mWin, SIGNAL(activeWindowChanged(WId)), this, SLOT(slotWindowActivate(WId))); + connect(mWin, SIGNAL(windowRemoved(WId)), this, SLOT(slotWindowRemove(WId))); + connect(mWin, SIGNAL(stackingOrderChanged()), this, SLOT(slotStackingChanged())); + connect(mWin, SIGNAL(windowChanged(WId)), this, SLOT(slotWindowChange(WId))); + connect(mWin, SIGNAL(currentDesktopChanged(int)), this, SLOT(slotDesktopChange(int))); + + WId activeWin = mWin->activeWindow(); + if (activeWin && (activeWin != winId())) + { + KWin::WindowInfo winInf = KWin::windowInfo(activeWin, NET::WMKDEFrameStrut); + if(winInf.valid()) + { + mDockToWin = activeWin; + mDockWindowRect = winInf.frameGeometry(); + slotWindowActivate(mDockToWin); + hide(); + restack(); + } + } +} + +void KJLoader::returnFromDockmode() +{ +// kdDebug(66666) << "KJLoader::returnFromDockmode()" << endl; + mWin->disconnect(); + loadSkin(mCurrentDefaultSkin); +} + +void KJLoader::slotWindowActivate(WId win) +{ + if(mCurrentSkin != mCurrentDockModeSkin) + return; + + KWin::WindowInfo winInf = KWin::windowInfo( + win, NET::WMWindowType); + if((win != winId()) && winInf.valid()) + { + // ensure we dock to the active window _except_ our own + // and stick to the last window if the NEW current one is a desktop + NET::WindowType winType = winInf.windowType( + NET::NormalMask|NET::DesktopMask|NET::DockMask| + NET::ToolbarMask|NET::MenuMask|NET::DialogMask| + NET::OverrideMask|NET::TopMenuMask|NET::UtilityMask| + NET::SplashMask); + + if(winType == NET::Unknown || winType == NET::Normal || winType == NET::Dialog) + { + //kdDebug(66666) << k_funcinfo << "Now docking to window: " << win << endl; + mDockToWin = win; + } + + } + + if(mDockToWin != 0) + { + mDockWindowRect = KWin::windowInfo(mDockToWin, NET::WMKDEFrameStrut).frameGeometry(); + /*kdDebug(66666) << k_funcinfo << "winrect: " << mDockWindowRect.x() << ", " << + mDockWindowRect.y() << endl;*/ + switch ( mDockPosition ) + { + case 0: + move( mDockWindowRect.x() + mDockPositionX, mDockWindowRect.y() + mDockPositionY ); + break; + case 2: + move( mDockWindowRect.x() + mDockPositionX, mDockWindowRect.y() + mDockWindowRect.height() + mDockPositionY ); + break; + } + + if(!isVisible()) + { + show(); + KWin::setState(winId(), NET::SkipTaskbar); + } + restack(); + } + else + { + // We don't want to do anything until a window comes into + // focus. + //kdDebug(66666) << "No window having focus, hiding" << endl; + hide(); + } + +// kdDebug(66666) << "END slotWindowActivate()" << endl; +} + +void KJLoader::slotWindowRemove(WId win) +{ +// kdDebug(66666) << "START slotWindowRemove()" << endl; + if ( mCurrentSkin != mCurrentDockModeSkin ) + return; + + if (win == mDockToWin) + { +// kdDebug(66666) << "our window removed: " << win << endl; + hide(); + mDockToWin = 0; + } +// kdDebug(66666) << "END slotWindowRemove()" << endl; +} + +void KJLoader::slotWindowChange(WId win) +{ +// kdDebug(66666) << "START slotWindowChange()" << endl; + if ( mCurrentSkin != mCurrentDockModeSkin ) + return; + + if ( win == mDockToWin ) + { +// kdDebug(66666) << "changed our window:" << win << endl; + KWin::WindowInfo winInf = KWin::windowInfo( + mDockToWin, NET::WMKDEFrameStrut|NET::WMWindowType| + NET::WMState|NET::XAWMState|NET::WMDesktop); + + if(!winInf.valid()) + { + /*kdDebug(66666) << k_funcinfo << + "No valid WindowInfo for tracked window: " << win << endl;*/ + hide(); + mDockToWin = 0; + return; + } + + NET::WindowType winType = winInf.windowType( + NET::NormalMask|NET::DesktopMask|NET::DockMask| + NET::ToolbarMask|NET::MenuMask|NET::DialogMask| + NET::OverrideMask|NET::TopMenuMask|NET::UtilityMask| + NET::SplashMask); + + if ( + (winInf.state() & NET::Hidden) || + (winInf.state() & NET::FullScreen) || + (winType != NET::Unknown && winType != NET::Normal && winType != NET::Dialog) + ) + { + /*kdDebug(66666) << k_funcinfo << + "Our window changed: " << win << + ". Either iconified or special window" << endl;*/ + // target-window has been iconified or window is desktop + hide(); + mDockToWin = 0; + return; + } + + // Size or position of target-window changed. + mDockWindowRect = winInf.frameGeometry(); + /*kdDebug(66666) << k_funcinfo << "winrect: " << mDockWindowRect.x() << ", " << + mDockWindowRect.y() << endl;*/ + // Ensure we are still on the window. + switch(mDockPosition) + { + case 0: + { + move( + mDockWindowRect.x() + mDockPositionX, + mDockWindowRect.y() + mDockPositionY); + break; + } + case 2: + { + move( + mDockWindowRect.x() + mDockPositionX, + mDockWindowRect.y() + mDockWindowRect.height() + mDockPositionY); + break; + } + } + restack(); + } +} + +void KJLoader::slotDesktopChange(int) +{ +// kdDebug(66666) << "START slotDesktopChange()" << endl; + if ( mCurrentSkin != mCurrentDockModeSkin ) + return; + + hide(); + mDockToWin = 0L; +// kdDebug(66666) << "END slotDesktopChange()" << endl; +} + +void KJLoader::slotStackingChanged() +{ +// kdDebug(66666) << "START slotStackingChanged()" << endl; + if ( mCurrentSkin != mCurrentDockModeSkin ) + return; + + // We seem to get this signal before the window has been restacked, + // so we just schedule a restack. + QTimer::singleShot ( 10, this, SLOT(restack()) ); + +// kdDebug(66666) << "END slotStackingChanged()" << endl; +} + +// Set the animation's stacking order to be just above the target window's +// window decoration, or on top. +void KJLoader::restack() +{ +// kdDebug(66666) << "START restack()" << endl; + + if ( !mDockToWin ) + { +// kdDebug(66666) << "No window to dock to, no restacking" << endl; + hide(); + return; + } + + // simply raise ourselves to the top + raise(); + // and then ensure our target-window gets focus +// NET::setActiveWindow (mDockToWin); + +// kdDebug(66666) << "END restack()" << endl; +} + +KJLoader::~KJLoader() +{ +// kdDebug(66666) << "KJLoader::~KJLoader()" << endl; + delete mWin; +} + +void KJLoader::paintEvent(QPaintEvent *e) +{ + QPainter p(this); + for (KJWidget* i=subwidgets.first(); i!=0; i=subwidgets.next()) + if (i->rect().intersects(e->rect())) + i->paint(&p, e->rect().intersect(i->rect())); +// QWidget::paintEvent(e); +} + +void KJLoader::mouseMoveEvent(QMouseEvent *e) +{ + if (moving) + { + move ( QCursor::pos()-mMousePoint ); + return; + } + + +// QWidget::mouseMoveEvent(e); + // not on background but on a widget: pass event to subwidget + if ( !moving && mClickedIn && subwidgets.findRef(mClickedIn) != -1 ) + { + mClickedIn->mouseMove ( + e->pos()-mClickedIn->rect().topLeft(), + mClickedIn->rect().contains(mapFromGlobal(QCursor::pos())) ); + } +} + +void KJLoader::mousePressEvent(QMouseEvent *e) +{ +// kdDebug(66666) << "KJLoader::mousePressEvent(QMouseEvent *e)" << endl; + +// QWidget::mousePressEvent(e); + + if ( e->button()==RightButton ) + NoatunStdAction::ContextMenu::showContextMenu(); + else /* if ( e->button()==LeftButton ) */ + { + mMousePoint = mapFromGlobal(QCursor::pos()); + // try to find a KJWidget that is here + for (KJWidget* i=subwidgets.first(); i!=0; i=subwidgets.next()) + if (i->rect().contains(mMousePoint)) + { + if (i->mousePress(mMousePoint-i->rect().topLeft())) + { + mClickedIn=i; + return; + } + } + // can't find a widget, so move the window + if ( mCurrentSkin != mCurrentDockModeSkin) + moving = true; + } +} + +void KJLoader::mouseReleaseEvent(QMouseEvent */*e*/) +{ +// kdDebug(66666) << "KJLoader::mouseReleaseEvent(QMouseEvent *e)" << endl; + +// QWidget::mouseReleaseEvent(e); + + if (!moving && mClickedIn && subwidgets.findRef(mClickedIn)!=-1) + { + mClickedIn->mouseRelease(mapFromGlobal(QCursor::pos())- + mClickedIn->rect().topLeft(), + mClickedIn->rect().contains( + mapFromGlobal(QCursor::pos()))); + mClickedIn=0; + } + + moving = false; +} + +void KJLoader::timeUpdate() +{ + for (KJWidget* widget=subwidgets.first(); widget; widget=subwidgets.next()) + widget->timeUpdate(napp->player()->getTime()/1000); // pass seconds to all Widgets +} + +void KJLoader::newSong() +{ + if (!napp->player()->current()) + return; + for ( KJWidget* i=subwidgets.first(); i!=0; i=subwidgets.next() ) + i->newFile(); +} + +void KJLoader::readConfig() +{ +// kdDebug(66666) << "KJLoader::readConfig()" << endl; + for (KJWidget* i=subwidgets.first(); i!=0; i=subwidgets.next()) + i->readConfig(); +} + +void KJLoader::showSplash() +{ + splashScreen = new QLabel( 0L, "SplashScreen", + WType_TopLevel | WStyle_NoBorder | WRepaintNoErase | WX11BypassWM ); + + QPixmap splashPix = pixmap(item("splashscreen")[1]); + splashScreen->setPixmap( splashPix ); + splashScreen->setBackgroundMode ( NoBackground ); + splashScreen->setMask( KJWidget::getMask(image(item("splashscreen")[1])) ); + + QSize sh = splashScreen->sizeHint(); + + QRect desk = KGlobalSettings::splashScreenDesktopGeometry(); + splashScreen->move (desk.x() + (desk.width() - sh.width())/2, + desk.y() + (desk.height() - sh.height())/2 ); + + splashScreen->setFixedSize(sh); + splashScreen->show(); + napp->processEvents(); // we want this one time to get the splash actually displayed ASAP + + QTimer::singleShot(3000, this, SLOT(hideSplash()) ); +} + +void KJLoader::hideSplash() +{ + splashScreen->hide(); + delete splashScreen; +} diff --git a/noatun/modules/kjofol-skin/kjloader.h b/noatun/modules/kjofol-skin/kjloader.h new file mode 100644 index 00000000..44b507d6 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjloader.h @@ -0,0 +1,129 @@ +#ifndef KJLOADER_H +#define KJLOADER_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +// local includes +#include "parser.h" + +// noatun-specific includes +#include <noatun/plugin.h> +#include <noatun/app.h> + +// system includes +#include <qwidget.h> +#include <qbitmap.h> +#include <qptrlist.h> +#include <qcstring.h> + +#include <kwinmodule.h> + +class QLabel; +class KJWidget; +class KHelpMenu; +class KJSeeker; +class NoatunPreferences; +class KJToolTip; +class KJFont; +class KJPrefs; + + +class KJLoader : public QWidget, public UserInterface, public Parser +{ +Q_OBJECT +NOATUNPLUGIND + + friend class KJWidget; +public: + KJLoader(); + ~KJLoader(); + +public: + void minimize(); + KHelpMenu *helpMenu() const { return mHelpMenu; } + QStringList &item(const QString &key) { return *Parser::find(key); } + + // returns path to currently loaded configfile + // can be either a newly loaded one or one of the three below + QString currentSkin() { return mCurrentSkin; } + + // returns path to mainskin-configfile + QString currentDefaultSkin() { return mCurrentDefaultSkin; } + + //returns path to dockmode-configfile if present + QString currentDockModeSkin() { return mCurrentDockModeSkin; } + + //returns path to winshademode-configfile if present (not supported yet) + QString currentWinshadeModeSkin() { return mCurrentWinshadeModeSkin; } + + KJPrefs *prefs() const { return mPrefs; } + + QPtrList<KJWidget> widgetsAt(const QPoint &pt) const; + + void removeChild(KJWidget *c); + void addChild(KJWidget *c); + +public slots: + void loadSkin(const QString &file); + void readConfig(); + void switchToDockmode(); + void returnFromDockmode(); + +protected: + void unloadSkin(); + void showSplash(); + +public slots: + void timeUpdate(); + void newSong(); + +private slots: + void loadSeeker(); + void slotWindowActivate(WId win); + void slotWindowRemove(WId win); + void slotWindowChange(WId win); + void slotDesktopChange(int); + void slotStackingChanged(); + void restack(); + void hideSplash(); + +protected: + virtual void mouseMoveEvent(QMouseEvent *e); + virtual void mousePressEvent(QMouseEvent *e); + virtual void mouseReleaseEvent(QMouseEvent *e); + virtual void paintEvent(QPaintEvent *e); + virtual void closeEvent(QCloseEvent*e); + virtual void wheelEvent(QWheelEvent *e); + + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dropEvent(QDropEvent *event); + +public: + static KJLoader* kjofol; + +private: + // ==== docking stuff ==== + KWinModule *mWin; + WId mDockToWin; + int mDockPositionX, mDockPositionY, mDockPosition; + QRect mDockWindowRect; + // ==== end of docking stuff ==== + bool moving; + QPoint mMousePoint; + QPtrList<KJWidget> subwidgets; + KJWidget *mClickedIn; + KHelpMenu *mHelpMenu; + KJFont *mText, *mNumbers, *mVolumeFont, *mPitchFont; + QLabel *splashScreen; + KJToolTip *mTooltips; + QString mCurrentSkin; + QString mCurrentDefaultSkin; + QString mCurrentDockModeSkin; + QString mCurrentWinshadeModeSkin; + + KJPrefs *mPrefs; +}; + +#endif // KJLOADER_H diff --git a/noatun/modules/kjofol-skin/kjofolui.plugin b/noatun/modules/kjofol-skin/kjofolui.plugin new file mode 100644 index 00000000..f6037cdb --- /dev/null +++ b/noatun/modules/kjofol-skin/kjofolui.plugin @@ -0,0 +1,64 @@ +Filename=noatun_kjofol.la +Author=Charles Samuels, Stefan Gehn +Site=http://noatun.kde.org/ +Email=charles@kde.org +Type=userinterface +License=Artistic +Name=K-Jöfol +Name[eo]=K-Jofol +Name[hi]=के-जॉफ़ॉल +Name[is]=K-Jofol +Name[ne]=के-जोफोल +Name[pt_BR]=K-Jofol +Name[ta]=K-Jofol +Name[xh]=K-Jofol +Comment=Skin loader for K-Jofol skins +Comment[bg]=Зареждане на теми за K-Jofol +Comment[br]=Ur c'harger a groc'hen evit K-Jofol +Comment[bs]=Skin Loader za K-Jofol skinove +Comment[ca]=Carregador d'aparences per les aparences K-Jofol +Comment[cs]=Nahrávání motivů pro motivy K-Jofolu +Comment[cy]=Llwythydd croen ar gyfer crwyn K-Jofol +Comment[da]=Forsideindlæser for K-Jöfol-forsider +Comment[de]=Importprogramm für K-Jöfol-Designs +Comment[el]=Φόρτωση θέματος για θέματα K-Jofol +Comment[eo]=Ŝargilo por K-Jofol-etosoj +Comment[es]=Cargador de pieles de K-Jofol +Comment[et]=K-Jöfoli rüüde laadija +Comment[eu]=Azal kargatzailea K-Jöfol azalentzat +Comment[fa]=بارکننده Skin برای K-Jofol skins +Comment[fi]=K-Jofol-nahkojen latausohjelma +Comment[fr]=Chargeur de revêtements K-Jöfol +Comment[gl]=Cargador de peles para as peles de K-Jofol +Comment[he]=טוען Skins של K-Jofol +Comment[hu]=Betöltőprogram a K-Jofol-os kinézetekhez +Comment[is]=Hleður inn K-Jofol skinn +Comment[it]=Caricatore di skin per K-Jöfol +Comment[ja]=K-Jöfol スキンのローダ +Comment[kk]=K-Jofol тыстарының жүктегіші +Comment[km]=កម្មវិធីផ្ទុកស្បែក K-Jofol +Comment[ko]=K-Jofol 스킨 로더 +Comment[lt]=K-Jofol apvalkalų pakrovėjas +Comment[mk]=Вчитувач на маски за маски K-Jofol +Comment[nb]=Drakthenter for K-Jöfol-drakt +Comment[nds]=Böversietlader för "K-Jöfol"-Böversieden +Comment[ne]=के-जोफोल स्किनका लागि स्किन लोडर +Comment[nl]=Skinlader voor K-Jofol-skins +Comment[nn]=Skal-lastar for K-Jofol-skal +Comment[pl]=Ładowarka skór dla skór K-Jofol +Comment[pt]=Leitor de aspectos do K-Jofol +Comment[pt_BR]=Carregador de aparências (skins) para o K-Jofol +Comment[ro]=Încărcător de interfeţe pentru tematici K-Jofol +Comment[ru]=Загрузчик образов K-Jofol +Comment[sk]=Nahrávanie tém K-Jofol +Comment[sl]=Nalagalnik za preobleke K-Jofol +Comment[sr]=Учитавач кошуљица за К-Jofol кошуљице +Comment[sr@Latn]=Učitavač košuljica za K-Jofol košuljice +Comment[sv]=Skalladdare för K-Jofol-skal +Comment[ta]=கே-ஜோபோல் அலங்கார அமைப்புக்கான ஏற்றி +Comment[th]=ตัวโหลดหน้ากากสำหรับ K-Jofol +Comment[tr]=K-Jofol arayüzleri için yükleyici +Comment[uk]=Завантажувач жупанів для K-Jofol +Comment[zh_CN]=K-Jofol 外观载入器 +Comment[zh_HK]=用於 K-Jofol 外貌的外貌載入器 +Comment[zh_TW]= K-Jofol 面板載入器 diff --git a/noatun/modules/kjofol-skin/kjprefs.cpp b/noatun/modules/kjofol-skin/kjprefs.cpp new file mode 100644 index 00000000..0cadc5ac --- /dev/null +++ b/noatun/modules/kjofol-skin/kjprefs.cpp @@ -0,0 +1,658 @@ +/*************************************************************************** + kjprefs.cpp - Preferences-Dialog for KJ�ol-Skinloader + -------------------------------------------------------- + Maintainer: Stefan Gehn <sgehn@gmx.net> + + ***************************************************************************/ + +// local includes +#include "kjprefs.h" +#include "kjprefs.moc" +#include "kjloader.h" +#include "kjwidget.h" +#include "kjvis.h" +#include "parser.h" + +// system includes +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qradiobutton.h> +#include <qslider.h> +#include <qpixmap.h> +#include <qtabwidget.h> +#include <qtextbrowser.h> +#include <qfileinfo.h> +#include <qstringlist.h> +#include <qregexp.h> + +#include <knuminput.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kio/job.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kmimemagic.h> +#include <knotifyclient.h> +#include <kprocess.h> +#include <kstandarddirs.h> +#include <kglobalsettings.h> +#include <kfontcombo.h> +#include <kcolorcombo.h> + +static QString expand(QString s); + +KJPrefs::KJPrefs(QObject* parent) + : CModule(i18n("K-Jöfol Skins"), i18n("Skin Selection For the K-Jöfol Plugin"), "style", parent) +{ + cfg = KGlobal::config(); + + QVBoxLayout *vbox = new QVBoxLayout(this); + vbox->setAutoAdd(true); + vbox->setSpacing( 0 ); + vbox->setMargin( 0 ); + + mTabWidget = new QTabWidget( this, "mTabWidget" ); + + mSkinselectorWidget = new KJSkinselector ( mTabWidget, "mSkinselectorWidget" ); + mGuiSettingsWidget = new KJGuiSettings ( mTabWidget, "mGuiSettingsWidget" ); + + mTabWidget->insertTab( mSkinselectorWidget, i18n("&Skin Selector") ); + mTabWidget->insertTab( mGuiSettingsWidget, i18n("O&ther Settings") ); + + connect ( mSkinselectorWidget->mSkins, SIGNAL(activated(const QString&)), SLOT(showPreview(const QString&)) ); + connect ( mSkinselectorWidget->installButton, SIGNAL(clicked()), this, SLOT(installNewSkin()) ); + connect ( mSkinselectorWidget->mRemoveButton, SIGNAL(clicked()), this, SLOT(removeSelectedSkin()) ); + + reopen(); // fill the skinlist and draw a preview +} + + +void KJPrefs::reopen() // reload config and set stuff in dialog +{ +// kdDebug(66666) << "[KJPrefs] reopen()" << endl; + + cfg->setGroup("KJofol-Skins"); + +// mGuiSettingsWidget->timeCountdown->setChecked( cfg->readBoolEntry("TimeCountMode", false) ); + mGuiSettingsWidget->displayTooltips->setChecked( cfg->readBoolEntry("DisplayTooltips", true) ); + mGuiSettingsWidget->displaySplash->setChecked( cfg->readBoolEntry("DisplaySplashScreen", true) ); + + mGuiSettingsWidget->minPitch->setValue( cfg->readNumEntry("minimumPitch", 50) ); + mGuiSettingsWidget->maxPitch->setValue( cfg->readNumEntry("maximumPitch", 200) ); + mGuiSettingsWidget->visTimerValue->setValue( cfg->readNumEntry("VisualizationSpeed", 30) ); + + mGuiSettingsWidget->useSysFont->setChecked( cfg->readBoolEntry("Use SysFont", false) ); + mGuiSettingsWidget->cmbSysFont->setCurrentFont( + cfg->readEntry("SysFont Family", KGlobalSettings::generalFont().family()) ); + QColor tmpColor = QColor(255,255,255); + mGuiSettingsWidget->cmbSysFontColor->setColor( + cfg->readColorEntry("SysFont Color", &tmpColor)); + + // TODO somehow honor both config-entries, I want a custom mode + switch ( cfg->readNumEntry("TitleScrollSpeed", 400 ) ) + { + case 800: + mGuiSettingsWidget->titleScrollSpeed->setValue(1); + break; + case 400: + mGuiSettingsWidget->titleScrollSpeed->setValue(2); + break; + case 200: + mGuiSettingsWidget->titleScrollSpeed->setValue(3); + break; + } + + switch ( cfg->readNumEntry("AnalyzerType", KJVisScope::FFT ) ) + { + case KJVisScope::Null: + mGuiSettingsWidget->visNone->setChecked(true); + mGuiSettingsWidget->visScope->setChecked(false); + mGuiSettingsWidget->visAnalyzer->setChecked(false); + break; + + case KJVisScope::FFT: + mGuiSettingsWidget->visNone->setChecked(false); + mGuiSettingsWidget->visScope->setChecked(false); + mGuiSettingsWidget->visAnalyzer->setChecked(true); + break; + + case KJVisScope::Mono: + mGuiSettingsWidget->visNone->setChecked(false); + mGuiSettingsWidget->visScope->setChecked(true); + mGuiSettingsWidget->visAnalyzer->setChecked(false); + break; + } + + QStringList skins; + QStringList skinLocations = KGlobal::dirs()->findDirs("data", "noatun/skins/kjofol"); + // iterate through all paths where Noatun is searching for kjofol-skins + for (uint i = 0; i < skinLocations.count(); ++i ) + { + QStringList skinDirs = QDir(skinLocations[i]).entryList(); + // iterate trough all dirs (normally, users can fsck every dir-struct *g*) containing a skin + for (uint k = 2; k < skinDirs.count(); ++k ) + { + QDir skinDirCnt = QDir ( skinLocations[i]+skinDirs[k], "*.rc", QDir::Name|QDir::IgnoreCase, QDir::Files ); + // make a list of all .rc-files in a skindir + QStringList rcFiles = skinDirCnt.entryList(); + // iterate trough all those rc.-files in a skindir + for (uint j = 0; j < rcFiles.count(); j++ ) + { +// kdDebug(66666) << "found: " << rcFiles[j].latin1() << endl; + skins += ( rcFiles[j] ); + } + } + } + + skins.sort(); + + QString loaded = cfg->readEntry("SkinResource", locate("data", "noatun/skins/kjofol/kjofol/kjofol.rc") ); + loaded = loaded.mid(loaded.findRev("/")+1); // remove path + loaded = loaded.left( loaded.length() - 3 ); // remove ".rc" + + mSkinselectorWidget->mSkins->clear(); + + int index = 0; + for (QStringList::Iterator i=skins.begin(); i!=skins.end(); ++i) + { + *i = (*i).left( (*i).length() - 3 ); + mSkinselectorWidget->mSkins->insertItem(*i); + if ( (*i) == loaded ) + index = mSkinselectorWidget->mSkins->count()-1; // save index no. to set active item later on + } + + mSkinselectorWidget->mSkins->setCurrentItem(index); + + showPreview( mSkinselectorWidget->mSkins->currentText() ); +} + + +void KJPrefs::save() +{ +// kdDebug(66666) << k_funcinfo << "called." << endl; + QString skin=::expand ( mSkinselectorWidget->mSkins->currentText() ); + + // first load skin and then save config to prevent + // reloading a broken skin after a crash + KJLoader *l=KJLoader::kjofol; + if (l) + l->loadSkin(skin); + + cfg->setGroup("KJofol-Skins"); + + cfg->writeEntry("SkinResource", skin); +// cfg->writeEntry("TimeCountMode", timeCountMode() ); + cfg->writeEntry("DisplayTooltips", displayTooltips() ); + cfg->writeEntry("DisplaySplashScreen", displaySplash() ); + + cfg->writeEntry("TitleScrollSpeed", titleMovingUpdates() ); + cfg->writeEntry("TitleScrollAmount", titleMovingDistance() ); + cfg->writeEntry("AnalyzerType", (int)visType() ); + cfg->writeEntry("minimumPitch", minimumPitch() ); + cfg->writeEntry("maximumPitch", maximumPitch() ); + cfg->writeEntry("VisualizationSpeed", visTimerValue() ); + + cfg->writeEntry("Use SysFont", mGuiSettingsWidget->useSysFont->isChecked()); + cfg->writeEntry("SysFont Family", mGuiSettingsWidget->cmbSysFont->currentFont()); +// kdDebug(66666) << k_funcinfo << "currentfont=" << mGuiSettingsWidget->cmbSysFont->currentFont() << endl; + cfg->writeEntry("SysFont Color", mGuiSettingsWidget->cmbSysFontColor->color()); + + cfg->sync(); + + emit configChanged(); +} + +QString KJPrefs::skin( void ) const +{ + // return full path to currently loaded skin + return ::expand( mSkinselectorWidget->mSkins->currentText() ); +} + +int KJPrefs::minimumPitch( void ) const +{ + return mGuiSettingsWidget->minPitch->value(); +} + +int KJPrefs::maximumPitch( void ) const +{ + return mGuiSettingsWidget->maxPitch->value(); +} + +int KJPrefs::visTimerValue ( void ) const +{ + return mGuiSettingsWidget->visTimerValue->value(); +} + +int KJPrefs::titleMovingUpdates ( void ) const +{ + switch ( mGuiSettingsWidget->titleScrollSpeed->value() ) + { + case 1: + return 800; + case 2: + return 400; + case 3: + return 200; + default: + return 400; // emergency exit :) + } +} + +float KJPrefs::titleMovingDistance ( void ) const +{ + switch ( mGuiSettingsWidget->titleScrollSpeed->value() ) + { + case 1: + return 0.2f; + case 2: + return 0.5f; + case 3: + return 1.0f; + default: + return 0.5f; // emergency exit :) + } +} + +int KJPrefs::visType ( void ) const +{ + if ( mGuiSettingsWidget->visNone->isChecked() ) // No Vis + return KJVisScope::Null; + else if ( mGuiSettingsWidget->visScope->isChecked() ) // MonoScope + return KJVisScope::Mono; + else if ( mGuiSettingsWidget->visAnalyzer->isChecked() ) // FFT Analyzer + return KJVisScope::FFT; + else + return KJVisScope::StereoFFT; //Null; // emergency exit :) +} + +void KJPrefs::setVisType ( int vis ) +{ + switch ( vis ) + { + case KJVisScope::Null: + mGuiSettingsWidget->visNone->setChecked(true); + mGuiSettingsWidget->visScope->setChecked(false); + mGuiSettingsWidget->visAnalyzer->setChecked(false); + break; + + case KJVisScope::FFT: + mGuiSettingsWidget->visNone->setChecked(false); + mGuiSettingsWidget->visScope->setChecked(false); + mGuiSettingsWidget->visAnalyzer->setChecked(true); + break; + + case KJVisScope::StereoFFT: + mGuiSettingsWidget->visNone->setChecked(false); + mGuiSettingsWidget->visScope->setChecked(false); + mGuiSettingsWidget->visAnalyzer->setChecked(false); + break; + + case KJVisScope::Mono: + mGuiSettingsWidget->visNone->setChecked(false); + mGuiSettingsWidget->visScope->setChecked(true); + mGuiSettingsWidget->visAnalyzer->setChecked(false); + break; + } + save(); // not sure if that's a good idea or doing saving by hand in here +} + + +bool KJPrefs::useSysFont( void ) const +{ + return mGuiSettingsWidget->useSysFont->isChecked(); +} + +void KJPrefs::setUseSysFont( bool mode ) +{ + mGuiSettingsWidget->useSysFont->setChecked( mode ); + save(); // not sure if that's a good idea or doing saving by hand in here +} + +QFont KJPrefs::sysFont(void) const +{ + QString family = mGuiSettingsWidget->cmbSysFont->currentFont(); +// kdDebug(66666) << k_funcinfo << "family=" << family << endl; + return QFont( family ); +} + +void KJPrefs::setSysFont(QFont &fnt) +{ + mGuiSettingsWidget->cmbSysFont->setCurrentFont( fnt.family() ); +} + +QColor KJPrefs::sysFontColor(void) const +{ + return mGuiSettingsWidget->cmbSysFontColor->color(); +} + +void KJPrefs::sysFontColor(QColor &c) +{ + mGuiSettingsWidget->cmbSysFontColor->setColor( c ); +} + +bool KJPrefs::displayTooltips( void ) const +{ + return mGuiSettingsWidget->displayTooltips->isChecked(); +} + +bool KJPrefs::displaySplash( void ) const +{ + return mGuiSettingsWidget->displaySplash->isChecked(); +} + + +void KJPrefs::showPreview(const QString &_skin) +{ + Parser p; + p.open( ::expand(_skin) ); + + QImage image = p.image(p["BackgroundImage"][1]); + if (!image.isNull()) + { + mPixmap.convertFromImage(image); + mPixmap.setMask( KJWidget::getMask(image) ); + } + else + mPixmap=QPixmap(); + + mSkinselectorWidget->mPreview->setPixmap(mPixmap); + mSkinselectorWidget->mAboutText->setText(p.about()); + mSkinselectorWidget->updateGeometry(); +} + + +/* =================================================================================== */ + + +void KJPrefs::installNewSkin( void ) +{ + bool skinInstalled = false; // flag showing wether a skindir got installed + KURL src, dst; // sourcedir and destinationdir for skin-installation + + KURL srcFile ( mSkinselectorWidget->mSkinRequester->url() ); + + //kdDebug(66666) << "file to work on: " << srcFile.path().latin1() << endl; + + if ( !srcFile.isValid() || srcFile.isEmpty() ) // stop working on broken URLs + { + kdDebug(66666) << "srcFile is malformed or empty !!!" << endl; + return; + } + + if ( !srcFile.isLocalFile() ) // TODO: Download file into tmp dir + unpack afterwards + { + KMessageBox::sorry ( this, i18n("Non-Local files are not supported yet") ); + return; + } + + // Determine file-format trough mimetype (no stupid .ext test) + KMimeMagicResult * result = KMimeMagic::self()->findFileType( srcFile.path() ); + + if ( !result->isValid() ) + { + kdDebug(66666) << "Could not determine filetype of srcFile !!!" << endl; + return; + } + + if ( result->mimeType() != "application/x-zip" ) + { + KMessageBox::error ( this, i18n("The selected file does not appear to be a valid zip-archive") ); + return; + } + + // create a dir with name of the skinarchive + // path to unpack to: pathToTmp/filename.ext/ + QString tmpUnpackPath = locateLocal("tmp", srcFile.fileName()+"/" ); + kdDebug(66666) << "tmpUnpackPath: " << tmpUnpackPath.latin1() << endl; + + // Our extract-process, TODO: wanna have kio_(un)zip instead :) + KShellProcess proc; + + // "unzip -d whereToUnpack whatToUnpack" + proc << "unzip -d " << proc.quote(tmpUnpackPath) << " " << proc.quote(srcFile.path()); + kdDebug(66666) << "unzip -d " << tmpUnpackPath.latin1() << " " << srcFile.path().latin1() << endl; + + proc.start( KProcess::Block, KProcess::NoCommunication ); + + // "unzip" spits out errorcodes > 0 only, 0 on success + if ( proc.exitStatus() != 0 ) + { + KMessageBox::error ( this, i18n("Extracting skin-archive failed") ); + // FIXME: Do I have to wait for the job to finish? + // I'd say no because I don't care about the temp-dir + // anyway after leaving this method :) + KIO::del( tmpUnpackPath ); + return; + } + + QDir tmpCnt = QDir ( tmpUnpackPath ); + tmpCnt.setFilter ( QDir::Dirs ); + + QStringList dirList = tmpCnt.entryList(); + // Iterate trough all subdirs of tmpUnpackPath (including "."!) + for ( unsigned int i = 0; i < dirList.count(); i++ ) + { + // FIXME: is the following portable? + if ( dirList[i] == ".." ) + continue; + + QDir tmpSubCnt = QDir( tmpUnpackPath + dirList[i], "*.rc;*.RC;*.Rc;*.rC", QDir::Name|QDir::IgnoreCase, QDir::Files ); + kdDebug(66666) << "Searching for *.rc in " << QString(tmpUnpackPath+dirList[i]).latin1() << endl; + + // oh, no .rc file in current dir, let's go to next dir in list + if ( tmpSubCnt.count() == 0 ) + continue; + + src = KURL::encode_string(tmpUnpackPath+dirList[i]); + dst = KURL::encode_string(locateLocal("data","noatun/skins/kjofol/")); // destination to copy skindir into + + if ( dirList[i] == "." ) // zip did not contain a subdir, we have to create one + { + // skindir is named like the archive without extension (FIXME: extension is not stripped from name) + + int dotPos = srcFile.fileName().findRev('.'); + if ( dotPos > 0 ) // found a dot -> (hopefully) strip the extension + { + dst.addPath( srcFile.fileName().left(dotPos) ); + } + else // we don't seem to have any extension, just append the archivename + { + dst.addPath( srcFile.fileName() ); + } + + kdDebug(66666) << "want to create: " << dst.path().latin1() << endl; + + if ( !dst.isValid() ) + { + KMessageBox::error ( this, + i18n("Installing new skin failed: Destination path is invalid.\n" + "Please report a bug to the K-Jöfol maintainer") ); + KIO::del( tmpUnpackPath ); + return; + } + KIO::mkdir( dst ); + } + + if ( !src.isValid() || !dst.isValid() ) + { + KMessageBox::error ( this, + i18n("Installing new skin failed: Either source or destination path is invalid.\n" + "Please report a bug to the K-Jöfol maintainer") ); + } + else + { + kdDebug(66666) << "src: " << src.path().latin1() << endl; + kdDebug(66666) << "dst: " << dst.path().latin1() << endl; + KIO::Job *job = KIO::copy(src,dst); + connect ( job, SIGNAL(result(KIO::Job*)), this, SLOT(slotResult(KIO::Job*)) ); + skinInstalled = true; + } + } // END iterate trough dirList + + if ( !skinInstalled ) + { + KMessageBox::sorry ( this, i18n("No new skin has been installed.\nMake sure the archive contains a valid K-Jöfol skin") ); + } + else + { + KMessageBox::information ( this, i18n("The new skin has been successfully installed") ); + } + + KIO::del( tmpUnpackPath ); +} + + +void KJPrefs::removeSelectedSkin( void ) +{ + QString question = i18n("Are you sure you want to remove %1?\n" + "This will delete the files installed by this skin "). + arg ( mSkinselectorWidget->mSkins->currentText() ); + + cfg->setGroup("KJofol-Skins"); + QString loadedSkin = cfg->readEntry("SkinResource", "kjofol"); +// kdDebug(66666) << "loaded Skin Name: " << QFileInfo(loadedSkin).baseName().latin1() << endl; + + int r = KMessageBox::warningContinueCancel ( this, question, i18n("Confirmation"), KStdGuiItem::del() ); + if ( r != KMessageBox::Continue ) + return; + + bool deletingCurrentSkin = ( mSkinselectorWidget->mSkins->currentText() == QFileInfo(loadedSkin).baseName() ); + + // Now find the dir to delete !!! + + QString dirToDelete = QString (""); + QStringList skinLocations = KGlobal::dirs()->findDirs("data", "noatun/skins/kjofol"); + + // iterate through all paths where Noatun is searching for kjofol-skins + for (uint i = 0; i < skinLocations.count(); ++i ) + { + QStringList skinDirs = QDir(skinLocations[i]).entryList(); + + // iterate trough all dirs containing a skin + for (uint k = 0; k < skinDirs.count(); ++k ) + { + QDir skinDirCnt = QDir ( skinLocations[i]+skinDirs[k], "*.rc", QDir::Name|QDir::IgnoreCase, QDir::Files ); + // make a list of all .rc-files in a skindir + QStringList rcFiles = skinDirCnt.entryList(); + + // iterate trough all those rc.-files in a skindir + for (uint j = 0; j < rcFiles.count(); j++ ) + { + if ( rcFiles[j].left(rcFiles[j].length()-3) == mSkinselectorWidget->mSkins->currentText() ) // found skinname.rc :) + { + dirToDelete = QString ( skinLocations[i]+skinDirs[k] ); + kdDebug(66666) << "FOUND SKIN @ " << dirToDelete.latin1() << endl; + } + } + } + } + + if ( dirToDelete.length() != 0 ) + { + kdDebug(66666) << "Deleting Skindir: " << dirToDelete.latin1() << endl; + KIO::Job *job = KIO::del( dirToDelete, false, true ); + connect ( job, SIGNAL(result(KIO::Job*)), this, SLOT(slotResult(KIO::Job*)) ); + } + + int item = -1; + // Fallback to kjofol-skin (the default one) if we've deleted the current skin + if ( deletingCurrentSkin ) + { + for ( int i = 0; i < mSkinselectorWidget->mSkins->count(); i++ ) + { // FIXME: no check wether "kjofol" is ever found, well, it HAS to be in the list + if ( mSkinselectorWidget->mSkins->text(i) == "kjofol" ) + item = i; + } + } + else + item = mSkinselectorWidget->mSkins->currentItem(); + + if ( item != -1 ) + mSkinselectorWidget->mSkins->setCurrentItem( item ); + + // update configuration + if ( deletingCurrentSkin ) + save(); +} + +void KJPrefs::slotResult(KIO::Job *job ) +{ + if ( job->error() ) + { + job->showErrorDialog(this); + } + else + { + // Reload Skinlist + reopen(); + } +} + + +/* =================================================================================== */ + + +// takes name of rc-file without .rc at the end and returns full path to rc-file +static QString expand(QString s) +{ +// kdDebug(66666) << "expand( "<< s.latin1() << " )" << endl; + + QStringList skinLocations = KGlobal::dirs()->findDirs("data", "noatun/skins/kjofol"); + + // iterate through all paths where Noatun is searching for kjofol-skins + for (uint i = 0; i < skinLocations.count(); ++i ) + { + QStringList skinDirs = QDir(skinLocations[i]).entryList(); + + // iterate trough all dirs containing a skin + for (uint k = 0; k < skinDirs.count(); ++k ) + { + QDir skinDirCnt = QDir ( skinLocations[i]+skinDirs[k], "*.rc", QDir::Name|QDir::IgnoreCase, QDir::Files ); + // make a list of all .rc-files in a skindir + QStringList rcFiles = skinDirCnt.entryList(); + + // iterate trough all those rc.-files in a skindir + for (uint j = 0; j < rcFiles.count(); j++ ) + { + if ( rcFiles[j].left(rcFiles[j].length()-3) == s ) // found $s.rc :) + { +// kdDebug(66666) << "expand() found: " << QString(skinLocations[i]+skinDirs[k]+"/"+rcFiles[j]).latin1() << endl; + return (skinLocations[i]+skinDirs[k]+"/"+rcFiles[j]); + } + } + } + } + return QString(); +} + +QString filenameNoCase(const QString &filename, int badNodes) +{ + QStringList names=QStringList::split('/', filename); + QString full; + int number=(int)names.count(); + for (QStringList::Iterator i=names.begin(); i!=names.end(); ++i) + { + full+="/"; + if (number<=badNodes) + { + QDir d(full); + QStringList files=d.entryList(); + files=files.grep(QRegExp("^"+ (*i) + "$", false)); + if (!files.count()) + return ""; + *i=files.grep(*i, false)[0]; + } + + full+=*i; + + number--; + } + + if (filename.right(1)=="/") + full+="/"; + return full; +} diff --git a/noatun/modules/kjofol-skin/kjprefs.h b/noatun/modules/kjofol-skin/kjprefs.h new file mode 100644 index 00000000..ce1725d5 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjprefs.h @@ -0,0 +1,96 @@ +#ifndef KJPREFS_H +#define KJPREFS_H + +//#include "kjprefswidget.h" +#include "kjskinselectorwidget.h" +#include "kjguisettingswidget.h" + +// system includes +#include <qwidget.h> +#include <noatun/pref.h> + +#include <kio/job.h> +#include <kurlrequester.h> + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QComboBox; +class QLabel; +class QPushButton; +class QTabWidget; +class KConfig; +class KJLoader; + +class KJPrefs : public CModule +{ +Q_OBJECT +public: + KJPrefs(QObject* parent); + + // Save which Skin is currently selected + virtual void save(); + + // Rebuild the Skinlist + virtual void reopen(); + + QString skin( void ) const; + + int minimumPitch( void ) const; + int maximumPitch( void ) const; + + int visTimerValue ( void ) const; + + int titleMovingUpdates ( void ) const; + float titleMovingDistance ( void ) const; + + int visType ( void ) const; + void setVisType ( int vis ); + + bool useSysFont( void ) const; + void setUseSysFont( bool ); + + QFont sysFont(void) const; + void setSysFont(QFont&); + + QColor sysFontColor(void) const; + void sysFontColor(QColor &); + + bool displayTooltips( void ) const; + bool displaySplash( void ) const; + +public slots: + // Installs a skin defined by the URL in mSkinRequester + void installNewSkin( void ); + + // Delete the currently selected Skin (does not work for systemwide skins!) + void removeSelectedSkin ( void ); + + // Show a preview of "skin" in mPixmap + void showPreview(const QString &skin); + + // gets called after a KIO-action has finished + // KIO is used for installing/removing skins + void slotResult(KIO::Job *job); + +signals: + void configChanged(); + +private: + QPixmap mPixmap; // preview Pixmap + KConfig *cfg; + + // Dialog-Widgets + QTabWidget *mTabWidget; + KJSkinselector *mSkinselectorWidget; + KJGuiSettings *mGuiSettingsWidget; +}; + +/** + * resolve a filename to its correct case. + * badNodes is the amount of directories/files (at the end) + * that aren't known) + **/ +QString filenameNoCase(const QString &filename, int badNodes=1); + +#endif // KJPREFS_H diff --git a/noatun/modules/kjofol-skin/kjseeker.cpp b/noatun/modules/kjofol-skin/kjseeker.cpp new file mode 100644 index 00000000..41e4db13 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjseeker.cpp @@ -0,0 +1,210 @@ +/*************************************************************************** + kjseeker.cpp + --------------------------------------------- + slider that lets the user jump inside the currently played file + --------------------------------------------- + Maintainer: Stefan Gehn <sgehn@gmx.net> + + ***************************************************************************/ + +#include "kjseeker.h" +#include "kjloader.h" + +#include "helpers.cpp" +#include <noatun/player.h> + +#include <kdebug.h> + +KJSeeker::KJSeeker(const QStringList &i, KJLoader *l) : KJWidget(l), g(0) +{ + QString activeBg = backgroundPressed("bmp1"); + if(activeBg.isEmpty()) + { + kdDebug(66666) << k_funcinfo << "No pressed background found for seeker," << + " using default background!" << endl; + parent()->image(parser()["backgroundimage"][1]); + } + else + mActive = parent()->image(activeBg); + + mScale = parent()->image(parser()["seekimage"][1]); + QImage pixmapNoPress = parent()->image(parser()["backgroundimage"][1]); + + // generate transparent mask + int x, y, xs, ys; + x=i[1].toInt(); + y=i[2].toInt(); + xs=i[3].toInt()-x; + ys=i[4].toInt()-y; + setRect(x,y,xs,ys); + QImage transmask(xs, ys, 1, 2, QImage::LittleEndian); +#if QT_VERSION < 0x030300 + transmask.setColor(0, qRgb(0,0,0)); + transmask.setColor(1, qRgb(255,255,255)); +#else + transmask.setColor(1, qRgb(0,0,0)); + transmask.setColor(0, qRgb(255,255,255)); +#endif + + // clear the pointers + memset(barmodeImages, 0, 256*sizeof(QImage*)); + memset(barmode, 0, 256*sizeof(QPixmap*)); + + // Now do the pixel fking +// kdDebug(66666) << "creating Pixmaps for Seeker" << endl; + for (int iy=y;iy<y+ys; iy++) + { + for (int ix=x;ix<x+xs; ix++) + { + QRgb checkmScale = mScale.pixel(ix, iy); + // am I transparent? + if (!isGray(checkmScale)) + { + setPixel1BPP(transmask, ix-x, iy-y, 0); + continue; + } + setPixel1BPP(transmask, ix-x, iy-y, 1); + + // what is the level + int level=grayRgb(checkmScale)+1; + if (level>255) level=255; + // allocate the pixmap of the level proper + // copy the color to the surface proper + QRgb activeColor=mActive.pixel(ix,iy); + QRgb inactiveColor=pixmapNoPress.pixel(ix,iy); + // set this pixel and everything before it + for(int i=0; i<level; i++) + { + if (!barmodeImages[i]) + barmodeImages[i]=new QImage(xs,ys, 32); + QRgb *l=(QRgb*)barmodeImages[i]->scanLine(iy-y); + l[ix-x]=inactiveColor; + } + + do + { + if (!barmodeImages[level]) + barmodeImages[level]=new QImage(xs,ys, 32); + QRgb *l=(QRgb*)barmodeImages[level]->scanLine(iy-y); + l[ix-x]=activeColor; + } while (level++<255); + } + } +// kdDebug(66666) << "finished creating Pixmaps" << endl; + + // create the blank one + barmode[0]=new QPixmap(xs, ys); + QPixmap px=parent()->pixmap(parser()["backgroundimage"][1]); + bitBlt(barmode[0], 0, 0, &px, x, y, xs, ys, Qt::CopyROP); + px.convertFromImage(transmask); + barModeMask=px; + +// kdDebug(66666) << "END KJSeeker constructor" << endl; +} + +QPixmap *KJSeeker::toPixmap(int n) +{ + if (!barmodeImages[n]) return barmode[n]; + + barmode[n]=new QPixmap( + barmodeImages[n]->width(), + barmodeImages[n]->height() + ); + barmode[n]->convertFromImage(*barmodeImages[n]); + + delete barmodeImages[n]; + barmodeImages[n]=0; + return barmode[n]; +} + + +KJSeeker::~KJSeeker() +{ + for (uint i=0; i<256; i++) + { + if (barmode[i]) + delete barmode[i]; + if (barmodeImages[i]) + delete barmodeImages[i]; + } +} + +void KJSeeker::paint(QPainter *p, const QRect &) +{ + closest(); + QPixmap *pixmap = toPixmap(g); + pixmap->setMask(barModeMask); + bitBlt(p->device(), rect().topLeft().x(), rect().topLeft().y(), + pixmap, 0, 0, rect().width(), rect().height(), Qt::CopyROP); +} + +bool KJSeeker::mousePress(const QPoint &pos) +{ + return (isGray(mScale.pixel(rect().topLeft().x()+pos.x(), rect().topLeft().y()+pos.y()))); +} + +void KJSeeker::mouseRelease(const QPoint &pos, bool in) +{ + int x = rect().topLeft().x()+pos.x(); + int y = rect().topLeft().y()+pos.y(); + + if(napp->player()->isStopped()) + return; + + if(!mScale.valid(x, y)) + return; + + QRgb color=mScale.pixel(x, y); + + // user released mousebutton outside of the seeker-area (which is gray) + if ( (!isGray(color)) || (!in) ) + return; + + g = grayRgb(color); + repaint(); + +// kdDebug(66666) << "length : " << napp->player()->getLength() << endl; +// kdDebug(66666) << "skip to: " << ((long long)g*(long long)napp->player()->getLength())/255 << endl; + + // g * titlelength can get REALLY HUGE, that's why I used (long long) + napp->player()->skipTo( ((long long)g*(long long)napp->player()->getLength())/255 ); + + return; +} + +void KJSeeker::timeUpdate(int sec) +{ + int length = napp->player()->getLength() / 1000; + if (length<1) + length=1; + + if (sec > length) + sec = length; + else if ( sec < 0 ) + sec=0; + + g = sec * 255 / length; + //kdDebug(66666) << "sec: " << sec << " len: " << length << " g: " << g << endl; + QPainter p(parent()); + paint(&p, rect()); +} + +void KJSeeker::closest() +{ + int south=g, north=g; + bool southtried=false, northtried=false; + while ( + !barmode[south] && !barmodeImages[south] + && !barmode[north] && !barmodeImages[north]) + { + if (southtried && northtried) { g=0; return; } + south--; + north++; + if (north>255) {northtried=true; north=g;} + if (south<0) {southtried=true; south=g;} + } + if (barmode[south] || barmodeImages[south]) + g=south; + else if (barmode[north] || barmodeImages[north]) + g=north; +} diff --git a/noatun/modules/kjofol-skin/kjseeker.h b/noatun/modules/kjofol-skin/kjseeker.h new file mode 100644 index 00000000..78fea6fb --- /dev/null +++ b/noatun/modules/kjofol-skin/kjseeker.h @@ -0,0 +1,37 @@ +#ifndef KJSEEKER_H +#define KJSEEKER_H + +#include "kjwidget.h" +//#include "kjloader.h" +class KJLoader; + +#include <qpainter.h> + +class KJSeeker : public KJWidget +{ +public: + KJSeeker(const QStringList &i, KJLoader *); + ~KJSeeker(); + + + virtual void paint(QPainter *, const QRect &rect); + virtual bool mousePress(const QPoint &pos); + virtual void mouseRelease(const QPoint &pos, bool); + + void timeUpdate(int mille); + + void closest(); + +private: + QPixmap *toPixmap(int n); + +private: + QImage mScale; + QImage mActive; + QPixmap *barmode[256]; + QImage *barmodeImages[256]; + QBitmap barModeMask; + int g; +}; + +#endif diff --git a/noatun/modules/kjofol-skin/kjskinselectorwidget.ui b/noatun/modules/kjofol-skin/kjskinselectorwidget.ui new file mode 100644 index 00000000..1540ad5e --- /dev/null +++ b/noatun/modules/kjofol-skin/kjskinselectorwidget.ui @@ -0,0 +1,227 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>KJSkinselector</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KJSkinselector</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>461</width> + <height>345</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QComboBox"> + <property name="name"> + <cstring>mSkins</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>previewGroup</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Preview</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <spacer row="0" column="1"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>31</height> + </size> + </property> + </spacer> + <spacer row="2" column="2"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>51</width> + <height>21</height> + </size> + </property> + </spacer> + <spacer row="3" column="1"> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>41</height> + </size> + </property> + </spacer> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>31</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="1" column="1" rowspan="2" colspan="1"> + <property name="name"> + <cstring>mPreview</cstring> + </property> + <property name="scaledContents"> + <bool>false</bool> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + <property name="hAlign" stdset="0"> + </property> + <property name="vAlign" stdset="0"> + </property> + </widget> + </grid> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>About skin:</string> + </property> + </widget> + <widget class="QTextBrowser"> + <property name="name"> + <cstring>mAboutText</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Here you will see all the comments people wrote about their skins. +It can be several lines and usually does not contain anything interesting but still this will be shown.</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="KURLRequester"> + <property name="name"> + <cstring>mSkinRequester</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>installButton</cstring> + </property> + <property name="text"> + <string>Install Skin</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>mRemoveButton</cstring> + </property> + <property name="text"> + <string>Remove Skin</string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/noatun/modules/kjofol-skin/kjsliders.cpp b/noatun/modules/kjofol-skin/kjsliders.cpp new file mode 100644 index 00000000..8cadd04f --- /dev/null +++ b/noatun/modules/kjofol-skin/kjsliders.cpp @@ -0,0 +1,336 @@ +/*************************************************************************** + kjsliders.cpp + --------------------------------------------- + Sliders for Volume and Pitch + --------------------------------------------- + Maintainer: Stefan Gehn <sgehn@gmx.net> + + ***************************************************************************/ + +// local includes +#include "kjsliders.h" +#include "kjtextdisplay.h" +#include "kjprefs.h" + +#include "helpers.cpp" + +// kde includes +#include <klocale.h> +#include <kdebug.h> + +// arts-includes, needed for pitch +#include <artsmodules.h> +#include <reference.h> +#include <soundserver.h> +#include <kmedia2.h> + +// noatun includes +#include <noatun/player.h> +#include <noatun/engine.h> + +/******************************************* + * KJVolumeBar + *******************************************/ + +KJVolumeBar::KJVolumeBar(const QStringList &i, KJLoader *p) + : KJWidget(p), mVolume(0), mText(0) +{ + int x, y, xs, ys; + x=i[1].toInt(); + y=i[2].toInt(); + xs=i[3].toInt()-x; + ys=i[4].toInt()-y; + setRect ( x, y, xs, ys ); + +// kdDebug(66666) << "x: " << x << " y: " << y << " w: " << xs << " h: " << ys << endl; + + mBack = parent()->pixmap(parser()["backgroundimage"][1]); + mSlider = parent()->pixmap(parser()["volumecontrolimage"][1]); +} + +QString KJVolumeBar::tip() +{ + return i18n("Volume"); +} + +void KJVolumeBar::paint(QPainter *p, const QRect &) +{ +// kdDebug(66666) << "x: " << rect().x() << " y: " << rect().y() << endl; +// kdDebug(66666) << "vol x: " << rect().x()+(mVolume*rect().width())/100 << endl; + + // center of that slider-pixmap +// QPoint hotSpot = QPoint( mSlider.width()/2, mSlider.height()/2 ); + + // draw our background + bitBlt( + p->device(), + rect().x() /*- hotSpot.x()*/, + rect().y() /*- hotSpot.y()*/, + &mBack, + rect().x() /*- hotSpot.x()*/, + rect().y() /*- hotSpot.y()*/, + rect().width() /*+ (2*hotSpot.x())*/, + rect().height() /*+ (2*hotSpot.y())*/, + Qt::CopyROP); + + // draw our slider + bitBlt( + p->device(), + rect().x() + ((mVolume*rect().width())/100) /*- hotSpot.x()*/, + rect().y() /*- hotSpot.y()*/, + &mSlider, + 0, + 0, + mSlider.width(), + mSlider.height(), + Qt::CopyROP); + + if (mText) + mText->repaint(); +} + +bool KJVolumeBar::mousePress(const QPoint &pos) +{ + mVolume = (pos.x()*100) / rect().width(); +// kdDebug(66666) << "volume: " << mVolume << endl; + repaint(); + napp->player()->setVolume(mVolume); + return true; +} + +void KJVolumeBar::mouseRelease(const QPoint &, bool) +{ +} + +void KJVolumeBar::mouseMove(const QPoint &pos, bool in) +{ + if (!in) + return; + mousePress(pos); +} + +void KJVolumeBar::timeUpdate(int) +{ + mVolume = napp->player()->volume(); + repaint(); +} + + +/******************************************* + * KJVolumeBMP + *******************************************/ + +KJVolumeBMP::KJVolumeBMP(const QStringList &i, KJLoader *p) + : KJWidget(p), mVolume(0), mOldVolume(0), mText(0) +{ + int x, y, xs, ys; + x=i[1].toInt(); + y=i[2].toInt(); + xs=i[3].toInt()-x; + ys=i[4].toInt()-y; + setRect ( x, y, xs, ys ); + + mWidth = parser()["volumecontrolimagexsize"][1].toInt(); + mCount = parser()["volumecontrolimagenb"][1].toInt()-1; + + mImages = parent()->pixmap(parser()["volumecontrolimage"][1]); + mPos = parent()->image(parser()["volumecontrolimageposition"][1]); + timeUpdate(0); +} + +QString KJVolumeBMP::tip() +{ + return i18n("Volume"); +} + +void KJVolumeBMP::paint(QPainter *p, const QRect &) +{ + QRect from(mVolume*mCount/100*mWidth, 0, mWidth, mImages.height()); + bitBlt(p->device(), rect().topLeft(), &mImages, from, Qt::CopyROP); + if (mText) + mText->repaint(); +} + +bool KJVolumeBMP::mousePress(const QPoint &pos) +{ + QRgb color = mPos.pixel ( rect().topLeft().x()+pos.x(), rect().topLeft().y()+pos.y() ); + + if (!isGray(color)) + return false; + + mVolume = grayRgb(color)*100/255; +// kdDebug(66666) << "gray : " << grayRgb(color) << endl; +// kdDebug(66666) << "volume: " << mVolume << endl; + + repaint(); + + napp->player()->setVolume(mVolume); + + return true; +} + +void KJVolumeBMP::mouseRelease(const QPoint &, bool) +{} + +void KJVolumeBMP::mouseMove(const QPoint &pos, bool in) +{ + if (!in) return; + mousePress(pos); +} + +void KJVolumeBMP::timeUpdate(int) +{ + mVolume = napp->player()->volume(); + + if ( mVolume == mOldVolume ) // dont redraw if nothing changed + return; + + mOldVolume = mVolume; + + repaint(); +} + + +/******************************************* + * KJPitchBMP + *******************************************/ + +KJPitchBMP::KJPitchBMP(const QStringList &i, KJLoader *p) + : KJWidget(p), mText(0) +{ + int x = i[1].toInt(); + int y = i[2].toInt(); + int xs = i[3].toInt() - x; + int ys = i[4].toInt() - y; + + setRect ( x, y, xs, ys ); + + mWidth = parser()["pitchcontrolimagexsize"][1].toInt(); + mCount = parser()["pitchcontrolimagenb"][1].toInt()-1; + + mImages = parent()->pixmap(parser()["pitchcontrolimage"][1]); + mPos = parent()->image(parser()["pitchcontrolimageposition"][1]); + + // makes all pixels with rgb(255,0,255) transparent + QImage ibackground; + ibackground = parent()->image(parser()["pitchcontrolimage"][1]); + mImages.setMask( getMask(ibackground) ); + + Arts::PlayObject playobject = napp->player()->engine()->playObject(); + Arts::PitchablePlayObject pitchable = Arts::DynamicCast(playobject); + + if ( pitchable.isNull() ) + mCurrentPitch = 1.0; + else + mCurrentPitch = pitchable.speed(); + +// kdDebug() << "[KJPitchBMP] starting with pitch: " << mCurrentPitch << endl; +/* + mMinPitch = 0.5; + mMaxPitch = 2.0; + + mMinPitch = 0.8; + mMaxPitch = 1.2; +*/ + + readConfig(); + + if (mText) + mText->repaint(); +} + +QString KJPitchBMP::tip() +{ + return i18n("Pitch"); +} + +void KJPitchBMP::paint(QPainter *p, const QRect &) +{ + float xPos = (int)((mCurrentPitch-mMinPitch)*100.0) * mCount / (int)((mMaxPitch-mMinPitch)*100.0) * mWidth; + + QRect from( (int)xPos, 0, mWidth, mImages.height()); + + bitBlt(p->device(), rect().topLeft(), &mImages, from, Qt::CopyROP); + + if (mText) + mText->repaint(); +} + +bool KJPitchBMP::mousePress(const QPoint &pos) +{ + QRgb color = mPos.pixel ( rect().topLeft().x()+pos.x(), rect().topLeft().y()+pos.y() ); + + if (!isGray(color)) + return false; + + mCurrentPitch = mMinPitch + ( (grayRgb(color)*(mMaxPitch-mMinPitch)) / 255 ); +// kdDebug(66666) << "[KJPitchBMP] mousePress() mCurrentPitch: " << mCurrentPitch << endl; + + repaint(); + + newFile(); // wrong naming, in fact it just sets pitch + + return true; +} + +void KJPitchBMP::mouseRelease(const QPoint &, bool) +{} + +void KJPitchBMP::mouseMove(const QPoint &pos, bool in) +{ + if (!in) return; + mousePress(pos); +} + +void KJPitchBMP::timeUpdate(int) +{ +// kdDebug(66666) << "[KJPitchBMP] :timeUpdate(int)" << endl; + + Arts::PlayObject playobject = napp->player()->engine()->playObject(); + Arts::PitchablePlayObject pitchable = Arts::DynamicCast(playobject); + + if ( !pitchable.isNull() ) + { + mCurrentPitch = pitchable.speed(); +// kdDebug(66666) << "[KJPitchBMP] mCurrentPitch: " << mCurrentPitch << endl; + } + + if ( mCurrentPitch == mOldPitch ) // dont redraw if nothing changed + return; + + mOldPitch = mCurrentPitch; + + repaint(); +} + +void KJPitchBMP::newFile() +{ +// kdDebug(66666) << "[KJPitchBMP] newFile()" << endl; + + Arts::PlayObject playobject = napp->player()->engine()->playObject(); + Arts::PitchablePlayObject pitchable = Arts::DynamicCast(playobject); + + if (!pitchable.isNull()) + { +// kdDebug(66666) << "[KJPitchBMP] new speed: " << mCurrentPitch << endl; + pitchable.speed( mCurrentPitch ); + } +} + +void KJPitchBMP::readConfig() +{ +// kdDebug(66666) << "KJPitchBMP::readConfig()" << endl; + + mMinPitch = KJLoader::kjofol->prefs()->minimumPitch() / 100.0; + mMaxPitch = KJLoader::kjofol->prefs()->maximumPitch() / 100.0; + + // Now comes the range checking if the user changed the setting :) + if ( mCurrentPitch < mMinPitch || mCurrentPitch > mMaxPitch ) + { + if ( mCurrentPitch < mMinPitch ) + mCurrentPitch = mMinPitch; + if ( mCurrentPitch > mMaxPitch ) + mCurrentPitch = mMaxPitch; + newFile(); // wrong naming, in fact it just sets pitch + } +} diff --git a/noatun/modules/kjofol-skin/kjsliders.h b/noatun/modules/kjofol-skin/kjsliders.h new file mode 100644 index 00000000..94f10934 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjsliders.h @@ -0,0 +1,88 @@ +#ifndef KJSLIDERS_H +#define KJSLIDERS_H + +#include "kjwidget.h" +#include <qpainter.h> + +class KJLoader; +class KJPitchText; +class KJVolumeText; + + +class KJVolumeBMP : public KJWidget +{ +public: + KJVolumeBMP(const QStringList &, KJLoader *parent); + + virtual void paint(QPainter *, const QRect &rect); + virtual bool mousePress(const QPoint &pos); + virtual void mouseRelease(const QPoint &pos, bool); + virtual void timeUpdate(int); + virtual void mouseMove(const QPoint &pos, bool); + + virtual QString tip(); + + void setText(KJVolumeText *t) { mText=t; } + +private: + QPixmap mImages; + QImage mPos; + int mVolume, mOldVolume; + int mWidth, mCount; + KJVolumeText *mText; +}; + + +class KJVolumeBar : public KJWidget +{ +public: + KJVolumeBar(const QStringList &, KJLoader *parent); + + virtual void paint(QPainter *, const QRect &rect); + virtual bool mousePress(const QPoint &pos); + virtual void mouseRelease(const QPoint &pos, bool); + virtual void timeUpdate(int); + virtual void mouseMove(const QPoint &pos, bool); + + virtual QString tip(); + + void setText(KJVolumeText *t) { mText=t; } + +private: + QPixmap mSlider; + QPixmap mBack; + int mVolume; + KJVolumeText *mText; +}; + + +class KJPitchBMP : public KJWidget +{ +public: + KJPitchBMP(const QStringList &, KJLoader *parent); + + virtual void paint(QPainter *, const QRect &rect); + virtual bool mousePress(const QPoint &pos); + virtual void mouseRelease(const QPoint &pos, bool); + virtual void timeUpdate(int); + virtual void newFile(); + virtual void mouseMove(const QPoint &pos, bool); + virtual void readConfig(); + + virtual QString tip(); + + void setText(KJPitchText *t) { mText=t; } + +private: + QPixmap mImages; + QImage mPos; + int mWidth, mCount; + float mCurrentPitch; + float mOldPitch; + float mMinPitch; + float mMaxPitch; + + KJPitchText *mText; +}; + +#endif diff --git a/noatun/modules/kjofol-skin/kjtextdisplay.cpp b/noatun/modules/kjofol-skin/kjtextdisplay.cpp new file mode 100644 index 00000000..89f92526 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjtextdisplay.cpp @@ -0,0 +1,650 @@ +/*************************************************************************** + kjtexdisplay.cpp + --------------------------------------------- + Displays for time and other things + using fonts provided by KJFont + --------------------------------------------- + Maintainer: Stefan Gehn <sgehn@gmx.net> + + ***************************************************************************/ + +// local includes +#include "kjtextdisplay.h" +#include "kjfont.h" +#include "kjprefs.h" + +// kde includes +#include <klocale.h> +#include <kdebug.h> +#include <kpixmap.h> +#include <kurl.h> +#include <krun.h> +#include <kmimemagic.h> + +// arts-includes, needed for pitch +#include <artsmodules.h> +#include <arts/reference.h> +#include <arts/soundserver.h> +#include <arts/kmedia2.h> + +// noatun includes +#include <noatun/player.h> +#include <noatun/engine.h> + +/******************************************* + * KJFilename + *******************************************/ + +KJFilename::KJFilename(const QStringList &l, KJLoader *p) + : QObject(0), KJWidget(p), mBack(0) +{ + int x = l[1].toInt(); + int y = l[2].toInt(); + int xs = l[3].toInt() - x; + int ys = l[4].toInt() - y; + + // fix for all those weird skins where the filenamewindow has more + // height than needed for the font + // ( ... usually resulting in garbage on-screen ) + if ( ys > (textFont().fontHeight()) ) + ys = textFont().fontHeight(); + + // background under filename-scroller + QPixmap tmp = p->pixmap(p->item("backgroundimage")[1]); + mBack = new KPixmap ( QSize(xs,ys) ); + bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP ); + + setRect(x,y,xs,ys); + + // how far it moves per cycle + // TODO: make that configurable for the user + + //mDistance = 1; +// mDistance = (int)(textFont().fontWidth()/2); + readConfig(); + + prepareString(i18n("Welcome to Noatun").local8Bit()); + killTimers(); +} + +KJFilename::~KJFilename() +{ + delete mBack; +} + +void KJFilename::paint(QPainter *p, const QRect &) +{ + QPixmap temp ( rect().width(), rect().height() ); + + // draw background into buffer + bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP ); + // draw font into buffer + bitBlt( &temp, 0, 0, &mView, 0, 0, rect().width(), rect().height(), Qt::CopyROP); + // and draw it on screen + bitBlt(p->device(), rect().topLeft(), &temp, + QRect(0,0,-1,-1), Qt::CopyROP); +} + +void KJFilename::timerEvent(QTimerEvent *) +{ + int height = mView.height(); + int width = mView.width(); + + QBitmap cycleMask ( mDistance, height ); // temporary-space for moving parts of the mask + QPixmap cycle ( mDistance, height ); // temporary-space for moving parts of the pixmap + QBitmap newMask ( *mView.mask() ); // save old mask + + // copy mask like the same way we're doing it with the pixmap + // a mask does not get copied on a bitblt automatically, we have to do + // it "by hand" + bitBlt(&cycleMask, 0,0, &newMask, 0,0, mDistance, height, Qt::CopyROP); + bitBlt(&newMask, 0,0, &newMask, mDistance, 0, width-mDistance, height, Qt::CopyROP); + bitBlt(&newMask, width-mDistance, 0, &cycleMask, 0,0, mDistance, height, Qt::CopyROP); + + bitBlt(&cycle, 0,0, &mView, 0,0, mDistance, height, Qt::CopyROP); + bitBlt(&mView, 0,0, &mView, mDistance, 0, width-mDistance, height, Qt::CopyROP); + bitBlt(&mView, width-mDistance, 0, &cycle, 0,0, mDistance, height, Qt::CopyROP); + + // apply the newly created mask + mView.setMask(newMask); + + repaint(); +} + +bool KJFilename::mousePress(const QPoint &) +{ + return true; +} + +void KJFilename::mouseRelease(const QPoint &, bool in) +{ + if (!in) // only do something if users is still inside the button + return; + + if ( !napp->player()->current() ) + return; + + KURL dirURL = napp->player()->current().url().upURL(); + + KMimeMagicResult *result = KMimeMagic::self()->findFileType( dirURL.path() ); + + // TODO: Maybe test for protocol type? +// if ( napp->player()->current().url().protocol() == "file" ) + if ( result->isValid() ) + KRun::runURL ( dirURL, result->mimeType() ); +} + +void KJFilename::readConfig() +{ + kdDebug(66666) << "KJFilename::readConfig()" << endl; + mDistance = (int)( textFont().fontWidth() * KJLoader::kjofol->prefs()->titleMovingDistance() ); + if ( mDistance <= 0 ) + mDistance = 1; + mTimerUpdates = KJLoader::kjofol->prefs()->titleMovingUpdates(); + textFont().recalcSysFont(); + mLastTitle=""; // invalidate title so it gets repainted on next timeUpdate() +} + +void KJFilename::prepareString(const QCString &str) +{ + killTimers(); // i.e. stop timers + + mView = textFont().draw(str, rect().width()); + + startTimer(mTimerUpdates); +} + +void KJFilename::timeUpdate(int) +{ + if ( !napp->player()->current() ) // just for safety + return; + + QCString title = QCString( napp->player()->current().title().local8Bit() ); + + if ( title == mLastTitle ) + return; + + mLastTitle = title; + + QCString timestring = napp->player()->lengthString().local8Bit(); + timestring = timestring.mid(timestring.find('/')+1); + prepareString ( title + " (" + timestring + ") "); +} + +QString KJFilename::tip() +{ + if ( !napp->player()->current() ) // just for safety + return i18n("Filename"); + else + return napp->player()->current().url().prettyURL(); +} + + +/******************************************* + * KJTime + *******************************************/ + +KJTime::KJTime(const QStringList &l, KJLoader *p) + : KJWidget(p), mBack(0) +{ + int x = l[1].toInt(); + int y = l[2].toInt(); + int xs = l[3].toInt() - x; + int ys = l[4].toInt() - y; + + // fix for all those weird skins where the timewindow + // has more space than needed for the font + int maxNeededHeight = timeFont().fontHeight(); + if ( ys > maxNeededHeight ) + ys = maxNeededHeight; + + // five digits + spacing between them + int maxNeededWidth = ( 5 *timeFont().fontWidth() ) + ( 4 * timeFont().fontSpacing() ); + if ( xs > maxNeededWidth ) + xs = maxNeededWidth; + + // background under time-display + QPixmap tmp = p->pixmap(p->item("backgroundimage")[1]); + mBack = new KPixmap ( QSize(xs,ys) ); + bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP ); + + setRect(x,y,xs,ys); + + readConfig(); + + prepareString("00:00"); +} + +KJTime::~KJTime() +{ + delete mBack; +} + +void KJTime::paint(QPainter *p, const QRect &) +{ +// kdDebug(66666) << "KJTime::paint(QPainter *p, const QRect &)" << endl; + QPixmap temp ( rect().width(), rect().height() ); + + // draw background into buffer + bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP ); + // draw time-display into buffer (that's a pixmap with a mask applied) + bitBlt( &temp, 0, 0, &mTime, 0, 0, rect().width(), rect().height(), Qt::CopyROP); + + // and draw it on screen + bitBlt(p->device(), rect().topLeft(), &temp, + QRect(0,0, rect().width(), rect().height()), Qt::CopyROP); +} + +bool KJTime::mousePress(const QPoint &) +{ + return true; +} + +void KJTime::mouseRelease(const QPoint &, bool in) +{ + if (!in) // only do something if users is still inside the button + return; + + countDown = !countDown; + napp->setDisplayRemaining( countDown ); +// KJLoader::kjofol->prefs()->setTimeCountMode( countDown ); +} + +void KJTime::readConfig() +{ +// kdDebug(66666) << "KJTime::readConfig()" << endl; + countDown = napp->displayRemaining(); + timeFont().recalcSysFont(); + mLastTime=""; // invalidate time so it gets repainted on next timeUpdate() +} + +QString KJTime::lengthString ( void ) +{ + int pos = 0; + QString posString; + int secs = 0, + seconds = 0, + minutes = 0, + hours = 0; + + if ( countDown ) + { // current remaining time + pos = napp->player()->getLength() - napp->player()->getTime(); + } + else + { // current time + pos = napp->player()->getTime(); + } + + if ( pos < 0 ) + { + posString = "00:00"; + } + else + { // get the position + secs = pos / 1000; // convert milliseconds -> seconds + + seconds = secs % 60; + minutes = (secs - seconds) / 60; + hours = minutes / 60; + minutes %= 60; // remove the hours from minutes ;) + +// cerr << " " << hours << ":" << minutes << ":" << seconds << endl; + +// if ( hours > 0 ) // looks ugly :) + if ( (napp->player()->getLength()/1000) >= 3600 ) // displays hh:mm if file is long + { + posString.sprintf("%d:%.2d", hours, minutes); + } + else // displays mm:ss + { + posString.sprintf("%.2d:%.2d", minutes, seconds); + } + } + + return posString; +} + +void KJTime::timeUpdate(int) +{ +// kdDebug(66666) << "START KJTime::timeUpdate(int)" << endl; + if (!napp->player()->current()) + return; + + prepareString( (lengthString()).latin1() ); + +// kdDebug(66666) << "END KJTime::timeUpdate(int)" << endl; +} + +void KJTime::prepareString(const QCString &str) +{ +// kdDebug(66666) << "START KJTime::prepareString(const QCString &str)" << endl; + if ( str == mLastTime ) + return; + + mLastTime = str; + mTime = timeFont().draw(str, rect().width()); + + repaint(); +// kdDebug(66666) << "END KJTime::prepareString(const QCString &str)" << endl; +} + +QString KJTime::tip() +{ + if ( countDown ) + return i18n("Play time left"); + else + return i18n("Current play time"); +} + + +/******************************************* + * KJVolumeText + *******************************************/ + +KJVolumeText::KJVolumeText(const QStringList &l, KJLoader *p) + : KJWidget(p), mBack(0) +{ + int x=l[1].toInt(); + int y=l[2].toInt(); + int xs=l[3].toInt()-x; + int ys=l[4].toInt()-y; + + // fix for all those weird skins where the timewindow has more space than needed for the font + if ( ys > (volumeFont().fontHeight()) ) + ys = volumeFont().fontHeight(); + + // 3 digits for volume (1-100) + // + spaces according to spacing + // + percentage letter (seems to be 1px wider than a normal char) + int tempWidth = (3*volumeFont().fontWidth()) + (2*volumeFont().fontSpacing()) + ((volumeFont().fontWidth()+1)); + if ( xs > ( tempWidth ) ) + xs = tempWidth; + + // background under volumetext-display + QPixmap tmp = p->pixmap(p->item("backgroundimage")[1]); + mBack = new KPixmap ( QSize(xs,ys) ); + bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP ); + + setRect(x,y,xs,ys); + + prepareString("100%"); +} + +KJVolumeText::~KJVolumeText() +{ + delete mBack; +} + +void KJVolumeText::paint(QPainter *p, const QRect &) +{ + QPixmap temp ( rect().width(), rect().height() ); + + // draw background into buffer + bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP ); + // draw time-display into buffer + bitBlt( &temp, 0, 0, &mVolume, 0, 0, rect().width(), rect().height(), Qt::CopyROP); + + // and draw it on screen + bitBlt(p->device(), rect().topLeft(), &temp, + QRect(0,0,-1,-1), Qt::CopyROP); +} + +bool KJVolumeText::mousePress(const QPoint &) +{ + return false; +} + +void KJVolumeText::readConfig() +{ + volumeFont().recalcSysFont(); + mLastVolume=""; // invalidate value so it gets repainted on next timeUpdate() +} + +void KJVolumeText::timeUpdate(int) +{ + QCString volume; + + if (!napp->player()->current()) + return; + + volume.sprintf("%d%%", napp->player()->volume() ); // FIXME: is sprintf safe to use? + + prepareString(volume); +} + +void KJVolumeText::prepareString(const QCString &str) +{ + if ( str == mLastVolume ) + return; + + mLastVolume = str; + mVolume = volumeFont().draw(str, rect().width()); + + repaint(); +} + +QString KJVolumeText::tip() +{ + return i18n("Volume"); +} + + +/******************************************* + * KJPitchText + *******************************************/ + +KJPitchText::KJPitchText(const QStringList &l, KJLoader *p) + : KJWidget(p), mBack(0) +{ + int x = l[1].toInt(); + int y = l[2].toInt(); + int xs = l[3].toInt() - x; + int ys = l[4].toInt() - y; + + // fix for all those weird skins where the timewindow has more space than needed for the font + if ( ys > (pitchFont().fontHeight()) ) + ys = pitchFont().fontHeight(); + + // 3 digits for volume (1-100), spaces according to spacing and percentage letter + int tempWidth = (3*pitchFont().fontWidth()) + (2*pitchFont().fontSpacing()); + if ( xs > tempWidth ) + xs = tempWidth; + + // background under time-display + QPixmap tmp = p->pixmap(p->item("backgroundimage")[1]); + mBack = new KPixmap ( QSize(xs,ys) ); + bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP ); + + setRect(x,y,xs,ys); + + prepareString("100"); +} + +KJPitchText::~KJPitchText() +{ + delete mBack; +} + + +void KJPitchText::paint(QPainter *p, const QRect &) +{ + QPixmap temp ( rect().width(), rect().height() ); + + // draw background into buffer + bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP ); + // draw time-display into buffer + bitBlt( &temp, 0, 0, &mSpeed, 0, 0, rect().width(), rect().height(), Qt::CopyROP); + // and draw it on screen + bitBlt(p->device(), rect().topLeft(), &temp, QRect(0,0,-1,-1), Qt::CopyROP); +} + +bool KJPitchText::mousePress(const QPoint &) +{ + return true; +} + +void KJPitchText::mouseRelease(const QPoint &, bool in) +{ + if (!in) + return; + + Arts::PlayObject playobject = napp->player()->engine()->playObject(); + Arts::PitchablePlayObject pitchable = Arts::DynamicCast(playobject); + + if (pitchable.isNull()) + return; + + pitchable.speed( 1.00f ); // reset pitch +} + +void KJPitchText::readConfig() +{ + pitchFont().recalcSysFont(); + mLastPitch=""; // invalidate value so it gets repainted on next timeUpdate() +} + +void KJPitchText::timeUpdate(int) +{ + QCString speed; + + if (!napp->player()->current()) + return; + + Arts::PlayObject playobject = napp->player()->engine()->playObject(); + Arts::PitchablePlayObject pitchable = Arts::DynamicCast(playobject); + + if (pitchable.isNull()) + return; + + speed.setNum ( (int) ((float)pitchable.speed()*(float)100) ); + prepareString ( speed ); +} + +void KJPitchText::prepareString(const QCString &str) +{ + if ( str == mLastPitch ) + return; + + mLastPitch = str; + mSpeed = pitchFont().draw(str, rect().width()); + + repaint(); +} + +QString KJPitchText::tip() +{ + return i18n("Pitch"); +} + + +/******************************************* + * KJFileInfo + *******************************************/ + +KJFileInfo::KJFileInfo(const QStringList &l, KJLoader *p) + : KJWidget(p), mBack(0) +{ + mInfoType = l[0]; // type of info-display + + int x = l[1].toInt(); + int y = l[2].toInt(); + int xs = l[3].toInt() - x; + int ys = l[4].toInt() - y; + + // fix for all those weird skins where the timewindow + // has more space than needed for the font + int maxNeededHeight = timeFont().fontHeight(); + if ( ys > maxNeededHeight ) + ys = maxNeededHeight; + + // five digits + spacing between them + int maxNeededWidth = ( 3 *timeFont().fontWidth() ) + ( 2 * timeFont().fontSpacing() ); + if ( xs > maxNeededWidth ) + xs = maxNeededWidth; + + // background under info-display + QPixmap tmp = p->pixmap(p->item("backgroundimage")[1]); + mBack = new KPixmap ( QSize(xs,ys) ); + bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP ); + + setRect(x,y,xs,ys); + + prepareString(""); +} + +KJFileInfo::~KJFileInfo() +{ + delete mBack; +} + +void KJFileInfo::paint(QPainter *p, const QRect &) +{ + QPixmap temp ( rect().width(), rect().height() ); + + // draw background into buffer + bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP ); + // draw time-display into buffer (that's a pixmap with a mask applied) + bitBlt( &temp, 0, 0, &mTime, 0, 0, rect().width(), rect().height(), Qt::CopyROP); + + // and draw it on screen + bitBlt(p->device(), rect().topLeft(), &temp, + QRect(0,0, rect().width(), rect().height()), Qt::CopyROP); +} + +bool KJFileInfo::mousePress(const QPoint &) +{ + return false; +} + +void KJFileInfo::readConfig() +{ + textFont().recalcSysFont(); + mLastTime=""; // invalidate value so it gets repainted on next timeUpdate() +} + +void KJFileInfo::timeUpdate(int) +{ + if (!napp->player()->current()) + return; + + const PlaylistItem &item = napp->player()->current(); + QString prop; + + if ( mInfoType == "mp3khzwindow" ) + { + prop = item.property("samplerate"); + prop.truncate(2); // we just want 44 instead of 44100 + } + else if ( mInfoType == "mp3kbpswindow" ) + { + prop = item.property("bitrate"); + } + else // for safety: no infoType we know of + return; + + if (prop.isNull()) + prop=""; + prepareString( prop.latin1() ); +} + +void KJFileInfo::prepareString(const QCString &str) +{ + if ( str == mLastTime ) + return; + mLastTime = str; + mTime = textFont().draw(str, rect().width()); + repaint(); +} + +QString KJFileInfo::tip() +{ + if ( mInfoType == "mp3khzwindow" ) + return i18n("Sample rate in kHz"); + else if ( mInfoType == "mp3kbpswindow" ) + return i18n("Bitrate in kbps"); + + return QString(); +} + +#include "kjtextdisplay.moc" diff --git a/noatun/modules/kjofol-skin/kjtextdisplay.h b/noatun/modules/kjofol-skin/kjtextdisplay.h new file mode 100644 index 00000000..11098b0c --- /dev/null +++ b/noatun/modules/kjofol-skin/kjtextdisplay.h @@ -0,0 +1,139 @@ +#ifndef KJTEXTDISPLAY_H +#define KJTEXTDISPLAY_H + +#include "kjwidget.h" +class KJLoader; +class KPixmap; +//#include "kjloader.h" + +#include <qobject.h> +#include <qpainter.h> + +class KJFilename : public QObject, public KJWidget +{ +Q_OBJECT +public: + KJFilename(const QStringList &, KJLoader *parent); + ~KJFilename(); + + virtual void paint(QPainter *, const QRect &rect); + virtual bool mousePress(const QPoint &pos); + virtual void mouseRelease(const QPoint &, bool in); +// virtual void newFile(); + virtual void timeUpdate(int); + virtual void readConfig(); + + void prepareString(const QCString &str); + virtual QString tip(); + + virtual void timerEvent(QTimerEvent *); + +private: + QCString mLastTitle; + int mDistance; + int mTimerUpdates; + int mWidth; + int mTickerPos; + QPixmap mView; + KPixmap *mBack; +}; + + +class KJTime : public KJWidget +{ +public: + KJTime(const QStringList &, KJLoader *parent); + ~KJTime(); + + virtual void paint(QPainter *, const QRect &rect); + virtual bool mousePress(const QPoint &pos); + virtual void mouseRelease(const QPoint &, bool in); + virtual void timeUpdate(int); + virtual void readConfig(); + + void prepareString(const QCString &time); + virtual QString tip(); + +// enum countModes { Up=0, Down }; + +private: + QCString mLastTime; + int mWidth; + bool countDown; + QPixmap mTime; + KPixmap *mBack; + +private: + QString lengthString ( void ); + +}; + + +class KJVolumeText : public KJWidget +{ +public: + KJVolumeText(const QStringList &, KJLoader *parent); + ~KJVolumeText(); + + virtual void paint(QPainter *, const QRect &rect); + virtual bool mousePress(const QPoint &pos); + virtual void timeUpdate(int); + virtual void readConfig(); + + void prepareString(const QCString &time); + virtual QString tip(); + +private: + QCString mLastVolume; + int mWidth; + QPixmap mVolume; + KPixmap *mBack; +}; + + +class KJPitchText : public KJWidget +{ +public: + KJPitchText(const QStringList &, KJLoader *parent); + ~KJPitchText(); + + virtual void paint(QPainter *, const QRect &rect); + virtual bool mousePress(const QPoint &pos); + virtual void mouseRelease(const QPoint &, bool in); + virtual void timeUpdate(int); + virtual void readConfig(); + + void prepareString(const QCString &time); + virtual QString tip(); + +private: + QCString mLastPitch; + int mWidth; + QPixmap mSpeed; + KPixmap *mBack; +}; + + +class KJFileInfo : public KJWidget +{ +public: + KJFileInfo(const QStringList &, KJLoader *parent); + ~KJFileInfo(); + + virtual void paint(QPainter *, const QRect &rect); + virtual bool mousePress(const QPoint &pos); + virtual void timeUpdate(int); + virtual void readConfig(); + + void prepareString(const QCString &time); + virtual QString tip(); + +private: + QCString mLastTime; + QString mInfoType; + int mWidth; + QPixmap mTime; + KPixmap *mBack; +}; + +#endif diff --git a/noatun/modules/kjofol-skin/kjvis.cpp b/noatun/modules/kjofol-skin/kjvis.cpp new file mode 100644 index 00000000..71246089 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjvis.cpp @@ -0,0 +1,538 @@ +/*************************************************************************** + kjvis.cpp - Visualizations used in the KJfol-GUI + -------------------------------------- + Maintainer: Stefan Gehn <metz AT gehn.net> + + ***************************************************************************/ + +// local includes +#include "kjvis.h" +#include "kjprefs.h" + +// system includes +#include <math.h> + +//qt includes +#include <qpainter.h> +#include <qsize.h> + +//kde includes +#include <kdebug.h> +#include <kglobal.h> +#include <kconfig.h> +#include <kpixmapeffect.h> +#include <kpixmap.h> + +// noatun includes +#include <noatun/player.h> + +#define _KJ_GRADIENT_DIFF 130 + +/******************************************* + * KJFFTScope + *******************************************/ + +void KJVisScope::swapScope(Visuals newOne) +{ + //kdDebug(66666) << k_funcinfo << endl; + QStringList line = parent()->item("analyzerwindow"); + KJLoader *p=parent(); + p->removeChild(this); + delete this; + + KJLoader::kjofol->prefs()->setVisType ( newOne ); + + KJWidget *w = 0; + switch (newOne) + { + case Null: + w = new KJNullScope(line, p); + break; + case FFT: + w = new KJFFT(line, p); + break; + case StereoFFT: + w = new KJStereoFFT(line, p); + break; + case Mono: + w = new KJScope(line, p); + break; + }; + + p->addChild(w); +} + +/******************************************* + * KJNullScope + *******************************************/ + +KJNullScope::KJNullScope(const QStringList &l, KJLoader *parent) + : KJVisScope(parent) +{ + int x = l[1].toInt(); + int y = l[2].toInt(); + int xs = l[3].toInt() - x; + int ys = l[4].toInt() - y; + + // background under vis + QPixmap tmp = parent->pixmap(parent->item("backgroundimage")[1]); + mBack = new KPixmap ( QSize(xs,ys) ); + bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP ); + setRect ( x, y, xs, ys ); + repaint(); +} + +void KJNullScope::paint(QPainter *p, const QRect &) +{ + // just redraw the background + bitBlt ( p->device(), rect().topLeft(), mBack, QRect(0,0,-1,-1), Qt::CopyROP ); +} + +bool KJNullScope::mousePress(const QPoint &) +{ + return true; +} + +void KJNullScope::mouseRelease(const QPoint &, bool in) +{ + if (!in) // only do something if users is still inside the button + return; + + parent()->repaint(rect(), false); + swapScope(FFT); +} + +void KJNullScope::readConfig() +{ +// kdDebug(66666) << "[KJNullScope] readConfig()" << endl; + Visuals v = (Visuals) KJLoader::kjofol->prefs()->visType(); + if ( v != Null ) + { + parent()->repaint(rect(), false); + swapScope ( v ); + } +} + + +/************************************************* + * KJFFT - Analyzer like visualization, mono + *************************************************/ + +KJFFT::KJFFT(const QStringList &l, KJLoader *parent) + : KJVisScope(parent), MonoFFTScope(50), mGradient(0) +{ + int x = l[1].toInt(); + int y = l[2].toInt(); + int xs = l[3].toInt()-x; + int ys = l[4].toInt()-y; + + // each bar will be 1px wide + mMultiples=1; + + if ( parent->exist("analyzercolor") ) + { + QStringList &col = parser()["analyzercolor"]; + mColor.setRgb ( col[1].toInt(), col[2].toInt(), col[3].toInt() ); + } + else // TODO: what should be default colors for Vis? + { + mColor.setRgb ( 255, 255, 255 ); // white is default + } + + // background under vis + QPixmap tmp = parent->pixmap(parent->item("backgroundimage")[1]); + mBack = new KPixmap ( QSize(xs,ys) ); + bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP ); + + mAnalyzer = new KPixmap ( QSize(xs,ys) ); + bitBlt( mAnalyzer, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP ); + + // create a gradient for the bars going from 30% lighter to 30% darker than mColor + mGradient = new KPixmap ( QSize(xs,ys) ); + KPixmapEffect::gradient ( *mGradient, mColor.light(_KJ_GRADIENT_DIFF), + mColor.dark(_KJ_GRADIENT_DIFF), KPixmapEffect::VerticalGradient ); + + setRect (x,y,xs,ys); + setBands(magic(xs/mMultiples)); + readConfig(); // read our config settings + start(); +} + +void KJFFT::scopeEvent(float *d, int size) +{ + if ( !napp->player()->isPlaying() ) // don't draw if we aren't playing (either paused or stopped) + { + if ( napp->player()->isStopped() ) // clear vis-window if playing has been stopped + parent()->repaint(rect(), false); + return; + } + + int x = 0; + int h = rect().height(); + + QBitmap mGradientMask ( rect().width(), h, true ); + QPainter mask( &mGradientMask ); + + float *start = d ; + float *end = d + size /*- 1*/; + + // loop creating the mask for vis-gradient + for ( ; start < end; ++start ) + { + // 5 has been 8 before and I have no idea how this scaling works :/ + // FIXME: somebody please make it scale to 100% of height, + // I guess that would be nicer to look at +// float n = log((*start)+1) * (float)h * 5; + float n = log((*start)+1) * (float)h * 5; + int amp=(int)n; + + // range check + if ( amp < 0 ) amp = 0; + else if ( amp > h ) amp = h; + + // make a part of the analyzer-gradient visible + mask.fillRect ( x, (h-amp), mMultiples, amp, Qt::color1 ); + x += mMultiples; + } + // done creating our mask + + // draw background of vis into it + bitBlt ( mAnalyzer, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP ); + + // draw the analyzer + mGradient->setMask(mGradientMask); + bitBlt ( mAnalyzer, 0, 0, mGradient, 0, 0, -1, -1, Qt::CopyROP ); + + repaint(); +} + +void KJFFT::paint(QPainter *p, const QRect &) +{ + // put that thing on screen + if ( !napp->player()->isStopped() ) + bitBlt ( p->device(), rect().topLeft(), mAnalyzer, QRect(0,0,-1,-1), Qt::CopyROP ); +} + + +bool KJFFT::mousePress(const QPoint &) +{ + return true; +} + +void KJFFT::mouseRelease(const QPoint &, bool in) +{ + if (!in) // only do something if users is still inside the button + return; + + stop(); + parent()->repaint(rect(), false); + swapScope(Mono); +} + +void KJFFT::readConfig() +{ +// kdDebug(66666) << "[KJFFT] readConfig()" << endl; + Visuals v = (Visuals) KJLoader::kjofol->prefs()->visType(); + if ( v != FFT ) + { + stop(); + parent()->repaint(rect(), false); + swapScope ( v ); + return; + } + + mTimerValue = KJLoader::kjofol->prefs()->visTimerValue(); + setInterval( mTimerValue ); +} + + +/************************************************* + * KJStereoFFT - Analyzer like visualization, stereo + *************************************************/ + +KJStereoFFT::KJStereoFFT(const QStringList &l, KJLoader *parent) + : KJVisScope(parent), StereoFFTScope(50), mGradient(0) +{ + //kdDebug(66666) << k_funcinfo << endl; + + int x = l[1].toInt(); + int y = l[2].toInt(); + int xs = l[3].toInt()-x; + int ys = l[4].toInt()-y; + + // each bar will be 1px wide + mMultiples=1; + + if ( parent->exist("analyzercolor") ) + { + QStringList &col = parser()["analyzercolor"]; + mColor.setRgb ( col[1].toInt(), col[2].toInt(), col[3].toInt() ); + } + else // TODO: what should be default colors for Vis? + { + mColor.setRgb ( 255, 255, 255 ); // white is default + } + + // background under vis + QPixmap tmp = parent->pixmap(parent->item("backgroundimage")[1]); + mBack = new KPixmap ( QSize(xs,ys) ); + bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP ); + + mAnalyzer = new KPixmap ( QSize(xs,ys) ); + bitBlt( mAnalyzer, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP ); + + // create a gradient for the bars going from 30% lighter to 30% darker than mColor + mGradient = new KPixmap ( QSize(xs,ys) ); + KPixmapEffect::gradient ( *mGradient, mColor.light(_KJ_GRADIENT_DIFF), + mColor.dark(_KJ_GRADIENT_DIFF), KPixmapEffect::VerticalGradient ); + + setRect (x,y,xs,ys); + setBands(magic(xs/mMultiples)); + readConfig(); // read our config settings + start(); +} + +void KJStereoFFT::scopeEvent(float *left, float *right, int len) +{ + if ( !napp->player()->isPlaying() ) // don't draw if we aren't playing (either paused or stopped) + { + if ( napp->player()->isStopped() ) // clear vis-window if playing has been stopped + parent()->repaint(rect(), false); + return; + } + + unsigned int h = rect().height(); + int hh = (int)(rect().height()/2); + + QBitmap mGradientMask ( rect().width(), h, true ); + QPainter mask( &mGradientMask ); + + float *start = left; + float *end = left + len; + float n = 0.0; + int amp = 0; + int x = 0; + + // loop creating the mask for vis-gradient + for ( ; start < end; ++start ) + { + n = log((*start)+1) * (float)hh * 5; + amp = (int)n; + + // range check + if ( amp < 0 ) amp = 0; + else if ( amp > hh ) amp = hh; + + // make a part of the analyzer-gradient visible + mask.fillRect ( x, (h-amp), mMultiples, amp, Qt::color1 ); + x += mMultiples; + } + // done creating our mask + + + start = right; + end = right + len; + x = 0; + // loop creating the mask for vis-gradient + for ( ; start < end; ++start ) + { + n = log((*start)+1) * (float)hh * 5; + amp = (int)n; + + // range check + if ( amp < 0 ) amp = 0; + else if ( amp > hh ) amp = hh; + + // make a part of the analyzer-gradient visible + mask.fillRect ( x, 0, mMultiples, amp, Qt::color1 ); + x += mMultiples; + } + + + // draw background of vis into it + bitBlt ( mAnalyzer, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP ); + + // draw the analyzer + mGradient->setMask(mGradientMask); + bitBlt ( mAnalyzer, 0, 0, mGradient, 0, 0, -1, -1, Qt::CopyROP ); + + repaint(); +} + +void KJStereoFFT::paint(QPainter *p, const QRect &) +{ + // put that thing on screen + if ( !napp->player()->isStopped() ) + bitBlt ( p->device(), rect().topLeft(), mAnalyzer, QRect(0,0,-1,-1), Qt::CopyROP ); +} + +bool KJStereoFFT::mousePress(const QPoint &) +{ + return true; +} + +void KJStereoFFT::mouseRelease(const QPoint &, bool in) +{ + if (!in) // only do something if users is still inside the button + return; + stop(); + parent()->repaint(rect(), false); + swapScope(Null); +} + +void KJStereoFFT::readConfig() +{ + //kdDebug(66666) << k_funcinfo << endl; + Visuals v = (Visuals) KJLoader::kjofol->prefs()->visType(); + if ( v != StereoFFT ) + { + stop(); + parent()->repaint(rect(), false); + swapScope ( v ); + return; + } + setInterval(KJLoader::kjofol->prefs()->visTimerValue()); +} + + +/************************************************* + * KJScope - oscilloscope like visualization + *************************************************/ + +KJScope::KJScope(const QStringList &l, KJLoader *parent) + : KJVisScope(parent), MonoScope(50)/*, blurnum(0), mOsci(0)*/ +{ + int x=l[1].toInt(); + int y=l[2].toInt(); + int xs = mWidth = l[3].toInt()-x; + int ys = mHeight = l[4].toInt()-y; + + blurnum = 0; + +// kdDebug(66666) << "Analyzer Window " << x << "," << y << " " << mWidth << "," << mHeight << endl; + + if ( parent->exist("analyzercolor") ) + { + QStringList &col = parser()["analyzercolor"]; + mColor.setRgb ( col[1].toInt(), col[2].toInt(), col[3].toInt() ); + } + else // FIXME: what should be default colors for Vis? + mColor.setRgb ( 255, 255, 255 ); + + // background under vis + QPixmap tmp = parent->pixmap(parent->item("backgroundimage")[1]); + mBack = new KPixmap ( QSize(xs,ys) ); + bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP ); + + mOsci = new KPixmap ( QSize(xs,ys) ); + bitBlt( mOsci, 0, 0, &tmp, x, y, xs, ys, Qt::CopyROP ); + + // create a gradient + mGradient = new KPixmap ( QSize(xs,ys) ); + KPixmapEffect::gradient ( *mGradient, mColor.light(_KJ_GRADIENT_DIFF), + mColor.dark(_KJ_GRADIENT_DIFF), KPixmapEffect::VerticalGradient ); + + setRect ( x, y, xs, ys ); + + // set the samplewidth to the largest integer divisible by mWidth + setSamples ( xs ); + + readConfig(); + start(); +} + +void KJScope::scopeEvent(float *d, int size) +{ + if ( !napp->player()->isPlaying() ) + { + if ( napp->player()->isStopped() ) + { + bitBlt ( mOsci, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP ); + repaint(); + } + return; + } + + float *start = d; + float *end = d + size; + + int heightHalf = rect().height()/2 /* -1 */; + int x = 0; + + QPainter tempP( mOsci ); + + if ( blurnum == 3 ) + { // clear whole Vis + bitBlt ( mOsci, 0, 0, mBack, 0, 0, -1, -1, Qt::CopyROP ); + tempP.setPen( mColor.light(110) ); // 10% lighter than mColor + blurnum=0; + } + else + { + blurnum++; + // reduce color for blur-effect + tempP.setPen( mColor.dark(90+(10*blurnum)) ); // darken color + } + + for ( ; start < end; ++start ) + { + float n = (*start) * (float)heightHalf; + int amp = (int)n; + + // range check + if ( amp > heightHalf ) amp = heightHalf; + else if ( amp < -heightHalf) amp = -heightHalf; + + // draw +// tempP.drawLine(x, heightHalf, x, heightHalf+amp); + if ( amp > 0 ) + { + bitBlt ( tempP.device(), QPoint(x,heightHalf), mGradient, QRect(x,heightHalf,1,amp), Qt::CopyROP ); + } + else + { + amp = -amp; + bitBlt ( tempP.device(), QPoint(x,heightHalf-amp), mGradient, QRect(x,(heightHalf-amp),1,amp), Qt::CopyROP ); + } + x++; + } + + repaint(); +} + +void KJScope::paint(QPainter *p, const QRect &) +{ + // put that thing on screen + bitBlt ( p->device(), rect().topLeft(), mOsci, QRect(0,0,-1,-1), Qt::CopyROP ); +} + +bool KJScope::mousePress(const QPoint &) +{ + return true; +} + +void KJScope::mouseRelease(const QPoint &, bool in) +{ + if (!in) // only do something if users is still inside the button + return; + + stop(); + parent()->repaint(rect(), false); + swapScope(/*Null*/ StereoFFT); +} + +void KJScope::readConfig() +{ +// kdDebug(66666) << "[KJScope] readConfig()" << endl; + Visuals v = (Visuals) KJLoader::kjofol->prefs()->visType(); + if ( v != Mono ) + { + stop(); + parent()->repaint(rect(), false); + swapScope ( v ); + return; + } + + mTimerValue = KJLoader::kjofol->prefs()->visTimerValue(); + setInterval( mTimerValue ); +} diff --git a/noatun/modules/kjofol-skin/kjvis.h b/noatun/modules/kjofol-skin/kjvis.h new file mode 100644 index 00000000..d2a43700 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjvis.h @@ -0,0 +1,102 @@ +#ifndef KJVIS_H +#define KJVIS_H + +#include "kjwidget.h" +class KJLoader; +class KPixmap; + +class KJVisScope : public KJWidget +{ +public: + KJVisScope(KJLoader *parent) : KJWidget(parent) {}; + enum Visuals { Null=0, FFT, Mono, StereoFFT }; + void swapScope(Visuals newOne); +// virtual void readConfig(); +}; + + +// dummy-scope displaying nothing +class KJNullScope : public KJVisScope +{ +public: + KJNullScope(const QStringList &, KJLoader *parent); + virtual void paint(QPainter *p, const QRect &); + virtual bool mousePress(const QPoint&); + virtual void mouseRelease(const QPoint &, bool in); + virtual void readConfig(void); + +private: + KPixmap *mBack; + +}; + + +// analyzer-like scope +class KJFFT : public KJVisScope, public MonoFFTScope +{ +public: + KJFFT(const QStringList &, KJLoader *parent); + virtual void paint(QPainter *p, const QRect &); + virtual void scopeEvent(float *d, int size); + + virtual bool mousePress(const QPoint&); + virtual void mouseRelease(const QPoint &, bool in); + virtual void readConfig(void); + +private: + QColor mColor; + KPixmap *mGradient; + KPixmap *mBack; + KPixmap *mAnalyzer; + int mMultiples; + int mTimerValue; +}; + + +// analyzer-like scope, stereo version +class KJStereoFFT : public KJVisScope, public StereoFFTScope +{ +public: + KJStereoFFT(const QStringList &, KJLoader *parent); + virtual void paint(QPainter *p, const QRect &); + virtual void scopeEvent(float *left, float *right, int len); + + virtual bool mousePress(const QPoint&); + virtual void mouseRelease(const QPoint &, bool in); + virtual void readConfig(void); + +private: + QColor mColor; + KPixmap *mGradient; + KPixmap *mBack; + KPixmap *mAnalyzer; + int mMultiples; + int mTimerValue; +}; + + +// oscilloscope showing waveform +class KJScope : public KJVisScope, public MonoScope +{ +public: + KJScope ( const QStringList &, KJLoader *parent); + virtual void paint(QPainter *p, const QRect &); + virtual void scopeEvent(float *d, int size); + + virtual bool mousePress(const QPoint&); + virtual void mouseRelease(const QPoint &, bool in); + virtual void readConfig(void); + +private: + QColor mColor; + KPixmap *mGradient; + KPixmap *mBack; + KPixmap *mOsci; + int mMultiples; + int mWidth; + int mHeight; + unsigned int blurnum; + int mTimerValue; +}; + +#endif diff --git a/noatun/modules/kjofol-skin/kjwidget.cpp b/noatun/modules/kjofol-skin/kjwidget.cpp new file mode 100644 index 00000000..e7b6a4d1 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjwidget.cpp @@ -0,0 +1,70 @@ +/*************************************************************************** + kjwidget.cpp - Base Class for all widgets + -------------------------------------- + Maintainer: Stefan Gehn <sgehn@gmx.net> + + ***************************************************************************/ + +// local includes +#include "kjwidget.h" +//#include <kdebug.h> + +// ugly static functions and stuff +#include "helpers.cpp" + +#include <qpainter.h> + +KJWidget::KJWidget(KJLoader *p) : mParent(p) +{ +} + +QBitmap KJWidget::getMask(const QImage &_rect, register QRgb transparent) +{ + QImage result(_rect.width(), _rect.height(), 1,2, QImage::LittleEndian); +#if QT_VERSION < 0x030300 + result.setColor(0, qRgb(0,0,0)); //TODO: maybe use Qt::color0 and Qt::color1 + result.setColor(1, qRgb(255,255,255)); +#else + result.setColor(1, qRgb(0,0,0)); + result.setColor(0, qRgb(255,255,255)); +#endif + + for(int height=0;height<_rect.height(); height++) + { + for(int width=0; width<_rect.width(); width++) + setPixel1BPP(result, width, height, _rect.pixel(width, height)!=transparent); + } + QBitmap bm; + bm.convertFromImage(result); + return bm; +} + +void KJWidget::repaint(bool me, const QRect &r, bool clear) +{ + QPainter p(parent()); + if (me) + paint(&p, r.isValid() ? r : rect()); + else + parent()->repaint(r.isValid() ? r : rect(), clear); +} + +const QString &KJWidget::backgroundPressed(const QString &bmp) const +{ + if(bmp.isEmpty()) // play safe + { +// kdDebug(66666) << k_funcinfo << "empty argument 'bmp', returning QString::null!" << endl; + return QString::null; + } + +// kdDebug(66666) << k_funcinfo << "Returning pressed pixmap for '" << bmp.latin1() << "'" << endl; + + // make absolutely sure the wanted backgroundimagepressedX line is there + QStringList item = parser()["backgroundimagepressed"+QString::number(bmp.mid(3).toInt())]; + if(item.count() < 2) + { +// kdDebug(66666) << k_funcinfo << "backgroundimagepressed doesn't have enough keys in its line!" << endl; + return QString::null; + } + else + return item[1]; +} diff --git a/noatun/modules/kjofol-skin/kjwidget.h b/noatun/modules/kjofol-skin/kjwidget.h new file mode 100644 index 00000000..cc7ddf53 --- /dev/null +++ b/noatun/modules/kjofol-skin/kjwidget.h @@ -0,0 +1,53 @@ +#ifndef KJWIDGET_H +#define KJWIDGET_H + +#include "kjloader.h" + +class KJWidget +{ +public: + KJWidget(KJLoader *); + virtual ~KJWidget() {}; + // called when the widget should paint + virtual void paint(QPainter *, const QRect &) {}; + // called to receive the rect this widget is in + virtual QRect rect() const { return mRect; } + // called when pressed in this widget + virtual bool mousePress(const QPoint &) {return false; } + // called when the mouse is released after clicked in this widget + virtual void mouseRelease(const QPoint &, bool){} + virtual void mouseMove(const QPoint &, bool) {} + // called with the current time (mille) + virtual void timeUpdate(int) {} + // called when a new song is playing, player() is ready with it too + virtual void newFile() {} + // called when config-entries have to be read, is a TODO for most widgets + virtual void readConfig() {} + + // called when the mouse is moved while clicked in this widget + // repaint myself + virtual void repaint(bool me=true, const QRect &rect=QRect(), bool clear=false); + + virtual QString tip() { return 0; } + +public: + static QBitmap getMask(const QImage &color, register QRgb=qRgb(255,0,255)); + +protected: + const QString &backgroundPressed(const QString &bmp) const; + KJLoader *parent() const {return mParent;} + KJLoader &parser() const {return *mParent;} + + KJFont &textFont() const {return *mParent->mText;} + KJFont &timeFont() const {return *mParent->mNumbers;} + KJFont &volumeFont() const {return *mParent->mVolumeFont;} + KJFont &pitchFont() const {return *mParent->mPitchFont;} + + void setRect(const QRect& rect) {mRect=rect;} + void setRect(int x, int y, int xs, int ys) {mRect=QRect(x,y,xs,ys);} +private: + KJLoader *mParent; + QRect mRect; +}; + +#endif diff --git a/noatun/modules/kjofol-skin/noatunui.cpp b/noatun/modules/kjofol-skin/noatunui.cpp new file mode 100644 index 00000000..b5be87fd --- /dev/null +++ b/noatun/modules/kjofol-skin/noatunui.cpp @@ -0,0 +1,9 @@ +#include "kjloader.h" + +extern "C" +{ + KDE_EXPORT Plugin *create_plugin() + { + return new KJLoader(); + } +} diff --git a/noatun/modules/kjofol-skin/parser.cpp b/noatun/modules/kjofol-skin/parser.cpp new file mode 100644 index 00000000..df5fdc40 --- /dev/null +++ b/noatun/modules/kjofol-skin/parser.cpp @@ -0,0 +1,132 @@ +/*************************************************************************** + parser.cpp - Reads *.rc files in kjfol-config-format into a QDict + -------------------------------------- + Maintainer: Stefan Gehn <sgehn@gmx.net> + + ***************************************************************************/ + +// local includes +#include "parser.h" +#include "kjprefs.h" + +// system includes +#include <qtextstream.h> +#include <qimage.h> +#include <qfile.h> +#include <kdebug.h> +#include <kmimemagic.h> +#include <kurl.h> + +Parser::Parser() : QDict<QStringList>(17,false) +{ + mSkinAbout=""; + mImageCache.setAutoDelete(true); + setAutoDelete(true); +} + +void Parser::conserveMemory() +{ + mImageCache.clear(); +} + +void Parser::open(const QString &file) +{ + clear(); + mImageCache.clear(); + mSkinAbout=""; + mDir=KURL(file).directory(); + QFile f(file); + if ( !f.exists() ) + return; + f.open(IO_ReadOnly); + + f.at(0); + QTextStream stream(&f); + while (!stream.eof()) + { + QString line=stream.readLine(); + line=line.simplifyWhiteSpace(); + if ((!line.length()) || line[0]=='#') + continue; + QStringList *l=new QStringList(QStringList::split(" ", (line.lower()))); + QString first=l->first(); + + // special handling for about-texts as the key "about" can appear multiple + // times and thus does not fit into qdict. + if (first=="about") + { + if (!mSkinAbout.isEmpty()) + mSkinAbout+="\n"; + + mSkinAbout += line.mid(6); +// kdDebug(66666) << "found About-line, mSkinAbout is now '" << mSkinAbout << "'" << endl; + delete l; // don't need the stringlist anymore + } + else + insert(first, l); + } +} + +QString Parser::fileItem(const QString &i) const +{ + return dir()+'/'+i; +} + +QString Parser::dir() const +{ + return mDir; +} + +Parser::ImagePixmap* Parser::getPair(const QString &filenameOld) const +{ + // is it in there? + ImagePixmap *pair; + { + pair=mImageCache.find(filenameOld); + if (pair) + return pair; + } + + QString filename=fileItem(filenameOld); + + QImage image; + + // Determine file-format trough mimetype (no stupid .ext test) + KMimeMagicResult * result = KMimeMagic::self()->findFileType( filename ); + + if ( result->mimeType() == "image/png" ) + { +// image = NoatunApp::readPNG(filenameNoCase(filename)); + QImageIO iio; + iio.setFileName( filenameNoCase(filename) ); + // forget about gamma-value, fix for broken PNGs + iio.setGamma( 0.00000001 ); + if ( iio.read() ) + { + image = iio.image(); + image.setAlphaBuffer(false); // we don't want/support alpha-channels + } + else + { + kdDebug(66666) << "Could not load file: " << filename.latin1() << endl; + } + } + else + { + image = QImage(filenameNoCase(filename)); + } + + //add to the cache + QPixmap pixmap; + pixmap.convertFromImage(image, QPixmap::AutoColor|QPixmap::ThresholdDither|QPixmap::AvoidDither); + pair = new Parser::ImagePixmap; + pair->mImage = image; + pair->mPixmap = pixmap; + mImageCache.insert(filenameOld, pair); + return pair; +} + +bool Parser::exist(const QString &i) const +{ + return (bool)find(i); +} diff --git a/noatun/modules/kjofol-skin/parser.h b/noatun/modules/kjofol-skin/parser.h new file mode 100644 index 00000000..97e20d99 --- /dev/null +++ b/noatun/modules/kjofol-skin/parser.h @@ -0,0 +1,49 @@ +#ifndef PARSER_H +#define PARSER_H + +// system includes +#include <qstringlist.h> +#include <qpixmap.h> +#include <qimage.h> +#include <qdict.h> + +class Parser : public QDict<QStringList> +{ + class ImagePixmap + { + public: + ImagePixmap() : mImage(0), mPixmap(0) {} + ~ImagePixmap() {} + QImage mImage; + QPixmap mPixmap; + }; + + public: + Parser(); + + void conserveMemory(); + void open(const QString &file); + + QString dir() const; + QPixmap pixmap(const QString &pixmap) const + { return getPair(pixmap)->mPixmap; } + QImage image(const QString &image) const + { return getPair(image)->mImage; } + QString about() const { return mSkinAbout; }; + + QString fileItem(const QString &file) const; + + bool exist(const QString &i) const; + + public: + QStringList& operator[](const QString &l) { return *find(l);} + + private: + ImagePixmap *getPair(const QString &i) const; + + private: + mutable QDict<ImagePixmap> mImageCache; + QString mDir; + QString mSkinAbout; +}; +#endif // PARSER_H diff --git a/noatun/modules/kjofol-skin/skins/HexoBronx/HexoBronx.rc b/noatun/modules/kjofol-skin/skins/HexoBronx/HexoBronx.rc new file mode 100644 index 00000000..76e9d10c --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/HexoBronx/HexoBronx.rc @@ -0,0 +1,77 @@ +About .: HexoBronx :. + +BackgroundImage inactive.png +BackgroundImagePressed1 active.png +BackgroundImageInactive inactive.png + +SplashScreen splash.png + + +FontImage font.png +FontSize 5 7 +FontSpacing 0 +FontTransparent 1 + +TimeFontImage eckig_font.png +TimeFontSize 7 7 +TimeFontSpacing 0 +TimeFontTransparent 1 + +PitchFontImage volume_pitch_font.png +PitchFontSize 5 7 +PitchFontSpacing 0 +PitchFontTransparent 1 + +VolumeFontImage volume_pitch_font.png +VolumeFontSize 5 7 +VolumeFontSpacing 0 +VolumeFontTransparent 1 + + +SeekRegion 100 138 222 178 +SeekImage mask.png + +VolumeControlType BMP +VolumeControlImage volume.png +VolumeControlImagePosition mask.png +VolumeControlImageXSize 33 +VolumeControlImageNb 39 +VolumeControlButton 16 108 48 146 vol + +PitchControlImage pitch.png +PitchControlImagePosition mask.png +PitchControlImageXSize 33 +PitchControlImageNb 39 +PitchControlButton 272 108 304 146 pitch + +CloseButton 233 31 245 42 close BMP1 +MinimizeButton 77 32 89 41 min BMP1 + +PlayButton 124 21 160 59 play BMP1 +PauseButton 161 21 197 59 pause BMP1 + +RewindButton 52 62 111 99 rwd BMP1 +ForwardButton 211 62 271 99 fwd BMP1 + +AboutButton 144 76 176 86 about BMP1 +PlaylistButton 137 89 185 102 pl BMP1 + +RepeatButton 85 119 103 136 repeat BMP1 +PreferencesButton 220 118 236 136 pref BMP1 + +PreviousSongButton 52 156 109 192 prevsong BMP1 +NextSongButton 212 156 271 192 nextsong BMP1 + +StopButton 123 197 197 233 stop BMP1 + + +MP3TimeWindow 144 104 179 111 + +VolumeText 118 115 138 122 + +PitchText 190 115 205 122 + +FilenameWindow 108 125 215 132 + +AnalyzerWindow 130 134 192 153 analyzer +AnalyzerColor 136 217 144 diff --git a/noatun/modules/kjofol-skin/skins/HexoBronx/Makefile.am b/noatun/modules/kjofol-skin/skins/HexoBronx/Makefile.am new file mode 100644 index 00000000..5be0735d --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/HexoBronx/Makefile.am @@ -0,0 +1,7 @@ + +skin_DATA = HexoBronx.rc README.txt active.png eckig_font.png \ + font.png inactive.png mask.png pitch.png splash.png time_font.png volume.png \ + volume_pitch_font.png + +skindir = $(kde_datadir)/noatun/skins/kjofol/HexoBronx +EXTRA_DIST = $(skin_DATA) diff --git a/noatun/modules/kjofol-skin/skins/HexoBronx/README.txt b/noatun/modules/kjofol-skin/skins/HexoBronx/README.txt new file mode 100644 index 00000000..640ca023 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/HexoBronx/README.txt @@ -0,0 +1,79 @@ +HeXoBronX - Desktop Media Control Interface + for Noatun's K-Jfol Skin Loader + + ...brought to you by mETz, Crix and Sush +--------------------------------------------------------------- + +We would like to thank you for downloading/installing this little piece +of art. This is our first try with K-Jfol skinning and we hope you +enjoy the result. + +Features +-------- +The skin features the following buttons/functions + + - play, pause, stop + - fastforward, rewind + - previous and next track + - volume and pitch + - seeker + - playlist button + - repeat + - preferences + - about + - window controls: minimize, close + - works with Noatun and XMMS + +What you could possibly miss +---------------------------- +Things this skin doesn't support: + + - There is no skinned playlist because playlists suck with K-Jfol skins. + + - There is no skinned dockmode. + + - It lacks support for original K-Jfol player. Sounds odd but it's true. + This skin does not work with that player. During design we forgot to + make sizes divisible by four which seems to be a quite important skin + spec. When we actually realized that it was already too late to make + the appropriate changes :/ + However it works very well with Noatun's K-Jfol skin loader. + If there is anyone out there who want's to use this skin for + the original K-Jfol player he might drop us a line and we'll see. + + +Credits +------- + - Design concept, scripting and idea: + Stefan "mETz" Gehn, <sgehn@gmx.net> + + - Executive artist: + Christian "Crix" Hoffmann + be sure to visit http://www.crixensgfxcorner.de.vu + + - Assistance and suggestions: + Sascha "Sush" Hoffmann + +Special thanks to +----------------- + - Lars "die.viper" Kluge for improving the first scribbles of this skin + be sure to visit http://www.die-viper.de + + - You for reading this file and trying this skin + +Licensing stuff +--------------- +This skin is copyright 2002 by the people mentioned in the Credits above +and distributed under the Clarified Artistic Licence. + +The most important things to mention: + + - you are allowed to redistribute it + + - you are allowed to alter it but please give credits and give it a new name + + +Hey! Why are you wasting your time with this readme? Just go ahead and try the skin! +Have fun! + + -mETz, Crix and Sush, 01/25/2002 diff --git a/noatun/modules/kjofol-skin/skins/HexoBronx/active.png b/noatun/modules/kjofol-skin/skins/HexoBronx/active.png Binary files differnew file mode 100644 index 00000000..f82388e8 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/HexoBronx/active.png diff --git a/noatun/modules/kjofol-skin/skins/HexoBronx/eckig_font.png b/noatun/modules/kjofol-skin/skins/HexoBronx/eckig_font.png Binary files differnew file mode 100644 index 00000000..ad137023 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/HexoBronx/eckig_font.png diff --git a/noatun/modules/kjofol-skin/skins/HexoBronx/font.png b/noatun/modules/kjofol-skin/skins/HexoBronx/font.png Binary files differnew file mode 100644 index 00000000..ba1c2f7e --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/HexoBronx/font.png diff --git a/noatun/modules/kjofol-skin/skins/HexoBronx/inactive.png b/noatun/modules/kjofol-skin/skins/HexoBronx/inactive.png Binary files differnew file mode 100644 index 00000000..2c19d06a --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/HexoBronx/inactive.png diff --git a/noatun/modules/kjofol-skin/skins/HexoBronx/mask.png b/noatun/modules/kjofol-skin/skins/HexoBronx/mask.png Binary files differnew file mode 100644 index 00000000..d9e376c1 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/HexoBronx/mask.png diff --git a/noatun/modules/kjofol-skin/skins/HexoBronx/pitch.png b/noatun/modules/kjofol-skin/skins/HexoBronx/pitch.png Binary files differnew file mode 100644 index 00000000..97c9c464 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/HexoBronx/pitch.png diff --git a/noatun/modules/kjofol-skin/skins/HexoBronx/splash.png b/noatun/modules/kjofol-skin/skins/HexoBronx/splash.png Binary files differnew file mode 100644 index 00000000..d7433a5f --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/HexoBronx/splash.png diff --git a/noatun/modules/kjofol-skin/skins/HexoBronx/time_font.png b/noatun/modules/kjofol-skin/skins/HexoBronx/time_font.png Binary files differnew file mode 100644 index 00000000..bd409d7f --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/HexoBronx/time_font.png diff --git a/noatun/modules/kjofol-skin/skins/HexoBronx/volume.png b/noatun/modules/kjofol-skin/skins/HexoBronx/volume.png Binary files differnew file mode 100644 index 00000000..1db32364 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/HexoBronx/volume.png diff --git a/noatun/modules/kjofol-skin/skins/HexoBronx/volume_pitch_font.png b/noatun/modules/kjofol-skin/skins/HexoBronx/volume_pitch_font.png Binary files differnew file mode 100644 index 00000000..df0160f9 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/HexoBronx/volume_pitch_font.png diff --git a/noatun/modules/kjofol-skin/skins/Makefile.am b/noatun/modules/kjofol-skin/skins/Makefile.am new file mode 100644 index 00000000..47e5721d --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/Makefile.am @@ -0,0 +1,3 @@ + +SUBDIRS=kjofol phong vibrocentric HexoBronx + diff --git a/noatun/modules/kjofol-skin/skins/kjofol/Makefile.am b/noatun/modules/kjofol-skin/skins/kjofol/Makefile.am new file mode 100644 index 00000000..f549bccc --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/Makefile.am @@ -0,0 +1,11 @@ + +skin_DATA = kjofol.dck kjofol.pl kjofol.rc kjofol.wsh sgdock2.png \ + sgdock.png sgdocksk.png sgdockvp.png sgeq.png sg_num.png \ + sgpitch.png sgpitchp.png sgplist2.png sgplist.png sg.png \ + sgpres1.png sgpres2.png sgpres3.png sg_seek.bmp sg_seek.png \ + sg_text.png sgvolnum.png sgvol.png sgvolpos.png sgwshad2.png \ + sgwshad.png sgwshdsk.png sgwshvol.png sgwshvp.png + +skindir = $(kde_datadir)/noatun/skins/kjofol/kjofol +EXTRA_DIST = $(skin_DATA) + diff --git a/noatun/modules/kjofol-skin/skins/kjofol/kjofol.dck b/noatun/modules/kjofol-skin/skins/kjofol/kjofol.dck new file mode 100644 index 00000000..7af3b666 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/kjofol.dck @@ -0,0 +1,62 @@ +# Kjofol Default resource file - DOCKING MODE
+
+# Command : BackgroundImage <Name of .BMP file>
+# Desc. : This is the back image.
+BackgroundImage sgdock.png
+
+# Command : BackgroundImageInactive <Name of .BMP file>
+# Desc. : This is the back image when the window is not selected.
+# : If you do not want this feature, just put the same name as
+# : BackgroundImage
+BackgroundImageInactive sgdock.png
+
+# Command : BackgroundImagePressed[1-3] <Name of .BMP file>
+# Desc. : This is the back images when all the buttons are pressed
+# : Used if you use the BMP option in the buttons options.
+# : You can have 3 backimages so you can do nifty things for the
+# : buttons =)
+BackgroundImagePressed1 sgdock2.png
+
+FontImage sg_text.png
+FontSize 5 9
+FontSpacing 0
+FontTransparent 0
+
+# Command : VolumeControlType <BAR/BMP>
+# Desc. : Put BAR if you want a bar style volume control, BMP if you want
+# : to customize it by a BMP animation file ...
+VolumeControlType BMP
+VolumeControlImage sgwshvol.png
+VolumeControlImagePosition sgdockvp.png
+VolumeControlImageXSize 30
+VolumeControlImageNb 28
+VolumeControlButton 100 17 129 23 vOLUME
+
+# Command : [Option]Button <Position X> <Position Y> <End X> <End Y> <Tooltip Text> <DARKEN/BMP[?]>
+# The DARKEN option just dark the button when the user click on it.
+# The BMP[?] option use the BackgroundImagePressed[?] defined above.
+# Be sure to define a BackgroundImagePressed if you use the BMP option !!
+AboutButton 10 12 27 32 About BMP1
+OpenFileButton 14 73 32 91 Open BMP1
+StopButton 14 56 32 73 Stop BMP1
+PlayButton 14 37 32 55 Play BMP1
+PreviousSongButton 14 92 33 109 PreviousSong BMP1
+NextSongButton 14 110 33 127 NextSong BMP1
+UnDockModeButton 14 127 33 140 UnDock BMP1
+
+# Command : FilenameWindow
+# Desc. : This is the window where the file name appears
+FilenameWindow 65 23 141 32
+
+SeekRegion 56 18 84 21
+SeekImage sgdocksk.png
+
+# Command : AnalyzerWindow <X> <Y> <MaxX> <MaxY> <TipTool>
+# Desc. : Spectrum Analyzer area. If you doesn't want one, just comment the
+# line ...
+AnalyzerWindow 41 23 62 32 Analyzer
+# Command : AnalyzerColor <Red> <Green> <Blue>
+# Desc. : Spectrum Analyzer color. Colors range are 0-255.
+AnalyzerColor 81 94 81
+
+IncludeRCFile kjofol.pl
\ No newline at end of file diff --git a/noatun/modules/kjofol-skin/skins/kjofol/kjofol.pl b/noatun/modules/kjofol-skin/skins/kjofol/kjofol.pl new file mode 100644 index 00000000..e7eaf45a --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/kjofol.pl @@ -0,0 +1,39 @@ +# Playlist screen section +PlaylistBmp sgplist.png +PlaylistBmpPressed sgplist2.png + +# Command : PlaylistWindowText <X> <Y> <MaxX> <MaxY> +# Desc. : Where all the playlist files will be placed on the playlist +# screen +PlaylistWindowText 43 42 170 211 +PlaylistWindowFontName Arial +PlaylistWindowFontSize 12 +PlaylistWindowFontYSpacing 10 +PlaylistWindowNbSelectedTrack 79 215 93 225 +PlaylistWindowNbTotalTracks 79 230 93 240 + +PlaylistWindowLinkButton 180 33 194 48 +PlaylistWindowCloseButton 174 21 187 35 +PlaylistWindowUpButton 146 226 179 242 +PlaylistWindowDownButton 146 243 179 259 +PlaylistWindowShuffleButton 189 175 233 185 +PlaylistWindowSortButton 188 144 234 155 +PlaylistWindowSortInverseButton 187 159 234 170 +PlaylistWindowMinimizeButton 184 50 193 59 +PlaylistWindowAddButton 188 74 234 84 +PlaylistWindowDelButton 189 87 234 99 +PlaylistWindowResetButton 192 102 232 113 +PlaylistWindowLoadPlaylistButton 191 129 231 141 +PlaylistWindowSavePlaylistButton 189 115 232 127 +PlaylistWindowSelectionUpButton 27 42 41 55 +PlaylistWindowSelectionDownButton 27 198 41 211 +PlaylistWindowAboutButton 194 29 217 59 +PlaylistWindowPlayButton 113 285 147 311 +PlaylistWindowPreviousButton 76 285 109 310 +PlaylistWindowNextButton 153 283 185 308 +PlaylistWindowPauseButton 187 266 217 290 +PlaylistWindowStopButton 198 239 234 262 +PlaylistWindowOpenButton 202 210 236 233 +PlaylistWindowColor 0 0 0 +PlaylistWindowCurrentTrackColor 0 0 136 +PlaylistWindowCurrentSelectionColor 153 207 181 diff --git a/noatun/modules/kjofol-skin/skins/kjofol/kjofol.rc b/noatun/modules/kjofol-skin/skins/kjofol/kjofol.rc new file mode 100644 index 00000000..daf99638 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/kjofol.rc @@ -0,0 +1,150 @@ +# If you want to know all secrets about K-Jofol's resources files,
+# Just check out the great tutorial at : http://www.angelfire.com/mo/nequiem/
+
+# Command : About <text>
+# Desc. : This text will appear when the users selects "About ..."
+# : You have 5 lines of text ...
+About
+About Made by Steve Gedikian for K-Jofol.
+
+# Command : BackgroundImage <Name of .BMP file>
+# Desc. : This is the back image.
+BackgroundImage sg.png
+
+# Command : BackgroundImageInactive <Name of .BMP file>
+# Desc. : This is the back image when the window is not selected.
+# : If you do not want this feature, just put the same name as
+# : BackgroundImage
+BackgroundImageInactive sg.png
+
+# Command : BackgroundImagePressed[1-3] <Name of .BMP file>
+# Desc. : This is the back images when all the buttons are pressed
+# : Used if you use the BMP option in the buttons options.
+# : You can have 3 backimages so you can do nifty things for the
+# : buttons =)
+BackgroundImagePressed1 sgpres1.png
+BackgroundImagePressed2 sgpres2.png
+BackgroundImagePressed3 sgpres3.png
+
+FontImage sg_text.png
+FontSize 5 9
+FontSpacing 0
+FontTransparent 0
+TimeFontImage sg_num.png
+TimeFontSize 8 9
+TimeFontSpacing 0
+TimeFontTransparent 0
+
+# Command : VolumeControlType <BAR/BMP>
+# Desc. : Put BAR if you want a bar style volume control, BMP if you want
+# : to customize it by a BMP animation file ...
+# VolumeControlType BAR
+# VolumeControlImage btn_vol.bmp
+# VolumeControlButton 235 166 275 174 vOLUME
+VolumeControlType BMP
+VolumeControlImage sgvol.png
+VolumeControlImagePosition sgvolpos.png
+VolumeControlImageXSize 86
+VolumeControlImageNb 83
+VolumeControlButton 211 133 296 209 vOLUME
+
+SeekImage sg_seek.png
+SeekRegion 91 22 300 127
+
+# Pitch control definition
+PitchText 243 93 260 102
+PitchControlImage sgpitch.png
+PitchControlImageXSize 58
+PitchControlImageNb 36
+PitchControlButton 222 68 280 125 pITCH
+PitchControlImagePosition sgpitchp.png
+
+PitchFontImage sgvolnum.png
+PitchFontSize 5 10
+PitchFontSpacing 0
+PitchFontTransparent 0
+
+# Command : [Option]Button <Position X> <Position Y> <End X> <End Y> <Tooltip Text> <DARKEN/BMP[?]>
+# The DARKEN option just dark the button when the user click on it.
+# The BMP[?] option use the BackgroundImagePressed[?] defined above.
+# Be sure to define a BackgroundImagePressed if you use the BMP option !!
+CloseButton 310 116 322 128 Close BMP1
+MinimizeButton 306 132 319 140 Minimize BMP1
+AboutButton 306 83 334 116 About BMP1
+OpenFileButton 25 8 61 26 Open BMP1
+StopButton 54 16 81 51 Stop BMP2
+PlayButton 28 27 57 56 Play BMP3
+#RewindButton 11 49 43 78 FastRewind BMP1
+#ForwardButton 45 49 73 77 FastForward BMP1
+PreviousSongButton 11 49 43 78 PreviousSong BMP1
+NextSongButton 45 49 73 77 NextSong BMP1
+PauseButton 9 18 31 51 Pause BMP2
+PreferencesButton 267 43 300 51 Options BMP1
+EqualizerButton 125 152 135 159 Equalizer BMP1
+EqualizerResetButton 175 104 200 112 Reset BMP1
+EqualizerOnButton 141 150 152 157 On BMP1
+EqualizerOffButton 156 150 167 157 Off BMP1
+RepeatButton 278 51 308 59 Repeat BMP1
+PlaylistButton 292 67 325 77 Playlist BMP1
+
+# Command : EqualizerWindow <X> <Y> <MaxX> <MaxY> <TipTool> <# of bands> <X-Space between bands>
+EqualizerWindow 111 115 180 148 Equalizer 12 6
+# Command : EqualizerBmp <X-Size> <Nb Equalizer> <BMP File>
+EqualizerBmp 4 17 sgeq.png
+
+# Inactive Zone
+# This put a button that does NOTHING :)
+# In fact, this option is very useful for designing the "Spectrum Analyzer" and
+# the "Oscilliscope" buttons because they are not rectangulars.
+# Inactive zones for the Spectrum Analyzer button
+InactiveZone 91 124 159 136
+InactiveZone 99 136 159 152
+InactiveZone 113 153 163 166
+# Inactive zones for the Oscilloscope butoon
+InactiveZone 159 123 198 137
+InactiveZone 159 138 190 149
+InactiveZone 163 151 177 160
+# Remember to put first your inactive zones BEFORE the buttons
+
+# Now that we have put our inactive zones, we could safely put the buttons
+SpectrumAnalyzerButton 68 123 167 185 SpectrumAnalyzer
+OscilloscopeButton 165 122 211 172 Oscilloscope
+
+# Dock Mode
+DockModeButton 243 27 268 36 DockMode BMP1
+DockModeRCFile kjofol.dck
+# DockModePosition : 0 - Upper Left 1 - Upper Right
+# 2 - Bottom Left 3 - Bottom Right
+DockModePosition 0
+DockModePositionXY -33 -38
+WinshadeModeRCFile kjofol.wsh
+WinshadeModePosition 1
+WinshadeModePositionXY -405 -9
+
+# Command : FilenameWindow
+# Desc. : This is the window where the file name appears
+FilenameWindow 96 80 200 89
+
+MP3KbpsWindow 93 90 110 97
+MP3KbpsString
+MP3KhzWindow 135 90 146 97
+Mp3KhzString
+
+MP3TimeWindow 124 50 165 59
+CurrentTrackWindow 191 90 204 97
+
+# Command : AnalyzerWindow <X> <Y> <MaxX> <MaxY> <TipTool>
+# Desc. : Spectrum Analyzer area. If you doesn't want one, just comment the
+# line ...
+AnalyzerWindow 106 61 184 78 Analyzer
+# Command : AnalyzerColor <Red> <Green> <Blue>
+# Desc. : Spectrum Analyzer color. Colors range are 0-255.
+AnalyzerColor 81 94 81
+
+VolumeFontImage sgvolnum.png
+VolumeFontSize 5 10
+VolumeFontSpacing 0
+VolumeFontTransparent 0
+VolumeText 247 168 265 176
+
+IncludeRCFile kjofol.pl
diff --git a/noatun/modules/kjofol-skin/skins/kjofol/kjofol.wsh b/noatun/modules/kjofol-skin/skins/kjofol/kjofol.wsh new file mode 100644 index 00000000..2910f636 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/kjofol.wsh @@ -0,0 +1,63 @@ +# Kjofol Default resource file - WINDOW SHADE MODE
+
+# Command : BackgroundImage <Name of .BMP file>
+# Desc. : This is the back image.
+BackgroundImage sgwshad.png
+
+# Command : BackgroundImageInactive <Name of .BMP file>
+# Desc. : This is the back image when the window is not selected.
+# : If you do not want this feature, just put the same name as
+# : BackgroundImage
+BackgroundImageInactive sgwshad.png
+
+# Command : BackgroundImagePressed[1-3] <Name of .BMP file>
+# Desc. : This is the back images when all the buttons are pressed
+# : Used if you use the BMP option in the buttons options.
+# : You can have 3 backimages so you can do nifty things for the
+# : buttons =)
+BackgroundImagePressed1 sgwshad2.png
+
+FontImage sg_text.png
+FontSize 5 9
+FontSpacing 0
+FontTransparent 0
+
+# Command : VolumeControlType <BAR/BMP>
+# Desc. : Put BAR if you want a bar style volume control, BMP if you want
+# : to customize it by a BMP animation file ...
+VolumeControlType BMP
+VolumeControlImage sgwshvol.png
+VolumeControlImagePosition sgwshvp.png
+VolumeControlImageXSize 30
+VolumeControlImageNb 28
+VolumeControlButton 192 18 221 22 vOLUME
+
+
+# Command : [Option]Button <Position X> <Position Y> <End X> <End Y> <Tooltip Text> <DARKEN/BMP[?]>
+# The DARKEN option just dark the button when the user click on it.
+# The BMP[?] option use the BackgroundImagePressed[?] defined above.
+# Be sure to define a BackgroundImagePressed if you use the BMP option !!
+AboutButton 10 13 26 29 About BMP1
+PlayButton 230 13 247 29 Play BMP1
+StopButton 249 13 265 30 Stop BMP1
+OpenFileButton 267 14 284 28 Open BMP1
+PreviousSongButton 285 14 302 30 PreviousSong BMP1
+NextSongButton 303 13 319 29 NextSong BMP1
+UnDockModeButton 322 14 336 28 UnDock BMP1
+
+# Command : FilenameWindow
+# Desc. : This is the window where the file name appears
+FilenameWindow 38 16 114 25
+
+SeekRegion 148 19 176 22
+SeekImage sgwshdsk.png
+
+# Command : AnalyzerWindow <X> <Y> <MaxX> <MaxY> <TipTool>
+# Desc. : Spectrum Analyzer area. If you doesn't want one, just comment the
+# line ...
+AnalyzerWindow 117 16 130 25 Analyzer
+# Command : AnalyzerColor <Red> <Green> <Blue>
+# Desc. : Spectrum Analyzer color. Colors range are 0-255.
+AnalyzerColor 81 94 81
+
+IncludeRCFile kjofol.pl
\ No newline at end of file diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sg.png b/noatun/modules/kjofol-skin/skins/kjofol/sg.png Binary files differnew file mode 100644 index 00000000..6195fbe2 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sg.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sg_num.png b/noatun/modules/kjofol-skin/skins/kjofol/sg_num.png Binary files differnew file mode 100644 index 00000000..ec1b6df8 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sg_num.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sg_seek.bmp b/noatun/modules/kjofol-skin/skins/kjofol/sg_seek.bmp Binary files differnew file mode 100644 index 00000000..209014fa --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sg_seek.bmp diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sg_seek.png b/noatun/modules/kjofol-skin/skins/kjofol/sg_seek.png Binary files differnew file mode 100644 index 00000000..92145805 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sg_seek.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sg_text.png b/noatun/modules/kjofol-skin/skins/kjofol/sg_text.png Binary files differnew file mode 100644 index 00000000..a867da1b --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sg_text.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgdock.png b/noatun/modules/kjofol-skin/skins/kjofol/sgdock.png Binary files differnew file mode 100644 index 00000000..49663245 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgdock.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgdock2.png b/noatun/modules/kjofol-skin/skins/kjofol/sgdock2.png Binary files differnew file mode 100644 index 00000000..c932db01 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgdock2.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgdocksk.png b/noatun/modules/kjofol-skin/skins/kjofol/sgdocksk.png Binary files differnew file mode 100644 index 00000000..9c6e5209 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgdocksk.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgdockvp.png b/noatun/modules/kjofol-skin/skins/kjofol/sgdockvp.png Binary files differnew file mode 100644 index 00000000..056f29e4 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgdockvp.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgeq.png b/noatun/modules/kjofol-skin/skins/kjofol/sgeq.png Binary files differnew file mode 100644 index 00000000..5d2ffeb6 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgeq.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgpitch.png b/noatun/modules/kjofol-skin/skins/kjofol/sgpitch.png Binary files differnew file mode 100644 index 00000000..e0fff521 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgpitch.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgpitchp.png b/noatun/modules/kjofol-skin/skins/kjofol/sgpitchp.png Binary files differnew file mode 100644 index 00000000..fa9b3121 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgpitchp.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgplist.png b/noatun/modules/kjofol-skin/skins/kjofol/sgplist.png Binary files differnew file mode 100644 index 00000000..de165370 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgplist.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgplist2.png b/noatun/modules/kjofol-skin/skins/kjofol/sgplist2.png Binary files differnew file mode 100644 index 00000000..2516a029 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgplist2.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgpres1.png b/noatun/modules/kjofol-skin/skins/kjofol/sgpres1.png Binary files differnew file mode 100644 index 00000000..555ffa90 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgpres1.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgpres2.png b/noatun/modules/kjofol-skin/skins/kjofol/sgpres2.png Binary files differnew file mode 100644 index 00000000..70bae784 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgpres2.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgpres3.png b/noatun/modules/kjofol-skin/skins/kjofol/sgpres3.png Binary files differnew file mode 100644 index 00000000..f440f739 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgpres3.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgvol.png b/noatun/modules/kjofol-skin/skins/kjofol/sgvol.png Binary files differnew file mode 100644 index 00000000..85d2a5dd --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgvol.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgvolnum.png b/noatun/modules/kjofol-skin/skins/kjofol/sgvolnum.png Binary files differnew file mode 100644 index 00000000..ecb5aa1c --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgvolnum.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgvolpos.png b/noatun/modules/kjofol-skin/skins/kjofol/sgvolpos.png Binary files differnew file mode 100644 index 00000000..b6e08a9f --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgvolpos.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgwshad.png b/noatun/modules/kjofol-skin/skins/kjofol/sgwshad.png Binary files differnew file mode 100644 index 00000000..ab603003 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgwshad.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgwshad2.png b/noatun/modules/kjofol-skin/skins/kjofol/sgwshad2.png Binary files differnew file mode 100644 index 00000000..0a456cea --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgwshad2.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgwshdsk.png b/noatun/modules/kjofol-skin/skins/kjofol/sgwshdsk.png Binary files differnew file mode 100644 index 00000000..b63f09e2 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgwshdsk.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgwshvol.png b/noatun/modules/kjofol-skin/skins/kjofol/sgwshvol.png Binary files differnew file mode 100644 index 00000000..394134fd --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgwshvol.png diff --git a/noatun/modules/kjofol-skin/skins/kjofol/sgwshvp.png b/noatun/modules/kjofol-skin/skins/kjofol/sgwshvp.png Binary files differnew file mode 100644 index 00000000..e072545a --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/kjofol/sgwshvp.png diff --git a/noatun/modules/kjofol-skin/skins/phong/Makefile.am b/noatun/modules/kjofol-skin/skins/phong/Makefile.am new file mode 100644 index 00000000..fb299a01 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/Makefile.am @@ -0,0 +1,8 @@ + +skin_DATA = p_eq.png p_numbers.png p_propos.png p_volpos.png phong.wsh \ + p_main.png p_playback.png p_text.png phong.dck phong_readme.txt \ + p_mainback.png p_playlist.png p_volbar.png phong.rc + +skindir = $(kde_datadir)/noatun/skins/kjofol/phong +EXTRA_DIST = $(skin_DATA) + diff --git a/noatun/modules/kjofol-skin/skins/phong/p_eq.png b/noatun/modules/kjofol-skin/skins/phong/p_eq.png Binary files differnew file mode 100644 index 00000000..7b5390a0 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/p_eq.png diff --git a/noatun/modules/kjofol-skin/skins/phong/p_main.png b/noatun/modules/kjofol-skin/skins/phong/p_main.png Binary files differnew file mode 100644 index 00000000..1e1b5110 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/p_main.png diff --git a/noatun/modules/kjofol-skin/skins/phong/p_mainback.png b/noatun/modules/kjofol-skin/skins/phong/p_mainback.png Binary files differnew file mode 100644 index 00000000..1f12b323 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/p_mainback.png diff --git a/noatun/modules/kjofol-skin/skins/phong/p_numbers.png b/noatun/modules/kjofol-skin/skins/phong/p_numbers.png Binary files differnew file mode 100644 index 00000000..51865529 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/p_numbers.png diff --git a/noatun/modules/kjofol-skin/skins/phong/p_playback.png b/noatun/modules/kjofol-skin/skins/phong/p_playback.png Binary files differnew file mode 100644 index 00000000..233b681d --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/p_playback.png diff --git a/noatun/modules/kjofol-skin/skins/phong/p_playlist.png b/noatun/modules/kjofol-skin/skins/phong/p_playlist.png Binary files differnew file mode 100644 index 00000000..b98b0a9b --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/p_playlist.png diff --git a/noatun/modules/kjofol-skin/skins/phong/p_propos.png b/noatun/modules/kjofol-skin/skins/phong/p_propos.png Binary files differnew file mode 100644 index 00000000..e5ed17e3 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/p_propos.png diff --git a/noatun/modules/kjofol-skin/skins/phong/p_text.png b/noatun/modules/kjofol-skin/skins/phong/p_text.png Binary files differnew file mode 100644 index 00000000..8254b6d2 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/p_text.png diff --git a/noatun/modules/kjofol-skin/skins/phong/p_volbar.png b/noatun/modules/kjofol-skin/skins/phong/p_volbar.png Binary files differnew file mode 100644 index 00000000..61c4ea0e --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/p_volbar.png diff --git a/noatun/modules/kjofol-skin/skins/phong/p_volpos.png b/noatun/modules/kjofol-skin/skins/phong/p_volpos.png Binary files differnew file mode 100644 index 00000000..0052097f --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/p_volpos.png diff --git a/noatun/modules/kjofol-skin/skins/phong/phong.dck b/noatun/modules/kjofol-skin/skins/phong/phong.dck new file mode 100644 index 00000000..f4fadf52 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/phong.dck @@ -0,0 +1,26 @@ +BackgroundImage ../kjofol/sgdock.png
+BackgroundImageInactive ../kjofol/sgdock.png
+BackgroundImagePressed1 ../kjofol/sgdock2.png
+FontImage ../kjofol/sg_text.png
+FontSize 5 9
+FontSpacing 0
+FontTransparent 0
+VolumeControlType BMP
+VolumeControlImage ../kjofol/sgwshvol.png
+VolumeControlImagePosition ../kjofol/sgdockvp.png
+VolumeControlImageXSize 30
+VolumeControlImageNb 28
+VolumeControlButton 100 17 129 23 vOLUME
+AboutButton 10 12 27 32 About BMP1
+OpenFileButton 14 73 32 91 Open BMP1
+StopButton 14 56 32 73 Stop BMP1
+PlayButton 14 37 32 55 Play BMP1
+PreviousSongButton 14 92 33 109 PreviousSong BMP1
+NextSongButton 14 110 33 127 NextSong BMP1
+UnDockModeButton 14 127 33 140 UnDock BMP1
+FilenameWindow 65 23 141 32
+SeekRegion 56 18 84 21
+SeekImage ../kjofol/sgdocksk.png
+AnalyzerWindow 41 23 62 32 Analyzer
+AnalyzerColor 81 94 81
+IncludeRCFile noirotic.pl
\ No newline at end of file diff --git a/noatun/modules/kjofol-skin/skins/phong/phong.rc b/noatun/modules/kjofol-skin/skins/phong/phong.rc new file mode 100644 index 00000000..ee90005c --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/phong.rc @@ -0,0 +1,104 @@ +About : : : phong : : :
+About by misery in motion 1999
+About misery_in_motion@hotmail.com
+About http://misery.mp3s.com.au
+
+BackgroundImage p_main.png
+BackgroundImageInactive p_main.png
+BackgroundImagePressed1 p_mainback.png
+
+
+FontImage p_text.png
+FontSize 5 9
+FontSpacing 1
+FontTransparent 0
+TimeFontImage p_numbers.png
+TimeFontSize 8 11
+TimeFontSpacing 1
+TimeFontTransparent 0
+
+VolumeControlType BMP
+VolumeControlImage p_volbar.png
+VolumeControlImagePosition p_volpos.png
+VolumeControlImageXSize 37
+VolumeControlImageNb 20
+VolumeControlButton 190 53 227 181 vOLUME
+
+SeekRegion 68 55 193 173
+SeekImage p_propos.png
+
+CloseButton 185 41 196 51 Close BMP1
+MinimizeButton 174 32 183 42 Minimize BMP1
+AboutButton 107 194 147 229 About BMP1
+OpenFileButton 237 95 257 130 Open BMP1
+StopButton 28 137 53 171 Stop BMP1
+PlayButton 24 96 45 130 Play BMP1
+#RewindButton 16 35 32 48 FastRewind BMP1
+#ForwardButton 33 11 49 25 FastForward BMP1
+PreviousSongButton 49 31 76 56 PreviousSong BMP1
+NextSongButton 49 172 77 202 NextSong BMP1
+PauseButton 32 60 53 91 Pause BMP1
+PreferencesButton 198 2 205 11 Options BMP1
+#EqualizerButton 76 103 82 107 Equalizer BMP1
+EqualizerResetButton 121 150 153 161 Reset BMP1
+EqualizerOnButton 98 130 107 142 On BMP1
+EqualizerOffButton 146 130 159 141 Off BMP1
+RepeatButton 221 66 253 92 Repeat BMP1
+PlaylistButton 227 131 252 162 Playlist BMP1
+
+FilenameWindow 86 119 168 129
+MP3KbpsWindow 150 108 170 116
+MP3KbpsString
+MP3KhzWindow 88 108 103 116
+Mp3KhzString
+MP3TimeWindow 105 106 153 122
+
+AnalyzerWindow 106 89 147 104 Analyzer
+AnalyzerColor 88 88 88
+EqualizerWindow 109 131 144 145 Equalizer 12 3
+EqualizerBmp 2 12 p_eq.png
+
+DockModeButton 158 23 171 36 DockMode BMP1
+DockModeRCFile phong.dck
+DockModePosition 0
+DockModePositionXY -33 -38
+WinshadeModeRCFile phong.wsh
+WinshadeModePosition 1
+WinshadeModePositionXY -405 -9
+
+PlaylistBmp p_playlist.png
+PlaylistBmpPressed p_playback.png
+PlaylistWindowText 45 88 177 198
+PlaylistWindowFontName Arial
+PlaylistWindowFontSize 12
+PlaylistWindowFontYSpacing 10
+PlaylistWindowNbSelectedTrack 58 211 68 221
+PlaylistWindowNbTotalTracks 83 211 93 221
+
+PlaylistWindowLinkButton 148 15 160 25
+PlaylistWindowCloseButton 174 31 184 41
+PlaylistWindowUpButton 98 67 122 81
+PlaylistWindowDownButton 98 207 122 220
+PlaylistWindowShuffleButton 157 232 174 248
+PlaylistWindowSortButton 115 232 132 248
+PlaylistWindowSortInverseButton 137 232 153 248
+PlaylistWindowMinimizeButton 161 21 172 32
+PlaylistWindowAddButton 48 232 64 248
+PlaylistWindowDelButton 70 232 86 248
+PlaylistWindowResetButton 91 232 107 248
+PlaylistWindowLoadPlaylistButton 41 71 74 78
+PlaylistWindowSavePlaylistButton 127 71 164 78
+PlaylistWindowSelectionUpButton 185 83 195 90
+PlaylistWindowSelectionDownButton 185 199 195 206
+PlaylistWindowAboutButton 140 210 193 220
+PlaylistWindowPlayButton 84 37 100 53
+PlaylistWindowPreviousButton 66 37 82 53
+PlaylistWindowNextButton 138 37 153 53
+PlaylistWindowPauseButton 101 37 118 53
+PlaylistWindowStopButton 120 37 136 53
+PlaylistWindowOpenButton 202 210 236 233
+PlaylistWindowColor 97 97 97
+PlaylistWindowCurrentTrackColor 60 60 60
+PlaylistWindowCurrentSelectionColor 150 150 150
+
+
diff --git a/noatun/modules/kjofol-skin/skins/phong/phong.wsh b/noatun/modules/kjofol-skin/skins/phong/phong.wsh new file mode 100644 index 00000000..0fc338e7 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/phong.wsh @@ -0,0 +1,26 @@ +BackgroundImage ../kjofol/sgwshad.png
+BackgroundImageInactive ../kjofol/sgwshad.png
+BackgroundImagePressed1 ../kjofol/sgwshad2.png
+FontImage ../kjofol/sg_text.png
+FontSize 5 9
+FontSpacing 0
+FontTransparent 0
+VolumeControlType BMP
+VolumeControlImage ../kjofol/sgwshvol.png
+VolumeControlImagePosition ../kjofol/sgwshvp.png
+VolumeControlImageXSize 30
+VolumeControlImageNb 28
+VolumeControlButton 192 18 221 22 vOLUME
+AboutButton 10 13 26 29 About BMP1
+PlayButton 230 13 247 29 Play BMP1
+StopButton 249 13 265 30 Stop BMP1
+OpenFileButton 267 14 284 28 Open BMP1
+PreviousSongButton 285 14 302 30 PreviousSong BMP1
+NextSongButton 303 13 319 29 NextSong BMP1
+UnDockModeButton 322 14 336 28 UnDock BMP1
+FilenameWindow 38 16 114 25
+SeekRegion 148 19 176 22
+SeekImage ../kjofol/sgwshdsk.png
+AnalyzerWindow 117 16 130 25 Analyzer
+AnalyzerColor 81 94 81
+IncludeRCFile noirotic.pl
\ No newline at end of file diff --git a/noatun/modules/kjofol-skin/skins/phong/phong_readme.txt b/noatun/modules/kjofol-skin/skins/phong/phong_readme.txt new file mode 100644 index 00000000..a6030dc9 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/phong/phong_readme.txt @@ -0,0 +1,62 @@ +This is the original phong skin by misery + +Included is his little readme + + +p h o n g 1 . 5 +------------------------------------------------- + +well, err... yes, its phong... created in +photoshop 4 & 5 during the last two months + +does not include an individual dock/shade mode, +but the wsh, rc and dk are set properly so you +can use the default. + +i've also included a rather decent phong wallpaper +(phong_wallpaper.jpg) +its in 1024 x 768, but you can use it in other +resolutions too. for 800x600 just be sure that +you do not stretch the file, for bigger resolutions +than 1024 x 768 make also sure to pick a 50% grey +as background color. + + +other skins by misery +-------------------------------------------------- + +winamp 1.x/2.x + +miseryamp 1.0 (-) +phreak 0.667 +xtended 1.0 +stainless 2.0 (*) +metropolis 2.01 (*) +pandemonium 1.0 +coldbringer 2.01 (*) +boost VIII 2.0 (*) +schubduese 2.0 (*) +asmith.net 2.0 (*) +crystal bastard 2.0 (*) +zorg 2.0 (*) + +k-jofol + +wintermute 1.0 +wintermute 2.0 +phong 1.5 + +* winamp 2.0x support +- shitty skin, removed + +distibute this skin freely, but don't delete the +readme. manipulators and modifiers of this skin +will be eaten by myself personally :-0. + +------------------------------------------------- +misery, 08.04.99 + +web: http://misery.mp3s.com.au +mail: misery_in_motion@hotmail.com + +(c) m i s e r y i n m o t i o n ( 9 9 ) diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/Makefile.am b/noatun/modules/kjofol-skin/skins/vibrocentric/Makefile.am new file mode 100644 index 00000000..37461998 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/Makefile.am @@ -0,0 +1,8 @@ + +skin_DATA = i_base2.png i_pl.png i_text.png vibrocentric.dck vibrocentric_readme.txt \ + i_eq.png i_pl2.png i_vol.png vibrocentric.rc i_base.png \ + i_font.png i_pro.png i_volpos.png vibrocentric.wsh + +skindir = $(kde_datadir)/noatun/skins/kjofol/vibrocentric +EXTRA_DIST = $(skin_DATA) + diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/i_base.png b/noatun/modules/kjofol-skin/skins/vibrocentric/i_base.png Binary files differnew file mode 100644 index 00000000..331dc169 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/i_base.png diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/i_base2.png b/noatun/modules/kjofol-skin/skins/vibrocentric/i_base2.png Binary files differnew file mode 100644 index 00000000..d32f5460 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/i_base2.png diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/i_eq.png b/noatun/modules/kjofol-skin/skins/vibrocentric/i_eq.png Binary files differnew file mode 100644 index 00000000..0174afa7 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/i_eq.png diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/i_font.png b/noatun/modules/kjofol-skin/skins/vibrocentric/i_font.png Binary files differnew file mode 100644 index 00000000..7b37dc22 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/i_font.png diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/i_pl.png b/noatun/modules/kjofol-skin/skins/vibrocentric/i_pl.png Binary files differnew file mode 100644 index 00000000..1e203bd9 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/i_pl.png diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/i_pl2.png b/noatun/modules/kjofol-skin/skins/vibrocentric/i_pl2.png Binary files differnew file mode 100644 index 00000000..748d55cf --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/i_pl2.png diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/i_pro.png b/noatun/modules/kjofol-skin/skins/vibrocentric/i_pro.png Binary files differnew file mode 100644 index 00000000..37e30816 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/i_pro.png diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/i_text.png b/noatun/modules/kjofol-skin/skins/vibrocentric/i_text.png Binary files differnew file mode 100644 index 00000000..28ddfd39 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/i_text.png diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/i_vol.png b/noatun/modules/kjofol-skin/skins/vibrocentric/i_vol.png Binary files differnew file mode 100644 index 00000000..53170e92 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/i_vol.png diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/i_volpos.png b/noatun/modules/kjofol-skin/skins/vibrocentric/i_volpos.png Binary files differnew file mode 100644 index 00000000..b40ec693 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/i_volpos.png diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/vibrocentric.dck b/noatun/modules/kjofol-skin/skins/vibrocentric/vibrocentric.dck new file mode 100644 index 00000000..f4fadf52 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/vibrocentric.dck @@ -0,0 +1,26 @@ +BackgroundImage ../kjofol/sgdock.png
+BackgroundImageInactive ../kjofol/sgdock.png
+BackgroundImagePressed1 ../kjofol/sgdock2.png
+FontImage ../kjofol/sg_text.png
+FontSize 5 9
+FontSpacing 0
+FontTransparent 0
+VolumeControlType BMP
+VolumeControlImage ../kjofol/sgwshvol.png
+VolumeControlImagePosition ../kjofol/sgdockvp.png
+VolumeControlImageXSize 30
+VolumeControlImageNb 28
+VolumeControlButton 100 17 129 23 vOLUME
+AboutButton 10 12 27 32 About BMP1
+OpenFileButton 14 73 32 91 Open BMP1
+StopButton 14 56 32 73 Stop BMP1
+PlayButton 14 37 32 55 Play BMP1
+PreviousSongButton 14 92 33 109 PreviousSong BMP1
+NextSongButton 14 110 33 127 NextSong BMP1
+UnDockModeButton 14 127 33 140 UnDock BMP1
+FilenameWindow 65 23 141 32
+SeekRegion 56 18 84 21
+SeekImage ../kjofol/sgdocksk.png
+AnalyzerWindow 41 23 62 32 Analyzer
+AnalyzerColor 81 94 81
+IncludeRCFile noirotic.pl
\ No newline at end of file diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/vibrocentric.rc b/noatun/modules/kjofol-skin/skins/vibrocentric/vibrocentric.rc new file mode 100644 index 00000000..cd2840d2 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/vibrocentric.rc @@ -0,0 +1,105 @@ +
+
+About idoru xt 1 : vibrocentric
+About part of the idoru litestep theme
+About by misery in motion 1999
+About misery_in_motion@mindless.com
+About http://misery.subnet.at
+
+BackgroundImage i_base.png
+BackgroundImageInactive i_base.png
+BackgroundImagePressed1 i_base2.png
+
+
+FontImage i_text.png
+FontSize 5 6
+FontSpacing 0
+FontTransparent 0
+TimeFontImage i_font.png
+TimeFontSize 9 8
+TimeFontSpacing 1
+TimeFontTransparent 0
+
+VolumeControlType BMP
+VolumeControlImage i_vol.png
+VolumeControlImagePosition i_volpos.png
+VolumeControlImageXSize 51
+VolumeControlImageNb 16
+VolumeControlButton 41 19 91 69 vOLUME
+
+SeekRegion 58 65 180 186
+SeekImage i_pro.png
+
+CloseButton 123 49 136 61 Close BMP1
+MinimizeButton 101 191 114 204 Minimize BMP1
+AboutButton 32 79 50 97 About BMP1
+OpenFileButton 144 51 161 69 Open BMP1
+StopButton 183 88 201 105 Stop BMP1
+PlayButton 159 181 186 206 Play BMP1
+#RewindButton 16 35 32 48 FastRewind BMP1
+#ForwardButton 33 11 49 25 FastForward BMP1
+PreviousSongButton 166 63 185 80 PreviousSong BMP1
+NextSongButton 185 149 204 166 NextSong BMP1
+PauseButton 190 117 208 135 Pause BMP1
+PreferencesButton 29 113 47 131 Options BMP1
+#EqualizerButton 76 103 82 107 Equalizer BMP1
+EqualizerResetButton 116 166 123 172 Reset BMP1
+EqualizerOnButton 105 166 114 172 On BMP1
+EqualizerOffButton 125 166 137 172 Off BMP1
+RepeatButton 35 144 54 160 Repeat BMP1
+PlaylistButton 75 185 93 201 Playlist BMP1
+
+FilenameWindow 72 131 169 137
+MP3KbpsWindow 74 117 90 122
+#MP3KbpsString
+MP3KhzWindow 79 123 90 129
+#Mp3KhzString
+MP3TimeWindow 111 118 166 128
+
+AnalyzerWindow 90 90 149 112 Analyzer
+AnalyzerColor 206 208 210
+EqualizerWindow 92 139 150 162 Equalizer 12 5
+EqualizerBmp 4 14 i_eq.png
+
+DockModeButton 53 168 71 186 DockMode BMP1
+DockModeRCFile vibrocentric.dck
+DockModePosition 0
+DockModePositionXY -33 -38
+WinshadeModeRCFile vibrocentric.wsh
+WinshadeModePosition 1
+WinshadeModePositionXY -405 -9
+
+PlaylistBmp i_pl.png
+PlaylistBmpPressed i_pl2.png
+PlaylistWindowText 60 108 176 181
+PlaylistWindowFontName Arial
+PlaylistWindowFontSize 12
+PlaylistWindowFontYSpacing 8
+PlaylistWindowNbSelectedTrack 106 186 120 195
+PlaylistWindowNbTotalTracks 106 198 120 207
+
+PlaylistWindowLinkButton 148 46 161 59
+PlaylistWindowCloseButton 189 82 202 95
+PlaylistWindowUpButton 148 86 158 93
+PlaylistWindowDownButton 148 96 158 103
+PlaylistWindowShuffleButton 136 186 146 196
+PlaylistWindowSortButton 124 186 134 196
+PlaylistWindowSortInverseButton 148 186 159 196
+PlaylistWindowMinimizeButton 124 42 136 55
+PlaylistWindowAddButton 124 198 134 208
+PlaylistWindowDelButton 136 198 146 208
+PlaylistWindowResetButton 148 198 158 208
+PlaylistWindowLoadPlaylistButton 88 210 116 219
+PlaylistWindowSavePlaylistButton 118 210 147 219
+PlaylistWindowSelectionUpButton 44 19 84 38
+PlaylistWindowSelectionDownButton 42 39 84 57
+PlaylistWindowAboutButton 169 59 183 73
+PlaylistWindowPlayButton 157 234 182 257
+PlaylistWindowPreviousButton 31 196 44 209
+PlaylistWindowNextButton 100 238 112 252
+PlaylistWindowPauseButton 75 234 88 247
+PlaylistWindowStopButton 50 221 63 234
+PlaylistWindowOpenButton 21 165 35 178
+PlaylistWindowColor 130 135 139
+PlaylistWindowCurrentTrackColor 164 168 171
+PlaylistWindowCurrentSelectionColor 81 89 94
diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/vibrocentric.wsh b/noatun/modules/kjofol-skin/skins/vibrocentric/vibrocentric.wsh new file mode 100644 index 00000000..0fc338e7 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/vibrocentric.wsh @@ -0,0 +1,26 @@ +BackgroundImage ../kjofol/sgwshad.png
+BackgroundImageInactive ../kjofol/sgwshad.png
+BackgroundImagePressed1 ../kjofol/sgwshad2.png
+FontImage ../kjofol/sg_text.png
+FontSize 5 9
+FontSpacing 0
+FontTransparent 0
+VolumeControlType BMP
+VolumeControlImage ../kjofol/sgwshvol.png
+VolumeControlImagePosition ../kjofol/sgwshvp.png
+VolumeControlImageXSize 30
+VolumeControlImageNb 28
+VolumeControlButton 192 18 221 22 vOLUME
+AboutButton 10 13 26 29 About BMP1
+PlayButton 230 13 247 29 Play BMP1
+StopButton 249 13 265 30 Stop BMP1
+OpenFileButton 267 14 284 28 Open BMP1
+PreviousSongButton 285 14 302 30 PreviousSong BMP1
+NextSongButton 303 13 319 29 NextSong BMP1
+UnDockModeButton 322 14 336 28 UnDock BMP1
+FilenameWindow 38 16 114 25
+SeekRegion 148 19 176 22
+SeekImage ../kjofol/sgwshdsk.png
+AnalyzerWindow 117 16 130 25 Analyzer
+AnalyzerColor 81 94 81
+IncludeRCFile noirotic.pl
\ No newline at end of file diff --git a/noatun/modules/kjofol-skin/skins/vibrocentric/vibrocentric_readme.txt b/noatun/modules/kjofol-skin/skins/vibrocentric/vibrocentric_readme.txt new file mode 100644 index 00000000..c2180678 --- /dev/null +++ b/noatun/modules/kjofol-skin/skins/vibrocentric/vibrocentric_readme.txt @@ -0,0 +1,19 @@ +This is the original vibrocentric skin by misery + +I couldn't find any readmes.... +but i hope this sentence from the phong skin +is also okay for this skin + +<< +distibute this skin freely, but don't delete the +readme. manipulators and modifiers of this skin +will be eaten by myself personally :-0. + +------------------------------------------------- +misery, 08.04.99 + +web: http://misery.mp3s.com.au +mail: misery_in_motion@hotmail.com + +(c) m i s e r y i n m o t i o n ( 9 9 ) +>>
\ No newline at end of file diff --git a/noatun/modules/making_plugins b/noatun/modules/making_plugins new file mode 100644 index 00000000..cb921cc2 --- /dev/null +++ b/noatun/modules/making_plugins @@ -0,0 +1,23 @@ +Welcome to the wonderful world of noatun plugin development! + +This is just a "notes" file. It won't show you _how_ to do it. + +You're free to use the net plugin as a base, I've licensed it under the +public domain, so you can relicense it however you wish (preferably not +GPL, though :) + +Remember that QObject must derive first. + +Do a "return this;" in the PlayList *playlist() const; function, if your class +is a playlist, otherwise, don't even override that function. + +If your playlist can't seem to get activated, you might have left out the +"const". + +For your create_plugin class, it should return Plugin*, not ClassName *: +Plugin *create_plugin() {...} // good +MyClass *create_plugin() {...{ // bad +(this is important) + +A lot should be available to you with the 'napp' variable. It returns +the global NoatunApp* type. diff --git a/noatun/modules/marquis/Makefile.am b/noatun/modules/marquis/Makefile.am new file mode 100644 index 00000000..a2fc3e3f --- /dev/null +++ b/noatun/modules/marquis/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES= -I$(top_srcdir)/noatun/library $(all_includes) +kde_module_LTLIBRARIES = noatun_marquis.la + +noatun_marquis_la_SOURCES = marquis.cpp plugin.cpp + +noatun_marquis_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_marquis_la_LIBADD = $(LIB_KFILE) $(top_builddir)/noatun/library/libnoatun.la \ + -lqtmcop -lkmedia2_idl -lsoundserver_idl + +noatun_marquis_la_METASOURCES = AUTO + +noinst_HEADERS = marquis.h + +noatun_modules_marquis_DATA = marquis.plugin +noatun_modules_marquisdir = $(kde_datadir)/noatun diff --git a/noatun/modules/marquis/marquis.cpp b/noatun/modules/marquis/marquis.cpp new file mode 100644 index 00000000..29ca7364 --- /dev/null +++ b/noatun/modules/marquis/marquis.cpp @@ -0,0 +1,186 @@ +// marquis.cpp +// +// Copyright (C) 2000 Neil Stevens <multivac@fcmail.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name(s) of the author(s) shall not be +// used in advertising or otherwise to promote the sale, use or other dealings +// in this Software without prior written authorization from the author(s). + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <kconfig.h> +#include <kdebug.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <noatun/pluginloader.h> +#include "marquis.h" +#include <noatun/player.h> +#include <noatun/engine.h> +#include <kaction.h> + +static int getPlayStatus( Player *player ) +{ + if ( player->isPlaying() ) + return 1; + if ( player->isPaused() ) + return 2; + return 0; +} + +static void setPlayStatus( Player *player, int status ) +{ + switch( status ) + { + default: + case 0: + player->stop(); + break; + case 1: + player->play(); + break; + case 2: + if ( !player->isPaused() ) + { + player->play(); + player->playpause(); + } + break; + } +} + + +Marquis::Marquis() + : KMainWindow(0, "Marquis") + , SessionManagement() +{ + hide(); + kdDebug(66666) << k_funcinfo << "number of members == " << memberList->count() << endl; + +// for testing: uncomment this and use +// dcop `dcop | grep noatun` Marquis activateAction dynamicRestore +// and dynamicSave accordingly. +// (void) new KAction("Restore", 0, this, SLOT( dynamicRestore() ), actionCollection(), "dynamicRestore" ); +// (void) new KAction("Save", 0, this, SLOT( dynamicSave() ), actionCollection(), "dynamicSave" ); + connect( napp, SIGNAL( saveYourself() ), SLOT( dynamicSave() )); +} + +Marquis::~Marquis() +{ +} + +void Marquis::restore(void) +{ + kdDebug(66666) << k_funcinfo << endl; + dynamicRestore(); +} + +// unload every window, and save the config as QStringList of those loaded +void Marquis::saveSessionConfig(KConfig *c) +{ + kdDebug(66666) << k_funcinfo << endl; + + Player *player = napp->player(); + c->writeEntry("Volume", player->volume()); + c->writeEntry("Loop Style", player->loopStyle()); + if ( napp->playlist() ) + c->writeEntry("Playlist Visible", napp->playlist()->listVisible()); + + if ( !player->current().isNull() ) + { + KURL songURL = player->current().url(); + songURL.setPass( QString::null ); // don't save passwords + c->writePathEntry("Current Song", songURL.url()); + } + else + c->writePathEntry("Current Song", QString::null); + + c->writeEntry("Current Position", player->getTime()); + c->writeEntry("PlayStatus", getPlayStatus( player )); + + // borrowed from Plugin config dialog + QStringList specList; + + QValueList<NoatunLibraryInfo> loaded = napp->libraryLoader()->loaded(); + for( QValueList<NoatunLibraryInfo>::Iterator i = loaded.begin(); i != loaded.end(); ++i) + { + if(!specList.contains((*i).specfile) + && napp->libraryLoader()->isLoaded((*i).specfile) + && (*i).specfile != "marquis.plugin") + { + specList += (*i).specfile; + napp->libraryLoader()->remove((*i).specfile, false); + } + } + + c->writeEntry("Loaded Plugins", specList); +} + +// get the list of loaded plugins from the config, and load them +void Marquis::readSessionConfig(KConfig *c) +{ + Player *player = napp->player(); + + c->setGroup(QString::null); + + // First set volume, then load modules, some module could start + // playback and that would be with 100% volume! + player->setVolume( c->readNumEntry("Volume", 100) ); + //player->setVolume( 0 ); + player->loop( c->readNumEntry("Loop Style", (int) Player::None) ); + + QStringList list = c->readListEntry("Loaded Plugins"); + /* + kdDebug(66666) << "Marquis::readSessionConfig()" << endl; + for(QStringList::ConstIterator i=list.begin(); i!=list.end(); ++i) + kdDebug(66666) << *i << endl; + kdDebug(66666) << "Marquis::readSessionConfig() there we go" << endl; + */ + napp->libraryLoader()->loadAll(list); + + if (!napp->playlist()) + { + KMessageBox::error(0,i18n("No playlist plugin was found. " \ + "Please make sure that Noatun was installed correctly.")); + napp->quit(); + return; + } + + if ( c->readBoolEntry( "Playlist Visible", false )) + napp->playlist()->showList(); + + napp->player()->engine()->setInitialized(); + // TODO: restore the playback state (also save it ;) +} + +void Marquis::dynamicSave() +{ + KConfig config( "marquisrc" ); + saveSessionConfig( &config ); +} + +void Marquis::dynamicRestore() +{ + KConfig config( "marquisrc" ); + readSessionConfig( &config ); +} + +#include "marquis.moc" diff --git a/noatun/modules/marquis/marquis.h b/noatun/modules/marquis/marquis.h new file mode 100644 index 00000000..5b166d57 --- /dev/null +++ b/noatun/modules/marquis/marquis.h @@ -0,0 +1,52 @@ +// marquis.h +// +// Copyright (C) 2000 Neil Stevens <multivac@fcmail.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name(s) of the author(s) shall not be +// used in advertising or otherwise to promote the sale, use or other dealings +// in this Software without prior written authorization from the author(s). + +#ifndef MARQUIS_H +#define MARQUIS_H + +#include <noatun/plugin.h> +#include <noatun/app.h> +#include <kmainwindow.h> + +class Player; + +class Marquis : public KMainWindow, public SessionManagement +{ +Q_OBJECT +NOATUNPLUGIND +public: + Marquis(); + virtual ~Marquis(); + + virtual void restore(void); +private: + void saveSessionConfig(KConfig *); + void readSessionConfig(KConfig *); +private slots: + void dynamicSave(); + void dynamicRestore(); +}; + +#endif diff --git a/noatun/modules/marquis/marquis.plugin b/noatun/modules/marquis/marquis.plugin new file mode 100644 index 00000000..7987d7b2 --- /dev/null +++ b/noatun/modules/marquis/marquis.plugin @@ -0,0 +1,83 @@ +Filename=noatun_marquis.la +Author=Neil Stevens +Site=http://www.derkarl.org/noatun +Email=neil@qualityassistant.com +Type=sm +License=X11-like +Name=Marquis +Name[af]=Markies +Name[ar]=ماركيس +Name[cs]=Markýz +Name[eo]=Markizo +Name[es]=Marqués +Name[hi]=मरक्यू +Name[lt]=Markizas +Name[lv]=Marķīzs +Name[mk]=Маркиз +Name[mt]=Markis +Name[ne]=मार्किज +Name[ru]=Маркиз +Name[zh_CN]=侯爵 +Name[zh_HK]=侯爵 +Name[zh_TW]=侯爵 +Comment=Plugin to interact with the Session Manager +Comment[af]=Inplak na interaksie het met die Sessie Bestuurder +Comment[az]=İclas idarəcisi ilə interaksiya əlavəsi +Comment[bg]=Взаимодействие с мениджъра на сесии +Comment[bs]=Dodatak za interakciju sa upraviteljem sesija +Comment[ca]=Connector per interactuar amb el gestor de sessió +Comment[cs]=Modul pro spolupráci se správcem relace +Comment[cy]=Atodyn i ryngweithredu efo'r Rheolwr Sesiynau +Comment[da]=Plugin til at fungere sammen med sessionshåndteringen +Comment[de]=Modul zur Kommunikation mit dem Sitzungsmanager +Comment[el]=Πρόσθετο για αλληλεπίδραση με το διαχειριστή συνεδρίας +Comment[eo]=Kromaĵo por interago kun la seancokonservilo +Comment[es]=Plugin para interactuar con el Administrador de sesiones +Comment[et]=Seansihalduriga suhtlemise plugin +Comment[eu]=Sesio kudeatzailearekin komunikatzeko plugin-a +Comment[fa]=وصله، برای کنش با مدیر نشست +Comment[fi]=Sovelma istunnonhallinnan ohjaamiseen +Comment[fr]=Un module pour interagir avec le gestionnaire de session +Comment[gl]=Extensión para interaccionar co Xestor de Sesións +Comment[he]=תוסף לתקשורת עם מנהל ההפעלה +Comment[hi]=सत्र प्रबंधक से इंटरेक्ट करने का प्लगइन +Comment[hr]=Dodatak za interakciju sa upravljačem seansa +Comment[hu]=Beépülő modul a munkafolyamat-kezelő beállításához +Comment[is]=Viðbót til að hafa samband við setustjórann +Comment[it]=Plugin per interagire con la gestione delle sessioni +Comment[ja]=セッションマネージャと情報をやり取りするためのプラグイン +Comment[kk]=Сеанс менеджерімен әрекеттесу плагин модулі +Comment[km]=កម្មវិធីជំនួយដើម្បីធ្វើអន្តរកម្មជាមួយកម្មវិធីគ្រប់គ្រងសម័យ +Comment[ko]=세션 관리자와 작동하는 플러그인 +Comment[lt]=Sąveikos su sesijos tvarkykle priemonė +Comment[lv]=Iespraudnis sadarbībai ar Sesiju Menedžeri +Comment[mk]=Приклучок за содејство со менаџерот на сесијата +Comment[ms]=Plug masuk untuk berinteraksi dengan Pengurus Sesi +Comment[mt]=Plugin biex jaqbad mal-Manager tas-Sessjoni +Comment[nb]=Programtillegg for å kommunisere med øktbehandleren +Comment[nds]=Moduul för't Tosamenwerken mit den Törnpleger +Comment[ne]=सत्र प्रबन्धकसँग अन्तरक्रिया गर्न प्लगइन +Comment[nl]=Plugin om te communiceren met de sessiebeheerder +Comment[nn]=Tilleggsmodul for å kommunisera med økthandsamaren +Comment[pl]=Wtyczka do współpracy z menedżerem sesji +Comment[pt]=Um 'plugin' para interagir com o gestor de sessões +Comment[pt_BR]=Plug-in para interagir com o gerenciador de sessão +Comment[ro]=Modul de interacţiune cu managerul de sesiune +Comment[ru]=Модуль взаимодействия с менеджером сеанса +Comment[se]=Lassemoduvla mainna gulahalla bargovuorrugieđahalliin +Comment[sk]=Modul pre spoluprácu so Správcom sedenia +Comment[sl]=Vstavek za delovanje z Upravljalnikom sej +Comment[sr]=Прикључак за интеракцију са менаџером сесије +Comment[sr@Latn]=Priključak za interakciju sa menadžerom sesije +Comment[sv]=Insticksprogram för att samverka med sessionshanteraren +Comment[ta]=அமர்வு மேலாளருடன் தொடர்பாடும் சொருகுப்பொருள் +Comment[tg]=Модул барои амали мутақобила бо Мудири Сеанс +Comment[th]=ปลั๊กอินสำหรับโต้ตอบกับตัวจัดการโปรเซส +Comment[tr]=Oturum yöneticisi ile etkileşim eklentisi +Comment[uk]=Втулок для взаємодії з Менеджером сеансів +Comment[ven]=U plaga u itela u tangana na mulanguli wa tshitenwa +Comment[xh]=Faka iplagi ukusebenza ngaphakathi noMphathi weNtlanganiso +Comment[zh_CN]=和会话管理器交互的插件 +Comment[zh_HK]=用於和工作階段管理員互動的插件 +Comment[zh_TW]=用來給工作階段管理程式使用的外掛程式 +Comment[zu]=Faka iplagi ukusebenza ngaphakathi noMphathi weNhlanganiso diff --git a/noatun/modules/marquis/plugin.cpp b/noatun/modules/marquis/plugin.cpp new file mode 100644 index 00000000..146b0979 --- /dev/null +++ b/noatun/modules/marquis/plugin.cpp @@ -0,0 +1,9 @@ +#include "marquis.h" + +extern "C" +{ + KDE_EXPORT Plugin *create_plugin() + { + return new Marquis(); + } +} diff --git a/noatun/modules/metatag/HANDLED_ITEMS b/noatun/modules/metatag/HANDLED_ITEMS new file mode 100644 index 00000000..3c369a9e --- /dev/null +++ b/noatun/modules/metatag/HANDLED_ITEMS @@ -0,0 +1,21 @@ + Here are the mappings between the items returned from KFileMetaInfo, and the +properties Metatag sets based on those items. These properties may or may be +set depending on the file's type and contents, and will not be set for +non-local files or streams. + +|=============================================================================| +| KFileMetaInfo Key | Noatun Property | Description | +|===================|=================|=======================================| +| Artist | author | Author | +| Album | album | Album from which the file originates | +| Bitrate | bitrate | Average bitrate (kilobits per second) | +| Channels | channels | Number of audio channels | +| Comment | comment | Free-form text comment | +| Date | date | Date the file was released | +| Genre | genre | Genre of file | +| Location | location | Location of recording | +| Organization | organization | | +| Sample Rate | samplerate | File's audio sample rate (hertz) | +| Title | title | Title of file | +| Tracknumber | track | Track number of file on it's album | +|=============================================================================| diff --git a/noatun/modules/metatag/Makefile.am b/noatun/modules/metatag/Makefile.am new file mode 100644 index 00000000..330e9f34 --- /dev/null +++ b/noatun/modules/metatag/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES= -I$(top_srcdir)/noatun/library -I$(kde_includes)/arts $(all_includes) +kde_module_LTLIBRARIES = noatun_metatag.la + +noatun_metatag_la_SOURCES = metatag.cpp edit.cpp + +noatun_metatag_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_metatag_la_LIBADD = $(LIB_KIO) $(top_builddir)/noatun/library/libnoatun.la \ + $(top_builddir)/noatun/library/noatuntags/libnoatuntags.la + +noatun_metatag_la_METASOURCES = AUTO + +noinst_HEADERS = metatag.h edit.h + +noatun_modules_metatag_DATA = metatag.plugin +noatun_modules_metatagdir = $(kde_datadir)/noatun diff --git a/noatun/modules/metatag/edit.cpp b/noatun/modules/metatag/edit.cpp new file mode 100644 index 00000000..d5ccb0c4 --- /dev/null +++ b/noatun/modules/metatag/edit.cpp @@ -0,0 +1,312 @@ +#include <klocale.h> +#include <qlayout.h> +#include <klineedit.h> +#include <qlabel.h> +#include <qptrlist.h> + +#include <kmimetype.h> +#include <kicontheme.h> +#include <qtooltip.h> +#include <kstringvalidator.h> +#include <qspinbox.h> +#include <qhbox.h> +#include <qfile.h> +#include <qfileinfo.h> +#include <qcombobox.h> +#include <qpushbutton.h> +#include <kdialogbase.h> +#include <kdebug.h> +#include <kseparator.h> +#include <kfilemetainfo.h> +#include <qvalidator.h> + +#include "metatag.h" +#include "edit.h" + +Editor::Editor() +: KDialogBase((QWidget*)0L, 0, false, i18n("Tag Editor"), Ok | Cancel) +{ + mMainWidget = makeMainWidget(); +// mMainWidget->setMinimumWidth(325); + + mGrid = new QGridLayout(mMainWidget, 1, 1, 0, spacingHint(), "Editor::mGrid"); + + mGrid->setColStretch(1, 1); + mGrid->setColStretch(2, 1); + + QHBox *heading = new QHBox(mMainWidget, "Editor::heading"); + heading->setSpacing(4); + mFileIcon = new QLabel(heading); + mFileIcon->setAlignment(AlignVCenter | AlignLeft); + mFile = new QLabel(heading); + mFile->setAlignment(AlignVCenter | AlignLeft); + heading->setStretchFactor(mFile, 2); + mGrid->addMultiCellWidget(heading, 0, 0, 0, 2); + + KSeparator *sep = new KSeparator(KSeparator::HLine, mMainWidget); + mGrid->addMultiCellWidget(sep, 1, 1, 0, 2); + + mControls.setAutoDelete(true); + mNextRow = 2; + + connect(this, SIGNAL(closeClicked()), SLOT(delayedDestruct())); + connect(this, SIGNAL(okClicked()), SLOT(save())); + + enableButtonSeparator(true); + setFixedHeight(sizeHint().height()); +} + +void Editor::open(const PlaylistItem & file) +{ + KFileMetaInfo file_meta_info(file.file(), file.mimetype()); + KFileMetaInfoItem info_item; + + item = file; + mDirty = false; + + mFile->setText("<nobr><b>" + file.url().fileName(false) + "</b></nobr>"); + QToolTip::add(mFile, file.url().prettyURL()); + mFileIcon-> + setPixmap(KMimeType::pixmapForURL(file.url(), 0, KIcon::Small)); + + if (file.url().isLocalFile()) { + QFileInfo file_info(file.file()); + mFileWritable = file_info.isWritable(); + } + else { + // KFileMetaInfo doesn't work on remote files + mFileWritable = false; + } + + if ( !file_meta_info.isValid() ) // go ahead people, nothing to see here + return; + + mControls.append(createControl(file_meta_info, i18n("&Title"), "Title", QVariant::String, false, mMainWidget)); + mControls.append(createControl(file_meta_info, i18n("&Artist"), "Artist", QVariant::String, false, mMainWidget)); + mControls.append(createControl(file_meta_info, i18n("A&lbum"), "Album", QVariant::String, false, mMainWidget)); + mControls.append(createControl(file_meta_info, i18n("&Date"), "Date", QVariant::String, false, mMainWidget)); + mControls.append(createControl(file_meta_info, i18n("T&rack"), "Tracknumber", QVariant::UInt, false, mMainWidget)); + mControls.append(createControl(file_meta_info, i18n("&Genre"), "Genre", QVariant::String, false, mMainWidget)); + mControls.append(createControl(file_meta_info, i18n("Co&mment"), "Comment", QVariant::String, false, mMainWidget)); +} + +void Editor::save() +{ + // Only write to disk if something actually changed + if (!mDirty) + { + delayedDestruct(); + return; + } + + KFileMetaInfo meta_info(item.file(), item.mimetype()); + if ( !meta_info.isValid() ) + { + delayedDestruct(); + return; + } + + for (MetaWidget *meta_widget = mControls.first(); meta_widget; meta_widget = mControls.next() ) + saveControl(meta_info, *meta_widget); + + meta_info.applyChanges(); + + emit(saved(item)); + delayedDestruct(); +} + +void Editor::saveControl(KFileMetaInfo& meta_info, const MetaWidget &meta_widget) { + QVariant value; + const KFileMimeTypeInfo *info = KFileMetaInfoProvider::self()->mimeTypeInfo( meta_info.mimeType() ); + + if (!meta_widget.widget->isEnabled()) + return; + + if (meta_widget.widget->inherits("QSpinBox")) + value = static_cast<QSpinBox *>(meta_widget.widget)->value(); + else if (meta_widget.widget->inherits("QComboBox")) + value = static_cast<QComboBox *>(meta_widget.widget)->currentText(); + else if (meta_widget.widget->inherits("QLineEdit")) + value = static_cast<QLineEdit *>(meta_widget.widget)->text(); + + QString group = keyGroup(meta_info, meta_widget.key); + + if (group.isNull()) { + kdWarning() << "Cannot find group for " << meta_widget.key << endl; + return; + } + + if (info->groupInfo(group)->itemInfo(meta_widget.key)) { + if (info->groupInfo(group)->attributes() & KFileMimeTypeInfo::Addable) { + kdDebug(66666) << "Adding group " << group << endl; + if (!meta_info.addGroup(group)) + kdWarning() << "Adding group \"" << group << "\" failed!" << endl; + } + + if (info->groupInfo(group)->itemInfo(meta_widget.key)->attributes() & KFileMimeTypeInfo::Addable) { + kdDebug(66666) << "Adding key " << meta_widget.key << endl; + if (!meta_info.group(group).addItem(meta_widget.key).isValid()) + kdWarning() << "Adding key \"" << meta_widget.key << "\" failed!" << endl; + } + } + + if (value.cast(meta_info.item(meta_widget.key).type())) { + if (!meta_info.item(meta_widget.key).setValue(value)) + kdWarning() << "setValue() failed on " << group << "/" << meta_widget.key << endl; + } + else + kdWarning() << "Cannot save " << meta_widget.key << " as required type." << endl; +} + +MetaWidget* Editor::createControl(KFileMetaInfo& meta_info, const QString &label, const QString &key, QVariant::Type default_type, bool optional, QWidget *parent) { + QLabel *tmp_label = 0L; + KFileMetaInfoItem info_item = meta_info.item(key); + QVariant::Type type; + MetaWidget *meta_widget = 0L; + QValidator *validator = 0L; + QString groupName = keyGroup(meta_info, key); + bool known_key = ((!groupName.isNull()) && meta_info.group(groupName).contains(key)); + bool addable = keyAddable(meta_info, key); + const KFileMimeTypeInfo *info = KFileMetaInfoProvider::self()->mimeTypeInfo( meta_info.mimeType() ); + + // This key isn't a real thing, and we can't even create it + if ((!info_item.isEditable()) && (!addable) && optional) + return 0; + + if (!groupName.isNull()) { + type = info->groupInfo(groupName)->itemInfo(key)->type(); + } + else { + type = default_type; + } + + // Get the correct validator + if ( info && !groupName.isNull() ) + validator = info->createValidator( groupName, key, parent ); + + // meta_widget is used for book-keeping internally + meta_widget = new MetaWidget; + meta_widget->key = key; + + if ((type == QVariant::Int) || (type == QVariant::UInt)) { + // We're an int, make a spin box + QSpinBox *box = new QSpinBox(parent); + + // Well, normally metatag doesn't care that much about suffixes + // and prefixes, but this is just too easy. + box->setPrefix(info_item.prefix()); + box->setSuffix(info_item.suffix()); + // Kinda a hack... display " " instead of "0" (think track numbers) + box->setSpecialValueText(" "); + + // Do we have a validator? + if (validator) { + box->setValidator(validator); + + // Is it an integer validator + if (validator->inherits("QIntValidator")) { + QIntValidator *int_validator = static_cast<QIntValidator *>(validator); + + // FIXME: Why the -hell- doesn't QSpinBox::setValidator() do this?? + box->setMinValue(int_validator->bottom()); + box->setMaxValue(int_validator->top()); + } + } + + box->setValue(info_item.value().toInt()); + + connect(box, SIGNAL(valueChanged(int)), this, SLOT(modified())); + meta_widget->widget = box; + } + else { + // We're not an int, make a KLineEdit/QComboBox, depending on our validator + bool combo_box = false; + + if (validator) + combo_box = validator->isA("KStringListValidator"); + + if (combo_box) { + QComboBox *combo = new QComboBox(parent); + + combo->clear(); + combo->insertStringList(static_cast< + KStringListValidator * + >(validator)->stringList()); + + combo->setCurrentText(info_item.value().toString()); + connect(combo, SIGNAL(activated(int)), this, SLOT(modified())); + + meta_widget->widget = combo; + } + else { + KLineEdit *edit; + + edit = new KLineEdit(parent); + edit->setText(info_item.value().toString()); + edit->setValidator(validator); + connect(edit, SIGNAL(textChanged(const QString &)), this, SLOT(modified())); + + meta_widget->widget = edit; + } + } + + if (known_key) + meta_widget->widget->setEnabled(info_item.isEditable() && mFileWritable); + else + meta_widget->widget->setEnabled(addable && mFileWritable); + + mGrid->addMultiCellWidget(meta_widget->widget, mNextRow, mNextRow, 1, 2); + + // Add our label. This is the easy part + tmp_label = new QLabel(meta_widget->widget, label + ":", parent); + mGrid->addWidget(tmp_label, mNextRow, 0); + + + mNextRow++; + + return meta_widget; +} + +QString Editor::keyGroup(const KFileMetaInfo& i, QString key) { + const KFileMimeTypeInfo *info = KFileMetaInfoProvider::self()->mimeTypeInfo( i.mimeType() ); + QStringList groups = info->supportedGroups(); + + for (QStringList::Iterator it = groups.begin();it != groups.end();++it) { + if (info->groupInfo(*it)->itemInfo(key)) { + return *it; + } + } + + return QString::null; +} + +bool Editor::keyAddable(const KFileMetaInfo &i, QString key) { + const KFileMimeTypeInfo *info = KFileMetaInfoProvider::self()->mimeTypeInfo( i.mimeType() ); + QStringList groups = info->supportedGroups(); + + kdDebug(66666) << "Testing if " << key << " is addable" << endl; + for (QStringList::Iterator it = groups.begin();it != groups.end();++it) { + if (info->groupInfo(*it)->supportsVariableKeys()) { + kdDebug(66666) << "Group " << *it << " supports variable keys" << endl; + return true; + } + + if (info->groupInfo(*it)->itemInfo(key)) { + if (info->groupInfo(*it)->attributes() & KFileMimeTypeInfo::Addable) { + kdDebug(66666) << "Group " << *it << " is addable" << endl; + return true; + } + + if (info->groupInfo(*it)->itemInfo(key)->attributes() & KFileMimeTypeInfo::Addable) + return true; + } + } + + return false; +} + +void Editor::modified() { + mDirty = true; +} + +#include "edit.moc" diff --git a/noatun/modules/metatag/edit.h b/noatun/modules/metatag/edit.h new file mode 100644 index 00000000..d6b0ab9c --- /dev/null +++ b/noatun/modules/metatag/edit.h @@ -0,0 +1,55 @@ +#ifndef EDITOR_H +#define EDITOR_H + +#include <kdialogbase.h> +#include <noatun/playlist.h> +#include <qptrlist.h> +#include <qvariant.h> + +class KFileMetaInfo; +class KFileMetaInfoItem; +class QGridLayout; + +struct MetaWidget { + QWidget *widget; + QString key; +}; + +class Editor:public KDialogBase { + Q_OBJECT + public: + Editor(); + + signals: + void saved(PlaylistItem &); + + public slots: + void open(const PlaylistItem & i); + + protected slots: + void save(); + void modified(); + + protected: + bool keyAddable(const KFileMetaInfo &, QString); + QString keyGroup(const KFileMetaInfo &, QString); + + void saveControl(KFileMetaInfo& meta_info, const MetaWidget&); + MetaWidget *createControl(KFileMetaInfo& meta_info, const QString &label, const QString &key, QVariant::Type default_type, bool optional, QWidget *parent); + + QPtrList<MetaWidget> mControls; + + QWidget *mMainWidget; + QGridLayout *mGrid; + int mNextRow; + + bool mFileWritable; + bool mDirty; + + QLabel *mFile; + QLabel *mFileIcon; + const char *filename; + PlaylistItem item; +}; + +#endif diff --git a/noatun/modules/metatag/metatag.cpp b/noatun/modules/metatag/metatag.cpp new file mode 100644 index 00000000..d0531092 --- /dev/null +++ b/noatun/modules/metatag/metatag.cpp @@ -0,0 +1,124 @@ + +#include "metatag.h" +#include "edit.h" + +#include <string.h> + +#include <noatun/app.h> +#include <noatun/stdaction.h> + +#include <qfile.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qregexp.h> + +#include <klocale.h> +#include <kaction.h> +#include <kglobal.h> +#include <klineedit.h> +#include <kconfig.h> +#include <kaction.h> +#include <kiconloader.h> +#include <kpopupmenu.h> +#include <kfilemetainfo.h> + +extern "C" +{ + KDE_EXPORT Plugin *create_plugin() + { + return new MetaTagLoader; + } +} + +MetaTagLoader::MetaTagLoader():Plugin() +{ + mAction = new KAction(i18n("&Tag Editor..."), "edit", 0, this, SLOT(editTag()), this, "edittag"); + napp->pluginActionMenu()->insert(mAction); +} + +MetaTagLoader::~MetaTagLoader() +{ + napp->pluginActionMenu()->remove(mAction); +} + +void MetaTagLoader::editTag() +{ + PlaylistItem i = napp->player()->current(); + + if(!i) + return; + + Editor *e = new Editor(); + e->open(i); + e->show(); + + connect(e, SIGNAL(saved(PlaylistItem &)), + SLOT(update(PlaylistItem &))); +} + +bool MetaTagLoader::update(PlaylistItem & item) +{ + KFileMetaInfo file_info(item.file(),item.mimetype()); + + // Ack, no file info :( + if ( !file_info.isValid() ) + return false; + + if(item.length() == -1) // no value set, set almost correct id3tag time + { + KFileMetaInfoItem length_item = file_info.item("Length"); + if(length_item.isValid()) + { + int numVal = length_item.value().toInt(); + if (numVal != 0) + item.setLength(numVal * 1000); + } + } + + // Yes, this is icky. It maps KFileMetaInfo property names to Noatun's + setProperty(file_info, item, "Title", "title"); + setProperty(file_info, item, "Artist", "author"); + setProperty(file_info, item, "Album", "album"); + setProperty(file_info, item, "Genre", "genre"); + setProperty(file_info, item, "Tracknumber", "track"); + setProperty(file_info, item, "Date", "date"); + setProperty(file_info, item, "Comment", "comment"); + setProperty(file_info, item, "Location", "location"); + setProperty(file_info, item, "Organization", "organization"); + + // Now map the audio properties over + setProperty(file_info, item, "Bitrate", "bitrate"); + setProperty(file_info, item, "Sample Rate", "samplerate"); + setProperty(file_info, item, "Channels", "channels"); + + return true; +} + +bool MetaTagLoader::setProperty(KFileMetaInfo &info, PlaylistItem &item, const QString &key, const QString &property) +{ + KFileMetaInfoItem info_item = info.item(key); + + if ( info_item.isValid() ) + { + if (!info_item.value().toString().stripWhiteSpace().isEmpty()) + { + // The item is valid and non-empty, add it + item.setProperty(property, info_item.value().toString()); + } + else + { + // If the info_item is valid, but empty. + // This means we know for a fact that this + // property has no value. Blow it away. + item.clearProperty(property); + } + return true; + } + + // The item isn't valid, so we don't know that it has + // no value. Don't remove the property, so we can work + // well with other tag readers, like Lucky + return false; +} + +#include "metatag.moc" diff --git a/noatun/modules/metatag/metatag.h b/noatun/modules/metatag/metatag.h new file mode 100644 index 00000000..ff5c277f --- /dev/null +++ b/noatun/modules/metatag/metatag.h @@ -0,0 +1,30 @@ +#ifndef NID3_H +#define NID3_H + +#include <noatun/player.h> +#include <noatun/plugin.h> +#include <noatun/pref.h> +#include <noatuntags/tags.h> + +#include <qobject.h> + +class KFileMetaInfo; +class KAction; + +class MetaTagLoader:public QObject, public Tags, public Plugin { + Q_OBJECT + public: + MetaTagLoader(); + ~MetaTagLoader(); + + public slots: + bool update(PlaylistItem & item); + void editTag(); + + private: + bool setProperty(KFileMetaInfo &info, PlaylistItem &item, const QString &key, const QString &property); + int menuID; + KAction *mAction; +}; + +#endif diff --git a/noatun/modules/metatag/metatag.plugin b/noatun/modules/metatag/metatag.plugin new file mode 100644 index 00000000..0e359350 --- /dev/null +++ b/noatun/modules/metatag/metatag.plugin @@ -0,0 +1,125 @@ +Filename=noatun_metatag.la +Author=Ryan Cumming +Site=http://noatun.derkarl.org/ +Email=bodnar42@phalynx.dhs.org +Type=other +License=Artistic +Name=Tag Reader +Name[af]=Etiket Leser +Name[ar]=قارئ معلومات الرقعة +Name[br]=Lenner al liketennoù +Name[bs]=Čitač tagova +Name[ca]=Lector de marques +Name[cs]=Čtení tagů +Name[cy]=Darllenydd Tag +Name[da]=Mærkelæser +Name[de]=Meta-Info-Leser +Name[el]=Αναγνώστης ετικετών +Name[eo]=Indiklegilo +Name[es]=Lector de etiquetas +Name[et]=Tagide lugeja +Name[eu]=Etiketa irakurlea +Name[fa]=خوانندۀ برچسب +Name[fi]=Tagilukija +Name[fr]=Lecteur de balise +Name[ga]=Léitheoir Clibe +Name[gl]=Lector de Etiquetas +Name[he]=קורא תגיות +Name[hi]=टैग रीडर +Name[hr]=Čitač tag-ova +Name[hu]=Azonosító-olvasó +Name[is]=Tagabirtir +Name[it]=Lettore tag +Name[ja]=タグリーダー +Name[kk]=Тегтерді оқу +Name[km]=កម្មវិធីអានស្លាក +Name[ko]=태그 리더 +Name[lt]=Etikečių skaityklė +Name[lv]=Tagu Lasītājs +Name[mk]=Читач на ознаки +Name[nb]=Taggleser +Name[nds]=Beteker-Kieker +Name[ne]=ट्याग रिडर +Name[nl]=Tag-lezer +Name[nn]=Tagglesar +Name[pa]=ਟੈਗ ਰੀਡਰ +Name[pl]=Czytnik znaczników +Name[pt]=Leitor de Marcas +Name[pt_BR]=Leitor de símbolos +Name[ro]=Cititor taguri +Name[ru]=Чтение тегов +Name[se]=Sárggislohkki +Name[sk]=Čítačka tagov +Name[sl]=Bralnik oznak +Name[sr]=Читач ознака +Name[sr@Latn]=Čitač oznaka +Name[sv]=Taggläsare +Name[ta]=ஒட்டு வாசிப்பாளர் +Name[tg]=Хонандаи Борчасп +Name[th]=โปรแกรมอ่านแท็ก +Name[tr]=İm Okuyucu +Name[uk]=Читач етикеток +Name[ven]=Muvhali wa Tag +Name[zh_CN]=标签读取程序 +Name[zh_HK]=標籤閱讀器 +Name[zh_TW]=標籤閱讀器 +Name[zu]=Umfundi we Tag +Comment=Support for reading and writing to tags in media files +Comment[af]=Ondersteun vir lees en om te skryf na etiket in media lêers +Comment[ar]=دعم قراءة و كتابة الرقع في ملفات الوسائط +Comment[bg]=Поддръжка на четене и запис на информацията в мултимедийни файловете +Comment[bs]=Podrška za čitanje i pisanje tagova u multimedijalnim datotekama +Comment[ca]=Suport per llegir i escriure etiquetes a fitxers multimèdia +Comment[cs]=Podpora čtení a zápisu tagů v multimediálních souborech +Comment[cy]=Cynhaliaeth ar gyfer darllen ac ysgrifennu i dagiau mewn ffeiliau cyfryngau +Comment[da]=Understøttelse af læsning fra og skrivning til mærker i mediefiler +Comment[de]=Lesen und Schreiben von Meta-Infos (Tags) in Media-Dateien +Comment[el]=Υποστήριξη για ανάγνωση και εγγραφή στις ετικέτες των αρχείων μέσων +Comment[eo]=Subteno por legado kaj skribado de indikoj en sonordosieroj +Comment[es]=Soporte para lectura y escritura de etiquetas en archivos multimedia +Comment[et]=Multimeediafailide tagide lugemise ja kirjutamise toetus +Comment[eu]=Euskarri fitxategien etiketak irakurtzeko eta idazteko euskarria +Comment[fa]=پشتیبانی برای خواندن و نوشتن در برچسبهای پروندههای رسانه +Comment[fi]=Tuki mediatiedostojen tagien lukuun ja kirjoittamiseen +Comment[fr]=Lecture et écriture des balises ID3 dans les fichiers multimedia +Comment[gl]=Soporte para a lectura e escritura de etiquetas en ficheiros multimedia +Comment[he]=תמיכה בקריאה וכתיבה של תגיות בקבצי מדיה +Comment[hi]=मीडिया फ़ाइलों के टैग पढ़ने तथा लिखने का समर्थन +Comment[hr]=Podrška za čitanje i pisanje dodatnih informacija (tag-ova) u medijske datoteke +Comment[hu]=Támogatás médiafájlok azonosítóinak olvasásához és írásához +Comment[is]=Stuðningur til að lesa og skrifa ID3 tög í MP3 skrám +Comment[it]=Supporto per la lettura e la scrittura dei tag nei file multimediali +Comment[ja]=メディアファイル内のタグの読み書きをサポート +Comment[kk]=Медиа файлдарының тегтерін оқу-жазу құралы +Comment[km]=ការគាំទ្រដើម្បីអាន និងសរសេរស្លាកក្នុងឯកសារមេឌៀ +Comment[ko]=미디어 파일의 태그 읽고 쓰기 지원 +Comment[lt]=Palaiko etikečių skaitymą ir rašymą media bylose +Comment[lv]=Tagu lasīšanas un rakstīšanas uzturēšana mēdiju failos +Comment[mk]=Поддршка за читање и запишување на ознаките од мултимедијални датотеки +Comment[ms]=Sokongan untuk baca dan tulis tag pada fail media +Comment[nb]=Støtte for lesing og skriving til merkelapper i mediafiler +Comment[nds]=Ünnerstütten för't Lesen un Schrieven vun Betekers binnen Mediendateien +Comment[ne]=मिडिया फाइलको ट्यागमा लेख्न र पढ्नका लागि समर्थन +Comment[nl]=Ondersteuning voor het lezen van en schrijven naar tags in mediabestanden +Comment[nn]=Støtte for lesing og skriving av taggar i mediefiler +Comment[pl]=Obsługa odczytu i zapisu znaczników w plikach medialnych +Comment[pt]=O suporte de leitura/escrita de marcas em ficheiros multimédia +Comment[pt_BR]=Suporte a leitura e gravação de símbolos em arquivos de mídia +Comment[ro]=Suport pentru citirea şi scrierea tagurilor în fişiere multimedia +Comment[ru]=Поддержка чтения и записи тегов в медиафайлах +Comment[se]=Doarju sárggislohkama ja -čállima mediefiillain +Comment[sk]=Podpora pre čítanie a zápis do tagov v multimediálnych súboroch +Comment[sl]=Podpora branju in pisanju oznak za večpredstavnostne datoteke +Comment[sr]=Подршка за читање и писање ID3 ознака у MP3 фајловима +Comment[sr@Latn]=Podrška za čitanje i pisanje ID3 oznaka u MP3 fajlovima +Comment[sv]=Stöd för att läsa och skriva taggar i mediafiler +Comment[ta]=ஊடகக் கோப்புகளில் குறியொட்டுக்களை எழுத வாசிக்கப்பதற்கு ஆதரவு +Comment[tg]=Пуштибонии хондан ва навиштани борчаспҳо дар файлҳои расона +Comment[th]=รองรับการอ่านและเขียนแท็กในแฟ้มสื่อ +Comment[tr]=Medya dosyalarındaki imleri okumak ve yazmak için destek +Comment[uk]=Підтримка для читання та запису етикеток в медіафайлах +Comment[ven]=Thikhedzo ya u vhala na u nwala u itela u tag kha dzifaela dza media +Comment[zh_CN]=支持对媒体文件的标签进行读取和写入 +Comment[zh_HK]=讀取或寫入媒體檔案標籤的支援 +Comment[zh_TW]=支援讀取或寫入媒體檔案的標籤 +Comment[zu]=Inxaso yokufunda nokubhala amathegi kumafayela ezezindaba diff --git a/noatun/modules/monoscope/Makefile.am b/noatun/modules/monoscope/Makefile.am new file mode 100644 index 00000000..55c58a05 --- /dev/null +++ b/noatun/modules/monoscope/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES= -I$(top_srcdir)/noatun/library $(all_includes) +kde_module_LTLIBRARIES = noatun_monoscope.la + +noatun_monoscope_la_SOURCES = monoscope.cpp +#prefs.cpp + +noatun_monoscope_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_monoscope_la_LIBADD = $(LIB_KFILE) $(top_builddir)/noatun/library/libnoatun.la -lm + +noatun_monoscope_la_METASOURCES = AUTO + +noinst_HEADERS = monoscope.h +#prefs.h + +noatun_modules_monoscope_DATA = monoscope.plugin +noatun_modules_monoscopedir = $(kde_datadir)/noatun diff --git a/noatun/modules/monoscope/monoscope.cpp b/noatun/modules/monoscope/monoscope.cpp new file mode 100644 index 00000000..5ab63ecc --- /dev/null +++ b/noatun/modules/monoscope/monoscope.cpp @@ -0,0 +1,112 @@ +#include "monoscope.h" +#include <noatun/player.h> +#include <noatun/app.h> +#include <math.h> +#include <qpainter.h> +#include <kactionclasses.h> +#include <noatun/stdaction.h> +#include <klocale.h> + +extern "C" +{ + KDE_EXPORT Plugin *create_plugin() + { + return new Monoscope(); + } +} + +Monoscope::Monoscope() : QWidget(0,0,WRepaintNoErase), MonoScope(30), Plugin() +{ + NOATUNPLUGINC(Monoscope); + + mAction=0L; + mLowColor=qRgb(0,0,0); + mHighColor=qRgb(238,238,238); + resize(320, 240); + MonoScope::start(); + setCaption(i18n("Monoscope")); + show(); + resizeEvent(0); + repaint(0,0, QWidget::width(), height(), false); + resizeEvent(0); + setBackgroundColor(mLowColor); +} + +Monoscope::~Monoscope() +{ + if(mAction) + napp->pluginActionMenu()->remove(mAction); +} + +void Monoscope::init() +{ + mAction = new KToggleAction(i18n("Toggle Monoscope"), 0, 0, + this, SLOT(toggle()), this, "togglemonoscope"); + mAction->setChecked(!isHidden()); + napp->pluginActionMenu()->insert(mAction); +} + +void Monoscope::toggle(void) +{ + if(isHidden()) + show(); + else + hide(); +} + +void Monoscope::closeEvent(QCloseEvent *) +{ + hide(); +} + +void Monoscope::resizeEvent(QResizeEvent *) +{ + setSamples(width()); +} + +void Monoscope::scopeEvent(float *d, int size) +{ + // save cpu + if(isHidden()) return; + + const bool line=false; + + int viewWidth =width(); + int viewHeight=height(); + + float *end=d+size; + int x=0; + int heightHalf=viewHeight/4; + int y=viewHeight/2; + // reduce flicker + QPixmap buffer(viewWidth, viewHeight, -1, QPixmap::BestOptim); + buffer.fill(mLowColor); + QPainter p(&buffer); + p.setPen(mHighColor); + repaint(rect()); + + if (line) + p.moveTo(0, y); + + while (d<=end) + { + float &n=*d; + + n *= heightHalf; + int amp=(int)n; + + if (line) // line + p.lineTo(x, y+amp); + else // fill + p.drawLine(x, y, x, y+amp); + d++; + x++; + + } + if (line) + p.drawLine(0, y, size, y); + bitBlt(this, 0, 0, &buffer, 0, 0, viewWidth, viewHeight, Qt::CopyROP); +} + +#include "monoscope.moc" + diff --git a/noatun/modules/monoscope/monoscope.h b/noatun/modules/monoscope/monoscope.h new file mode 100644 index 00000000..37031a4b --- /dev/null +++ b/noatun/modules/monoscope/monoscope.h @@ -0,0 +1,34 @@ +#ifndef MONOSCOPE_H +#define MONOSCOPE_H + +#include <noatun/plugin.h> + +class KToggleAction; + +class Monoscope : public QWidget, public MonoScope, public Plugin +{ +Q_OBJECT +NOATUNPLUGIND + +public: + Monoscope(); + virtual ~Monoscope(); + + void init(); + +public slots: + void toggle(void); + +protected: + virtual void closeEvent(QCloseEvent *); + virtual void scopeEvent(float *data, int bands); + + virtual void resizeEvent(QResizeEvent *); + +private: + QRgb mHighColor, mLowColor; + KToggleAction *mAction; +}; + +#endif + diff --git a/noatun/modules/monoscope/monoscope.plugin b/noatun/modules/monoscope/monoscope.plugin new file mode 100644 index 00000000..b4533c0f --- /dev/null +++ b/noatun/modules/monoscope/monoscope.plugin @@ -0,0 +1,99 @@ +Filename=noatun_monoscope.la +Author=Charles Samuels +Site=http://noatun.kde.org/ +Email=charles@kde.org +Type=visualization +License=BSD +Name=Monoscope +Name[af]=Monoskoop +Name[ar]=مونوسكوب +Name[az]=Monoskop +Name[ca]=Monoscopi +Name[cs]=Monoskop +Name[da]=Monoskop +Name[eo]=Monoskopo +Name[es]=Monoscopio +Name[fa]=تک دامنهای +Name[gl]=Monoscopio +Name[hi]=मोनोस्कोप +Name[hu]=Monoszkóp +Name[it]=Monoscopio +Name[ja]=モノスコープ +Name[kk]=Осцилограф +Name[lv]=Monoskops +Name[mt]=Monoskopju +Name[ne]=मोमोस्कोप +Name[pa]=ਮੋਨੋਸਕੋਪ +Name[pl]=Monoskop +Name[ro]=Monoscop +Name[ru]=Моноскоп +Name[sk]=Monoskop +Name[sv]=Monoskop +Name[ta]=ஓரெல்லைப் பரப்பு +Name[tr]=Monoskop +Name[uk]=Моноскоп +Name[xh]=Isithuba esinye +Name[zh_CN]=单像管 +Name[zh_HK]=單像管 +Name[zh_TW]=單像管 +Name[zu]=Isithuba esinye +Comment=A neat waveform scope analyzer +Comment[af]='n netjiese golfvorm skoop analiseerder +Comment[az]=Dalğa şəklində analiz proqramı +Comment[bg]=Изящен осцилограф +Comment[bs]=Zgodan analizator talasne forme +Comment[ca]=Un analitzador pulcre de camps d'ones +Comment[cs]=Vkusný analyzátor vln +Comment[cy]=Dadansoddydd Twt ar gyfer Cwmpas Tonffurf +Comment[da]=En smart bølgeformsscope-analysator +Comment[de]=Ein Programm zur "Waveform/Scope"-Analyse +Comment[el]=Ένας θαυμάσιος αναλυτής φάσματος κυματομορφών +Comment[en_GB]=A neat waveform scope analyser +Comment[eo]=Uzinda ondo-analizilo +Comment[es]=Un analizador elegante de formas de onda +Comment[et]=Nunnu signaalikuju analüsaator +Comment[eu]=uhinforma esparruko analizatzailea +Comment[fa]=تحلیلکنندۀ دامنۀ موجی شکل ساده +Comment[fi]=Nätti oskilloskooppi +Comment[fr]=Un bel analyseur de spectre +Comment[gl]=Analizador suave da forma da onda +Comment[he]=מאבחן תחומי גל +Comment[hi]=एक साफ वेवफार्म स्कोप एनॉलाइजर +Comment[hr]=Simpatičan analizator zvuka +Comment[hu]=Egy kellemes hullámforma-analizáló program +Comment[is]=Flottur bylgjugreinir +Comment[it]=Un puro analizzatore di forme d'onda +Comment[ja]=かっこいい波形スコープアナライザ +Comment[kk]=Керемет бір осциллограф секілді аспап +Comment[km]=កម្មវិធីវិភាគវិសាលភាពទម្រង់ wave ហ្មត់ចត់ +Comment[ko]=파형을 관찰하고 분석하는 도구 +Comment[lt]=Gražus bangų formos vaizdo analizatorius +Comment[lv]=Vienkāršs viļņaformas analizators +Comment[mk]=Симпатичен осцилоскоп за анализа на бранови форми +Comment[ms]=Penganalisis skop bentuk gelombang +Comment[nb]=Et nett lite program for analysering av «waveform scope» +Comment[nds]=En smuck Bülgenformrebeetkieker +Comment[ne]=क्षेत्र विश्लेषकबाट निट तरङ +Comment[nl]=Een goed waveform scope-analyseprogramma +Comment[nn]=Analysering av «waveform scope» +Comment[pl]=Analizator fal dźwiękowych +Comment[pt]=Um analisador de formas de onda bonito +Comment[pt_BR]=Um analisador de formas de onda +Comment[ro]=Un analizor de formă de undă foarte bun +Comment[ru]=Симпатичный осциллограф +Comment[sk]=Milý analyzátor vĺn +Comment[sl]=Lep analizator zvoka +Comment[sr]=Уредан анализатор облика таласа +Comment[sr@Latn]=Uredan analizator oblika talasa +Comment[sv]=Elegant oscilloskop +Comment[ta]=ஒரு சீரான அலைவடிவ ஆய்வாளர் +Comment[tg]=Таҳлилгари намудсози шакли мавҷии шабакавӣ +Comment[th]=โปรแกรมวิเคราะห์รูปแบบคลื่นที่ปราณีต +Comment[tr]=Dalga formu analiz programı +Comment[uk]=Гарний аналізатор хвильових меж +Comment[ven]=Mugudi neat waveform scope +Comment[xh]=Umhlahleli wesithuba wendlela ecocekileyo yamaza +Comment[zh_CN]=一个小巧的波形范围分析器 +Comment[zh_HK]=小巧的波形範圍分析器 +Comment[zh_TW]=一個小巧的波形分析器 +Comment[zu]=Umhaziyi wesithuba wendlela ecehlanzekile diff --git a/noatun/modules/net/Makefile.am b/noatun/modules/net/Makefile.am new file mode 100644 index 00000000..9398a602 --- /dev/null +++ b/noatun/modules/net/Makefile.am @@ -0,0 +1,14 @@ +INCLUDES= -I$(top_srcdir)/noatun/library $(all_includes) +kde_module_LTLIBRARIES = noatun_net.la + +noatun_net_la_SOURCES = net.cpp + +noatun_net_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_net_la_LIBADD = $(LIB_KFILE) $(top_builddir)/noatun/library/libnoatun.la + +noatun_net_la_METASOURCES = AUTO + +noinst_HEADERS = net.h + +noatun_modules_net_DATA = net.plugin +noatun_modules_netdir = $(kde_datadir)/noatun diff --git a/noatun/modules/net/net.cpp b/noatun/modules/net/net.cpp new file mode 100644 index 00000000..5e3ba707 --- /dev/null +++ b/noatun/modules/net/net.cpp @@ -0,0 +1,57 @@ +#include "net.h" +#include <noatun/player.h> +#include <noatun/app.h> + +extern "C" +{ + KDE_EXPORT Plugin *create_plugin() + { + return new Net(); + } +} + + +Net::Net() : QServerSocket(7539, 10), Plugin() +{ + mFDs.setAutoDelete(true); + connect(napp->player(), SIGNAL(newSong()), SLOT(newSong())); +} + +Net::~Net() +{ +} + + +void Net::newConnection(int fd) +{ + QSocket *s=new QSocket; + s->setSocket(fd); + mFDs.append(s); +} + +void Net::newSong() +{ + if (!napp->player()->current()) + return; + + for (QSocket *i=mFDs.first(); i!=0; i=mFDs.next()) + { + QCString line; + line=napp->player()->current().title().latin1(); + line+='\n'; + ::write(i->socket(), (const void*)line.data(), line.length()); + } +} + +void Net::closed() +{ + for (QSocket *i=mFDs.first(); i!=0; i=mFDs.next()) + { + if (sender()==i) + mFDs.removeRef(i); + } +} + + + +#include "net.moc" diff --git a/noatun/modules/net/net.h b/noatun/modules/net/net.h new file mode 100644 index 00000000..7d0fcb11 --- /dev/null +++ b/noatun/modules/net/net.h @@ -0,0 +1,31 @@ +#ifndef DCOPIFACE_H +#define DCOPIFACE_H + +#include <noatun/player.h> +#include <noatun/plugin.h> +#include <qserversocket.h> +#include <qsocket.h> +#include <unistd.h> + +class Net : public QServerSocket, public Plugin +{ +Q_OBJECT + +public: + Net(); + ~Net(); + +public slots: + void newSong(); + +private slots: + void closed(); +protected: + virtual void newConnection(int socket); + +private: + QPtrList<QSocket> mFDs; +}; + +#endif + diff --git a/noatun/modules/net/net.plugin b/noatun/modules/net/net.plugin new file mode 100644 index 00000000..21683b5d --- /dev/null +++ b/noatun/modules/net/net.plugin @@ -0,0 +1,136 @@ +Filename=noatun_net.la +Author=Charles Samuels +Site=http://noatun.derkarl.org/ +Email=charles@kde.org +Type=other +License=Public Domain +Name=Network Interface +Name[af]=Netwerk Koppelvlak +Name[ar]=واجهة الشبكة +Name[az]=Şəbəkə Ara üzü +Name[bn]=নেটওয়ার্ক ইন্টারফেস +Name[br]=Etrefas Rouedad +Name[bs]=Mrežni interfejs +Name[ca]=Interfície de xarxa +Name[cs]=Síťové rozhraní +Name[cy]=Rhyngwyneb Rhwydwaith +Name[da]=Netværksgrænseflade +Name[de]=Netzwerk-Schnittstelle +Name[el]=Διασύνδεση δικτύου +Name[eo]=Retinterfaco +Name[es]=Interfaz de red +Name[et]=Võrguliides +Name[eu]=Sareko interfazea +Name[fa]=واسط شبکه +Name[fi]=Verkkokäyttöliittymä +Name[fr]=Interface réseau +Name[ga]=Comhéadan Gréasáin +Name[gl]=Interface de rede +Name[he]=ממשק רשת +Name[hi]= नेटवर्क इंटरफेस +Name[hr]=Mrežno sučelje +Name[hu]=Hálózati felület +Name[id]=Interface jaringan +Name[is]=Nettengi +Name[it]=Interfaccia di rete +Name[ja]=ネットワークインターフェース +Name[kk]=Желілік интерфейсі +Name[km]=ចំណុចប្រទាក់បណ្ដាញ +Name[ko]=네트워크 인터페이스 +Name[lt]=Tinklo sąsaja +Name[lv]=Tīkla Starpseja +Name[mk]=Мрежен интерфејс +Name[mt]=Interfaċċja tan-Network +Name[nb]=Nettverksgrensesnitt +Name[nds]=Nettwark-Koppelsteed +Name[ne]=सञ्जाल इन्टरफेस +Name[nl]=Netwerk-interface +Name[nn]=Nettverksgrensesnitt +Name[pa]=ਨੈਟਵਰਕ ਇੰਟਰਫੇਸ +Name[pl]=Interfejs sieciowy +Name[pt]=Interface de Rede +Name[pt_BR]=Interface de Rede +Name[ro]=Interfată reţea +Name[ru]=Сетевой интерфейс +Name[se]=Fierpmádatlakta +Name[sk]=Sieťové rozhranie +Name[sl]=Omrežni vmesnik +Name[sr]=Мрежни интерфејс +Name[sr@Latn]=Mrežni interfejs +Name[sv]=Nätverksgränssnitt +Name[ta]=வலைப்பின்னல் இடைமுகம் +Name[tg]=Интерфейси Шабакавӣ +Name[th]=แผงวงจรเครือข่าย +Name[tr]=Ağ Arayüzü +Name[uk]=Інтерфейс мережі +Name[uz]=Tarmoq interfeysi +Name[uz@cyrillic]=Тармоқ интерфейси +Name[ven]=Vhukwamani +Name[xh]=Ujongano nomsebenzi womnatha +Name[zh_CN]=网络接口 +Name[zh_HK]=網絡介面 +Name[zh_TW]=網路介面 +Name[zu]=Uxhumano Olubhekene loxhumaniso +Comment=A very simple read-only network interface on port 7539 +Comment[af]='n baie eenvoudige lees-alleen netwerk koppelvlak op poort 7539 +Comment[ar]=واجهة بسيطة للشبكة قابلة للقراءة فقط على المنفذ رقم 7539 +Comment[az]=Çox bəsit bir sırf-oxuma şəbəkə axtar üzü (7539.port) +Comment[bg]=Елементарен мрежов интерфейс само за четене на порт 7539 +Comment[bs]=Veoma jednostavan read-only mrežni interfejs na portu 7539 +Comment[ca]=Una interfície de xarxa molt simple de només lectura al port 7539 +Comment[cs]=Velmi jednoduché síťové rozhraní určené jen pro čtení na portu 7539 +Comment[cy]=Rhyngwyneb rhwydwaith syml darllen-yn-unig ar borth 7539 +Comment[da]=En meget simpel skrivebeskyttet netværksgrænseflade på port 7539 +Comment[de]=Einfache Netzwerkschnittstelle an Port 7539 +Comment[el]=Μια πολύ απλή διασύνδεση δικτύου, μόνο-ανάγνωσης, στη θύρα 7539 +Comment[eo]=Simpla nurlega retinterfaco por a pordo 7539 +Comment[es]=Una interfaz de red simple de sólo lectura en el puerto 7539 +Comment[et]=Väga lihtne pordil 7539 töötav võrguliides (ainult lugemiseks) +Comment[eu]=Irakurketarako bakarrik den 7539 atakako sare interfaze oso sinplea +Comment[fa]=یک واسط شبکه فقط خواندنی بسیار ساده روی درگاه ۷۵۳۹ +Comment[fi]=Yksinkertainen vain-luku-verkkokäyttöliittymä portissa 7539 +Comment[fr]=Une interface réseau très simple sur le port 7539 +Comment[ga]=Comhéadan an-simplí líonra ar phort 7539 +Comment[gl]=Unha interface de rede moi sinxela de só lectura no porto 7539 +Comment[he]=ממשק רשת פשוט מאוד לקריאה בלבד ביציאה 7539 +Comment[hi]=एक अत्यंत साधारण सिर्फ पढ़ने लायक नेटवर्क इंटरफेल पोर्ट 7539 पर +Comment[hr]=Vrlo jednostavno mrežno sučelje za čitanje s porta 7539 +Comment[hu]=Egy nagyon egyszerű, csak olvasható hálózati felület a 7539-es porton +Comment[is]=Mjög einfalt ritvarið nettengi á porti 7539 +Comment[it]=Un'interfaccia su porta 7539 di sola lettura molto semplice +Comment[ja]=ポート 7539 を使う非常にシンプルな読み込み専用のネットワークインターフェース +Comment[kk]=Өте қарапайым, 7539 портынан тек оқу үшін желілік интерфейсі +Comment[km]=ចំណុចប្រទាក់បណ្ដាញសាមញ្ញបំផុត ហើយបានតែអាន ដែលរត់លើច្រក 7539 +Comment[ko]=7539 포트에서 작동하는 간단한 읽기 전용 네트워크 인터페이스 +Comment[lt]=Labai paprasta tik skaitoma tinklo sąsaja 7539'am portui +Comment[lv]=Ļoti vienkārša tikai-lasīšana tīkla starpseja uz porta 7539 +Comment[mk]=Многу едноставен мрежен интерфејс, само за читање, на порта 7539 +Comment[ms]=Antaramuka jaringan baca sahaja yang ringkas untuk liang 7539 +Comment[mt]=Interfaċċja sempiliċi ħafna tinqara biss fuq port 7539 +Comment[nb]=Et veldig enkelt skrivebeskyttet nettverksgrensesnitt på port 7539 +Comment[nds]=En bannig eenfach "Bloots-lesen"-Nettwarkkoppelsteed op Port 7539 +Comment[ne]=पोर्ट ७५३९ मा धेरै साधारण पढ्ने-मात्र सञ्जाल +Comment[nl]=Een heel eenvoudige alleen-lezen netwerkinterface op poort 7539 +Comment[nn]=Eit svært enkelt nettverksgrensesnitt for lesing på port 7539 +Comment[pl]=Bardzo prosty interfejs sieciowy tylko do odczytu, na porcie 7539 +Comment[pt]=Uma interface de rede muito simples no porto 7539 +Comment[pt_BR]=Uma interface muito simples de rede, porta 7539, somente leitura +Comment[ro]=O interfaţă de reţea foarte simplă pe portul 7539 +Comment[ru]=Простейший сетевой интерфейс на 7539 порту только для чтения +Comment[se]=Hui oktageardanis fierpmádatlakta mii lohká dieđuid 7539 verráhis +Comment[sk]=Veľmi jednoduché sieťové rozhranie iba pre čítanie na porte 7539 +Comment[sl]=Zelo preprost bralni omrežni vmesnik na vratih 7539 +Comment[sr]=Једноставан, само-за-читање мрежни интерфејс на порту 7539 +Comment[sr@Latn]=Jednostavan, samo-za-čitanje mrežni interfejs na portu 7539 +Comment[sv]=Väldigt enkelt skrivskyddat nätverksgränssnitt på port 7539 +Comment[ta]=துறை 7539இலுள்ள மிக எளிய, வாசிக்க-மட்டும் வலைத்தள இடைமுடம் +Comment[tg]=Интерфейси хеле содда ва танҳо барои хониши шабакавӣ дар даргоҳи 7539 +Comment[th]=แผงวงจรเครือข่ายบนพอร์ต 7539 +Comment[tr]=Çok basit bir salt-oku ağ arayüzü (7539.port) +Comment[uk]=Дуже простий інтерфейс мережі для зчитування на порту 7539 +Comment[ven]=Vhukwamani ho leluwaho hau vhala kha port ya 7539 +Comment[xh]=Ufundo olulula kakhulu-lujongano lomsebenzi womnatha kuphela kwizibuko 7539 +Comment[zh_CN]=简单的位于 7539 端口的只读网络接口 +Comment[zh_HK]=工作於 7539 連接埠的唯讀簡易型網絡介面 +Comment[zh_TW]=一個位於 7539 Port 上唯讀存取的簡易型網路介面 +Comment[zu]=Okulula ukufunda kuphela kuxhumaniso olubhekeneyo kwi port 7539 diff --git a/noatun/modules/noatunui/Makefile.am b/noatun/modules/noatunui/Makefile.am new file mode 100644 index 00000000..443afd6c --- /dev/null +++ b/noatun/modules/noatunui/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES= -I$(top_srcdir)/noatun/library $(all_includes) +kde_module_LTLIBRARIES = noatun_ui.la + +noatun_ui_la_SOURCES = noatunui.cpp userinterface.cpp + +noatun_ui_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_ui_la_LIBADD = $(LIB_KFILE) $(top_builddir)/noatun/library/libnoatun.la \ + $(top_builddir)/noatun/library/libnoatuncontrols.la \ + -lqtmcop -lkmedia2_idl -lsoundserver_idl + +noatun_ui_la_METASOURCES = AUTO + +noinst_HEADERS = userinterface.h + +noatun_modules_ui_DATA = noatunui.plugin +noatun_modules_uidir = $(kde_datadir)/noatun diff --git a/noatun/modules/noatunui/noatunui.cpp b/noatun/modules/noatunui/noatunui.cpp new file mode 100644 index 00000000..adb9534b --- /dev/null +++ b/noatun/modules/noatunui/noatunui.cpp @@ -0,0 +1,9 @@ +#include "userinterface.h" + +extern "C" +{ + KDE_EXPORT Plugin *create_plugin() + { + return new MilkChocolate; + } +} diff --git a/noatun/modules/noatunui/noatunui.plugin b/noatun/modules/noatunui/noatunui.plugin new file mode 100644 index 00000000..e8413cd8 --- /dev/null +++ b/noatun/modules/noatunui/noatunui.plugin @@ -0,0 +1,120 @@ +Filename=noatun_ui.la +Author=Charles Samuels +Site=http://noatun.kde.org/plugins/milkchocolate/ +Email=charles@kde.org +Type=userinterface +License=Artistic +Name=Milk-Chocolate +Name[ar]=حليب-شوكولا +Name[az]=Şokaladlı Süd +Name[br]=Chokolad leizh +Name[bs]=Mlijeko-čokolada +Name[ca]=Xocolata amb llet +Name[cs]=Noatun mléčná čokoláda +Name[cy]=Sioclat Llefrith +Name[da]=Mælkechokolade +Name[de]=Milchschokolade +Name[eo]=Laktoĉokolado +Name[es]=Chocolate con leche +Name[fi]=Maitosuklaa +Name[fr]=Chocolat au lait +Name[gl]=Leite-Chocolate +Name[hi]=मिल्क-चॉकलेट +Name[hr]=Mliječna čokolada +Name[hu]=Tejcsoki +Name[is]=Mjólkursúkkulaði +Name[it]=Caffellatte +Name[km]=ទឹកដោះគោ-សូកូឡា +Name[ko]=밀크 초콜릿 +Name[lt]=Pieniškas šokoladas +Name[lv]=Piena-Šokolāde +Name[mk]=Млечна чоколада +Name[mt]=Ċikkulata +Name[nb]=Melkesjokolade +Name[nds]=Melkschokolaad +Name[ne]=दुध-मिठाइ +Name[nl]=Melkchocolade +Name[nn]=Mjølkesjokolade +Name[pl]=Czekolada mleczna +Name[pt]=Leite com Chocolate +Name[pt_BR]=Noatun Leite-Chocolate +Name[ro]=Ciocolată cu lapte +Name[ru]=Молочный шоколад +Name[se]=Mielkešokolada +Name[sk]=Mliečna čokoláda +Name[sl]=Mlečna čokolada +Name[sv]=Mjölkchoklad +Name[ta]=மில்க்-சாக்லேட் +Name[tg]=Шоколади Ширӣ +Name[tr]=Çikolatalı Süt +Name[uk]=Молочний шоколад +Name[ven]=Tshokholeiti ya mafhi +Name[xh]=Ubisi-ichocolate +Name[zh_CN]=牛奶巧克力 +Name[zh_HK]=牛奶巧克力 +Name[zh_TW]=牛奶巧克力 +Name[zu]=Ushokolade Wobisi +Comment=Noatun's simple GUI +Comment[ar]=واجهة بسيطة جدا لNoatun +Comment[az]=Noatun bəsit axtar üzü +Comment[bg]=Семпъл графичен интерфейс за Noatun +Comment[bs]=Jednostavan Noatunov GUI +Comment[ca]=IGU senzill pel Noatun +Comment[cs]=Jednoduché rozhraní pro Noatun +Comment[cy]=GUI syml Noatun +Comment[da]=Noatuns enkle GUI +Comment[de]=Noatuns einfache Oberfläche +Comment[el]=Το απλό περιβάλλον χρήσης του Noatun +Comment[eo]=La simpla grafika etoso de Noatun +Comment[es]=Interfaz simple de Noatun +Comment[et]=Lihtne Noatuni kasutajaliides +Comment[eu]=Noatun-en GUI simplea +Comment[fa]=ونک ساده Noatun +Comment[fi]=Noatunin yksinkertainen käyttöliittymä +Comment[fr]=Interface graphique simple de Noatun +Comment[ga]=Comhéadan simplí grafach ar Noatun +Comment[gl]=GUI sinxela de Noatun +Comment[he]=ממשק המשתמש הגרפי הפשוט של Noatun +Comment[hi]=नोआट्यून का साधारण जीयूआई +Comment[hr]=Noatunovo jednostavno sučelje +Comment[hu]=A Noatun egyszerű grafikus kezelői felülete +Comment[id]=Contoh Noatun'GUI +Comment[is]=Hið einfalda viðmót Nóatúns forritsins +Comment[it]=Interfaccia grafica semplice di Noatun +Comment[ja]=Noatun のシンプルな GUI +Comment[kk]=Noatun-ның қарапайым графикалық интерфейсі +Comment[km]=ចំណុចប្រទាក់ក្រាហ្វិកសាមញ្ញរបស់ Noatun +Comment[ko]=Noatun의 간단한 GUI +Comment[lt]=Noatun paprastas GUI +Comment[lv]=Vienkāršs Noatuna GUI +Comment[mk]=Едноставен графички интерфејс за Noatun +Comment[ms]=GUI Noatun yang ringkas +Comment[mt]=GUI sempliċi għal Noatun +Comment[nb]=Noatuns enkle GUI +Comment[nds]=Eenfach Böversiet vun Noatun +Comment[ne]=नोवटुनको साधारण GUI +Comment[nl]=Noatun's eenvoudige GUI +Comment[nn]=Det enkle Noatun-GUI-et +Comment[pa]=ਨੋਟੌਮ ਦਾ ਸਧਾਰਨ GUI +Comment[pl]=Prosty motyw Noatun +Comment[pt]=Uma interface simples do Noatun +Comment[pt_BR]=Interface simplificada do Noatun +Comment[ro]=Interfaţă grafică Noatun simplă +Comment[ru]=Простой графический интерфейс Noatun +Comment[se]=Noatuna oktageardanis grafihkkalaš lakta +Comment[sk]=Jednoduché rozhranie pre Noatun +Comment[sl]=Noatunov preprost uporabniški vmesnik +Comment[sr]=Noatun-ов једноставан GUI +Comment[sr@Latn]=Noatun-ov jednostavan GUI +Comment[sv]=Noatuns enkla gränssnitt +Comment[ta]=Noatun'இன் எளிய முகப்பொன்று +Comment[tg]=Интерфейси Графикии соддаи Noatun +Comment[th]=ส่วนติดต่อผู้ใช้แบบกราฟิกแบบเรียบง่ายของ Noatun +Comment[tr]=Noatun basit arayüzü +Comment[uk]=Простий графічний інтерфейс Noatun +Comment[ven]=Noatun yo leluwaho ya GUI +Comment[xh]=iGUI elula ye Noatun +Comment[zh_CN]=Noatun 的简单界面 +Comment[zh_HK]=Noatun 的簡單圖形界面 +Comment[zh_TW]=Noatun 簡單圖形界面 +Comment[zu]=I GUI elula ye Noatun diff --git a/noatun/modules/noatunui/userinterface.cpp b/noatun/modules/noatunui/userinterface.cpp new file mode 100644 index 00000000..c13d4d6d --- /dev/null +++ b/noatun/modules/noatunui/userinterface.cpp @@ -0,0 +1,315 @@ +/* + * noatun.cpp + * + * Copyright (C) 1999 Charles Samuels <charles@kde.org> + */ + +#include "userinterface.h" +#include <noatun/playlist.h> +#include <noatun/stdaction.h> +#include <noatun/app.h> +#include <noatun/player.h> +#include <noatun/controls.h> +#include <noatun/effects.h> + +#include <qpushbutton.h> +#include <qdragobject.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qobjectlist.h> +#include <qobjectdict.h> + +#include <kpopupmenu.h> +#include <kstatusbar.h> +#include <kglobal.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kurldrag.h> +#include <kfiledialog.h> +#include <kconfig.h> + +MilkChocolate::MilkChocolate() : QWidget(0,"NoatunUI"), UserInterface() +{ + setAcceptDrops(true); + static const int buttonSize=32; + + { // The buttons + mBack=new QPushButton(this); + mBack->setFixedSize(buttonSize,buttonSize); + mBack->setPixmap(BarIcon("noatunback")); + connect(mBack, SIGNAL(clicked()), napp->player(), SLOT(back())); + QToolTip::add(mBack,i18n("Back")); + + mStop=new QPushButton(this); + mStop->setFixedSize(buttonSize,buttonSize); + mStop->setPixmap(BarIcon("noatunstop")); + connect(mStop, SIGNAL(clicked()), napp->player(), SLOT(stop())); + QToolTip::add(mStop, i18n("Stop")); + + mPlay=new QPushButton(this); + mPlay->setToggleButton(true); + mPlay->setFixedSize(buttonSize,buttonSize); + mPlay->setPixmap(BarIcon("noatunplay")); + connect(mPlay, SIGNAL(clicked()), napp->player(), SLOT(playpause())); + QToolTip::add(mPlay, i18n("Play")); + + mForward=new QPushButton(this); + mForward->setFixedSize(buttonSize,buttonSize); + mForward->setPixmap(BarIcon("noatunforward")); + connect(mForward, SIGNAL(clicked()), napp->player(), SLOT(forward())); + QToolTip::add(mForward, i18n("Forward")); + + mPlaylist=new QPushButton(this); + mPlaylist->setToggleButton(true); + mPlaylist->setFixedSize(buttonSize,buttonSize); + mPlaylist->setPixmap(BarIcon("noatunplaylist")); + connect(mPlaylist, SIGNAL(clicked()), napp->player(), SLOT(toggleListView())); + QToolTip::add(mPlaylist, i18n("Playlist")); + + mLoop=new QPushButton(this); + mLoop->setFixedSize(buttonSize,buttonSize); + mLoop->setPixmap(BarIcon("noatunloopnone")); + connect(mLoop, SIGNAL(clicked()), napp->player(), SLOT(loop())); + QToolTip::add(mLoop, i18n("Change loop style")); + + mPopup=new QPushButton(this); + mPopup->setFixedSize(buttonSize,buttonSize); + mPopup->setPixmap(BarIcon("noatun")); + connect(mPopup, SIGNAL(clicked()), SLOT(popup())); +// QToolTip::add(mRemoveCurrent, i18n("Remove current file from playlist")); + + } + + mVolume=new L33tSlider(0,100,10,0, Horizontal, this); + mVolume->setValue(napp->player()->volume()); + mSeeker=new L33tSlider(0,1000,10,0, Horizontal, this); + + mStatusBar=new KStatusBar(this); + + + QGridLayout *l=new QGridLayout(this); + l->addWidget(mBack,0,0); + l->addWidget(mStop,0,1); + l->addWidget(mPlay,0,2); + l->addWidget(mForward,0,3); + l->addWidget(mPlaylist,0,4, Qt::AlignLeft); + l->addWidget(mLoop,0,5); + l->addWidget(mPopup,0,6); + l->addColSpacing(4, buttonSize+8); + + l->addMultiCellWidget(mVolume,1,1,0,6); + l->addMultiCellWidget(mSeeker,2,2,0,6); + l->addMultiCellWidget(mStatusBar,3,3,0,6); + + statusBar()->message(i18n("No File Loaded")); + statusBar()->insertItem("--:--/--:--", 1, 0, true); + + connect(napp, SIGNAL(hideYourself()), this, SLOT(hide()) ); + connect(napp, SIGNAL(showYourself()), this, SLOT(show()) ); + + connect(napp->player(), SIGNAL(playing()), this, SLOT(slotPlaying())); + connect(napp->player(), SIGNAL(stopped()), this, SLOT(slotStopped())); + connect(napp->player(), SIGNAL(paused()), this, SLOT(slotPaused())); + napp->player()->handleButtons(); + + connect(napp->player(), SIGNAL(timeout()), this, SLOT(slotTimeout())); + connect(napp->player(), SIGNAL(loopTypeChange(int)), this, SLOT(changeLoopType(int))); + +// if(seeker()) + { + /* This skipToWrapper is needed to pass milliseconds to Player() as everybody + * below the GUI is based on milliseconds instead of some unprecise thingy + * like seconds or mille */ + connect(seeker(), SIGNAL(userChanged(int)), this, SLOT(skipToWrapper(int))); + connect(this, SIGNAL(skipTo(int)), napp->player(), SLOT(skipTo(int))); + connect(seeker(), SIGNAL(sliderMoved(int)), SLOT(sliderMoved(int))); + } + connect(mVolume, SIGNAL(sliderMoved(int)), napp->player(), SLOT(setVolume(int))); + connect(mVolume, SIGNAL(userChanged(int)), napp->player(), SLOT(setVolume(int))); + + + connect(napp->player(), SIGNAL(playlistShown()), SLOT(playlistShown())); + connect(napp->player(), SIGNAL(playlistHidden()), SLOT(playlistHidden())); + + // Event Filter for the RMB + for (QPtrListIterator<QObject> i(*children()); i.current(); ++i) + (*i)->installEventFilter(this); + + setCaption("Noatun"); + setIcon(BarIcon("noatun")); + show(); + + // What it is now, stay, stay.. roll over, good boy! + setFixedSize(minimumSize()); +} + +MilkChocolate::~MilkChocolate() +{ + // If cfg dialog is still open, delete it so it saves it's position +// if(prefDlgExist) +// delete prefDlg; +} + +void MilkChocolate::closeEvent(QCloseEvent*) +{ + unload(); +} + +void MilkChocolate::showEvent(QShowEvent*e) +{ + QWidget::showEvent(e); +} + +void MilkChocolate::dragEnterEvent(QDragEnterEvent *event) +{ + // accept uri drops only + event->accept(KURLDrag::canDecode(event)); +} + +void MilkChocolate::dropEvent(QDropEvent *event) +{ + KURL::List uri; + if (KURLDrag::decode(event, uri)) + { + for (KURL::List::Iterator i = uri.begin(); i != uri.end(); ++i) + napp->player()->openFile(*i, false); + } +} + +void MilkChocolate::mouseReleaseEvent(QMouseEvent *e) +{ + QWidget::mouseReleaseEvent(e); + if (e->button()!=RightButton) return; + NoatunStdAction::ContextMenu::showContextMenu(); +} + +void MilkChocolate::changeStatusbar(const QString& text, const QString &text2) +{ + if (!text2.isNull()) + statusBar()->changeItem(text2, 1); + + statusBar()->message(!text.isNull() ? text : napp->player()->current().title()); +} + +void MilkChocolate::changeCaption(const QString& text) +{ + setCaption(text); +} + +void MilkChocolate::popup() +{ + NoatunStdAction::ContextMenu::showContextMenu( + mapToGlobal(mPopup->geometry().bottomLeft()) + ); +} + +void MilkChocolate::slotPlaying() +{ +// connect(kwinmodule, SIGNAL(windowAdded(WId)), view, SLOT(attemptReparent(WId))); + changeStatusbar(napp->player()->current().title(), napp->player()->lengthString()); + mPlay->setOn(true); + mStop->setEnabled(true); + mPlay->setPixmap(BarIcon("noatunpause")); +} + +void MilkChocolate::slotStopped() +{ + if (!napp->player()->current()) return; + changeStatusbar(i18n("No File Loaded"), napp->player()->lengthString()); + mStop->setEnabled(false); + mPlay->setOn(false); + seeker()->setValue(0); + mPlay->setPixmap(BarIcon("noatunplay")); +} + +void MilkChocolate::slotPaused() +{ + mStop->setEnabled(true); + mPlay->setOn(false); + mPlay->setPixmap(BarIcon("noatunplay")); +} + +void MilkChocolate::slotTimeout() +{ + mVolume->setValue(napp->player()->volume()); + + if (!napp->player()->current()) return; + if (static_cast<L33tSlider*>(seeker())->currentlyPressed()) return; + if (seeker()) + { + seeker()->setRange ( 0, (int)napp->player()->getLength()/1000 ); + seeker()->setValue ( (int)napp->player()->getTime()/1000 ); + } + changeStatusbar(0, napp->player()->lengthString()); +} + +void MilkChocolate::sliderMoved(int seconds) +{ + if (napp->player()->current()) + changeStatusbar(0, napp->player()->lengthString(seconds*1000)); +} + +void MilkChocolate::skipToWrapper(int second) +{ + emit skipTo((long)(second*1000)); +} + +void MilkChocolate::changeLoopType(int t) +{ + static const int time=2000; + switch (t) + { + case(Player::None): + statusBar()->message(i18n("No looping"), time); + mLoop->setPixmap(BarIcon("noatunloopnone")); + break; + case(Player::Song): + statusBar()->message(i18n("Song looping"), time); + mLoop->setPixmap(BarIcon("noatunloopsong")); + break; + case(Player::Playlist): + statusBar()->message(i18n("Playlist looping"), time); + mLoop->setPixmap(BarIcon("noatunloopplaylist")); + break; + case(Player::Random): + statusBar()->message(i18n("Random play"), time); + mLoop->setPixmap(BarIcon("noatunlooprandom")); + } + +} + +bool MilkChocolate::eventFilter(QObject *o, QEvent *e) +{ + if ((e->type() == QEvent::MouseButtonRelease) + && ((static_cast<QMouseEvent*>(e))->button()==RightButton)) + { + mouseReleaseEvent(static_cast<QMouseEvent*>(e)); + return true; + } + + if (e->type() == QEvent::Wheel) + { + wheelEvent(static_cast<QWheelEvent*>(e)); + return true; + } + return QWidget::eventFilter(o, e); +} + +void MilkChocolate::playlistShown() +{ + mPlaylist->setOn(true); +} + +void MilkChocolate::playlistHidden() +{ + mPlaylist->setOn(false); +} + +void MilkChocolate::wheelEvent(QWheelEvent *e) +{ + int delta=e->delta(); + mVolume->setValue(mVolume->value()+(delta/120)); + napp->player()->setVolume(mVolume->value()+(delta/120)); +} + +#include "userinterface.moc" diff --git a/noatun/modules/noatunui/userinterface.h b/noatun/modules/noatunui/userinterface.h new file mode 100644 index 00000000..94dc9c44 --- /dev/null +++ b/noatun/modules/noatunui/userinterface.h @@ -0,0 +1,72 @@ +#ifndef USERINTERFACE_H +#define USERINTERFACE_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <noatun/plugin.h> +#include <noatun/app.h> + +// Pref dialog pointer global now for position saving +#include <noatun/pref.h> + +class Player; +class QSlider; +class QPushButton; +class KStatusBar; + +/** + * @short Main window class + * @author Charles Samuels <charles@kde.org> + * @version 0.1 + */ +class MilkChocolate : public QWidget, public UserInterface +{ +Q_OBJECT +public: + MilkChocolate(); + virtual ~MilkChocolate(); + void load(const QString& url); + +protected: + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dropEvent(QDropEvent *event); + virtual void closeEvent(QCloseEvent*); + virtual void showEvent(QShowEvent*e); + virtual void mouseReleaseEvent(QMouseEvent *); + virtual bool eventFilter(QObject*, QEvent*); + virtual void wheelEvent(QWheelEvent *e); + +protected: + QSlider *seeker() const { return mSeeker; } + KStatusBar *statusBar() const { return mStatusBar; } + +public slots: + void slotPlaying(); + void slotStopped(); + void slotPaused(); + + void playlistShown(); + void playlistHidden(); + + void slotTimeout(); + void sliderMoved(int seconds); + void changeLoopType(int t); + void skipToWrapper(int second); + +signals: + void skipTo( int ); // emitted by skipToWrapper() + +private slots: + void changeStatusbar(const QString& text, const QString &text2=0); + void changeCaption(const QString& text); + void popup(); + +private: + QPushButton *mBack, *mStop, *mPlay, *mForward, *mPlaylist, *mPopup, *mLoop; + QSlider *mSeeker, *mVolume; + KStatusBar *mStatusBar; +}; + +#endif diff --git a/noatun/modules/simple/Makefile.am b/noatun/modules/simple/Makefile.am new file mode 100644 index 00000000..de5a7aa8 --- /dev/null +++ b/noatun/modules/simple/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES= -I$(top_srcdir)/noatun/library -I$(kde_includes)/arts $(all_includes) + +kde_module_LTLIBRARIES = noatunsimple.la + +noatunsimple_la_SOURCES = propertiesdialog.ui noatunui.cpp userinterface.cpp +noatunsimple_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +noatunsimple_la_LIBADD = $(top_builddir)/noatun/library/libnoatun.la \ + $(top_builddir)/noatun/library/libnoatuncontrols.la \ + -lkmedia2_idl -lsoundserver_idl -lartskde + +noatunsimple_la_METASOURCES = AUTO + +noinst_HEADERS = propertiesdialog.h userinterface.h + +noatun_modules_simple_DATA = simple.plugin simpleui.rc +noatun_modules_simpledir = $(kde_datadir)/noatun diff --git a/noatun/modules/simple/back.xpm b/noatun/modules/simple/back.xpm new file mode 100644 index 00000000..bd433e5e --- /dev/null +++ b/noatun/modules/simple/back.xpm @@ -0,0 +1,21 @@ +/* XPM */ +const char * back_xpm[] = { +"16 16 2 1", +" c None", +". c #000000", +" ", +" ", +" ", +" .... .. ", +" .... ... ", +" .... .... ", +" .... ..... ", +" .... ...... ", +" .... ...... ", +" .... ..... ", +" .... .... ", +" .... ... ", +" .... .. ", +" ", +" ", +" "}; diff --git a/noatun/modules/simple/forward.xpm b/noatun/modules/simple/forward.xpm new file mode 100644 index 00000000..c4e95ccc --- /dev/null +++ b/noatun/modules/simple/forward.xpm @@ -0,0 +1,21 @@ +/* XPM */ +const char * forward_xpm[] = { +"16 16 2 1", +" c None", +". c #000000", +" ", +" ", +" ", +" .. .... ", +" ... .... ", +" .... .... ", +" ..... .... ", +" ...... .... ", +" ...... .... ", +" ..... .... ", +" .... .... ", +" ... .... ", +" .. .... ", +" ", +" ", +" "}; diff --git a/noatun/modules/simple/noatunui.cpp b/noatun/modules/simple/noatunui.cpp new file mode 100644 index 00000000..3b647e42 --- /dev/null +++ b/noatun/modules/simple/noatunui.cpp @@ -0,0 +1,17 @@ +/* + This file is part of KDE/aRts (Noatun) - xine integration + Copyright (C) 2002 Ewald Snel <ewald@rambo.its.tudelft.nl> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. +*/ + +#include "userinterface.h" + + +extern "C" +{ + KDE_EXPORT Plugin *create_plugin() { return new SimpleUI(); } +} diff --git a/noatun/modules/simple/pause.xpm b/noatun/modules/simple/pause.xpm new file mode 100644 index 00000000..48d37568 --- /dev/null +++ b/noatun/modules/simple/pause.xpm @@ -0,0 +1,21 @@ +/* XPM */ +const char * pause_xpm[] = { +"16 16 2 1", +" c None", +". c #000000", +" ", +" ", +" ", +" .... .... ", +" .... .... ", +" .... .... ", +" .... .... ", +" .... .... ", +" .... .... ", +" .... .... ", +" .... .... ", +" .... .... ", +" .... .... ", +" ", +" ", +" "}; diff --git a/noatun/modules/simple/play.xpm b/noatun/modules/simple/play.xpm new file mode 100644 index 00000000..7cb55a88 --- /dev/null +++ b/noatun/modules/simple/play.xpm @@ -0,0 +1,21 @@ +/* XPM */ +const char * play_xpm[] = { +"16 16 2 1", +" c None", +". c #000000", +" ", +" ", +" ", +" .. ", +" ... ", +" .... ", +" ..... ", +" ...... ", +" ...... ", +" ..... ", +" .... ", +" ... ", +" .. ", +" ", +" ", +" "}; diff --git a/noatun/modules/simple/playlist.xpm b/noatun/modules/simple/playlist.xpm new file mode 100644 index 00000000..80b622ac --- /dev/null +++ b/noatun/modules/simple/playlist.xpm @@ -0,0 +1,21 @@ +/* XPM */ +const char * playlist_xpm[] = { +"16 16 2 1", +" c None", +". c #000000", +" ", +" ", +" .. ", +" .... ", +" ...... ", +" ........ ", +" .......... ", +" .......... ", +" ", +" ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" ", +" "}; diff --git a/noatun/modules/simple/propertiesdialog.ui b/noatun/modules/simple/propertiesdialog.ui new file mode 100644 index 00000000..08f4f71c --- /dev/null +++ b/noatun/modules/simple/propertiesdialog.ui @@ -0,0 +1,348 @@ +<!DOCTYPE UI><UI version="3.0" stdsetdef="1"> +<class>PropertiesDialog</class> +<author>Ewald Snel</author> +<widget class="QDialog"> + <property name="name"> + <cstring>PropertiesDialog</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>320</width> + <height>261</height> + </rect> + </property> + <property name="caption"> + <string>Properties</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QTabWidget"> + <property name="name"> + <cstring>TabWidget2</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>details</cstring> + </property> + <attribute name="title"> + <string>&Details</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>16</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLineEdit" row="0" column="2"> + <property name="name"> + <cstring>nameField</cstring> + </property> + <property name="minimumSize"> + <size> + <width>180</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + <widget class="Line" row="1" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>Line1</cstring> + </property> + <property name="frameShape" stdset="0"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>iconLabel</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignLeft</set> + </property> + </widget> + <widget class="QLabel" row="2" column="2"> + <property name="name"> + <cstring>typeLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <spacer row="7" column="2"> + <property name="name" stdset="0"> + <cstring>Spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="Line" row="6" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>Line1_2</cstring> + </property> + <property name="frameShape" stdset="0"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>TextLabel7_2</cstring> + </property> + <property name="text"> + <string>Type:</string> + </property> + </widget> + <widget class="QLabel" row="2" column="1" rowspan="4" colspan="1"> + <property name="name"> + <cstring>TextLabel2_2</cstring> + </property> + <property name="minimumSize"> + <size> + <width>25</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>25</width> + <height>32767</height> + </size> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>TextLabel5</cstring> + </property> + <property name="text"> + <string>Length:</string> + </property> + </widget> + <widget class="QLabel" row="3" column="2"> + <property name="name"> + <cstring>lengthLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>TextLabel6</cstring> + </property> + <property name="text"> + <string>Audio:</string> + </property> + </widget> + <widget class="QLabel" row="4" column="2"> + <property name="name"> + <cstring>audioLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QLabel" row="5" column="0"> + <property name="name"> + <cstring>TextLabel7</cstring> + </property> + <property name="text"> + <string>Video:</string> + </property> + </widget> + <widget class="QLabel" row="5" column="2"> + <property name="name"> + <cstring>videoLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>playobject</cstring> + </property> + <attribute name="title"> + <string>&PlayObject</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>16</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>TextLabel2</cstring> + </property> + <property name="minimumSize"> + <size> + <width>80</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>80</width> + <height>32767</height> + </size> + </property> + <property name="text"> + <string>Description:</string> + </property> + </widget> + <widget class="QLabel" row="0" column="1"> + <property name="name"> + <cstring>descriptionLabel</cstring> + </property> + </widget> + <widget class="QListView" row="1" column="0" rowspan="1" colspan="2"> + <column> + <property name="text"> + <string>Capabilities</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizeable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>capsList</cstring> + </property> + </widget> + </grid> + </widget> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>buttonLayout</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <spacer> + <property name="name" stdset="0"> + <cstring>Spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>okButton</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<connections> + <connection> + <sender>okButton</sender> + <signal>clicked()</signal> + <receiver>PropertiesDialog</receiver> + <slot>accept()</slot> + </connection> +</connections> +<includes> + <include location="global" impldecl="in declaration">noatun/playlist.h</include> + <include location="global" impldecl="in declaration">kmedia2.h</include> + <include location="global" impldecl="in declaration">kmimetype.h</include> + <include location="local" impldecl="in implementation">propertiesdialog.ui.h</include> +</includes> +<slots> + <slot specifier="non virtual">setPlayObject( PlaylistItem pi, Arts::PlayObject po )</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/noatun/modules/simple/propertiesdialog.ui.h b/noatun/modules/simple/propertiesdialog.ui.h new file mode 100644 index 00000000..a712d776 --- /dev/null +++ b/noatun/modules/simple/propertiesdialog.ui.h @@ -0,0 +1,58 @@ +/* + This file is part of KDE/aRts (Noatun) - xine integration + Copyright (C) 2002 Ewald Snel <ewald@rambo.its.tudelft.nl> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. +*/ + +#include <klocale.h> + +void PropertiesDialog::setPlayObject( PlaylistItem pi, Arts::PlayObject po ) +{ + // Arts::PlayObject properties + if (!po.isNull()) + { + Arts::poCapabilities ncaps = po.capabilities(); + QCheckListItem *item; + + descriptionLabel->setText( po.description().c_str() ); + + // Determine capabilities + if (!(item = (QCheckListItem *)capsList->findItem( "capSeek", 0 ))) + { + item = new QCheckListItem( capsList, "capSeek", + QCheckListItem::CheckBox ); + } + item->setOn( (ncaps & Arts::capSeek) ); + + if (!(item = (QCheckListItem *)capsList->findItem( "capPause", 0 ))) + { + item = new QCheckListItem( capsList, "capPause", + QCheckListItem::CheckBox ); + } + item->setOn( (ncaps & Arts::capPause) ); + + // Defaults + nameField->setText( i18n("unknown") ); + typeLabel->setText( i18n("unknown") ); + lengthLabel->setText( i18n("unknown") ); + audioLabel->setText( i18n("unknown") ); + videoLabel->setText( i18n("unknown") ); + } + + // PlaylistItem properties (name and mimetype) + if (!pi.isNull()) + { + setCaption( i18n("Properties for %1").arg(pi.url().fileName()) ); + + KSharedPtr<KMimeType> mime = KMimeType::mimeType( pi.mimetype() ); + iconLabel->setPixmap( mime->pixmap( KIcon::Desktop, KIcon::SizeMedium ) ); + + nameField->setText( pi.url().fileName() ); + typeLabel->setText( pi.mimetype() ); + lengthLabel->setText( pi.lengthString() ); + } +} diff --git a/noatun/modules/simple/simple.plugin b/noatun/modules/simple/simple.plugin new file mode 100644 index 00000000..9d7e4beb --- /dev/null +++ b/noatun/modules/simple/simple.plugin @@ -0,0 +1,126 @@ +Filename=noatunsimple.la +Author=Ewald Snel +Site=http://rambo.its.tudelft.nl/xine/ +Email=ewald@rambo.its.tudelft.nl +Type=userinterface +License=LGPL +Name=Simple +Name[af]=Eenvoudige +Name[ar]=بسيط +Name[az]=Bəsit +Name[bn]=সরল +Name[br]=Eeun +Name[bs]=Jednostavno +Name[ca]=Senzill +Name[cs]=Jednoduchý +Name[cy]=Syml +Name[da]=Simpel +Name[de]=Einfach +Name[el]=Απλό +Name[eo]=Simpla +Name[et]=Lihtne +Name[eu]=Sinplea +Name[fa]=ساده +Name[fi]=Yksinkertainen +Name[ga]=Simplí +Name[he]=פשוט +Name[hi]=साधारण +Name[hr]=Jednostavno +Name[hu]=Egyszerű +Name[id]=Sederhana +Name[is]=Einfalt +Name[it]=Semplice +Name[km]=សាមញ្ញ +Name[ko]=간단 +Name[lt]=Paprastas +Name[lv]=Vienkāršs +Name[mk]=Едноставен +Name[mt]=Sempliċi +Name[nb]=Enkel +Name[nds]=Eenfach +Name[ne]=साधारण +Name[nl]=Eenvoudig +Name[nn]=Enkel +Name[pa]=ਸਧਾਰਨ +Name[pl]=Prosty +Name[pt]=Simples +Name[pt_BR]=Simples +Name[ro]=Simplu +Name[ru]=Простой +Name[se]=Oktageardanis +Name[sk]=Jednoduchý +Name[sl]=Preprosto +Name[sr]=Једноставан +Name[sr@Latn]=Jednostavan +Name[sv]=Enkel +Name[ta]=எளிய +Name[tg]=Содда +Name[th]=เรียบง่าย +Name[tr]=Basit +Name[uk]=Простий +Name[uz]=Oddiy +Name[uz@cyrillic]=Оддий +Name[ven]=Zwoleluwa +Name[wa]=Simpe +Name[xh]=Lula +Name[zh_CN]=简单 +Name[zh_HK]=簡單 +Name[zh_TW]=簡單 +Name[zu]=Okulula +Comment=Simple GUI (embedded video) +Comment[af]=Eenvoudige Gui (ingebedde video) +Comment[bg]=Семпъл графичен интерфейс за Noatun +Comment[bs]=Jednostavan GUI (uključen video) +Comment[ca]=IGU senzill (vídeo incrustat) +Comment[cs]=Jednoduché GUI (vnořené video) +Comment[cy]=GUI Syml (fideo mewnol) +Comment[da]=Simpel GUI (indlejret video) +Comment[de]=Einfache Oberfläche (eingebettetes Video) +Comment[el]=Απλό περιβάλλον χρήσης (ενσωματωμένο βίντεο) +Comment[es]=Interfaz gráfica simple (vídeo empotrado) +Comment[et]=Lihtne kasutajaliides (põimitud video) +Comment[eu]=GUI sinplea (bideo kapsulatua) +Comment[fa]=ونک ساده )ویدیوی نهفته( +Comment[fi]=Yksinkertainen käyttöliittymä (upotettu video) +Comment[fr]=Interface graphique simple (video incorporée) +Comment[ga]=Comhéadan simplí (fís leabaithe) +Comment[gl]=GUI Sinxela (video incrustado) +Comment[he]=ממשק משתמש גרפי פשוט (וידאו מוטבע) +Comment[hi]=साधारण जीयूआई (एम्बेडेड वीडियो) +Comment[hu]=Egyszerű kezelőfelület (beágyazott videó) +Comment[is]=Einföld myndræn skil (innbyggt) +Comment[it]=Semplice GUI (video integrato) +Comment[ja]=シンプルな GUI (埋め込みビデオ) +Comment[kk]=Қарапайым инерфейсі (ендірілген бейне) +Comment[km]=ចំណុចប្រទាក់ក្រាហ្វិកសាមញ្ញ (វីដេអូបង្កប់) +Comment[ko]=간단한 GUI (내장된 비디오) +Comment[lt]=Paprastas GUI (įdedamas video) +Comment[mk]=Едноставен графички интерфејс (вградено видео) +Comment[ms]=GUI Ringkas (video diselitkan) +Comment[nb]=Enkel GUI (innebygget video) +Comment[nds]=Eenfach Böversiet (inbett Video) +Comment[ne]=साधारण GUI (सम्मिलित भिडियो) +Comment[nl]=Eenvoudige GUI (inbedbare video) +Comment[nn]=Enkelt grensesnitt (innebygd video) +Comment[pa]=ਸਧਾਰਨ GUI (ਸ਼ਾਮਲ ਵੀਡਿਓ) +Comment[pl]=Zwykły motyw (osadzone wideo) +Comment[pt]=Interface Simples (vídeo embebido) +Comment[pt_BR]=Interface Simples (vídeo integrado) +Comment[ro]=Interfaţă grafică simplă (video integrat) +Comment[ru]=Простой интерфейс (встроенное видео) +Comment[se]=Oktageardánis lakta (vuojuhuvvon video) +Comment[sk]=Jednoduché rozhranie (vložené video) +Comment[sl]=Preprost uporabniški vmesnik (vključen video) +Comment[sr]=Једноставан GUI (уграђен видео) +Comment[sr@Latn]=Jednostavan GUI (ugrađen video) +Comment[sv]=Enkelt grafiskt gränssnitt (inbäddad video) +Comment[ta]=எளிய GUI (உட்பொதிந்த தாரை) +Comment[tg]=Интерфейси Графикии содда (видеои дарунгузошта) +Comment[th]=ส่วนติดต่อผู้ใช้แบบกราฟิกแบบเรียบง่าย (วิดีโอแบบฝัง) +Comment[tr]=Basit arayüz (gömülü video) +Comment[uk]=Простий інтерфейс (вмонтоване відео) +Comment[xh]=GUI Elula (video ebekiweyo) +Comment[zh_CN]=简单图形用户界面 (嵌入式视频) +Comment[zh_HK]=簡單圖形用戶(嵌入式視訊) +Comment[zh_TW]=簡單圖形使用者界面(嵌入式視訊) +Comment[zu]=I-GUI Elula (ividiyo ehlanganiselwe) diff --git a/noatun/modules/simple/simpleui.rc b/noatun/modules/simple/simpleui.rc new file mode 100644 index 00000000..6e5fb86a --- /dev/null +++ b/noatun/modules/simple/simpleui.rc @@ -0,0 +1,37 @@ +<!DOCTYPE kpartgui> +<!-- +vim: syntax=xml +--> +<kpartgui name="simpleui" version="1"> +<MenuBar> + <Menu name="file"><text>&File</text> + <Action name="_file_open"/> + <Separator lineSeparator="true"/> + <Action name="_file_properties"/> + <Separator lineSeparator="true"/> + <Action name="_file_quit"/> + </Menu> + <Menu name="view"> + <Action name="view_playlist"/> + <Separator lineSeparator="true"/> + <Action name="half_size" /> + <Action name="normal_size" /> + <Action name="double_size" /> + <Separator lineSeparator="true"/> + <Action name="fullscreen_mode" /> + </Menu> + <Menu name="settings" noMerge="1"><text>&Settings</text> + <Action name="options_show_menubar"/> + <Action name="options_show_statusbar"/> + <Separator lineSeparator="true"/> + <Action name="effects"/> + <Action name="equalizer"/> + <Action name="loop_style"/> + <Separator lineSeparator="true"/> + <Action name="options_configure"/> + </Menu> + + <Action name="menu_actions" /> +</MenuBar> + +</kpartgui> diff --git a/noatun/modules/simple/stop.xpm b/noatun/modules/simple/stop.xpm new file mode 100644 index 00000000..6b080e94 --- /dev/null +++ b/noatun/modules/simple/stop.xpm @@ -0,0 +1,21 @@ +/* XPM */ +const char * stop_xpm[] = { +"16 16 2 1", +" c None", +". c #000000", +" ", +" ", +" ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" ", +" ", +" "}; diff --git a/noatun/modules/simple/userinterface.cpp b/noatun/modules/simple/userinterface.cpp new file mode 100644 index 00000000..6e7b486f --- /dev/null +++ b/noatun/modules/simple/userinterface.cpp @@ -0,0 +1,379 @@ +/* + This file is part of KDE/aRts (Noatun) - xine integration + Copyright (C) 2002 Ewald Snel <ewald@rambo.its.tudelft.nl> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <noatun/app.h> +#include <noatun/engine.h> +#include <noatun/player.h> +#include <noatun/stdaction.h> + +#include <kconfig.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kurldrag.h> +#include <kmenubar.h> +#include <kpopupmenu.h> +#include <kstatusbar.h> +#include <kstdaction.h> +#include <kstdguiitem.h> +#include <kurl.h> + +#include <qaccel.h> +#include <qdragobject.h> +#include <qhbox.h> +#include <qimage.h> +#include <qpixmap.h> +#include <qstrlist.h> +#include <qtooltip.h> +#include <qvbox.h> + +#include "userinterface.h" + +#include "back.xpm" +#include "forward.xpm" +#include "pause.xpm" +#include "play.xpm" +#include "playlist.xpm" +#include "stop.xpm" +#include "volume.xpm" + +SimpleUI::SimpleUI() + : KMainWindow(0, "NoatunSimpleUI"), UserInterface() +{ + setAcceptDrops( true ); + setCaption( i18n("Noatun") ); + setIcon( SmallIcon( "noatun" ) ); + + setupCentralWidget(); + setupActions(); + + contextMenu = video->popupMenu( this ); + + setupGUI( StatusBar|Create, "simpleui.rc" ); + + connect( napp->player(), SIGNAL(playing()), SLOT(slotPlaying()) ); + connect( napp->player(), SIGNAL(stopped()), SLOT(slotStopped()) ); + connect( napp->player(), SIGNAL(paused()), SLOT(slotPaused()) ); + connect( napp->player(), SIGNAL(timeout()), SLOT(slotTimeout()) ); + connect( napp->player(), SIGNAL(newSong()), SLOT(slotChanged()) ); + connect( napp->player(), SIGNAL(volumeChanged(int)), SLOT(slotVolumeChanged(int)) ); + connect( napp, SIGNAL(hideYourself()), SLOT(hide()) ); + connect( napp, SIGNAL(showYourself()), SLOT(show()) ); + + napp->player()->handleButtons(); + + resize( minimumSize() ); + + // Show UI and calculate video widget frame + show(); + + extra_width = (width() - video->width()); + extra_height = (height() - video->height()); + + // Load configuration + KConfig &config = *KGlobal::config(); + config.setGroup( "Simple" ); + QString str = config.readEntry( "View", "NormalSize" ); + + if (str == "HalfSize") + video->setHalfSize(); + else if (str == "NormalSize") + video->setNormalSize(); + else if (str == "DoubleSize") + video->setDoubleSize(); + else + applyMainWindowSettings( &config, "Simple" ); + + // PlayObject could be running, update video widget + slotChanged(); + + video->give(); +} + +SimpleUI::~SimpleUI() +{ + KConfig &config = *KGlobal::config(); + saveMainWindowSettings( &config, "Simple" ); + config.setGroup( "Simple" ); + QString str; + + if (video->isHalfSize()) + str = "HalfSize"; + else if (video->isNormalSize()) + str = "NormalSize"; + else if (video->isDoubleSize()) + str = "DoubleSize"; + else + str = "CustomSize"; + + config.writeEntry( "View", str ); + config.sync(); +} + + + +void SimpleUI::setupActions() +{ + KStdAction::open( napp, SLOT(fileOpen()), actionCollection(), "_file_open" ); + new KAction( i18n("&Properties"), 0, propertiesDialog, SLOT(show()), + actionCollection(), "_file_properties" ); + KStdAction::quit( napp, SLOT(quit()), actionCollection(), "_file_quit"); + + NoatunStdAction::playlist( actionCollection(), "view_playlist" ); + actionCollection()->insert(video->action( "half_size" )); + actionCollection()->insert(video->action( "normal_size" )); + actionCollection()->insert(video->action( "double_size" )); + actionCollection()->insert(video->action( "fullscreen_mode" )); + + actionCollection()->insert(napp->pluginActionMenu()); + + menubarAction = KStdAction::showMenubar(this, SLOT(showMenubar()), + actionCollection()); + statusbarAction = KStdAction::showStatusbar(this, SLOT(showStatusbar()), + actionCollection()); + NoatunStdAction::effects( actionCollection(), "effects" ); + NoatunStdAction::equalizer( actionCollection(), "equalizer" ); + NoatunStdAction::loop( actionCollection(), "loop_style" ); + KStdAction::preferences( napp, SLOT(preferences()), actionCollection() ); +} + +void SimpleUI::showMenubar() +{ + if(menubarAction->isChecked()) + menuBar()->show(); + else + menuBar()->hide(); +} + +void SimpleUI::showStatusbar() +{ + if(statusbarAction->isChecked()) + statusBar()->show(); + else + statusBar()->hide(); +} + + +void SimpleUI::setupCentralWidget() +{ + QVBox *npWidget = new QVBox( this ); + npWidget->setMargin( 0 ); + npWidget->setSpacing( 0 ); + + positionLabel = new QLabel( statusBar() ); + positionLabel->setAlignment( AlignVCenter | AlignCenter ); + positionLabel->setFixedSize( fontMetrics().size( 0, " 00:00/00:00 " ) ); + statusBar()->addWidget( positionLabel, 0, true ); + + video = new VideoFrame( npWidget ); + connect( video, SIGNAL(adaptSize(int,int)), + SLOT(slotAdaptSize(int,int)) ); + connect( video, SIGNAL(rightButtonPressed(const QPoint &)), + SLOT(slotContextMenu(const QPoint &)) ); + + QHBox *ctlFrame = new QHBox( npWidget ); + ctlFrame->setFixedHeight( 38 ); + ctlFrame->setFrameShape( QFrame::StyledPanel ); + ctlFrame->setFrameShadow( QFrame::Raised ); + ctlFrame->setMargin( 6 ); + ctlFrame->setSpacing( 6 ); + + QPushButton *backButton = new QPushButton( ctlFrame ); + backButton->setFixedSize( 24, 24 ); + backButton->setPixmap( QPixmap( back_xpm ) ); + QToolTip::add( backButton, i18n("Back") ); + connect( backButton, SIGNAL(clicked()), napp->player(), SLOT(back()) ); + + stopButton = new QPushButton( ctlFrame ); + stopButton->setFixedSize( 24, 24 ); + stopButton->setPixmap( QPixmap( stop_xpm ) ); + QToolTip::add( stopButton, i18n("Stop") ); + connect( stopButton, SIGNAL(clicked()), napp->player(), SLOT(stop()) ); + + playButton = new QPushButton( ctlFrame ); + playButton->setFixedSize( 24, 24 ); + playButton->setPixmap( QPixmap( play_xpm ) ); + QToolTip::add( playButton, i18n("Play / Pause") ); + connect( playButton, SIGNAL(clicked()), napp->player(), SLOT(playpause()) ); + + QPushButton *forwButton = new QPushButton( ctlFrame ); + forwButton->setFixedSize( 24, 24 ); + forwButton->setPixmap( QPixmap( forward_xpm ) ); + QToolTip::add( forwButton, i18n("Forward") ); + connect( forwButton, SIGNAL(clicked()), napp->player(), SLOT(forward()) ); + + slider = new L33tSlider( 0, 1000, 10, 0, L33tSlider::Horizontal, ctlFrame ); + slider->setFixedHeight( 24 ); + slider->setMinimumWidth( 100 ); + slider->setTickmarks( QSlider::NoMarks ); + connect( slider, SIGNAL(userChanged(int)), SLOT(slotSkipTo(int)) ); + connect( slider, SIGNAL(sliderMoved(int)), SLOT(slotSliderMoved(int)) ); + + QPushButton *playlistButton = new QPushButton( ctlFrame ); + playlistButton->setFixedSize( 24, 24 ); + playlistButton->setPixmap( QPixmap( playlist_xpm ) ); + QToolTip::add( playlistButton, i18n("Playlist") ); + connect( playlistButton, SIGNAL(clicked()), napp->player(), SLOT(toggleListView()) ); + + volumeButton = new QPushButton( ctlFrame ); + volumeButton->setFixedSize( 24, 24 ); + volumeButton->setPixmap( QPixmap( volume_xpm ) ); + QToolTip::add( volumeButton, i18n("Volume") ); + + volumeFrame = new QVBox( this, "Volume", WStyle_Customize | WType_Popup ); + volumeFrame->setFrameStyle( QFrame::PopupPanel ); + volumeFrame->setMargin( 4 ); + + volumeLabel = new QLabel( volumeFrame ); + volumeLabel->setText( "100%" ); + volumeLabel->setAlignment( AlignCenter ); + volumeLabel->setFixedSize( volumeLabel->sizeHint() ); + + QHBox *volumeSubFrame = new QHBox( volumeFrame ); + volumeSlider = new L33tSlider( 0, 100, 10, 0, Vertical, volumeSubFrame ); + volumeSlider->setValue( 100 - napp->player()->volume() ); + volumeSlider->setFixedSize( volumeSlider->sizeHint() ); + + volumeFrame->resize( volumeFrame->sizeHint() ); + + connect( volumeSlider, SIGNAL(sliderMoved(int)), SLOT(slotVolumeSliderMoved(int)) ); + connect( volumeSlider, SIGNAL(userChanged(int)), SLOT(slotVolumeSliderMoved(int)) ); + connect( volumeButton, SIGNAL(clicked()), SLOT(slotVolumeFrame()) ); + + setCentralWidget( npWidget ); + + video->setMinimumSize( minimumSizeHint().width(), 1 ); + + // Create properties dialog + propertiesDialog = new PropertiesDialog( this ); + propertiesDialog->resize( 375, 285 ); +} + +void SimpleUI::closeEvent( QCloseEvent * ) +{ + unload(); +} + +void SimpleUI::dragEnterEvent( QDragEnterEvent *event ) +{ + event->accept( KURLDrag::canDecode( event ) ); +} + +void SimpleUI::dropEvent( QDropEvent *event ) +{ + KURL::List uri; + if (KURLDrag::decode( event, uri )) + napp->player()->openFile( uri, false ); +} + +void SimpleUI::slotAdaptSize( int width, int height ) +{ + resize( width + extra_width, height + extra_height ); +} + +void SimpleUI::slotPlaying() +{ + playButton->setPixmap( QPixmap( pause_xpm ) ); + stopButton->setEnabled( true ); + slider->setEnabled( true ); + + if (napp->player()->current()) + statusBar()->message( napp->player()->current().title() ); +} + +void SimpleUI::slotStopped() +{ + playButton->setPixmap( QPixmap( play_xpm ) ); + stopButton->setEnabled( false ); + slider->setEnabled( false ); + slider->setValue( 0 ); + positionLabel->setText( "" ); + statusBar()->message( "" ); +} + +void SimpleUI::slotPaused() +{ + playButton->setPixmap( QPixmap( play_xpm ) ); + slider->setEnabled( true ); +} + +void SimpleUI::slotTimeout() +{ + if (napp->player()->current() && !slider->currentlyPressed()) + { + positionLabel->setText( napp->player()->lengthString() ); + slider->setRange( 0, (int)napp->player()->getLength() / 1000 ); + slider->setValue( (int)napp->player()->getTime() / 1000 ); + } +} + +void SimpleUI::slotSkipTo( int sec ) +{ + napp->player()->skipTo( sec * 1000 ); +} + +void SimpleUI::slotChanged() +{ + propertiesDialog->setPlayObject( napp->player()->current(), + napp->player()->engine()->playObject() ); +} + +void SimpleUI::slotContextMenu( const QPoint &pos ) +{ + contextMenu->exec( pos ); +} + +void SimpleUI::slotSliderMoved( int sec ) +{ + if (napp->player()->current()) + positionLabel->setText( napp->player()->lengthString( sec * 1000 ) ); +} + +void SimpleUI::slotVolumeChanged( int volume ) +{ + volumeLabel->setText( QString::number( volume ) + "%" ); + volumeSlider->setValue( 100 - volume ); +} + +void SimpleUI::slotVolumeFrame() +{ + if (volumeFrame->isVisible()) + { + volumeFrame->hide(); + } + else + { + int x = (volumeButton->width() - volumeFrame->width()) / 2; + int y = -(volumeFrame->height() + 5); + + QPoint point( volumeButton->mapToGlobal( QPoint( x, y ) ) ); + QRect deskRect = KGlobalSettings::desktopGeometry( point ); + + bool bottom = (point.y() + volumeFrame->height()) > (deskRect.y() + deskRect.height()); + bool right = (point.x() + volumeFrame->width()) > (deskRect.x() + deskRect.width()); + + volumeFrame->move( + right ? (deskRect.x() + deskRect.width()) - volumeFrame->width() : ( point.x() < 0 ? 0 : point.x() ), + bottom ? (deskRect.y() + deskRect.height()) - volumeFrame->height() : ( point.y() < 0 ? 0 : point.y() ) ); + volumeFrame->show(); + } +} + +void SimpleUI::slotVolumeSliderMoved( int slider ) +{ + napp->player()->setVolume( 100 - slider ); +} + +#include "userinterface.moc" diff --git a/noatun/modules/simple/userinterface.h b/noatun/modules/simple/userinterface.h new file mode 100644 index 00000000..c545fd2c --- /dev/null +++ b/noatun/modules/simple/userinterface.h @@ -0,0 +1,80 @@ +/* + This file is part of KDE/aRts (Noatun) - xine integration + Copyright (C) 2002 Ewald Snel <ewald@rambo.its.tudelft.nl> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. +*/ + +#ifndef __USERINTERFACE_H +#define __USERINTERFACE_H + +#include <noatun/controls.h> +#include <noatun/plugin.h> +#include <noatun/video.h> +#include <kaction.h> +#include <kmainwindow.h> +#include <kmedia2.h> +#include <qevent.h> +#include <qlabel.h> +#include <qpopupmenu.h> +#include <qpushbutton.h> +#include <qvbox.h> +#include "propertiesdialog.h" + + +class SimpleUI : public KMainWindow, public UserInterface +{ + Q_OBJECT + +public: + SimpleUI(); + ~SimpleUI(); + +protected: + void setupActions(); + void setupCentralWidget(); + + virtual void closeEvent( QCloseEvent * ); + virtual void dragEnterEvent( QDragEnterEvent *event ); + virtual void dropEvent( QDropEvent *event ); + +public slots: + void slotAdaptSize( int width, int height ); + void slotPlaying(); + void slotStopped(); + void slotPaused(); + void slotTimeout(); + void slotSkipTo( int sec ); + void slotChanged(); + void slotContextMenu( const QPoint &pos ); + +private slots: + void slotSliderMoved( int sec ); + void slotVolumeSliderMoved( int volume ); + void slotVolumeFrame(); + void slotVolumeChanged( int volume ); + void showMenubar(); + void showStatusbar(); + +private: + PropertiesDialog *propertiesDialog; + QPopupMenu *contextMenu; + QPushButton *stopButton; + QPushButton *playButton; + QPushButton *volumeButton; + QVBox *volumeFrame; + QLabel *volumeLabel; + QLabel *positionLabel; + VideoFrame *video; + L33tSlider *volumeSlider; + L33tSlider *slider; + int extra_width; + int extra_height; + KToggleAction *menubarAction; + KToggleAction *statusbarAction; +}; + +#endif diff --git a/noatun/modules/simple/volume.xpm b/noatun/modules/simple/volume.xpm new file mode 100644 index 00000000..fa240d42 --- /dev/null +++ b/noatun/modules/simple/volume.xpm @@ -0,0 +1,21 @@ +/* XPM */ +const char * volume_xpm[] = { +"16 16 2 1", +" c None", +". c #000000", +" ", +" ", +" . .. ", +" .. . . ", +" .... . . ", +" .... . . ", +" .. .. . ", +" . ... . ", +" .... . ", +" ..... . ", +" ...... . ", +" ....... . ", +" ........ . ", +" ............ ", +" ", +" "}; diff --git a/noatun/modules/splitplaylist/LICENSE b/noatun/modules/splitplaylist/LICENSE new file mode 100644 index 00000000..8f9bdefc --- /dev/null +++ b/noatun/modules/splitplaylist/LICENSE @@ -0,0 +1,124 @@ +The "Artistic License" + + Preamble + + The intent of this document is to state the conditions under which a + Package may be copied, such that the Copyright Holder maintains some + semblance of artistic control over the development of the package, + while giving the users of the package the right to use and distribute + the Package in a more-or-less customary fashion, plus the right to + make reasonable modifications. + + Definitions + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes of the + Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing this + Package. + + "Reasonable copying fee" is whatever you can justify on the basis + of media cost, duplication charges, time of people involved, and so + on. (You will not be required to justify it to the Copyright + Holder, but only to the computing community at large as a market + that must bear the fee.) + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. It + also means that recipients of the item may redistribute it under + the same conditions they received it. + + 1. You may make and give away verbatim copies of the source form of + the Standard Version of this Package without restriction, provided + that you duplicate all of the original copyright notices and + associated disclaimers. + 2. You may apply bug fixes, portability fixes and other modifications + derived from the Public Domain or from the Copyright Holder. A + Package modified in such a way shall still be considered the + Standard Version. + 3. You may otherwise modify your copy of this Package in any way, + provided that you insert a prominent notice in each changed file + stating how and when you changed that file, and provided that you + do at least ONE of the following: + + a. place your modifications in the Public Domain or otherwise make + them Freely Available, such as by posting said modifications to + Usenet or an equivalent medium, or placing the modifications on a + major archive site such as uunet.uu.net, or by allowing the + Copyright Holder to include your modifications in the Standard + Version of the Package. + b. use the modified Package only within your corporation or + organization. + c. rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and + provide a separate manual page for each non-standard executable + that clearly documents how it differs from the Standard Version. + d. make other distribution arrangements with the Copyright Holder. + + You may distribute the programs of this Package in object code or + executable form, provided that you do at least ONE of the following: + + a. distribute a Standard Version of the executables and library + files, together with instructions (in the manual page or + equivalent) on where to get the Standard Version. + b. accompany the distribution with the machine-readable source of the + Package with your modifications. + c. give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + d. make other distribution arrangements with the Copyright Holder. + + You may charge a reasonable copying fee for any distribution of this + Package. You may charge any fee you choose for support of this + Package. You may not charge a fee for this Package itself. However, + you may distribute this Package in aggregate with other (possibly + commercial) programs as part of a larger (possibly commercial) + software distribution provided that you do not advertise this Package + as a product of your own. You may embed this Package's interpreter + within an executable of yours (by linking); this shall be construed as + a mere form of aggregation, provided that the complete Standard + Version of the interpreter is so embedded. + + The scripts and library files supplied as input to or produced as + output from the programs of this Package do not automatically fall + under the copyright of this Package, but belong to whomever generated + them, and may be sold commercially, and may be aggregated with this + Package. If such scripts or library files are aggregated with this + Package via the so-called "undump" or "unexec" methods of producing a + binary executable image, then distribution of such an image shall + neither be construed as a distribution of this Package nor shall it + fall under the restrictions of Paragraphs 3 and 4, provided that you + do not represent such an executable image as a Standard Version of + this Package. + + C subroutines (or comparably compiled subroutines in other + languages) supplied by you and linked into this Package in order to + emulate subroutines and variables of the language defined by this + Package shall not be considered part of this Package, but are the + equivalent of input as in Paragraph 6, provided these subroutines do + not change the language in any way that would cause it to fail the + regression tests for the language. + + Aggregation of this Package with a commercial distribution is always + permitted provided that the use of this Package is embedded; that is, + when no overt attempt is made to make this Package's interfaces + visible to the end user of the commercial distribution. Such use shall + not be construed as a distribution of this Package. + + The name of the Copyright Holder may not be used to endorse or + promote products derived from this software without specific prior + written permission. + + THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End diff --git a/noatun/modules/splitplaylist/Makefile.am b/noatun/modules/splitplaylist/Makefile.am new file mode 100644 index 00000000..4ea511ac --- /dev/null +++ b/noatun/modules/splitplaylist/Makefile.am @@ -0,0 +1,17 @@ +INCLUDES= -I$(top_srcdir)/noatun/library $(all_includes) +kde_module_LTLIBRARIES = noatun_splitplaylist.la + +noatun_splitplaylist_la_SOURCES = splitplaylist.cpp playlist.cpp view.cpp find.cpp + +noatun_splitplaylist_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_splitplaylist_la_LIBADD = $(LIB_KIO) $(top_builddir)/noatun/library/libnoatun.la + +noatun_splitplaylist_la_METASOURCES = AUTO + +noinst_HEADERS = playlist.h view.h find.h + +noatun_modules_splitplaylist_DATA = splitplaylist.plugin +noatun_modules_splitplaylistdir = $(kde_datadir)/noatun + +rc_DATA = splui.rc +rcdir = $(kde_datadir)/noatun diff --git a/noatun/modules/splitplaylist/find.cpp b/noatun/modules/splitplaylist/find.cpp new file mode 100644 index 00000000..b6e196d9 --- /dev/null +++ b/noatun/modules/splitplaylist/find.cpp @@ -0,0 +1,63 @@ +#include "find.h" +#include <qlayout.h> +#include <kcombobox.h> +#include <qpushbutton.h> +#include <qcheckbox.h> +#include <klocale.h> + +Finder::Finder(QWidget *parent) : KDialogBase(parent, 0, false, i18n("Find"), Close | User1, User1, false, KGuiItem(i18n("&Find"),"find")) +{ + QWidget *mainWidget = new QWidget(this); + mainWidget->setMinimumWidth(320); + setMainWidget(mainWidget); + + QGridLayout *layout=new QGridLayout(mainWidget); + layout->setSpacing(KDialog::spacingHint()); + + mText=new KHistoryCombo(mainWidget); + mText->setMaxCount(10); + + mText->setFocus(); + + mRegexp=new QCheckBox(i18n("&Regular expression"), mainWidget); + mBackwards=new QCheckBox(i18n("Find &backwards"), mainWidget); + + layout->addMultiCellWidget(mText, 0, 0, 0, 1); + layout->addWidget(mRegexp, 1, 0); + layout->addWidget(mBackwards, 1, 1); + + connect(this, SIGNAL(user1Clicked()), SLOT(clicked())); + + connect(mText, SIGNAL(activated(int)), SLOT(clicked())); + connect(mText, SIGNAL(textChanged(const QString &)), SLOT(textChanged(const QString &))); + + enableButton(User1, false); +} + +void Finder::textChanged(const QString &text) { + enableButton(User1, !text.isEmpty()); +} + +bool Finder::regexp() const +{ + return mRegexp->isChecked(); +} + +bool Finder::isForward() const +{ + return !mBackwards->isChecked(); +} + +void Finder::clicked() +{ + mText->addToHistory( mText->currentText() ); + emit search(this); +} + +QString Finder::string() const +{ + return mText->currentText(); +} + + +#include "find.moc" diff --git a/noatun/modules/splitplaylist/find.h b/noatun/modules/splitplaylist/find.h new file mode 100644 index 00000000..a4791339 --- /dev/null +++ b/noatun/modules/splitplaylist/find.h @@ -0,0 +1,33 @@ +#ifndef FIND_H +#define FIND_H + +#include <kdialogbase.h> + +class KHistoryCombo; +class QCheckBox; +class QPushButton; + +class Finder : public KDialogBase +{ +Q_OBJECT +public: + Finder(QWidget *parent); + + bool regexp() const; + bool isForward() const; + + QString string() const; +signals: + void search(Finder *); + +public slots: + void textChanged(const QString &); + void clicked(); + +private: + KHistoryCombo *mText; + QCheckBox *mRegexp, *mBackwards; +}; + +#endif + diff --git a/noatun/modules/splitplaylist/playlist.cpp b/noatun/modules/splitplaylist/playlist.cpp new file mode 100644 index 00000000..57d6fb48 --- /dev/null +++ b/noatun/modules/splitplaylist/playlist.cpp @@ -0,0 +1,281 @@ +#include "playlist.h" +#include "view.h" +#include <noatun/player.h> + +#include <kapplication.h> +#include <krandomsequence.h> +#include <kdebug.h> +#include <kwin.h> + +#include <kiconloader.h> + +SplitPlaylist *SplitPlaylist::Self=0; + +SplitPlaylist::SplitPlaylist() + : Playlist(0, "SplitPlaylist"), Plugin(), mExiting(false) +{ + Self=this; +} + +void SplitPlaylist::init() +{ + view=new View(this); // 195 + connect(view->listView(), SIGNAL(executed(QListViewItem*)), SLOT(listItemSelected(QListViewItem*))); + connect(view, SIGNAL(shown()), SIGNAL(listShown())); + connect(view, SIGNAL(hidden()), SIGNAL(listHidden())); + + view->init(); // 1000 +} + +SplitPlaylist::~SplitPlaylist() +{ + mExiting=true; + delete view; +} + +void SplitPlaylist::reset() +{ + SafeListViewItem *i; + setCurrent(i=static_cast<SafeListViewItem*>(view->listView()->firstChild()), false); + if (i && !i->isOn()) + next(false); +} + +PlaylistItem SplitPlaylist::next() +{ + return next(true); +} + +PlaylistItem SplitPlaylist::next(bool play) +{ + PlaylistItem nextItem; + + if (napp->player()->loopStyle() == Player::Random) + { + // Ignore all this order stuff and select a random item + List *lview = view->listView(); + + if (lview->childCount()) + { + SafeListViewItem *slvi = static_cast<SafeListViewItem*>( + lview->itemAtIndex(KApplication::random() % lview->childCount()) + ); + nextItem = PlaylistItem(slvi); + } + else + { + nextItem = 0; + } + } + else + { + if(!current()) + { + nextItem = static_cast<SafeListViewItem*>(static_cast<SafeListViewItem*>(getFirst().data())); + } + else + { + nextItem = static_cast<SafeListViewItem*>( + static_cast<SafeListViewItem*>(current().data())->itemBelow()); + } + } + + if (!nextItem) // don't set a null-item as current item + { + return 0; +// nextItem = static_cast<SafeListViewItem*>(static_cast<SafeListViewItem*>(getFirst().data())); + } + + PlaylistItem oldCurrent = currentItem; + setCurrent(nextItem, play); + + // Hack for back button on randomized play + if (oldCurrent) + randomPrevious = oldCurrent; + + if (currentItem) + if (!static_cast<SafeListViewItem*>(currentItem.data())->isOn()) + return next(play); + + return currentItem; +} + +PlaylistItem SplitPlaylist::current() +{ + return currentItem; +} + +PlaylistItem SplitPlaylist::previous() +{ + if (napp->player()->loopStyle() == Player::Random && randomPrevious) + { + List *list = view->listView(); + // check if the item still exists (hackitude: 50%) + bool found=false; + for (QListViewItem *i = list->firstChild(); i; i = i->nextSibling()) + { + if (i == static_cast<SafeListViewItem*>(randomPrevious.data())) + { + found = true; + break; + } + } + + if (found) + { + // setCurrent modified randomPrevious, and setCurrent is pass-by-reference + PlaylistItem prev = randomPrevious; + + setCurrent(prev); + return currentItem; + } + } + // there's a possibility that I will fall out to here + // from the above branch + + PlaylistItem nextItem; + if(!current()) + { + nextItem = static_cast<SafeListViewItem*>(static_cast<SafeListViewItem*>(getFirst().data())); + } + else + { + nextItem = static_cast<SafeListViewItem*>( + static_cast<SafeListViewItem*>(current().data())->itemAbove()); + } + if (!nextItem) // don't set a null-item as current item + return 0; + + setCurrent(nextItem); + + if (currentItem) + if (!static_cast<SafeListViewItem*>(currentItem.data())->isOn()) + return previous(); + + return currentItem; +} + +PlaylistItem SplitPlaylist::getFirst() const +{ + return static_cast<SafeListViewItem*>(view->listView()->firstChild()); +} + +PlaylistItem SplitPlaylist::getAfter(const PlaylistItem &item) const +{ + if (item) + return static_cast<SafeListViewItem*>(static_cast<const SafeListViewItem*>(item.data())->nextSibling()); + return 0; +} + +bool SplitPlaylist::listVisible() const +{ + KWin::WindowInfo info = KWin::windowInfo(view->winId()); + return !(info.hasState(NET::Shaded) || info.hasState(NET::Hidden) || !info.valid() || !info.isOnCurrentDesktop()); +} + +void SplitPlaylist::showList() +{ + KWin::setOnDesktop(view->winId(), KWin::currentDesktop()); + view->show(); + if (view->isMinimized()) + view->showNormal(); + view->raise(); +} + +void SplitPlaylist::hideList() +{ + view->hide(); +} + +void SplitPlaylist::clear() +{ + view->listView()->clear(); +} + +void SplitPlaylist::addFile(const KURL &file, bool play) +{ + view->addFile(file, play); +} + +void SplitPlaylist::setCurrent(const PlaylistItem &i) +{ + setCurrent(i, true); +} + +void SplitPlaylist::setCurrent(const PlaylistItem &i, bool emitC) +{ + randomPrevious = PlaylistItem(); + emitC = emitC && currentItem; + if (!i) + { + currentItem=0; + } + else + { + // remove the old icon + SafeListViewItem *now=static_cast<SafeListViewItem*>(current().data()); + if (now) + now->setPixmap(0, QPixmap()); + + QRect rect(view->listView()->itemRect(static_cast<SafeListViewItem*>(current().data()))); + rect.setWidth(view->listView()->viewport()->width()); + currentItem=i; + view->listView()->viewport()->repaint(rect,true); + + view->listView()->ensureItemVisible(static_cast<SafeListViewItem*>(current().data())); + QRect currentRect= view->listView()->itemRect(static_cast<SafeListViewItem*>(current().data())); + view->listView()->viewport()->repaint(currentRect); + + now=static_cast<SafeListViewItem*>(current().data()); + if(now) + now->setPixmap(0, ::SmallIcon("noatunplay")); + } + + if (emitC && !exiting()) + emit playCurrent(); +} + +void SplitPlaylist::remove(const PlaylistItem &) +{ +// delete i; +} + +void SplitPlaylist::listItemSelected(QListViewItem *i) +{ + setCurrent(PlaylistItem(static_cast<SafeListViewItem*>(i)), false); + emit playCurrent(); +} + +void SplitPlaylist::randomize() +{ + // turning off sorting is necessary + // otherwise, the list will get randomized and promptly sorted again + view->setSorting(false); + List *lview = view->listView(); + // eeeeevil :) + QPtrList<void> list; + QPtrList<QListViewItem> items; + for(int i = 0; i < lview->childCount(); i++) + { + list.append( (void*) i ); + items.append( lview->itemAtIndex( i ) ); + } + + KRandomSequence seq; + seq.randomize( &list ); + + for(int i = 0; i < lview->childCount(); i++) + { + items.take()->moveItem(lview->itemAtIndex((long) list.take())); + } + + setCurrent(currentItem, false); +} + +void SplitPlaylist::sort() +{ + view->setSorting(true); + setCurrent(currentItem, false); +} + +#include "playlist.moc" diff --git a/noatun/modules/splitplaylist/playlist.h b/noatun/modules/splitplaylist/playlist.h new file mode 100644 index 00000000..04cb648d --- /dev/null +++ b/noatun/modules/splitplaylist/playlist.h @@ -0,0 +1,98 @@ +#ifndef PLAYLIST_H +#define PLAYLIST_H + +#include <noatun/playlist.h> +#include <noatun/plugin.h> + +/* +class PlaylistItem +{ + PlaylistItem(const KURL &u=0); + virtual ~PlaylistItem(); + + QString title() const; + virtual void setTitle(const QString &t); + + KURL url() const; + virtual void setUrl(const KURL &u); + + int length() const; + virtual void setLength(int l); +}; +*/ +class SafeListViewItem; +class View; +class List; +class QListViewItem; + +class SplitPlaylist : public Playlist, public Plugin +{ +Q_OBJECT +friend class SafeListViewItem; +friend class List; +public: + SplitPlaylist(); + ~SplitPlaylist(); + + /** + * go to the front + **/ + virtual void reset(); + + virtual void clear(); + virtual void addFile(const KURL&, bool play=false); + /** + * Cycle everthing through forward + **/ + virtual PlaylistItem next(); + PlaylistItem next(bool play); + /** + * return the one that might/should be playing now + **/ + virtual PlaylistItem current(); + /** + * Cycle through backwards + **/ + virtual PlaylistItem previous(); + + virtual PlaylistItem getFirst() const; + virtual PlaylistItem getAfter(const PlaylistItem &item) const; + + virtual bool listVisible() const; + virtual void init(); + + virtual Playlist *playlist() + { return this; } + + static SplitPlaylist *SPL() { return Self; } + inline bool exiting() const { return mExiting; } +public slots: + virtual void showList(); + virtual void hideList(); + virtual void remove(const PlaylistItem&); + virtual void sort(); + + +public slots: + void setCurrent(const PlaylistItem &, bool emitC); + void setCurrent(const PlaylistItem &); + + void listItemSelected(QListViewItem*); + + void randomize(); + +private: + PlaylistItem currentItem, randomPrevious; + +signals: + void play(PlaylistItem*); + +private: + bool mExiting; // HACK HACK HACK HACK!!! + View *view; +// QRect currentRect; + static SplitPlaylist *Self; +}; + + +#endif diff --git a/noatun/modules/splitplaylist/splitplaylist.cpp b/noatun/modules/splitplaylist/splitplaylist.cpp new file mode 100644 index 00000000..e86a3921 --- /dev/null +++ b/noatun/modules/splitplaylist/splitplaylist.cpp @@ -0,0 +1,13 @@ +#include <kcmodule.h> + +#include "playlist.h" + + +extern "C" +{ + KDE_EXPORT Plugin *create_plugin() + { + return new SplitPlaylist(); + } +} + diff --git a/noatun/modules/splitplaylist/splitplaylist.plugin b/noatun/modules/splitplaylist/splitplaylist.plugin new file mode 100644 index 00000000..3474dbed --- /dev/null +++ b/noatun/modules/splitplaylist/splitplaylist.plugin @@ -0,0 +1,118 @@ +Filename=noatun_splitplaylist.la +Author=Charles Samuels +Site=http://www.derkarl.org/noatun +Email=charles@kde.org +Type=playlist +License=Artistic +Name=Split Playlist +Name[af]=Skei Liedjielys +Name[az]=Çalma Siyahısını Ayır +Name[bn]=বিভাজিত সঙ্গীত-তালিকা +Name[br]=Didrochañ ar roll tonioù +Name[bs]=Podijeli playlistu +Name[ca]=Dividir la selecció de peces +Name[cs]=Oddělovací seznam skladeb +Name[cy]=Hollti Rhestr Chwarae +Name[da]=Opdelt spilleliste +Name[de]=Aufgeteilte Wiedergabeliste +Name[el]=Split λίστα αναπαραγωγής +Name[eo]=Dividu ludliston +Name[es]=Lista de reproducción dividida +Name[et]=Poolitatud nimekiri +Name[eu]=Erreprodukzio-zerrenda zatitu +Name[fa]=شکافتن فهرست پخش +Name[fi]=Jaettu soittolista +Name[fr]=Liste de lecture découpée +Name[ga]=Roinn Seinmliosta +Name[gl]=Dividir Lista de Reproducións +Name[hi]=स्प्लिट प्लेलिस्ट +Name[hr]=Razdvoji listu pjesama +Name[hu]=Osztott lejátszási lista +Name[is]=Tvískiptur lagalisti +Name[it]=Split playlist +Name[km]=ពុះបញ្ជីចាក់ +Name[ko]=재생 목록 나누기 +Name[lt]=Suskaidytas gaidaraštis +Name[lv]=Dalīt Plejlistu +Name[mk]=Раздели листа со нумери +Name[mt]=Playlist Maqsum +Name[nb]=Splittet spilleliste +Name[nds]=Opdeelt Afspeellist +Name[ne]=बजाउने सूची विभाजन गर्नुहोस् +Name[nl]=Gesplitste speellijst +Name[nn]=Delt speleliste +Name[pa]=ਸੰਗੀਤ-ਸੂਚੀ ਵੰਡੋ +Name[pl]=Zwykła lista odtwarzania +Name[pt]=Lista de Músicas Split +Name[pt_BR]=A lista de reprodução dividida +Name[ro]=Împarte lista de redare +Name[ru]=Разбить список произведений +Name[se]=Juhkkojuvvon čuojahanlistu +Name[sk]=Rozdeľovací playlist +Name[sl]=Razdeli predvajalni seznam +Name[sr]=Split листа нумера +Name[sr@Latn]=Split lista numera +Name[sv]=Delad spellista +Name[ta]=பாடல் பட்டியலை பிரி +Name[tg]=Рӯйхати бозикуниҳои Пора +Name[th]=แยกรายการเล่น +Name[tr]=Ayrılmış Parça Listesi +Name[uk]=Розбитий список композицій +Name[ven]=Mutevhe wa tshitambi tshau phadalala +Name[xh]=Chaka uluhlu lomdlalo +Name[zh_CN]=分割播放列表 +Name[zh_HK]=分割播放清單 +Name[zh_TW]=分割播放清單 +Name[zu]=Qhekeza uluhlu lomdlalo +Comment=The inaccurately titled playlist +Comment[bg]=Неподреден списък за поддръжка на файлове за изпълнение +Comment[bs]=Neispravno naslovljena playlista +Comment[ca]=Llista de reproducció titulada inexactament +Comment[cs]=Nesprávně pojmenovaný seznam skladeb +Comment[cy]=Y rhestr chwarae efo'r teitl gwallus +Comment[da]=Den upræcist benævnte spilleliste +Comment[de]=Die ungenaue Wiedergabeliste +Comment[el]=Η ανακριβώς ονομαζόμενη λίστα αναπαραγωγής +Comment[eo]=La neĝuste titolita ludlisto +Comment[es]=La lista de reproducción con título inexacto +Comment[et]=Ebaadekvaatselt nimetatud nimekiri +Comment[eu]=Zehatza ez den izenburudun erreprodukzio-zerrenda +Comment[fa]=فهرست پخش که با بیدقتی عنوانبندی شده است +Comment[fi]=Epätarkasti nimetty soittolista +Comment[fr]=La liste de lecture mal nommée +Comment[ga]=An seinmliosta le teideal neamhchruinn +Comment[gl]=A lista de reprodución con títulos inexactos +Comment[he]=רשימת הניגון עם השם הלא מדוייק +Comment[hi]=गलत शीर्षक युक्त गीत-सूची +Comment[hu]=Nem pontosan feliratozott lejátszási lista +Comment[is]=Lagalistinn með ónákvæma nafnið +Comment[it]=Playlist con i titoli non accurati +Comment[ja]=不正確なタイトルのプレイリスト (実際に分割はしません) +Comment[kk]=Дұрыс аталмаған орындау тізімі +Comment[km]=បញ្ជីចាក់ដែលមានចំណងជើងមិនសុក្រឹត +Comment[ko]=정확하지 않게 제목이 붙은 재생 목록 +Comment[lt]=Netiksliai pavadintas gaidaraštis +Comment[mk]=Неточно насловена листа со нумери +Comment[nb]=Den unøyaktig navngitte spillelisten +Comment[nds]=De nich nau nöömte Afspeellist +Comment[ne]=अशुद्ध तरिकाले शीर्षक दिइएको बजाउने सूची +Comment[nl]=De inaccuraat getitelde afspeellijst +Comment[nn]=Spelelista med unøyaktig namn +Comment[pl]=Zwykła, prosta lista odtwarzania +Comment[pt]=A lista mal intitulada +Comment[pt_BR]=A lista de reprodução erroneamente intitulada +Comment[ro]=Listă de redare incorect denumită +Comment[ru]=Список песен с неточными названиями +Comment[sk]=Nesprávne pomenovaný playlist +Comment[sl]=Nenatančno naslovljen predvajalni seznam +Comment[sr]=Непрецизно названа листа нумера +Comment[sr@Latn]=Neprecizno nazvana lista numera +Comment[sv]=Den felaktigt benämnda spellistan +Comment[ta]=பிழையாக தலைப்பிட்ட பாடல் பட்டியல் +Comment[tg]=Рӯйхати бозикуниҳои бетартибона номгузошташуда +Comment[th]=รายการเล่นที่มีชื่อไม่ถูกต้อง +Comment[tr]=Düzensiz başlıklı çalma listesi +Comment[uk]=Неохайно підписаний список композицій +Comment[zh_CN]=命名不确切的播放列表 +Comment[zh_HK]=未有正確命名的播放清單 +Comment[zh_TW]=未精確命名的撥放清單 diff --git a/noatun/modules/splitplaylist/splui.rc b/noatun/modules/splitplaylist/splui.rc new file mode 100644 index 00000000..2b0b0a32 --- /dev/null +++ b/noatun/modules/splitplaylist/splui.rc @@ -0,0 +1,34 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui name="SPL" version="1"> + +<MenuBar> + +<Menu name="file"> + <Action name="add_files" /> + <Action name="add_dir" /> +</Menu> + +<Menu name="edit"> + <Action name="delete" /> + <Action name="clear" /> + <Separator /> + <Action name="shuffle" /> +</Menu> + +</MenuBar> + +<ToolBar noMerge="1" name="mainToolBar"> + <text>Main Toolbar</text> + <Action name="add_files" /> + <Action name="add_dir" /> + <Separator /> + <Action name="delete" /> + <Separator /> + <Action name="file_open" /> + <Action name="file_save" /> + <Action name="file_save_as" /> + <Separator /> + <Action name="edit_find" /> +</ToolBar> + +</kpartgui> diff --git a/noatun/modules/splitplaylist/view.cpp b/noatun/modules/splitplaylist/view.cpp new file mode 100644 index 00000000..7f5584f9 --- /dev/null +++ b/noatun/modules/splitplaylist/view.cpp @@ -0,0 +1,1009 @@ +/** + * Copyright (c) 2000-2004 Charles Samuels <charles@kde.org> + * 2000-2001 Neil Stevens <neil@qualityassistant.com> + * + * Copyright (c) from the patches of: + * 2001 Klas Kalass <klas.kalass@gmx.de> + * 2001 Anno v. Heimburg <doktor.dos@gmx.de> + **/ + + +// Abandon All Hope, Ye Who Enter Here + +#include <qdragobject.h> +#include <qheader.h> +#include <qlayout.h> +#include <qmap.h> +#include <qregexp.h> +#include <qtextstream.h> +#include <qpainter.h> + +#include <kaction.h> +#include <kdebug.h> +#include <kfiledialog.h> +#include <kfileitem.h> +#include <kio/job.h> +#include <kio/netaccess.h> +#include <klocale.h> +#include <kmenubar.h> +#include <ksimpleconfig.h> +#include <kstandarddirs.h> +#include <kstdaction.h> +#include <kedittoolbar.h> +#include <kurldrag.h> +#include <kmessagebox.h> + +#include <noatun/app.h> +#include <noatun/player.h> +#include <noatun/playlistsaver.h> + +#include "playlist.h" +#include "view.h" +#include "find.h" + +#define SPL SplitPlaylist::SPL() + +SafeListViewItem::SafeListViewItem(QListView *parent, QListViewItem *after, const KURL &text) + : QCheckListItem(parent,0, QCheckListItem::CheckBox), PlaylistItemData(), removed(false) +{ + addRef(); + setUrl(text); + + static_cast<KListView*>(parent)->moveItem(this, 0, after); + setOn(true); + + // is this really needed, it makes the listview too wide for me :( +// setText(0,text.filename()); + + // if (!isDownloaded()) setText(1, "0%"); + +// mProperties.setAutoDelete(true); + + if (!streamable() && enqueue(url())) + setUrl(KURL(localFilename())); + + PlaylistItemData::added(); +} + +SafeListViewItem::SafeListViewItem(QListView *parent, QListViewItem *after, const QMap<QString,QString> &props) + : QCheckListItem(parent, 0, QCheckListItem::CheckBox), removed(false) +{ + addRef(); + + setOn(true); + + // A version of setProperty that assumes a key is unique, + // and doesn't call modified for every new key. + // Ugly, but this function is a very hot path on playlist loading + for (QMap<QString,QString>::ConstIterator i=props.begin(); i!=props.end(); ++i ) + { + QString n = i.key(); + QString val = i.data(); + + if (n=="enabled") + { + setOn(val!="false" && val!="0"); + } + else + { + Property p={n,val}; + mProperties += p; + } + } + + static_cast<KListView*>(parent)->moveItem(this, 0, after); + modified(); + + if (!streamable() && enqueue(url())) + { + KURL u; + u.setPath(localFilename()); + + setUrl(u); + } + PlaylistItemData::added(); +} + +SafeListViewItem::~SafeListViewItem() +{ + remove(); +} + +QString SafeListViewItem::file() const +{ + return localFilename(); +} + +static void pad(QString &str) +{ + int len=str.length(); + int at = 0; + int blocklen=0; + + static const int paddingsize=12; + + // not static for reason + const QChar chars[paddingsize] = + { + QChar('0'), QChar('0'), QChar('0'), QChar('0'), + QChar('0'), QChar('0'), QChar('0'), QChar('0'), + QChar('0'), QChar('0'), QChar('0'), QChar('0') + }; + + for (int i=0; i < len; i++) + { + if (str[i].isNumber()) + { + if (!blocklen) + at = i; + blocklen++; + } + else if (blocklen) + { + int pads=paddingsize; + pads -= blocklen; + str.insert(at, chars, pads); + i += pads; + blocklen = 0; + } + } + if (blocklen) + { + int pads=paddingsize; + pads -= blocklen; + str.insert(at, chars, pads); + } +} + +int SafeListViewItem::compare(QListViewItem * i, int col, bool) const +{ + QString text1 = text(col); + QString text2 = i->text(col); + + pad(text1); + pad(text2); + return text1.compare(text2); +} + +QString SafeListViewItem::property(const QString &n, const QString &def) const +{ + for (QValueList<Property>::ConstIterator i=mProperties.begin(); i != mProperties.end(); ++i) + { + if ((*i).key==n) + return (*i).value; + } + if (n=="enabled") + { + if (isOn()) return "true"; + else return "false"; + } + return def; +} + +void SafeListViewItem::setProperty(const QString &n, const QString &val) +{ + if (n=="enabled") + { + setOn(val!="false" && val!="0"); + } + else + { + if ( property(n,"") == val ) + { +// kdDebug(66666) << "SafeListViewItem::setProperty(), property unchanged!" << endl; + return; + } + + clearProperty(n); + Property p={n,val}; + mProperties += p; + } + modified(); +} + +void SafeListViewItem::clearProperty(const QString &n) +{ + if (n=="enabled") + { + setOn(true); + modified(); + return; + } + + for (QValueList<Property>::Iterator i=mProperties.begin(); i != mProperties.end(); ++i) + { + if ((*i).key==n) + { + mProperties.remove(i); + modified(); + break; + } + } +} + +QStringList SafeListViewItem::properties() const +{ + QStringList list; + for (QValueList<Property>::ConstIterator i=mProperties.begin(); i != mProperties.end(); ++i) + list += (*i).key; + list += "enabled"; + return list; +} + +bool SafeListViewItem::isProperty(const QString &n) const +{ + for (QValueList<Property>::ConstIterator i=mProperties.begin(); i != mProperties.end(); ++i) + { + if ((*i).key==n) + return true; + } + return n=="enabled"; +} + +void SafeListViewItem::downloaded(int percent) +{ + if (!removed) + setText(1, QString::number(percent)+'%'); +} + +void SafeListViewItem::downloadTimeout() +{ + if (!removed) + setText(1, "-"); +} + +void SafeListViewItem::downloadFinished() +{ + if (!removed) + setText(1, ""); +} + +void SafeListViewItem::modified() +{ + bool widthChangeNeeded = false; + + if (text(0)!=title()) + { + setText(0, title()); + widthChangeNeeded = true; + } + + if (isDownloaded() && length()!=-1 && text(1)!=lengthString()) + { + setText(1, lengthString()); + widthChangeNeeded = true; + } + + if (widthChangeNeeded) + widthChanged(-1); + + PlaylistItemData::modified(); +} + +void SafeListViewItem::stateChange(bool s) +{ + // if you uncheck this, uncheck thet others that + // are selected too + + QPtrList<QListViewItem> list=SPL->view->listView()->selectedItems(); + + // but not if I'm not selected + if (list.containsRef(this)) + for (QListViewItem *i=list.first(); i != 0; i=list.next()) + static_cast<QCheckListItem*>(i)->setOn(s); + else + QCheckListItem::stateChange(s); +} + +void SafeListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align) +{ + QCheckListItem::paintCell(p, cg, column, width, align); + + if (SPL->current() == this) + { + p->save(); + p->setRasterOp(XorROP); + p->fillRect(0, 0, width, height(), QColor(255,255,255)); + + p->restore(); + } +} + +void SafeListViewItem::remove() +{ + removed=true; + if (napp->player()->current()==this && !itemAbove() && !itemBelow()) + { + napp->player()->stop(); + SPL->setCurrent(0); + } + else if (napp->player()->current()==this) + { +// SPL->setCurrent(0); +// napp->player()->playCurrent(); + + if (napp->player()->isPlaying() && !SPL->exiting()) + napp->player()->forward(); + else + SPL->setCurrent(0); + } + + if (listView()) + { + if (SPL->currentItem==this) // just optimizing for least unreadably + SPL->setCurrent(static_cast<SafeListViewItem*>(itemBelow())); + + listView()->takeItem(this); + } + else if (SPL->currentItem==this) + { + SPL->setCurrent(0); + } + + dequeue(); + PlaylistItemData::removed(); +} + +List::List(View *parent) + : KListView(parent), recursiveAddAfter(0), listJob(0) +{ + addColumn(i18n("File")); + addColumn(i18n("Time")); + setAcceptDrops(true); + setSorting(-1); + setDropVisualizer(true); + setDragEnabled(true); + setItemsMovable(true); + setSelectionMode(QListView::Extended); + connect(this, SIGNAL(dropped(QDropEvent*, QListViewItem*)), SLOT(dropEvent(QDropEvent*, QListViewItem*))); + connect(this, SIGNAL(moved()), SLOT(move())); + connect(this, SIGNAL(aboutToMove()), parent, SLOT(setNoSorting())); + connect(this, SIGNAL(deleteCurrentItem()), parent, SLOT(deleteSelected())); +} + +List::~List() +{ +} + +void List::move() +{ + emit modified(); +} + +bool List::acceptDrag(QDropEvent *event) const +{ + return KURLDrag::canDecode(event) || KListView::acceptDrag(event); +} + +void List::dropEvent(QDropEvent *event, QListViewItem *after) +{ + static_cast<View*>(parent())->setNoSorting(); + KURL::List textlist; + if (!KURLDrag::decode(event, textlist)) return; + event->acceptAction(); + + for (KURL::List::Iterator i=textlist.begin(); i != textlist.end(); ++i) + { + after= addFile(*i, false, after); + } + + emit modified(); +} + +void List::keyPressEvent(QKeyEvent *e) +{ + if (e->key()==Key_Enter || e->key()==Key_Return) + { + if (currentItem()) + { + emit KListView::executed(currentItem()); + } + + return; + } + + if (e->key()==Key_Delete) + { + if (currentItem()) + { + emit deleteCurrentItem(); + } + + return; + } + + KListView::keyPressEvent(e); + + +} + +/** + * use this only once!!! + **/ +class NoatunSaver : public PlaylistSaver +{ + List *mList; + SafeListViewItem *after, *mFirst; +public: + NoatunSaver(List *l, QListViewItem *after=0) + : mList(l) + { + this->after = static_cast<SafeListViewItem*>(after); + mFirst = 0; + } + + QListViewItem *getAfter() { return after; } + QListViewItem *getFirst() { return mFirst; } + +protected: + virtual void readItem(const QMap<QString,QString> &properties) + { + after = new SafeListViewItem(mList, after, properties); + if (mFirst==0) + mFirst = after; + } + + virtual PlaylistItem writeItem() + { + if (!after) + { + after=static_cast<SafeListViewItem*>(mList->firstChild()); + } + else + { + after=static_cast<SafeListViewItem*>(static_cast<SafeListViewItem*>(after)->nextSibling()); + } + return PlaylistItem(after); + } +}; + + +bool View::saveToURL(const KURL &url) +{ + NoatunSaver saver(list); + if(saver.save(url)) + { + return true; + } + else + { + KMessageBox::error( this, i18n("Could not write to %1.").arg(url.prettyURL()) ); + return false; + } +} + +void View::exportTo(const KURL &url) +{ + QString local(napp->tempSaveName(url.path())); + QFile saver(local); + saver.open(IO_ReadWrite | IO_Truncate); + QTextStream t(&saver); + // navigate the list + for (SafeListViewItem *i=static_cast<SafeListViewItem*>(listView()->firstChild()); + i != 0; i=static_cast<SafeListViewItem*>(i->itemBelow())) + { + KURL u=i->url(); + if (u.isLocalFile()) + t<< u.path() << '\n'; + else + t << u.url() << '\n'; + } + saver.close(); + + KIO::NetAccess::upload(local, url, this); + + saver.remove(); +} + +QListViewItem *List::openGlobal(const KURL &u, QListViewItem *after) +{ + clear(); + NoatunSaver saver(this, after); + saver.metalist(u); + + return saver.getAfter(); +} + +// for m3u files +QListViewItem *List::importGlobal(const KURL &u, QListViewItem *after) +{ + NoatunSaver saver(this, after); + if (!saver.metalist(u)) + { + after=new SafeListViewItem(this, after, u); +// SPL->listItemSelected(after); + return after; + } + + // return the first item added from this playlist + // that way noatun can start playing the first item + if (saver.getFirst()) + return saver.getFirst(); + + // failsafe in case nothing was added, getFirst() may return 0 + return saver.getAfter(); +} + +QListViewItem *List::addFile(const KURL& url, bool play, QListViewItem *after) +{ + // when a new item is added, we don't want to sort anymore + SPL->view->setNoSorting(); + + if ( + url.path().right(4).lower()==".m3u" + || url.path().right(4).lower()==".pls" + || url.protocol().lower()=="http" + ) + { + // a playlist is requested + QListViewItem *i = importGlobal(url, after); + if (play) + SPL->listItemSelected(i); + return i; + } + else + { + if (!after) after=lastItem(); + KFileItem fileItem(KFileItem::Unknown,KFileItem::Unknown,url); + if (fileItem.isDir()) + { + addDirectoryRecursive(url, after); + return after; // don't (and can't) know better!? + } + else + { + QListViewItem *i = new SafeListViewItem(this, after, url); + if (play) + SPL->listItemSelected(i); + return i; + } + } +} + +// starts a new listJob if there is no active but work to do +void List::addNextPendingDirectory() +{ + KURL::List::Iterator pendingIt= pendingAddDirectories.begin(); + if (!listJob && (pendingIt!= pendingAddDirectories.end())) + { + currentJobURL= *pendingIt; + listJob= KIO::listRecursive(currentJobURL, false,false); + connect( + listJob, SIGNAL(entries(KIO::Job*, const KIO::UDSEntryList&)), + SLOT(slotEntries(KIO::Job*, const KIO::UDSEntryList&)) + ); + connect( + listJob, SIGNAL(result(KIO::Job *)), + SLOT(slotResult(KIO::Job *)) + ); + connect( + listJob, SIGNAL(redirection(KIO::Job *, const KURL &)), + SLOT(slotRedirection(KIO::Job *, const KURL &)) + ); + pendingAddDirectories.remove(pendingIt); + } +} + +void List::addDirectoryRecursive(const KURL &dir, QListViewItem *after) +{ + if (!after) after=lastItem(); + recursiveAddAfter= after; + pendingAddDirectories.append(dir); + addNextPendingDirectory(); +} + +void List::slotResult(KIO::Job *job) +{ + listJob= 0; + if (job && job->error()) + job->showErrorDialog(); + addNextPendingDirectory(); +} + +void List::slotEntries(KIO::Job *, const KIO::UDSEntryList &entries) +{ + QMap<QString,KURL> __list; // temp list to sort entries + + KIO::UDSEntryListConstIterator it = entries.begin(); + KIO::UDSEntryListConstIterator end = entries.end(); + + for (; it != end; ++it) + { + KFileItem file(*it, currentJobURL, false /* no mimetype detection */, true); + // "prudhomm: + // insert the path + url in the map to sort automatically by path + // note also that you use audiocd to rip your CDs then it will be sorted the right way + // now it is an easy fix to have a nice sort BUT it is not the best + // we should sort based on the tracknumber" + // - copied over from old kdirlister hack <hans_meine@gmx.de> + if (!file.isDir()) + __list.insert(file.url().path(), file.url()); + } + QMap<QString,KURL>::Iterator __it; + for( __it = __list.begin(); __it != __list.end(); ++__it ) + { + recursiveAddAfter= addFile(__it.data(), false, recursiveAddAfter); + } +} + +void List::slotRedirection(KIO::Job *, const KURL & url) +{ + currentJobURL= url; +} + +///////////////////////////////// + +View::View(SplitPlaylist *) + : KMainWindow(0, "NoatunSplitplaylistView") +{ + list=new List(this); + setCentralWidget(list); + connect(list, SIGNAL(modified(void)), this, SLOT(setModified(void)) ); + // connect the click on the header with sorting + connect(list->header(),SIGNAL(clicked(int)),this,SLOT(headerClicked(int)) ); + + mOpen=new KAction(i18n("Add &Files..."), "queue", 0, this, SLOT(addFiles()), actionCollection(), "add_files"); + (void) new KAction(i18n("Add Fol&ders..."), "folder", 0, this, SLOT(addDirectory()), actionCollection(), "add_dir"); + mDelete=new KAction(i18n("Delete"), "editdelete", Key_Delete, this, SLOT(deleteSelected()), actionCollection(), "delete"); + + mClose=KStdAction::close(this, SLOT(close()), actionCollection()); + mFind=KStdAction::find(this, SLOT(find()), actionCollection()); + + (void) KStdAction::configureToolbars(this, SLOT(configureToolBars()), actionCollection()); + mOpenNew=KStdAction::openNew(this, SLOT(openNew()), actionCollection()); + mOpenpl=KStdAction::open(this, SLOT(open()), actionCollection()); + mSave=KStdAction::save(this, SLOT(save()), actionCollection()); + mSaveAs=KStdAction::saveAs(this, SLOT(saveAs()), actionCollection()); + + (void) new KAction(i18n("Shuffle"), "misc", 0, SPL, SLOT( randomize() ), actionCollection(), "shuffle"); + (void) new KAction(i18n("Clear"), "editclear", 0, list, SLOT( clear() ), actionCollection(), "clear"); + + createGUI("splui.rc"); + + mFinder = new Finder(this); + + applyMainWindowSettings(KGlobal::config(), "SPL Window"); + list->setFocus(); +} + +void View::find() +{ + mFinder->show(); + connect(mFinder, SIGNAL(search(Finder*)), SLOT(findIt(Finder*))); +} + +static bool testWord(QListViewItem *i, const QString &finder) +{ + PlaylistItemData *item=static_cast<SafeListViewItem*>(i); + if (item->title().find(finder, 0, false) >=0) + return true; + if (item->file().find(finder, 0, false) >=0) + return true; + if (item->url().path().find(finder.local8Bit(), 0, false) >=0) + return true; + if (item->lengthString().find(finder, 0, false) >=0) + return true; + if (item->mimetype().find(finder.local8Bit(), 0, false) >=0) + return true; + return false; +} + +static bool testWord(QListViewItem *i, const QRegExp &finder) +{ + PlaylistItemData *item=static_cast<SafeListViewItem*>(i); + if (item->title().find(finder) >=0) + return true; + if (item->file().find(finder) >=0) + return true; + if (item->url().path().find(finder) >=0) + return true; + if (item->lengthString().find(finder) >=0) + return true; + if (item->mimetype().find(finder) >=0) + return true; + return false; +} + +void View::findIt(Finder *f) +{ + QListViewItem *search=list->currentItem(); + + if (list->currentItem()) + { + if (f->isForward()) + search=list->currentItem()->itemBelow(); + else + search=list->currentItem()->itemAbove(); + } + else + { + if (f->isForward()) + search=list->firstChild(); + else + search=list->lastChild(); + } + + + while (search) + { + if (f->regexp()) + { + if (testWord(search, QRegExp(f->string(), false))) + break; + } + else + { + if (testWord(search, f->string())) + break; + } + + if (f->isForward()) + search=search->itemBelow(); + else + search=search->itemAbove(); + + if (!search) + { + if (f->isForward()) + { + if (KMessageBox::questionYesNo(this, i18n("End of playlist reached. Continue searching from beginning?"),QString::null,KStdGuiItem::cont(),KStdGuiItem::cancel()) == KMessageBox::Yes) + search=list->firstChild(); + } + else + { + if (KMessageBox::questionYesNo(this, i18n("Beginning of playlist reached. Continue searching from end?"),QString::null,KStdGuiItem::cont(),KStdGuiItem::cancel()) == KMessageBox::Yes) + search=list->lastChild(); + } + } + } + + if (search) + { + { // select none + QPtrList<QListViewItem> sel=list->selectedItems(); + for (QListViewItem *i=sel.first(); i!=0; i=sel.next()) + list->setSelected(i, false); + } + list->setSelected(search, true); + list->setCurrentItem(search); + list->ensureItemVisible(search); + } +} + +View::~View() +{ + napp->player()->stop(); + hide(); + saveState(); + delete list; +} + +void View::init() +{ + // see if we are importing an old-style list + bool importing= ! QFile(napp->dirs()->saveLocation("data", "noatun/") + "splitplaylist.xml").exists(); + + if (importing) + { + KURL internalURL; + internalURL.setPath(napp->dirs()->saveLocation("data", "noatun/") + "splitplaylistdata"); + NoatunSaver saver(list, 0); + saver.load(internalURL, PlaylistSaver::M3U); + } + else + { + KURL internalURL; + internalURL.setPath(napp->dirs()->saveLocation("data", "noatun/") + "splitplaylist.xml"); + list->openGlobal(internalURL); + } + + KConfig &config = *KGlobal::config(); + config.setGroup("splitplaylist"); + + // this has to come after openGlobal, since openGlobal emits modified() + setModified(config.readBoolEntry("modified", false)); + QString path = config.readPathEntry("file"); + // don't call setPath with an empty path, that would make the url "valid" + if ( !path.isEmpty() ) + mPlaylistFile.setPath(path); + + SPL->reset(); + int saved = config.readNumEntry("current", 0); + + PlaylistItem item=SPL->getFirst(); + for(int i = 0 ; i < saved ; i++) + { + item=SPL->getAfter(item); + } + if (item) + SPL->setCurrent(item); +} + +void View::save() +{ + if(mPlaylistFile.isEmpty() || !mPlaylistFile.isValid()) + { + saveAs(); + return; + } + + if(saveToURL(mPlaylistFile)) + setModified(false); +} + +void View::saveAs() +{ + KURL u=KFileDialog::getSaveURL(0, "*.xml splitplaylistdata *.pls *.m3u\n*", this, i18n("Save Playlist")); + if(!u.isValid()) + return; + mPlaylistFile = u; + save(); +} + +void View::open() +{ + KURL u=KFileDialog::getOpenURL(0, "*.xml splitplaylistdata *.pls *.m3u\n*", this, i18n("Open Playlist")); + if(!u.isValid()) + return; + mPlaylistFile = u; + list->openGlobal(u); + setModified(false); +} + +void View::openNew() +{ + mPlaylistFile = ""; + listView()->clear(); +} + +void List::clear() +{ + SPL->setCurrent(0); + + QListView::clear(); +} + +void View::deleteSelected() +{ + QPtrList<QListViewItem> items(list->selectedItems()); + + bool stopped=false; + // noatun shouldn't play files for now + QListViewItem *afterLast=0; + + for (QPtrListIterator<QListViewItem> it(items); it.current(); ++it) + { + SafeListViewItem *i = static_cast<SafeListViewItem*>(*it); + if (!stopped && SPL->current() == i) + { + napp->player()->stop(); + SPL->setCurrent(0); + stopped = true; + } + i->remove(); + + afterLast = i->itemBelow(); + } + + if (stopped) + SPL->setCurrent(static_cast<SafeListViewItem*>(afterLast)); + + setModified(true); +} + +void View::addFiles() +{ + KURL::List files=KFileDialog::getOpenURLs(":mediadir", napp->mimeTypes(), this, i18n("Select File to Play")); + + QListViewItem *last = list->lastItem(); + for(KURL::List::Iterator it=files.begin(); it!=files.end(); ++it) + last = addFile(KURL(*it), false); + + setModified(true); +} + +void View::addDirectory() +{ + QString file=KFileDialog::getExistingDirectory(0, this, i18n("Select Folder")); + + if (!file) return; + KURL url; + url.setPath(file); + list->addDirectoryRecursive(url); + + setModified(true); +} + +void View::closeEvent(QCloseEvent*) +{ + hide(); +} + +void View::showEvent(QShowEvent *) +{ + emit shown(); +} + +void View::hideEvent(QHideEvent *) +{ + emit hidden(); +} + +void View::setModified(bool b) +{ + modified = b; + setCaption(i18n("Playlist"), modified); +} + +void View::setModified(void) +{ + setModified(true); +} + +void View::saveState(void) +{ + KConfig &config = *KGlobal::config(); + config.setGroup("splitplaylist"); + + config.writeEntry("modified", modified); + config.writePathEntry("file", mPlaylistFile.path()); + saveToURL(napp->dirs()->saveLocation("data", "noatun/") + "splitplaylist.xml"); + + unsigned int i; + PlaylistItem item=SPL->getFirst(); + for(i = 0; item && item != SPL->current(); ) + item=SPL->getAfter(item), i++; + + config.writeEntry("current", i); + saveMainWindowSettings(KGlobal::config(), "SPL Window"); + + config.sync(); +} + +void View::configureToolBars() +{ + saveMainWindowSettings(KGlobal::config(), "SPL Window"); + KEditToolbar dlg(actionCollection(), "splui.rc"); + connect(&dlg, SIGNAL(newToolbarConfig()), SLOT(newToolBarConfig())); + dlg.exec(); +} + +void View::newToolBarConfig() +{ + createGUI("splui.rc"); + applyMainWindowSettings(KGlobal::config(), "SPL Window"); +} + +// turns the sorting on or off +void View::setSorting(bool on, int column) +{ + if (on) + { + list->setSorting(column,true); + list->setShowSortIndicator(true); + } + else + { + list->setShowSortIndicator(false); + list->setSorting(-1); + } +} + +void View::headerClicked(int column) +{ + // this is to avoid that if we already have it sorted, + // we sort it again ascendingly this way, clicking on + // the header a second time will correctly toggle + // ascending/descending sort + if (list->showSortIndicator()) + { + return; + } + else + { + setSorting(true,column); + } +} + +#include "view.moc" + diff --git a/noatun/modules/splitplaylist/view.h b/noatun/modules/splitplaylist/view.h new file mode 100644 index 00000000..18dc917a --- /dev/null +++ b/noatun/modules/splitplaylist/view.h @@ -0,0 +1,165 @@ +#ifndef VIEW_H +#define VIEW_H + +#include <qevent.h> +#include <qptrlist.h> +#include <klistview.h> +#include <kmainwindow.h> +#include <qrect.h> +#include <qdict.h> +#include <kio/global.h> +#include <noatun/downloader.h> + +class Finder; +class View; +namespace KIO { class ListJob; } + + +class SafeListViewItem + : public QCheckListItem + , public PlaylistItemData + , public DownloadItem +{ +public: + SafeListViewItem(QListView *parent, QListViewItem *after, const KURL &text); + SafeListViewItem(QListView *parent, QListViewItem *after, const QMap<QString,QString> &properties); + virtual ~SafeListViewItem(); + + virtual QString property(const QString &, const QString & = 0) const; + virtual void setProperty(const QString &, const QString &); + virtual void clearProperty(const QString &); + virtual QStringList properties() const; + virtual bool isProperty(const QString &) const; + + virtual QString file() const; + + int compare(QListViewItem * i, int col, bool ascending) const; + virtual void remove(); + +protected: + virtual void downloaded(int percent); + virtual void downloadTimeout(); + virtual void downloadFinished(); + virtual void modified(); + virtual void stateChange(bool s); + + void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align); + +private: + struct Property + { + QString key; + QString value; + }; + QValueList<Property> mProperties; + bool removed; +}; + +class List : public KListView +{ +Q_OBJECT +friend class View; +public: + List(View *parent); + virtual ~List(); + QListViewItem *openGlobal(const KURL&, QListViewItem * =0); + QListViewItem *importGlobal(const KURL&, QListViewItem * =0); + QListViewItem *addFile(const KURL&, bool play=false, QListViewItem * =0); + void addDirectoryRecursive(const KURL &dir, QListViewItem *after= 0); + +public slots: + virtual void clear(); + +signals: + void modified(void); + void deleteCurrentItem(); + +protected: + virtual bool acceptDrag(QDropEvent *event) const; + virtual void keyPressEvent(QKeyEvent *e); + +protected slots: + virtual void dropEvent(QDropEvent *event, QListViewItem *after); + void move(); + +protected: + QListViewItem *recursiveAddAfter; + +protected slots: + // used when adding directories via KIO::listRecursive + void slotResult(KIO::Job *job); + void slotEntries(KIO::Job *job, const KIO::UDSEntryList &entries); + void slotRedirection(KIO::Job *, const KURL & url); + +protected: + void addNextPendingDirectory(); + KURL::List pendingAddDirectories; + KIO::ListJob *listJob; + KURL currentJobURL; +}; + +class KFileDialog; +class KToggleAction; +class KToolBar; + +class View : public KMainWindow +{ +Q_OBJECT +public: + View(SplitPlaylist *mother); + // load the SM playlist + void init(); + virtual ~View(); + List *listView() const { return list; } + QListViewItem *addFile(const KURL &u, bool play=false) + { return list->addFile(u, play, list->lastItem()); } + + +public slots: + void deleteSelected(); + void addFiles(); + void addDirectory(); + void save(); + void saveAs(); + void open(); + void openNew(); + void setSorting(bool on, int column = 0); + void setNoSorting() { setSorting(false); } + void headerClicked(int column);void find(); + void findIt(Finder *); + + +private slots: + void setModified(); + void saveState(); + + void configureToolBars(); + void newToolBarConfig(); + +protected: + void setupActions(); + + bool saveToURL(const KURL &); + void exportTo(const KURL &); + + void setModified(bool); + virtual void closeEvent(QCloseEvent*e); + virtual void showEvent(QShowEvent *); + virtual void hideEvent(QHideEvent *); + +signals: + void hidden(); + void shown(); + +private: + List *list; + KAction *mOpen, *mDelete, *mSave, *mSaveAs, *mOpenpl, *mOpenNew; + KAction *mClose; + KAction *mFind; + Finder *mFinder; + + KURL mPlaylistFile; + bool modified; +}; + +#endif diff --git a/noatun/modules/systray/Makefile.am b/noatun/modules/systray/Makefile.am new file mode 100644 index 00000000..1dcfdd25 --- /dev/null +++ b/noatun/modules/systray/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES= -I$(top_srcdir)/noatun/library $(all_includes) +kde_module_LTLIBRARIES = noatun_systray.la + +noatun_systray_la_SOURCES = systray.cpp noatunui.cpp kitsystemtray.cpp cmodule.cpp \ + yhconfig.kcfgc yhconfigwidget.ui + + +noatun_systray_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_systray_la_LIBADD = $(LIB_KFILE) $(top_builddir)/noatun/library/libnoatun.la + +noatun_systray_la_METASOURCES = AUTO + +noinst_HEADERS = systray.h kitsystemtray.h cmodule.h + +noatun_modules_systray_DATA = systray.plugin systrayui.rc yhconfig.kcfg +noatun_modules_systraydir = $(kde_datadir)/noatun diff --git a/noatun/modules/systray/cmodule.cpp b/noatun/modules/systray/cmodule.cpp new file mode 100644 index 00000000..4adf7e44 --- /dev/null +++ b/noatun/modules/systray/cmodule.cpp @@ -0,0 +1,192 @@ +// cmodule.cpp +// +// Copyright (C) 2001 Neil Stevens <multivac@fcmail.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name(s) of the author(s) shall not be +// used in advertising or otherwise to promote the sale, use or other dealings +// in this Software without prior written authorization from the author(s). + +#include "cmodule.h" +#include "yhconfig.h" +#include "yhconfigwidget.h" + +#include <kdebug.h> +//#include <kglobal.h> +#include <klocale.h> +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qradiobutton.h> +#include <qspinbox.h> + +#include <noatun/app.h> +#include <noatun/pluginloader.h> + +#include <fixx11h.h> + +YHModule::YHModule(QObject *_parent) + : CModule(i18n("System Tray Icon"), i18n("Configure System Tray Icon"), + "bottom", _parent) +{ + QVBoxLayout *top = new QVBoxLayout(this); + mWidget = new YHConfigWidget(this); + top->addWidget(mWidget); + + mWidget->cmbModifier->insertItem(i18n("None"), YHConfig::None); + mWidget->cmbModifier->insertItem(i18n("Shift"), YHConfig::Shift); + mWidget->cmbModifier->insertItem(i18n("Alt"), YHConfig::Alt); + mWidget->cmbModifier->insertItem(i18n("Ctrl"), YHConfig::Ctrl); + mWidget->cmbModifier->setCurrentItem(YHConfig::None); + + connect(mWidget->chkUsePopup, SIGNAL(toggled(bool)), this, SLOT(slotUsePopupToggled(bool))); + connect(mWidget->cmbModifier, SIGNAL(activated(int)), this, SLOT(slotModifierActivated(int))); + connect(mWidget->grpMwheel, SIGNAL(clicked(int)), this, SLOT(slotMwheelClicked(int))); + + reopen(); +} + + +void YHModule::reopen() +{ + kdDebug(66666) << k_funcinfo << endl; + YHConfig *c = YHConfig::self(); + + /** General TAB **/ + + mWidget->chkUseTooltip->setChecked(c->tip()); + mWidget->chkUseCovers->setChecked(c->passivePopupCovers()); + + mWidget->chkUsePopup->setChecked(c->passivePopup()); + mWidget->spinPopupTimeout->setValue(c->passivePopupTimeout()); + mWidget->chkPopupButtons->setChecked(c->passivePopupButtons()); + + switch(c->stateIconDisplay()) + { + case (YHConfig::Animation): + mWidget->rbStateAnim->setChecked(true); + break; + case (YHConfig::FlashingIcon): + mWidget->rbStateFlashing->setChecked(true); + break; + case (YHConfig::StaticIcon): + mWidget->rbStateStatic->setChecked(true); + break; + case (YHConfig::NoIcon): + mWidget->rbStateNone->setChecked(true); + break; + } + + /** Advanced TAB **/ + + if (c->middleMouseAction() == YHConfig::PlayPause) + mWidget->rbPlayPause->setChecked(true); + else + mWidget->rbHideShowPlaylist->setChecked(true); + + mActionMap[YHConfig::None] = YHConfig::self()->mouseWheelAction(YHConfig::None); + mActionMap[YHConfig::Shift] = YHConfig::self()->mouseWheelAction(YHConfig::Shift); + mActionMap[YHConfig::Alt] = YHConfig::self()->mouseWheelAction(YHConfig::Alt); + mActionMap[YHConfig::Ctrl] = YHConfig::self()->mouseWheelAction(YHConfig::Ctrl); + + slotModifierActivated(mWidget->cmbModifier->currentItem()); +} + + +void YHModule::save() +{ + kdDebug(66666) << k_funcinfo << endl; + + YHConfig *c = YHConfig::self(); + + /** General TAB **/ + + c->setTip(mWidget->chkUseTooltip->isChecked()); + c->setPassivePopupCovers(mWidget->chkUseCovers->isChecked()); + + c->setPassivePopup(mWidget->chkUsePopup->isChecked()); + c->setPassivePopupTimeout(mWidget->spinPopupTimeout->value()); + c->setPassivePopupButtons(mWidget->chkPopupButtons->isChecked()); + + if (mWidget->rbStateAnim->isChecked()) + c->setStateIconDisplay(YHConfig::Animation); + else if (mWidget->rbStateFlashing->isChecked()) + c->setStateIconDisplay(YHConfig::FlashingIcon); + else if (mWidget->rbStateStatic->isChecked()) + c->setStateIconDisplay(YHConfig::StaticIcon); + else + c->setStateIconDisplay(YHConfig::NoIcon); + + /** Advanced TAB **/ + + if (mWidget->rbPlayPause->isChecked()) + c->setMiddleMouseAction(YHConfig::PlayPause); + else + c->setMiddleMouseAction(YHConfig::HideShowPlaylist); + + c->setMouseWheelAction(YHConfig::None, mActionMap[YHConfig::None]); + c->setMouseWheelAction(YHConfig::Shift, mActionMap[YHConfig::Shift]); + c->setMouseWheelAction(YHConfig::Alt, mActionMap[YHConfig::Alt]); + c->setMouseWheelAction(YHConfig::Ctrl, mActionMap[YHConfig::Ctrl]); + + c->writeConfig(); + emit saved(); +} + + +void YHModule::slotUsePopupToggled(bool on) +{ + mWidget->lblPopupTimeout->setEnabled(on); + mWidget->spinPopupTimeout->setEnabled(on); + mWidget->chkPopupButtons->setEnabled(on); +} + + +void YHModule::slotModifierActivated(int index) +{ + kdDebug(66666) << k_funcinfo << endl; + switch(mActionMap[index]) + { + case (YHConfig::Nothing): + mWidget->rbActNothing->setChecked(true); + break; + case (YHConfig::ChangeVolume): + mWidget->rbActVolume->setChecked(true); + break; + case (YHConfig::ChangeTrack): + mWidget->rbActTrack->setChecked(true); + break; + } +} + +void YHModule::slotMwheelClicked(int index) +{ + kdDebug(66666) << k_funcinfo << endl; + if (index == 0) + mActionMap[mWidget->cmbModifier->currentItem()] = YHConfig::Nothing; + else if (index == 1) + mActionMap[mWidget->cmbModifier->currentItem()] = YHConfig::ChangeVolume; + else + mActionMap[mWidget->cmbModifier->currentItem()] = YHConfig::ChangeTrack; +} + +#include "cmodule.moc" diff --git a/noatun/modules/systray/cmodule.h b/noatun/modules/systray/cmodule.h new file mode 100644 index 00000000..fecc70e3 --- /dev/null +++ b/noatun/modules/systray/cmodule.h @@ -0,0 +1,55 @@ +// cmodule.h +// +// Copyright (C) 2001 Neil Stevens <multivac@fcmail.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name(s) of the author(s) shall not be +// used in advertising or otherwise to promote the sale, use or other dealings +// in this Software without prior written authorization from the author(s). + +#ifndef CMODULE_H +#define CMODULE_H + +#include <qmap.h> +#include <noatun/pref.h> + +class YHConfigWidget; + +class YHModule : public CModule +{ +Q_OBJECT + public: + YHModule(QObject *_parent); + virtual void save(); + virtual void reopen(); + + signals: + void saved(); + + private: + YHConfigWidget *mWidget; + QMap<int, int> mActionMap; + + private slots: + void slotUsePopupToggled(bool on); + void slotModifierActivated(int index); + void slotMwheelClicked(int index); +}; + +#endif diff --git a/noatun/modules/systray/kitsystemtray.cpp b/noatun/modules/systray/kitsystemtray.cpp new file mode 100644 index 00000000..5847d7da --- /dev/null +++ b/noatun/modules/systray/kitsystemtray.cpp @@ -0,0 +1,131 @@ +// $Id$ +// +// Kit +// +// Copyright (C) 1999 Neil Stevens <multivac@fcmail.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name(s) of the author(s) shall not be +// used in advertising or otherwise to promote the sale, use or other dealings +// in this Software without prior written authorization from the author(s). + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "yhconfig.h" + +#include <noatun/app.h> +#include <noatun/player.h> +#include <qdragobject.h> + +#include "kitsystemtray.h" +#include <kmainwindow.h> +#include <kpopupmenu.h> +#include <kxmlguifactory.h> +#include <kiconloader.h> +#include <kurldrag.h> + +#include <fixx11h.h> + +KitSystemTray::KitSystemTray(const QString &contextMenu, KMainWindow *parent, const char *name) + : KSystemTray(parent, name) +{ + setAlignment(AlignHCenter | AlignVCenter); + menu = (KPopupMenu *)parent->guiFactory()->container(contextMenu, parent); + menu->insertTitle(SmallIcon("noatun"), QString::null, 0, 0); + setAcceptDrops(true); +} + +void KitSystemTray::changeTitle(const QPixmap &pixmap, const QString &title) +{ + menu->changeTitle(0, pixmap, title); +} + +void KitSystemTray::showEvent(QShowEvent *) +{ + // empty +} + +void KitSystemTray::mousePressEvent(QMouseEvent *event) +{ + switch(event->button()) + { + case LeftButton: + napp->toggleInterfaces(); + break; + case MidButton: + if (YHConfig::self()->middleMouseAction() == YHConfig::HideShowPlaylist) + napp->playlist()->toggleList(); + else // play or pause + napp->player()->playpause(); + break; + default: + menu->popup(event->globalPos()); + break; + } +} + +void KitSystemTray::dragEnterEvent(QDragEnterEvent * event) +{ + event->accept(KURLDrag::canDecode(event)); // accept uri drops only +} + +void KitSystemTray::dropEvent(QDropEvent * event) +{ + KURL::List uris; + if (KURLDrag::decode(event, uris)) + { + KURL::List::ConstIterator it; + for (it = uris.begin(); it != uris.end(); ++it) + napp->player()->openFile(*it, false); + } +} + +void KitSystemTray::wheelEvent(QWheelEvent *event) +{ + YHConfig *c = YHConfig::self(); + + int action = 0; + if (event->state() & Qt::ShiftButton) + action = c->mouseWheelAction(YHConfig::Shift); + else if (event->state() & Qt::ControlButton) + action = c->mouseWheelAction(YHConfig::Ctrl); + else if (event->state() & Qt::AltButton) + action = c->mouseWheelAction(YHConfig::Alt); + else + action = c->mouseWheelAction(YHConfig::None); + + switch(action) + { + case (YHConfig::ChangeVolume): + napp->player()->setVolume(napp->player()->volume()+event->delta()/24); + break; + case (YHConfig::ChangeTrack): + if (event->delta() > 0) + napp->player()->forward(true); + else + napp->player()->back(); + break; + default: + break; + } +} + +#include "kitsystemtray.moc" diff --git a/noatun/modules/systray/kitsystemtray.h b/noatun/modules/systray/kitsystemtray.h new file mode 100644 index 00000000..2f640adb --- /dev/null +++ b/noatun/modules/systray/kitsystemtray.h @@ -0,0 +1,54 @@ +// $Id$ +// +// Kit +// +// Copyright (C) 1999 Neil Stevens <multivac@fcmail.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name(s) of the author(s) shall not be +// used in advertising or otherwise to promote the sale, use or other dealings +// in this Software without prior written authorization from the author(s). + +#ifndef KITSYSTEMTRAY_H +#define KITSYSTEMTRAY_H + +#include <ksystemtray.h> + +class KPopupMenu; +class KMainWindow; +class QPixmap; + +class KitSystemTray : public KSystemTray +{ +Q_OBJECT + +public: + KitSystemTray(const QString &contextMenu, KMainWindow *parent, const char *name = 0); + void changeTitle(const QPixmap &, const QString &); +protected: + virtual void showEvent(QShowEvent *); + virtual void mousePressEvent(QMouseEvent *); + virtual void dragEnterEvent(QDragEnterEvent *); + virtual void dropEvent(QDropEvent *); + virtual void wheelEvent(QWheelEvent *e); + + KPopupMenu *menu; +}; + +#endif diff --git a/noatun/modules/systray/noatunui.cpp b/noatun/modules/systray/noatunui.cpp new file mode 100644 index 00000000..76f9af25 --- /dev/null +++ b/noatun/modules/systray/noatunui.cpp @@ -0,0 +1,9 @@ +#include "systray.h" + +extern "C" +{ + KDE_EXPORT Plugin *create_plugin() + { + return new NoatunSystray(); + } +} diff --git a/noatun/modules/systray/systray.cpp b/noatun/modules/systray/systray.cpp new file mode 100644 index 00000000..c93080ca --- /dev/null +++ b/noatun/modules/systray/systray.cpp @@ -0,0 +1,467 @@ +// systray.h +// +// Copyright (C) 2000 Neil Stevens <multivac@fcmail.com> +// Copyright (C) 1999 Charles Samuels <charles@kde.org> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name(s) of the author(s) shall not be +// used in advertising or otherwise to promote the sale, use or other dealings +// in this Software without prior written authorization from the author(s). + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "systray.h" +#include "kitsystemtray.h" +#include "cmodule.h" +#include "yhconfig.h" + +#include <noatun/app.h> +#include <noatun/pref.h> +#include <noatun/player.h> +#include <noatun/stdaction.h> + +#include <kaction.h> +#include <kconfig.h> +#include <qfile.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kpassivepopup.h> +#include <kpixmapeffect.h> +#include <kstdaction.h> +#include <qbitmap.h> +#include <qhbox.h> +#include <qpainter.h> +#include <qpushbutton.h> +#include <qtooltip.h> +#include <qvbox.h> + +#include <qimage.h> +#include <kurl.h> +#include <kio/netaccess.h> +#include <kdebug.h> +#include <kstandarddirs.h> + +#include <netwm.h> +#include <kglobalsettings.h> + +// TODO: Maybe make this value configurable? +const int COVER_MAXW = 128; +const int COVER_MAXH = 128; +#define BASEICON "noatun" + +// From JuK +class PassivePopup : public KPassivePopup +{ +public: + PassivePopup(QWidget *parent = 0, const char *name = 0) : KPassivePopup(parent, name) {} + +protected: + virtual void enterEvent(QEvent *) + { + setTimeout(3000000); // Make timeout damn near infinite + } + + virtual void leaveEvent(QEvent *) + { + setTimeout(250); // Close quickly + } +}; + + +//NoatunSystray *NoatunSystray::self = 0; + + +NoatunSystray::NoatunSystray() : KMainWindow(0, "NoatunSystray"), Plugin(), + mTray(0), trayStatus(0), trayBase(0), mPassivePopup(0L) +{ + //self = this; + hide(); + + tmpCoverPath = locateLocal("tmp", "youngHickoryCover.png"); + + removeCover(); // make sure any old temp cover is gone + + KStdAction::quit(napp, SLOT(quit()), actionCollection()); + KStdAction::open(napp, SLOT(fileOpen()), actionCollection()); + KStdAction::preferences(napp, SLOT(preferences()), actionCollection()); + NoatunStdAction::back(actionCollection(), "back"); + NoatunStdAction::stop(actionCollection(), "stop"); + NoatunStdAction::playpause(actionCollection(), "play"); + NoatunStdAction::forward(actionCollection(), "forward"); + NoatunStdAction::playlist(actionCollection(), "show_playlist"); + NoatunStdAction::loop(actionCollection(), "loop_style"); + NoatunStdAction::effects(actionCollection(), "effects"); + NoatunStdAction::equalizer(actionCollection(), "equalizer"); + + createGUI("systrayui.rc"); + + mTray = new KitSystemTray("tray", this); + mTray->show(); + + trayBase = renderIcon(BASEICON, QString::null); + trayStatus = renderIcon(BASEICON, "player_stop"); + + mTray->changeTitle(*trayBase, i18n("Noatun")); + showingTrayStatus = false; + + mBlinkTimer = new QTimer(this); + connect(mBlinkTimer, SIGNAL(timeout()), this, SLOT(slotBlinkTimer())); + + connect(napp->player(), SIGNAL(playing()), this, SLOT(slotPlayPause())); + connect(napp->player(), SIGNAL(paused()), this, SLOT(slotPlayPause())); + connect(napp->player(), SIGNAL(stopped()), this, SLOT(slotStopped())); + //napp->player()->handleButtons(); +} + + +NoatunSystray::~NoatunSystray() +{ + //kdDebug(66666) << k_funcinfo << "Called." << endl; + removeCover(); + delete trayBase; + delete trayStatus; + napp->showInterfaces(); +} + + +void NoatunSystray::init() +{ + YHModule *cmod = new YHModule(this); + connect(cmod, SIGNAL(saved()), this, SLOT(slotLoadSettings())); + slotLoadSettings(); +} + + +void NoatunSystray::slotLoadSettings() +{ + kdDebug(66666) << k_funcinfo << endl; + + YHConfig *c = YHConfig::self(); + + if(c->stateIconDisplay() == YHConfig::FlashingIcon) + mBlinkTimer->start(1000); + else + mBlinkTimer->stop(); + slotBlinkTimer(); + + + if(c->tip()) + QToolTip::add(mTray, tipText); + else + QToolTip::remove(mTray); + + if (!c->passivePopupCovers()) + removeCover(); + + if(c->passivePopup()) + { + mPassivePopup = new PassivePopup(mTray, "NoatunPassivePopup"); + } + else + { + delete mPassivePopup; + mPassivePopup = 0L; + } +} + + +void NoatunSystray::closeEvent(QCloseEvent*) +{ + //kdDebug(66666) << k_funcinfo << "Called." << endl; + disconnect(napp->player(), 0, 0, 0); + unload(); +} + + +void NoatunSystray::slotPlayPause() +{ + QString status; + + if(napp->player()->isPaused()) + { + changeTray("player_pause"); + status = i18n("Noatun - Paused"); + } + else + { + changeTray("player_play"); + status = i18n("Noatun - Playing"); + } + + const PlaylistItem item = napp->player()->current(); + QString s; + + if(!item.isProperty("title")) + { + // No metadata + s = QString("<nobr>%1</nobr>").arg(item.title()); + } + else + { + s = QString("<h2><nobr>%1</nobr></h2>").arg(item.property("title")); + + if(item.isProperty("author")) + s += QString("<nobr>%1</nobr><br>").arg(item.property("author")); + + if(item.isProperty("album")) + { + if(item.isProperty("date")) + s += QString("<nobr>%1 (%2)</nobr><br>").arg(item.property("album")).arg(item.property("date")); + else + s += QString("<nobr>%1</nobr><br>").arg(item.property("album")); + } + } + + // prepare cover image for display + if (YHConfig::self()->passivePopupCovers()) + updateCover(); + + if(YHConfig::self()->passivePopupCovers() && QFile::exists(tmpCoverPath)) + { + // QT always adds an empty line after the table so we add en empty line before the + // table to get equal spacing on top and bottom + setTipText(QString("<qt><br><table cellspacing=0 cellpadding=0><tr>" \ + "<td align=center valign=center><h4><nobr>%1</nobr></h4>%2</td>" \ + "<td valign=center><img src='%3'></td>" \ + "</qt></tr></table>").arg(status).arg(s).arg(tmpCoverPath)); + } + else + { + setTipText(QString("<qt><center><h4><nobr>%1</nobr></h4>%2</center></qt>").arg(status).arg(s)); + } +} + + +void NoatunSystray::slotStopped() +{ + if(!napp->player()->current()) + return; + changeTray("player_stop"); + setTipText(QString("<qt><nobr><h4>%1</h4></nobr></qt>").arg(i18n("Noatun - Stopped"))); +} + + + +void NoatunSystray::changeTray(const QString &pm) +{ + delete trayStatus; + trayStatus = renderIcon(BASEICON, pm); + if(showingTrayStatus) + slotBlinkTimer(); +} + + +void NoatunSystray::slotBlinkTimer() +{ + switch(YHConfig::self()->stateIconDisplay()) + { + case (YHConfig::FlashingIcon): + showingTrayStatus ^= true; + break; + case (YHConfig::StaticIcon): + showingTrayStatus = true; + break; + case (YHConfig::NoIcon): + showingTrayStatus = false; + break; + } + + if(showingTrayStatus) + mTray->setPixmap(*trayStatus); + else + mTray->setPixmap(*trayBase); +} + + +// taken from patched karamba xmmssensor +// modified heavily to work in this place +void NoatunSystray::updateCover() +{ + //kdDebug(66666) << k_funcinfo << endl; + QString dir = napp->player()->current().url().directory(); + QString cover; + + // TODO: Maybe make these filenames configurable? + if(QFile::exists(dir + "/folder.png")) + cover = dir + "/folder.png"; + else if(QFile::exists(dir + "/.folder.png")) + cover = dir + "/.folder.png"; + else if(QFile::exists(dir + "/cover.png")) + cover = dir + "/cover.png"; + else if(QFile::exists(dir + "/cover.jpg")) + cover = dir + "/cover.jpg"; + else if(QFile::exists(dir + "/cover.jpeg")) + cover = dir + "/cover.jpeg"; + else // no cover + { + //kdDebug(66666) << k_funcinfo << "NO COVER" << endl; + removeCover(); + return; + } + + QString title = napp->player()->current().title(); + + QImage previmg; + previmg.load(tmpCoverPath); + + if(previmg.text("Title") != title) + { //Verify song change to limit CPU usage + /*kdDebug(66666) << k_funcinfo << "Creating new temp cover for '" << + cover << "'" << endl;*/ + + QImage src; + QImage tmpimg; + + if(src.load(cover)) + { + if(src.width() >= COVER_MAXW || src.height() >= COVER_MAXH) + tmpimg = src.scale(COVER_MAXW, COVER_MAXH, QImage::ScaleMin); + else + tmpimg = src; + + tmpimg.setText("Title", 0, title); //add Title in the image text for cache usage + tmpimg.save(tmpCoverPath, "PNG", 0); + } + else + { + removeCover(); + } + } +} + + +void NoatunSystray::removeCover() +{ + if(QFile::exists(tmpCoverPath)) + KIO::NetAccess::del(KURL(tmpCoverPath), this); +} + + +void NoatunSystray::setTipText(const QString& text) +{ + if(text == tipText) // save the planet, save cpu cycles ;) + return; + tipText = text; + + YHConfig *c = YHConfig::self(); + if(c->passivePopup()) + QTimer::singleShot(0, this, SLOT(showPassivePopup())); + + if(c->tip()) + QToolTip::add(mTray, tipText); +} + + +void NoatunSystray::showPassivePopup() +{ + if (!mPassivePopup) + { + kdDebug(66666) << k_funcinfo << "Called but no KPassivePopup created yet!" << endl; + return; + } + + mPassivePopup->reparent(0L, QPoint(0,0)); + + if (YHConfig::self()->passivePopupButtons() && !napp->player()->isStopped()) + { + QVBox *widget = mPassivePopup->standardView(QString::null, tipText, QPixmap()); + QHBox *box = new QHBox(mPassivePopup, "popupbox"); + + box->setSpacing(8); + + // Algorithm for determining popup location from kpassivepopup.cpp via JuK + NETWinInfo ni(qt_xdisplay(), mTray->winId(), qt_xrootwin(), + NET::WMIconGeometry | NET::WMKDESystemTrayWinFor); + NETRect frame, win; + ni.kdeGeometry(frame, win); + + QRect bounds = KGlobalSettings::desktopGeometry(QPoint(win.pos.x, win.pos.y)); + + if(win.pos.x < bounds.center().x()) + { + // Buttons to the left + + QVBox *buttonBox = new QVBox(box); + buttonBox->setSpacing(3); + + QPushButton *forwardButton = new QPushButton(action("forward")->iconSet(), 0, buttonBox, "popup_forward"); + forwardButton->setFlat(true); + connect(forwardButton, SIGNAL(clicked()), action("forward"), SLOT(activate())); + + QPushButton *backButton = new QPushButton(action("back")->iconSet(), 0, buttonBox, "popup_back"); + backButton->setFlat(true); + connect(backButton, SIGNAL(clicked()), action("back"), SLOT(activate())); + + QFrame *line = new QFrame(box); + line->setFrameShape(QFrame::VLine); + + widget->reparent(box, QPoint(0, 0)); + } + else + { + // Buttons to the right + widget->reparent(box, QPoint(0, 0)); + + QFrame *line = new QFrame(box); + line->setFrameShape(QFrame::VLine); + + QVBox *buttonBox = new QVBox(box); + buttonBox->setSpacing(3); + + QPushButton *forwardButton = new QPushButton(action("forward")->iconSet(), 0, buttonBox, "popup_forward"); + forwardButton->setFlat(true); + connect(forwardButton, SIGNAL(clicked()), action("forward"), SLOT(activate())); + + QPushButton *backButton = new QPushButton(action("back")->iconSet(), 0, buttonBox, "popup_back"); + backButton->setFlat(true); + connect(backButton, SIGNAL(clicked()), action("back"), SLOT(activate())); + } + mPassivePopup->setView(box); + } + else + { + mPassivePopup->setView(QString::null, tipText); + } + + mPassivePopup->setTimeout(YHConfig::self()->passivePopupTimeout()*1000); + mPassivePopup->show(); +} + + +QPixmap *NoatunSystray::renderIcon(const QString& baseIcon, const QString &overlayIcon) const +{ + QPixmap *base = new QPixmap(KSystemTray::loadIcon(baseIcon)); + + if(!(overlayIcon.isNull())) // otherwise leave the base as-is + { + QPixmap overlay = KSystemTray::loadIcon(overlayIcon); + if(!overlay.isNull()) + { + // draw the overlay on top of it + QPainter p(base); + p.drawPixmap(0, 0, overlay); + } + } + return base; +} + +#include "systray.moc" diff --git a/noatun/modules/systray/systray.h b/noatun/modules/systray/systray.h new file mode 100644 index 00000000..f602c4e3 --- /dev/null +++ b/noatun/modules/systray/systray.h @@ -0,0 +1,80 @@ +// systray.h +// +// Copyright (C) 2000 Neil Stevens <multivac@fcmail.com> +// Copyright (C) 1999 Charles Samuels <charles@kde.org> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name(s) of the author(s) shall not be +// used in advertising or otherwise to promote the sale, use or other dealings +// in this Software without prior written authorization from the author(s). + +#ifndef SYSTRAY_H +#define SYSTRAY_H + +#include <noatun/plugin.h> +#include <noatun/app.h> + +#include <qtimer.h> + +#include <kmainwindow.h> + +class KitSystemTray; +class QTimer; +class PassivePopup; + +class NoatunSystray : public KMainWindow, public Plugin +{ +Q_OBJECT +public: + NoatunSystray(); + virtual ~NoatunSystray(); + virtual void init(); + +protected: + virtual void closeEvent(QCloseEvent *); + +public slots: + void slotPlayPause(); + void slotStopped(); + +private slots: + void changeTray(const QString &); + void slotLoadSettings(); + void slotBlinkTimer(); + void showPassivePopup(); + QPixmap *renderIcon(const QString &, const QString &) const; + +private: + void setTipText(const QString&); + void updateCover(); + void removeCover(); + +private: + KitSystemTray *mTray; + QTimer *mBlinkTimer; + QPixmap *trayStatus; + QPixmap *trayBase; + PassivePopup *mPassivePopup; + + bool showingTrayStatus; + QString tipText; + QString tmpCoverPath; +}; + +#endif diff --git a/noatun/modules/systray/systray.plugin b/noatun/modules/systray/systray.plugin new file mode 100644 index 00000000..24af57f5 --- /dev/null +++ b/noatun/modules/systray/systray.plugin @@ -0,0 +1,100 @@ +Filename=noatun_systray.la +Author=Neil Stevens +Site=http://noatun.kde.org/plugins/yh/ +Email=neil@qualityassistant.com +Type=systray +License=X11-like +Name=Young Hickory +Name[af]=Jong Hickory +Name[ar]=شجرة الجوز الصغيرة +Name[az]=Gənc Hickory +Name[cs]=Mladý ořech +Name[eo]=Juna hikorio +Name[es]=Joven Nogal +Name[et]=Noor hikkor +Name[fa]=یانگ هیکوری +Name[fi]=Nuori Hickory +Name[fr]=Jeune Hickory +Name[hi]=यंग हिकॉरी +Name[is]=Ungi Hickory +Name[it]=Giovane nocciolina +Name[ko]=젊은 히코리 +Name[lt]=Jaunas Hickory +Name[lv]=Jaunais Hickorijs +Name[ne]=युवा हिक्कोरी +Name[pl]=Tacka systemowa +Name[ru]=Ветка гикори +Name[sk]=Mladý Hickory +Name[sl]=Mladi hikori +Name[sv]=Ung valnöt +Name[ta]=சின்ன ஒருவகை மரம் +Name[tr]=Genç Hickory +Name[ven]=Hickory mutuku +Name[xh]=iHickory encinane +Name[zh_CN]=小胡桃木 +Name[zh_HK]=小山胡桃 +Name[zh_TW]=小山胡桃 +Comment=A system tray interface +Comment[af]='n stelsel laai koppelvlak +Comment[ar]=واجهة للوحة النظام +Comment[az]=Sistem rəf paneli +Comment[bg]=Икона за управление от системния панел +Comment[bn]=একটি সিস্টেম ট্রে ইন্টারফেস +Comment[bs]=Interfejs za sistemski tray +Comment[ca]=Una interfície de la safata del sistema +Comment[cs]=Rozhraní systémové části panelu +Comment[cy]=Rhyngwyneb hambwrdd cysawd +Comment[da]=En statusfelt-grænseflade +Comment[de]=Oberfläche für den Systembereich der Kontrollleiste +Comment[el]=Μια διασύνδεση για το πλαίσιο συστήματος +Comment[eo]=Interfaco por la dokejo +Comment[es]=Una interfaz para la bandeja del sistema +Comment[et]=Süsteemse doki liides +Comment[eu]=Interfazea sistemaren bandejarentzat +Comment[fa]=یک واسط سینی سیستم +Comment[fi]=Järjestelmäikkunan rajapinta +Comment[fr]=Une interface intégrée dans la boîte à miniatures +Comment[gl]=Unha interface para a bandexa do sistema +Comment[he]=ממשק מגש מערכת +Comment[hi]=एक तंत्र तश्तरी इंटरफेस +Comment[hr]=Sučelje za sustavsku ladicu +Comment[hu]=A rendszertálca kezelői felülete +Comment[id]=interface tray sistem +Comment[is]=Aðgangur að kerfisbakka +Comment[it]=Un'interfaccia per il vassoio di sistema +Comment[ja]=システムトレイインターフェース +Comment[kk]=Жүйелік сөре интерфейсі +Comment[km]=ចំណុចប្រទាក់ថាសប្រព័ន្ធ +Comment[ko]=시스템 트레이 인터페이스 +Comment[lt]=Sistemos dėklo sąsaja +Comment[lv]=Sistēmas teknes starpseja +Comment[mk]=Интерфејс за системската лента +Comment[ms]=Antaramuka dulang sistem +Comment[mt]=Interfaċċja għat-tray tas-sistema +Comment[nb]=Systemkurv grensesnitt +Comment[nds]=Systeemafsnitt-Koppelsteed +Comment[ne]=प्रणाली ट्रे इन्टरफेस +Comment[nl]=Een systeemvakinterface +Comment[nn]=Systemtrau-grensesnitt +Comment[pa]=ਇੱਕ ਸਿਸਟਮ ਟਰੇ ਇੰਟਰਫੇਸ +Comment[pl]=Interfejs tacki systemowej +Comment[pt]=Uma interface para a bandeja do sistema +Comment[pt_BR]=Uma interface para os ícones de sistema +Comment[ro]=O interfaţă pentru tava de sistem +Comment[ru]=Интерфейс панели системного лотка +Comment[sk]=Rozhranie pre systémovú lištu +Comment[sl]=Vmesnik za sistemsko vrstico v pultu +Comment[sr]=Интерфејс за системску касету +Comment[sr@Latn]=Interfejs za sistemsku kasetu +Comment[sv]=Gränssnitt för aktivitetsfältet +Comment[ta]=அமைப்பு தொகுதித் தட்டு இடைமுகம் +Comment[tg]=Интерфейси сабади системавӣ +Comment[th]=ส่วนติดต่อกับถาดระบบ +Comment[tr]=Sistem çekmecesi arayüzü +Comment[uk]=Інтерфейс системного лотка +Comment[ven]=Thirei ya sisitemu +Comment[xh]=Ujongano lwendlela yetreyi +Comment[zh_CN]=一个系统托盘界面 +Comment[zh_HK]=系統匣介面 +Comment[zh_TW]=System Tray的介面 +Comment[zu]=Isistimu yetreyi loxhumano olubhekene diff --git a/noatun/modules/systray/systrayui.rc b/noatun/modules/systray/systrayui.rc new file mode 100644 index 00000000..2b50654b --- /dev/null +++ b/noatun/modules/systray/systrayui.rc @@ -0,0 +1,20 @@ +<!DOCTYPE kpartgui> +<kpartgui name="noatunsystray" version="12"> +<Menu name="tray"> + <Action name="file_open"/> + <Action name="show_playlist"/> + <Separator lineSeparator="true"/> + <Action name="back"/> + <Action name="stop"/> + <Action name="play"/> + <Action name="forward"/> + <Separator lineSeparator="true"/> + <Action name="loop_style"/> + <Action name="effects"/> + <Action name="equalizer"/> + <Separator lineSeparator="true"/> + <Action name="options_configure"/> + <Separator lineSeparator="true"/> + <Action name="file_quit"/> +</Menu> +</kpartgui> diff --git a/noatun/modules/systray/yhconfig.kcfg b/noatun/modules/systray/yhconfig.kcfg new file mode 100644 index 00000000..9b017aec --- /dev/null +++ b/noatun/modules/systray/yhconfig.kcfg @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <kcfgfile name="noatunrc"/> + <group name="Young Hickory"> + + <entry key="State Icon Display" type="Enum"> + <label>State Icon Display</label> + <choices> + <choice name="Animation"/> + <choice name="FlashingIcon"/> + <choice name="StaticIcon"/> + <choice name="NoIcon"/> + </choices> + <default>FlashingIcon</default> + </entry> + + <entry name="icon" type="Int"> + <label>Icon</label> + <default>1</default> + </entry> + + <entry name="tip" type="Bool"> + <label>Show a tooltip for the current track</label> + <default>true</default> + </entry> + + <entry name="passivePopup" type="Bool"> + <label>Announce tracks with a popup window</label> + <default>true</default> + </entry> + + <entry name="passivePopupTimeout" type="Int"> + <label>Display popup window for x seconds</label> + <default>5</default> + </entry> + + <entry name="passivePopupCovers" type="Bool"> + <label>Show covers in popup window and tooltip</label> + <default>true</default> + </entry> + + <entry name="passivePopupButtons" type="Bool"> + <label>Show buttons in popup window</label> + <default>true</default> + </entry> + + + <entry key="MiddleMouse Action" type="Enum"> + <label>Mode</label> + <choices> + <choice name="PlayPause"/> + <choice name="HideShowPlaylist"/> + </choices> + <default>HideShowPlaylist</default> + </entry> + + <entry name="MouseWheelAction$(Modifier)" type="Enum" key="mousewheelaction_$(Modifier)"> + <parameter name="Modifier" type="Enum"> + <values> + <value>None</value> + <value>Shift</value> + <value>Alt</value> + <value>Ctrl</value> + </values> + </parameter> + <choices> + <choice name="Nothing"/> + <choice name="ChangeVolume"/> + <choice name="ChangeTrack"/> + </choices> + <default param="None">ChangeVolume</default> + <default param="Shift">Nothing</default> + <default param="Alt">Nothing</default> + <default param="Ctrl">ChangeTrack</default> + </entry> + + </group> +</kcfg> diff --git a/noatun/modules/systray/yhconfig.kcfgc b/noatun/modules/systray/yhconfig.kcfgc new file mode 100644 index 00000000..5b4f99e4 --- /dev/null +++ b/noatun/modules/systray/yhconfig.kcfgc @@ -0,0 +1,7 @@ +# Code generation options for kconfig_compiler +File=yhconfig.kcfg +ClassName=YHConfig +Singleton=true +Mutators=true +MemberVariables=private +GlobalEnums=true diff --git a/noatun/modules/systray/yhconfigwidget.ui b/noatun/modules/systray/yhconfigwidget.ui new file mode 100644 index 00000000..48267c28 --- /dev/null +++ b/noatun/modules/systray/yhconfigwidget.ui @@ -0,0 +1,333 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>YHConfigWidget</class> +<widget class="QWidget"> + <property name="name"> + <cstring>YHConfigWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>371</width> + <height>379</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QTabWidget"> + <property name="name"> + <cstring>tabWidget2</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>&General</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>chkUseTooltip</cstring> + </property> + <property name="text"> + <string>Show a &tooltip for the current track</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>chkUseCovers</cstring> + </property> + <property name="text"> + <string>Show &covers in popup window and tooltip</string> + </property> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Popup Window</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>lblPopupTimeout</cstring> + </property> + <property name="text"> + <string>Display popup window t&ime:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>spinPopupTimeout</cstring> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>chkPopupButtons</cstring> + </property> + <property name="text"> + <string>Show &buttons in popup window</string> + </property> + </widget> + <widget class="QSpinBox" row="1" column="1"> + <property name="name"> + <cstring>spinPopupTimeout</cstring> + </property> + <property name="suffix"> + <string>s</string> + <comment>Seconds</comment> + </property> + <property name="maxValue"> + <number>600</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="value"> + <number>5</number> + </property> + </widget> + <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>chkUsePopup</cstring> + </property> + <property name="text"> + <string>Announce tracks with a &popup window</string> + </property> + </widget> + </grid> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>buttonGroup1</cstring> + </property> + <property name="title"> + <string>State Icon Display</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton" row="0" column="0"> + <property name="name"> + <cstring>rbStateAnim</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>&Animated</string> + </property> + </widget> + <widget class="QRadioButton" row="0" column="1"> + <property name="name"> + <cstring>rbStateFlashing</cstring> + </property> + <property name="text"> + <string>&Flashing</string> + </property> + </widget> + <widget class="QRadioButton" row="1" column="0"> + <property name="name"> + <cstring>rbStateStatic</cstring> + </property> + <property name="text"> + <string>&Static</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + <widget class="QRadioButton" row="1" column="1"> + <property name="name"> + <cstring>rbStateNone</cstring> + </property> + <property name="text"> + <string>&None</string> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>81</height> + </size> + </property> + </spacer> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Ad&vanced</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>grpMiddleMouse</cstring> + </property> + <property name="title"> + <string>Middle Mouse Button Action</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>rbHideShowPlaylist</cstring> + </property> + <property name="text"> + <string>Hide / Show play&list</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>rbPlayPause</cstring> + </property> + <property name="text"> + <string>&Play / Pause</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>grpMwheel</cstring> + </property> + <property name="title"> + <string>Mouse &Wheel</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>lblModifier</cstring> + </property> + <property name="text"> + <string>&Keyboard modifier:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>cmbModifier</cstring> + </property> + </widget> + <widget class="QComboBox"> + <property name="name"> + <cstring>cmbModifier</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>lblAction</cstring> + </property> + <property name="text"> + <string>Action:</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>rbActNothing</cstring> + </property> + <property name="text"> + <string>&Nothing</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>rbActVolume</cstring> + </property> + <property name="text"> + <string>Change v&olume</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>rbActTrack</cstring> + </property> + <property name="text"> + <string>Switch &track</string> + </property> + </widget> + </vbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>21</height> + </size> + </property> + </spacer> + </vbox> + </widget> + </widget> + </vbox> +</widget> +<tabstops> + <tabstop>tabWidget2</tabstop> + <tabstop>chkUseTooltip</tabstop> + <tabstop>chkUseCovers</tabstop> + <tabstop>chkUsePopup</tabstop> + <tabstop>spinPopupTimeout</tabstop> + <tabstop>chkPopupButtons</tabstop> + <tabstop>rbStateAnim</tabstop> + <tabstop>rbStateFlashing</tabstop> + <tabstop>rbStateStatic</tabstop> + <tabstop>rbStateNone</tabstop> + <tabstop>rbHideShowPlaylist</tabstop> + <tabstop>rbPlayPause</tabstop> + <tabstop>cmbModifier</tabstop> + <tabstop>rbActNothing</tabstop> + <tabstop>rbActVolume</tabstop> + <tabstop>rbActTrack</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/noatun/modules/voiceprint/Makefile.am b/noatun/modules/voiceprint/Makefile.am new file mode 100644 index 00000000..22c3f65c --- /dev/null +++ b/noatun/modules/voiceprint/Makefile.am @@ -0,0 +1,14 @@ +INCLUDES= -I$(top_srcdir)/noatun/library $(all_includes) +kde_module_LTLIBRARIES = noatun_voiceprint.la + +noatun_voiceprint_la_SOURCES = voiceprint.cpp prefs.cpp + +noatun_voiceprint_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +noatun_voiceprint_la_LIBADD = $(LIB_KFILE) $(top_builddir)/noatun/library/libnoatun.la -lm + +noatun_voiceprint_la_METASOURCES = AUTO + +noinst_HEADERS = voiceprint.h prefs.h + +noatun_modules_voiceprint_DATA = voiceprint.plugin +noatun_modules_voiceprintdir = $(kde_datadir)/noatun diff --git a/noatun/modules/voiceprint/prefs.cpp b/noatun/modules/voiceprint/prefs.cpp new file mode 100644 index 00000000..48998680 --- /dev/null +++ b/noatun/modules/voiceprint/prefs.cpp @@ -0,0 +1,67 @@ +#include "prefs.h" +#include "voiceprint.h" + +#include <klocale.h> +#include <kglobal.h> +#include <qlabel.h> +#include <qlayout.h> +#include <kcolorbutton.h> +#include <kconfig.h> + +Prefs::Prefs(QObject* parent) + : CModule(i18n("Voiceprint"), i18n("Options for the Voiceprint Visualization"), "xapp", parent) +{ + QVBoxLayout *king=new QVBoxLayout(this); + QHBoxLayout *minor; + + QLabel *label; + mForeground=new KColorButton(this); + label=new QLabel(mForeground, i18n("&Foreground color:"), this); + minor=new QHBoxLayout(king); + minor->addWidget(label); + minor->addWidget(mForeground); + + mBackground=new KColorButton(this); + label=new QLabel(mBackground, i18n("&Background color:"), this); + minor=new QHBoxLayout(king); + minor->addWidget(label); + minor->addWidget(mBackground); + + mLine=new KColorButton(this); + label=new QLabel(mForeground, i18n("&Sweep color:"), this); + minor=new QHBoxLayout(king); + minor->addWidget(label); + minor->addWidget(mLine); + + king->addStretch(); +} + +void Prefs::reopen() +{ + KConfig *config=KGlobal::config(); + config->setGroup("VoicePrint"); + QColor black(0, 0, 0); + QColor blue(0, 0, 222); + mBackground->setColor(config->readColorEntry("Background", &black)); + mForeground->setColor(config->readColorEntry("Foreground", &blue)); + mLine->setColor(config->readColorEntry("Line", &black)); +} + +void Prefs::save() +{ + KConfig *config=KGlobal::config(); + config->setGroup("VoicePrint"); + config->writeEntry("Background", mBackground->color()); + config->writeEntry("Foreground", mForeground->color()); + config->writeEntry("Line", mLine->color()); + + config->sync(); + + VoicePrint *l=VoicePrint::voicePrint; + if (l) + l->setColors(mBackground->color(), mForeground->color(), mLine->color()); + +} + +#include "prefs.moc" + diff --git a/noatun/modules/voiceprint/prefs.h b/noatun/modules/voiceprint/prefs.h new file mode 100644 index 00000000..6541b4de --- /dev/null +++ b/noatun/modules/voiceprint/prefs.h @@ -0,0 +1,22 @@ +#ifndef PREFS_H +#define PREFS_H + +#include <qwidget.h> +#include <noatun/pref.h> + +class KColorButton; + +class Prefs : public CModule +{ +Q_OBJECT +public: + Prefs(QObject* parent); + virtual void save(); + virtual void reopen(); + +private: + KColorButton *mForeground, *mBackground, *mLine; +}; + +#endif + diff --git a/noatun/modules/voiceprint/voiceprint.cpp b/noatun/modules/voiceprint/voiceprint.cpp new file mode 100644 index 00000000..4f6c7aea --- /dev/null +++ b/noatun/modules/voiceprint/voiceprint.cpp @@ -0,0 +1,126 @@ +#include "voiceprint.h" +#include <noatun/player.h> +#include <noatun/app.h> +#include <math.h> +#include <qpainter.h> +#include "prefs.h" +#include <klocale.h> +#include <stdio.h> + +extern "C" +{ + KDE_EXPORT Plugin *create_plugin() + { + return new VoicePrint(); + } +} + +VoicePrint *VoicePrint::voicePrint=0; + +VoicePrint::VoicePrint() : QWidget(0,0,WRepaintNoErase), MonoFFTScope(50), Plugin() +{ + voicePrint=this; + mOffset=0; + mSegmentWidth=2; + setCaption(i18n("Voiceprint")); + resize(320, 240); + MonoFFTScope::start(); + show(); + setMaximumHeight(1024); +} + +VoicePrint::~VoicePrint() +{ +} + +void VoicePrint::init() +{ + Prefs *p=new Prefs(this); + p->reopen(); + p->save(); + resizeEvent(0); +} + +void VoicePrint::setColors(const QColor &bg, const QColor &fg, const QColor &l) +{ + mProgress=l; + mLowColor=bg.rgb(); + mHighColor=fg.rgb(); + setBackgroundColor(mLowColor); +} + +void VoicePrint::closeEvent(QCloseEvent *) +{ + unload(); +} + +void VoicePrint::resizeEvent(QResizeEvent *) +{ + mOffset=0; + mBuffer.resize(size()); + QPainter paint(&mBuffer); + paint.fillRect(QRect(0,0, QWidget::width(), height()), QColor(mLowColor)); + setBands(magic(height()/mSegmentWidth)); +} + +#define COLOR(color, bgcolor, fgcolor, foctet) \ + (int)( color(bgcolor) + (foctet) * (color(fgcolor) - color(bgcolor)) ) + +inline static QRgb averageByIntensity(QRgb bgcolor, QRgb fgcolor, int octet) +{ + float foctet = octet / 255.0; + + return qRgb(COLOR(qRed, bgcolor, fgcolor, foctet), + COLOR(qGreen, bgcolor, fgcolor, foctet), + COLOR(qBlue, bgcolor, fgcolor, foctet) + ); +} + +#undef COLOR + +void VoicePrint::paintEvent(QPaintEvent *e) +{ + bitBlt(this, e->rect().topLeft(), &mBuffer, e->rect(), Qt::CopyROP); +} + +void VoicePrint::scopeEvent(float *data, int bands) +{ + // save cpu + if(isHidden()) return; + + QPainter paint(&mBuffer); + // each square has a width of mSegmentWidth + float brightness = float(bands * mSegmentWidth); + for (int i=0; i<bands ; i++) + { + float b=data[bands-i-1]+1.0; + // the more bands there are, the dimmer each becomes + b=log10(b)/log(2) * 16 * brightness; + int band=int(b); + if (band>255) band=255; + else if (band<0) band=0; + + QColor area(averageByIntensity(mLowColor, mHighColor, band)); + + int bandTop=i*height()/bands, bandBottom=(i+1)*height()/bands; + paint.fillRect(mOffset, bandTop, mSegmentWidth,bandBottom-bandTop,area); + } + + int newOffset = mOffset+mSegmentWidth; + if (newOffset>QWidget::width()) newOffset=0; + paint.fillRect(newOffset, 0, mSegmentWidth, height(), mProgress); + + // redraw changes with the minimum amount of work + if(newOffset != 0) + { + repaint(mOffset,0,mSegmentWidth*2,height(),false); + } + else + { + repaint(mOffset,0,mSegmentWidth,height(),false); + repaint(newOffset,0,mSegmentWidth,height(),false); + } + mOffset = newOffset; +} + +#include "voiceprint.moc" diff --git a/noatun/modules/voiceprint/voiceprint.h b/noatun/modules/voiceprint/voiceprint.h new file mode 100644 index 00000000..ab5af69d --- /dev/null +++ b/noatun/modules/voiceprint/voiceprint.h @@ -0,0 +1,33 @@ +#ifndef VOICEPRINT_H +#define VOICEPRINT_H + +#include <noatun/plugin.h> + +class VoicePrint : public QWidget, public MonoFFTScope, public Plugin +{ +Q_OBJECT + +public: + VoicePrint(); + virtual ~VoicePrint(); + + void setColors(const QColor &bg, const QColor &fg, const QColor &l); + void init(); + +protected: + virtual void closeEvent(QCloseEvent *); + virtual void scopeEvent(float *data, int bands); + virtual void resizeEvent(QResizeEvent *); + virtual void paintEvent(QPaintEvent *); + +public: + static VoicePrint* voicePrint; + +private: + QColor mProgress; + QPixmap mBuffer; + QRgb mLowColor, mHighColor; + int mOffset, mSegmentWidth; +}; +#endif + diff --git a/noatun/modules/voiceprint/voiceprint.plugin b/noatun/modules/voiceprint/voiceprint.plugin new file mode 100644 index 00000000..b7bca4f4 --- /dev/null +++ b/noatun/modules/voiceprint/voiceprint.plugin @@ -0,0 +1,92 @@ +Filename=noatun_voiceprint.la +Author=Charles Samuels +Site=http://noatun.derkarl.org/ +Email=charles@kde.org +Type=visualization +License=Artistic +Name=Voiceprint +Name[af]=Stem afdruk +Name[az]=Səs gözləyici +Name[ca]=Empremta de veu +Name[cy]=Argraff Lais +Name[el]=Φωνητικό αποτύπωμα +Name[eo]=Voĉvidigilo +Name[es]=Huella de voz +Name[et]=Visuaalne signaal +Name[fi]=Äänikuva +Name[ga]=Guthlorg +Name[hi]=वाइसप्रिंट +Name[hr]=Otisak glasa +Name[hu]=Hanglenyomat +Name[is]=Raddrit +Name[it]=Impronta vocale +Name[ja]=ボイスプリント +Name[km]=បង្ហាញសំឡេង +Name[ko]=성문 +Name[lt]=Balso antspaudas +Name[lv]=Balssdruka +Name[mt]=Stampavuċi +Name[ne]=आवाज मुद्रण +Name[nl]=Stemafdruk +Name[pl]=Zapis głosu +Name[pt]=Impressão Vocal +Name[ro]=Amprentă vocală +Name[sl]=Galsovni zapis +Name[sv]=Röstavtryck +Name[ta]=குரல் அச்சு +Name[tr]=Ses Gözlemcisi +Name[ven]=U phirintha ha Mukosi +Name[xh]=Ushicilelo lelizwi +Name[zh_CN]=声波纹 +Name[zh_HK]=聲波紋 +Name[zh_TW]=聲波紋 +Name[zu]=Ushicilelo lelizwi +Comment=A voiceprint visualizer +Comment[bg]=Визуализатор Voiceprint +Comment[bs]=Vizualizacija sa ispisom glasa +Comment[ca]=Un visualitzador d'empremta de veu +Comment[cs]=Vizualizátor hlasu +Comment[cy]=Gweledydd argraff lais +Comment[da]=En voiceprint-visualisering +Comment[de]=Klangvisualisierung +Comment[el]=Μια αναπαράσταση αποτυπώματος φωνής +Comment[en_GB]=A voiceprint visualiser +Comment[eo]=Voĉo-vidigilo +Comment[es]=Un visualizador de huellas de voz +Comment[et]=Signaali visualiseerimise plugin +Comment[eu]=Voiceprint ikustailea +Comment[fa]=یک تجسمکننده voiceprint +Comment[fi]=Äänikuvavisualisoija +Comment[fr]=Un afficheur Voiceprint +Comment[gl]=Visualizador voiceprint +Comment[he]=ממחיש טביעות קול +Comment[hu]=Hanglenyomat-analizáló +Comment[is]=Raddritsskjár +Comment[it]=Visualizzatore di impronta vocale +Comment[ja]=声紋の視覚効果 +Comment[kk]=Дыбыс таңба бейнекөрінісі +Comment[km]=ម៉ាកែតសម្រាប់បង្ហាញសំឡេង +Comment[ko]=성문 비주얼라이저 +Comment[lt]=Balso antspaudo vaizdavimo priemonė +Comment[nb]=Voiceprint-fremvisar +Comment[nds]=Stimmafdruck-Filmmaker +Comment[ne]=आवाज मुद्रण भिजुलाइजर +Comment[nl]=Stemafdruk visualisatie +Comment[nn]=Voiceprint-framvisar +Comment[pl]=Wizualizacja śladu głosu +Comment[pt]=Um visualizador do comportamento vocal +Comment[pt_BR]=Um visualizador voiceprint +Comment[ro]=Vizualizor de amprentă vocală +Comment[ru]=визуализация voiceprint +Comment[sk]=Vizualizátor voiceprint +Comment[sl]=Predstavitelj glasovnega zapisa +Comment[sr]=Визуализатор гласовног отиска +Comment[sr@Latn]=Vizualizator glasovnog otiska +Comment[sv]=En röstavtrycksvisare +Comment[ta]=குரல் அச்சு படக்காட்சி +Comment[th]=โปรแกรมสร้างวิฌวลไลเซอร์ voiceprint +Comment[tr]=Ses Dökümü İzleme Programı +Comment[uk]=Візуаліатор voiseprint +Comment[zh_CN]=声波纹视觉效果 +Comment[zh_HK]=聲波紋顯示程式 +Comment[zh_TW]=聲波紋顯示程式 diff --git a/noatun/modules/winskin/Makefile.am b/noatun/modules/winskin/Makefile.am new file mode 100644 index 00000000..5c0423e6 --- /dev/null +++ b/noatun/modules/winskin/Makefile.am @@ -0,0 +1,51 @@ +SUBDIRS = vis skins mimetypes + +noatun_modules_winskin_DATA = winskin.plugin +noatun_modules_winskindir = $(kde_datadir)/noatun + +INCLUDES = -I$(top_srcdir)/noatun/library \ + -I$(top_builddir)/noatun/library \ + -I$(kde_includes)/arts \ + $(all_includes) + +kde_module_LTLIBRARIES = noatun_winskin.la + +noatun_winskin_la_SOURCES = fileInfo.cpp \ + guiSpectrumAnalyser.cpp \ + plugin.cpp \ + waBalanceSlider.cpp \ + waButton.cpp \ + waClutterbar.cpp \ + waColor.cpp \ + waDigit.cpp \ + waInfo.cpp \ + waIndicator.cpp \ + waJumpSlider.cpp \ + waLabel.cpp \ + waMain.cpp \ + waRegion.cpp \ + waSkin.cpp \ + waSkinModel.cpp \ + waSlider.cpp \ + waStatus.cpp \ + waTitleBar.cpp \ + waVolumeSlider.cpp \ + waWidget.cpp \ + winSkinConfig.cpp \ + winSkinVis.cpp \ + waSkinManager.cpp \ + waSkinManager.skel + +noatun_winskin_la_LDFLAGS = $(all_libraries) \ + -module -avoid-version -no-undefined + +noatun_winskin_la_LIBADD = $(top_builddir)/noatun/library/libnoatun.la \ + $(top_builddir)/noatun/modules/winskin/vis/libwinskinvis.la + +noatun_winskin_la_METASOURCES = AUTO + + + +waSkin.lo: ../../library/noatunarts/noatunarts.h vis/winskinvis.h +winSkinVis.lo: ../../library/noatunarts/noatunarts.h vis/winskinvis.h +guiSpectrumAnalyser.lo: ../../library/noatunarts/noatunarts.h vis/winskinvis.h diff --git a/noatun/modules/winskin/fileInfo.cpp b/noatun/modules/winskin/fileInfo.cpp new file mode 100644 index 00000000..69f93215 --- /dev/null +++ b/noatun/modules/winskin/fileInfo.cpp @@ -0,0 +1,50 @@ +#include <noatun/app.h> +#include <noatun/playlist.h> + +#include <qstring.h> +#include <kfilemetainfo.h> + +#include "fileInfo.h" + +fileInfo::fileInfo(const PlaylistItem &item) +{ + QString prop; + + prop = item.property("bitrate"); + if (prop.isNull()) + _bps = 0; + else + _bps = prop.toInt(); + + prop = item.property("samplerate"); + if (prop.isNull()) + _KHz = 44100; + else + _KHz = prop.toInt(); + + prop = item.property("channels"); + if (prop.isNull()) + _channelCount = 2; + else + _channelCount = prop.toInt(); +} + +fileInfo::~fileInfo() +{ +} + +unsigned int fileInfo::bps() +{ + return _bps; +} + +unsigned int fileInfo::KHz() +{ + return _KHz; +} + +unsigned int fileInfo::channelCount() +{ + return _channelCount; +} + diff --git a/noatun/modules/winskin/fileInfo.h b/noatun/modules/winskin/fileInfo.h new file mode 100644 index 00000000..203af087 --- /dev/null +++ b/noatun/modules/winskin/fileInfo.h @@ -0,0 +1,21 @@ +#ifndef _FILEINFO_H +#define _FILEINFO_H + +#include <noatun/playlist.h> + +class fileInfo { + public: + fileInfo(const PlaylistItem &); + ~fileInfo(); + + unsigned int bps(); + unsigned int KHz(); + unsigned int channelCount(); + + private: + int _KHz; + int _bps; + int _channelCount; +}; + +#endif diff --git a/noatun/modules/winskin/guiSpectrumAnalyser.cpp b/noatun/modules/winskin/guiSpectrumAnalyser.cpp new file mode 100644 index 00000000..d015e5da --- /dev/null +++ b/noatun/modules/winskin/guiSpectrumAnalyser.cpp @@ -0,0 +1,224 @@ +/* + winamp visualisation plugin. + Copyright (C) 2001 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include <klocale.h> +#include <qcolor.h> +#include <qpopupmenu.h> +#include <qpainter.h> +#include <kconfig.h> + +#include "waColor.h" +#include "waSkinModel.h" + +#include "guiSpectrumAnalyser.h" +#include "vis/winskinvis.h" + +#define __BANDS 75 + +GuiSpectrumAnalyser::GuiSpectrumAnalyser() + : WaWidget(_WA_MAPPING_ANALYSER) +{ + connect(WaSkinModel::instance(), SIGNAL(skinChanged()), this, SLOT(pixmapChange())); + + contextMenu = new QPopupMenu(this); + visualizationMenu = new QPopupMenu(); + analyserMenu = new QPopupMenu(); + + contextMenu->insertItem(i18n("Visualization Mode"), visualizationMenu); + contextMenu->insertItem(i18n("Analyzer Mode"), analyserMenu); + + visualizationMenu->insertItem(i18n("Analyzer"), (int)MODE_ANALYSER); + visualizationMenu->insertItem(i18n("Disabled"), (int)MODE_DISABLED); + visualizationMenu->setCheckable(true); + connect(visualizationMenu, SIGNAL(activated(int)), this, SLOT(setVisualizationMode(int))); + + analyserMenu->insertItem(i18n("Normal"), (int)MODE_NORMAL); + analyserMenu->insertItem(i18n("Fire"), (int)MODE_FIRE); + analyserMenu->insertItem(i18n("Vertical Lines"), (int)MODE_VERTICAL_LINES); + analyserMenu->setCheckable(true); + connect(analyserMenu, SIGNAL(activated(int)), this, SLOT(setAnalyserMode(int))); + + analyserCache = NULL; + winSkinVis = NULL; + + KConfig *config = KGlobal::config(); + config->setGroup("Winskin"); + + setVisualizationMode(config->readNumEntry("visualizationMode", MODE_ANALYSER)); + setAnalyserMode(config->readNumEntry("analyserMode", MODE_NORMAL)); +} + + +GuiSpectrumAnalyser::~GuiSpectrumAnalyser() +{ + KConfig *config = KGlobal::config(); + config->setGroup("Winskin"); + + config->writeEntry("visualizationMode", visualization_mode); + config->writeEntry("analyserMode", analyser_mode); + + delete analyserCache; +} + +void GuiSpectrumAnalyser::mousePressEvent ( QMouseEvent *e ) +{ + if (e->button() == LeftButton) { + if (visualization_mode == MODE_DISABLED) + setVisualizationMode(MODE_ANALYSER); + else + setVisualizationMode(MODE_DISABLED); + } + else if (e->button() == RightButton) { + contextMenu->popup(mapToGlobal(QPoint(e->x(), e->y()))); + } +} + +void GuiSpectrumAnalyser::setAnalyserMode(int mode) +{ + analyser_mode = mode; + + analyserMenu->setItemChecked(MODE_NORMAL, (mode == MODE_NORMAL)); + analyserMenu->setItemChecked(MODE_FIRE, (mode == MODE_FIRE)); + analyserMenu->setItemChecked(MODE_VERTICAL_LINES, (mode == MODE_VERTICAL_LINES)); + + delete analyserCache; + analyserCache = NULL; +} + +void GuiSpectrumAnalyser::pauseVisualization() +{ + hide(); +} + +void GuiSpectrumAnalyser::resumeVisualization() +{ + show(); +} + +void GuiSpectrumAnalyser::updatePeaks() +{ + if ((visualization_mode == MODE_DISABLED) || (!isVisible())) + return; + + float* currentPeaks = winSkinVis->currentPeaks(); + + if (!analyserCache) + freshenAnalyserCache(); + + for (int x = 0;x < __BANDS;x++) { + int amp = int(currentPeaks[x]); + + if (amp < 0) + amp = 0; + else if (amp > 16) + amp = 16; + + bitBlt(this, x, 0, analyserCache, (amp * 2) + (x % 2), 0, 1, 16); + } +} + +void GuiSpectrumAnalyser::setVisualizationMode(int mode) +{ + visualization_mode = mode; + + visualizationMenu->setItemChecked(MODE_ANALYSER, (mode == MODE_ANALYSER)); + visualizationMenu->setItemChecked(MODE_DISABLED, (mode == MODE_DISABLED)); + + if (mode == MODE_ANALYSER) + { + if (!winSkinVis) + { + winSkinVis=new WinSkinVis(this,"WinSkinVis"); + connect(winSkinVis,SIGNAL(doRepaint()),this,SLOT(updatePeaks())); + } + } + else + { + delete winSkinVis; + winSkinVis = NULL; + } + + update(); +} + + +void GuiSpectrumAnalyser::freshenAnalyserCache() +{ + // We need a color scheme + if (!colorScheme) + return; + + // The analyser cache is a 34x16 pixmap containing all the bits needed + // to quickly draw the spectrum analyser + analyserCache = new QPixmap(34, 16); + QPainter p(analyserCache); + + for (unsigned int x = 0;x < 17;x++) { + if (x != 16) { + p.setPen(QPen(colorScheme->skinColors[INDEX_BACKGROUND_COLOR])); + p.drawLine(x * 2, 0, x * 2, 16 - x - 1); + } + + for (unsigned int y = 0; y < (16 - x);y++) { + if (y % 2) + p.setPen(QPen(colorScheme->skinColors[INDEX_GRID_COLOR])); + else + p.setPen(QPen(colorScheme->skinColors[INDEX_BACKGROUND_COLOR])); + + p.drawPoint((x * 2) + 1, y); + } + + if (!x) + continue; + + switch (analyser_mode) { + case MODE_FIRE: + for (unsigned int y = (16 - x); y < 16; y++) { + p.setPen(QPen(colorScheme->skinColors[INDEX_SPEC_BASE + (y - (16 - x))])); + p.drawPoint((x * 2), y); + p.drawPoint((x * 2) + 1, y); + } + break; + case MODE_VERTICAL_LINES: + p.setPen(QPen(colorScheme->skinColors[INDEX_SPEC_BASE + (16 - x)])); + p.drawLine((x * 2), (15 - x), (x * 2), 15); + p.drawLine((x * 2) + 1, (15 - x), (x * 2) + 1, 15); + break; + case MODE_NORMAL: + // Fall through + default: + for (unsigned int y = (16 - x); y < 16; y++) { + p.setPen(QPen(colorScheme->skinColors[INDEX_SPEC_BASE + y])); + p.drawPoint((x * 2), y); + p.drawPoint((x * 2) + 1, y); + } + break; + } + } +} + +void GuiSpectrumAnalyser::paintEvent (QPaintEvent *) +{ + if (visualization_mode == MODE_DISABLED) + paintBackground(); +} + +void GuiSpectrumAnalyser::pixmapChange() +{ + delete analyserCache; + analyserCache = NULL; +} + + +#include "guiSpectrumAnalyser.moc" + diff --git a/noatun/modules/winskin/guiSpectrumAnalyser.h b/noatun/modules/winskin/guiSpectrumAnalyser.h new file mode 100644 index 00000000..ecef8d37 --- /dev/null +++ b/noatun/modules/winskin/guiSpectrumAnalyser.h @@ -0,0 +1,66 @@ +/* + a GUI for a spectrum analyser + Copyright (C) 1998 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#ifndef _GUISPECTRUMANALYSER_H +#define _GUISPECTRUMANALYSER_H + +#include <math.h> + +#include "winSkinVis.h" +#include "waWidget.h" +#include "waColor.h" + + +#define MAX_MODE 1 + +enum visualizationMode {MODE_DISABLED = 0, MODE_ANALYSER = 1}; +enum analyserMode {MODE_NORMAL = 0, MODE_FIRE = 1, MODE_VERTICAL_LINES = 2}; + +class GuiSpectrumAnalyser : public WaWidget { + Q_OBJECT + + public: + GuiSpectrumAnalyser(); + ~GuiSpectrumAnalyser(); + + void mousePressEvent(QMouseEvent * mouseEvent); + + public slots: + void pauseVisualization(); + void resumeVisualization(); + + private slots: + void pixmapChange(); + void updatePeaks(); + + void setVisualizationMode(int); + void setAnalyserMode(int); + + private: + void paintEvent(QPaintEvent *); + + QPopupMenu *contextMenu; + QPopupMenu *visualizationMenu; + QPopupMenu *analyserMenu; + + void freshenAnalyserCache(); + + int visualization_mode; + int analyser_mode; + + QPixmap *analyserCache; + WinSkinVis *winSkinVis; +}; +#endif + diff --git a/noatun/modules/winskin/mimetypes/Makefile.am b/noatun/modules/winskin/mimetypes/Makefile.am new file mode 100644 index 00000000..c28d0e8e --- /dev/null +++ b/noatun/modules/winskin/mimetypes/Makefile.am @@ -0,0 +1,2 @@ + +SUBDIRS = interface diff --git a/noatun/modules/winskin/mimetypes/interface/Makefile.am b/noatun/modules/winskin/mimetypes/interface/Makefile.am new file mode 100644 index 00000000..9ca52284 --- /dev/null +++ b/noatun/modules/winskin/mimetypes/interface/Makefile.am @@ -0,0 +1,6 @@ +noatun_modules_winskin_mimetypes_interface_DATA = x-winamp-skin.desktop + +noatun_modules_winskin_mimetypes_interfacedir = $(kde_mimedir)/interface + +EXTRA_DIST = $(noatun_modules_winskin_mimetypes_interface_DATA) + diff --git a/noatun/modules/winskin/mimetypes/interface/x-winamp-skin.desktop b/noatun/modules/winskin/mimetypes/interface/x-winamp-skin.desktop new file mode 100644 index 00000000..34686e98 --- /dev/null +++ b/noatun/modules/winskin/mimetypes/interface/x-winamp-skin.desktop @@ -0,0 +1,58 @@ +[Desktop Entry] +Type=MimeType +MimeType=interface/x-winamp-skin +Icon=colorscm +Patterns=*.wsz;*.WSZ +Comment=Compressed Winamp Skin +Comment[bg]=Компресирана тема за Winamp +Comment[bn]=কম্প্রেস করা উইন-অ্যাম্প স্কিন +Comment[br]=Kroc'hen Winamp gwasket +Comment[bs]=Komprimirani Winamp skin +Comment[ca]=Aparença Winamp comprimida +Comment[cs]=Komprimovaný Winamp skin +Comment[cy]=Croen Winamp cywasgedig +Comment[da]=Komprimeret Winamp-forside +Comment[de]=Komprimierte Winamp-Oberfläche +Comment[el]=Συμπιεσμένο θέμα Winamp +Comment[eo]=Kunpremita Winamp-etoso +Comment[es]=Piel comprimida de Winamp +Comment[et]=Winampi pakitud kest (skin) +Comment[eu]=Winamp azal konprimitua +Comment[fa]=Winamp Skin فشرده +Comment[fi]=Pakattu Winamp-nahka +Comment[fr]=Revêtement Winamp compacté +Comment[gl]=Pel de Winamp Comprimida +Comment[he]=Winamp דחוס של Skin +Comment[hi]=संपीडित विनएम्प स्किन +Comment[hu]=Tömörített Winamp-kinézet +Comment[is]=Þjappað Winamp-skin +Comment[it]=Skin di Winamp compressa +Comment[ja]=圧縮された Winamp のスキン +Comment[kk]=Сығылған Winamp тысы +Comment[km]=ស្បែក Winamp បានបង្ហាប់ +Comment[ko]=압축된 Winamp 스킨 +Comment[lt]=Suglaudintas Winamp pavidalas +Comment[mk]=Компресирана маска Winamp +Comment[nb]=Komprimert Winamp-ham +Comment[nds]=Komprimeert Winamp-Böversiet +Comment[ne]=सङ्कुचित विन्याप स्किन +Comment[nl]=Gecomprimeerde Winamp-skin +Comment[nn]=Komprimert Winamp-drakt +Comment[pl]=Skompresowana skóra Winampa +Comment[pt]=Aspecto Comprimido do Winamp +Comment[pt_BR]=Skin do Winamp comprimido +Comment[ro]=Interfaţă Winamp comprimată +Comment[ru]=Сжатая тема Winamp +Comment[sk]=Komprimované rozhranie pre Winamp +Comment[sl]=Stisnjena preobleka za Winamp +Comment[sr]=Компресован Winamp-ов скин +Comment[sr@Latn]=Kompresovan Winamp-ov skin +Comment[sv]=Komprimerat Winamp-skal +Comment[ta]=அழுத்தப்பட்ட வின் ஆம்ப் அலங்கார அமைப்பு +Comment[tg]=Намуди Фишурдашудаи Winamp +Comment[th]=หน้ากากวินแอมป์บีบอัด Compress +Comment[tr]=Sıkıştırılmış Winamp Teması +Comment[uk]=Стиснутий жупан Winamp +Comment[zh_CN]=压缩的 Winamp 皮肤 +Comment[zh_HK]=已壓縮的 Winamp skin +Comment[zh_TW]=壓縮的 Winamp 面板 diff --git a/noatun/modules/winskin/plugin.cpp b/noatun/modules/winskin/plugin.cpp new file mode 100644 index 00000000..8890c515 --- /dev/null +++ b/noatun/modules/winskin/plugin.cpp @@ -0,0 +1,13 @@ +#include <kglobal.h> +#include <klocale.h> + +#include "winSkinConfig.h" +#include "waSkin.h" + +extern "C" { + KDE_EXPORT Plugin *create_plugin() { + WaSkin *new_skin = new WaSkin(); + new WinSkinConfig(new_skin, new_skin->skinManager()); + return new_skin; + } +} diff --git a/noatun/modules/winskin/skinMap.h b/noatun/modules/winskin/skinMap.h new file mode 100644 index 00000000..f67f1557 --- /dev/null +++ b/noatun/modules/winskin/skinMap.h @@ -0,0 +1,38 @@ +/* + generic type for describing skins. + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + + +#ifndef _SKINMAP_H +#define _SKINMAP_H + +#include <qpixmap.h> + +typedef struct { + int x; + int y; + int width; + int height; +} SkinMap; + +typedef struct { + int fileId; + int x; + int y; + int width; + int height; +} SkinDesc; + + + +#endif diff --git a/noatun/modules/winskin/skins/Makefile.am b/noatun/modules/winskin/skins/Makefile.am new file mode 100644 index 00000000..8f8e17ab --- /dev/null +++ b/noatun/modules/winskin/skins/Makefile.am @@ -0,0 +1,11 @@ +# widgetlib - Makefile.am + +SUBDIRS = winamp + + + + + + + + diff --git a/noatun/modules/winskin/skins/winamp/BALANCE.BMP b/noatun/modules/winskin/skins/winamp/BALANCE.BMP Binary files differnew file mode 100644 index 00000000..3ce036e9 --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/BALANCE.BMP diff --git a/noatun/modules/winskin/skins/winamp/CBUTTONS.BMP b/noatun/modules/winskin/skins/winamp/CBUTTONS.BMP Binary files differnew file mode 100644 index 00000000..8b335e55 --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/CBUTTONS.BMP diff --git a/noatun/modules/winskin/skins/winamp/FONT.BMP b/noatun/modules/winskin/skins/winamp/FONT.BMP Binary files differnew file mode 100644 index 00000000..57caa947 --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/FONT.BMP diff --git a/noatun/modules/winskin/skins/winamp/MAIN.BMP b/noatun/modules/winskin/skins/winamp/MAIN.BMP Binary files differnew file mode 100644 index 00000000..5e8a2cec --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/MAIN.BMP diff --git a/noatun/modules/winskin/skins/winamp/MONOSTER.BMP b/noatun/modules/winskin/skins/winamp/MONOSTER.BMP Binary files differnew file mode 100644 index 00000000..35fee70c --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/MONOSTER.BMP diff --git a/noatun/modules/winskin/skins/winamp/Makefile.am b/noatun/modules/winskin/skins/winamp/Makefile.am new file mode 100644 index 00000000..169e1bc5 --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/Makefile.am @@ -0,0 +1,8 @@ + +EXTRA_DIST = BALANCE.BMP CBUTTONS.BMP FONT.BMP MAIN.BMP \ + MONOSTER.BMP NUMS_EX.BMP PLAYPAUS.BMP \ + POSBAR.BMP SHUFREP.BMP SPEC.BMP \ + TEXT.BMP TITLEBAR.BMP VISCOLOR.TXT VOLUME.BMP + +skin_DATA = $(EXTRA_DIST) +skindir = $(kde_datadir)/noatun/skins/winamp/Winamp diff --git a/noatun/modules/winskin/skins/winamp/NUMS_EX.BMP b/noatun/modules/winskin/skins/winamp/NUMS_EX.BMP Binary files differnew file mode 100644 index 00000000..72c3215d --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/NUMS_EX.BMP diff --git a/noatun/modules/winskin/skins/winamp/PLAYPAUS.BMP b/noatun/modules/winskin/skins/winamp/PLAYPAUS.BMP Binary files differnew file mode 100644 index 00000000..90319a0e --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/PLAYPAUS.BMP diff --git a/noatun/modules/winskin/skins/winamp/POSBAR.BMP b/noatun/modules/winskin/skins/winamp/POSBAR.BMP Binary files differnew file mode 100644 index 00000000..be6636ca --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/POSBAR.BMP diff --git a/noatun/modules/winskin/skins/winamp/SHUFREP.BMP b/noatun/modules/winskin/skins/winamp/SHUFREP.BMP Binary files differnew file mode 100644 index 00000000..12f5e406 --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/SHUFREP.BMP diff --git a/noatun/modules/winskin/skins/winamp/SPEC.BMP b/noatun/modules/winskin/skins/winamp/SPEC.BMP Binary files differnew file mode 100644 index 00000000..38df7813 --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/SPEC.BMP diff --git a/noatun/modules/winskin/skins/winamp/TEXT.BMP b/noatun/modules/winskin/skins/winamp/TEXT.BMP Binary files differnew file mode 100644 index 00000000..5b0b3a77 --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/TEXT.BMP diff --git a/noatun/modules/winskin/skins/winamp/TITLEBAR.BMP b/noatun/modules/winskin/skins/winamp/TITLEBAR.BMP Binary files differnew file mode 100644 index 00000000..b3109235 --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/TITLEBAR.BMP diff --git a/noatun/modules/winskin/skins/winamp/VISCOLOR.TXT b/noatun/modules/winskin/skins/winamp/VISCOLOR.TXT new file mode 100644 index 00000000..5871ad89 --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/VISCOLOR.TXT @@ -0,0 +1,24 @@ +0,0,0, // color 0 = black
+24,33,41, // color 1 = grey for dots
+239,49,16, // color 2 = top of spec
+206,41,16, // 3
+214,90,0, // 4
+214,102,0, // 5
+214,115,0, // 6
+198,123,8, // 7
+222,165,24, // 8
+214,181,33, // 9
+189,222,41, // 10
+148,222,33, // 11
+41,206,16, // 12
+50,190,16, // 13
+57,181,16, // 14
+49,156,8, // 15
+41,148,0, // 16
+24,132,8, // 17 = bottom of spec
+255,255,255, // 18 = osc 1
+214,214,222, // 19 = osc 2 (slightly dimmer)
+181,189,189, // 20 = osc 3
+160,170,175, // 21 = osc 4
+148,156,165, // 22 = osc 4
+150, 150, 150, // 23 = analyzer peak dots
diff --git a/noatun/modules/winskin/skins/winamp/VOLUME.BMP b/noatun/modules/winskin/skins/winamp/VOLUME.BMP Binary files differnew file mode 100644 index 00000000..deb7e924 --- /dev/null +++ b/noatun/modules/winskin/skins/winamp/VOLUME.BMP diff --git a/noatun/modules/winskin/vis/Makefile.am b/noatun/modules/winskin/vis/Makefile.am new file mode 100644 index 00000000..6935d860 --- /dev/null +++ b/noatun/modules/winskin/vis/Makefile.am @@ -0,0 +1,39 @@ +INCLUDES= -I$(kde_includes)/arts $(all_includes) +KDE_OPTIONS = nofinal + +DISTCLEANFILES = winskinvis.h winskinvis.cc + +winskinvis.mcopclass: winskinvis.h +winskinvis.mcoptype: winskinvis.h +winskinvis.cc winskinvis.h : $(srcdir)/winskinvis.idl + $(MCOPIDL) -t -I$(kde_includes)/arts $(srcdir)/winskinvis.idl + +lib_LTLIBRARIES = libwinskinvis.la +libwinskinvis_la_SOURCES= winskinvis.cc \ + winSkinFFT_impl.cpp realFFT.cpp \ + realFFTFilter.cpp visQueue.cpp + + +libwinskinvis_la_LDFLAGS= $(all_libraries) -avoid-version \ + -no-undefined + +libwinskinvis_la_LIBADD = -lkmedia2_idl -lsoundserver_idl -lartsflow +libwinskinvis_la_COMPILE_FIRST = winskinvis.cc +libwinskinvis_la_METASOURCES = AUTO + + + +mcoptypedir = $(libdir)/mcop +mcoptype_DATA = winskinvis.mcoptype winskinvis.mcopclass + +mcopclassdir = $(libdir)/mcop/Noatun +mcopclass_DATA = WinSkinFFT.mcopclass + +noatuninclude_HEADERS = winskinvis.h + +noatunincludedir = $(includedir)/noatun + + +winSkinFFT_impl.lo: winskinvis.h +winskinvis.lo: winskinvis.h + diff --git a/noatun/modules/winskin/vis/WinSkinFFT.mcopclass b/noatun/modules/winskin/vis/WinSkinFFT.mcopclass new file mode 100644 index 00000000..90d21e61 --- /dev/null +++ b/noatun/modules/winskin/vis/WinSkinFFT.mcopclass @@ -0,0 +1,5 @@ +Interface=Noatun::WinSkinFFT,Arts::StereoEffect,Arts::Object +Language=C++ +Library=libwinskinvis.la + + diff --git a/noatun/modules/winskin/vis/realFFT.cpp b/noatun/modules/winskin/vis/realFFT.cpp new file mode 100644 index 00000000..330280ea --- /dev/null +++ b/noatun/modules/winskin/vis/realFFT.cpp @@ -0,0 +1,156 @@ +/* + a FFT class + Copyright (C) 1998 Martin Vogt;Philip VanBaren + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "realFFT.h" + +/* + * Initialize the Sine table and Twiddle pointers (bit-reversed pointers) + * for the FFT routine. + */ +RealFFT::RealFFT(int fftlen) { + int i; + int temp; + int mask; + + /* + * FFT size is only half the number of data points + * The full FFT output can be reconstructed from this FFT's output. + * (This optimization can be made since the data is real.) + */ + Points = fftlen; + + if((SinTable=(short *)malloc(Points*sizeof(short)))==NULL) + { + puts("Error allocating memory for Sine table."); + exit(1); + } + if((BitReversed=(int *)malloc(Points/2*sizeof(int)))==NULL) + { + puts("Error allocating memory for BitReversed."); + exit(1); + } + + for(i=0;i<Points/2;i++) + { + temp=0; + for(mask=Points/4;mask>0;mask >>= 1) + temp=(temp >> 1) + (i&mask ? Points/2 : 0); + + BitReversed[i]=temp; + } + + for(i=0;i<Points/2;i++) + { + register double s,c; + s=floor(-32768.0*sin(2*M_PI*i/(Points))+0.5); + c=floor(-32768.0*cos(2*M_PI*i/(Points))+0.5); + if(s>32767.5) s=32767; + if(c>32767.5) c=32767; + SinTable[BitReversed[i] ]=(short)s; + SinTable[BitReversed[i]+1]=(short)c; + } + +} + +/* + * Free up the memory allotted for Sin table and Twiddle Pointers + */ +RealFFT::~RealFFT() { + free(BitReversed); + free(SinTable); + Points=0; +} + + +/* + * Actual FFT routine. Must call InitializeFFT(fftlen) first! + * This routine has another parameter list than the other fft's + * But because we want a fast fft on pcm data this routine + * is better than the other two. + * The other two can be useful for inverse FFT. + * The format is an array of floats. (only real parts the img + * part does not exists) + */ +void RealFFT::fft(short* buffer) { + int ButterfliesPerGroup=Points/4; + + endptr1=buffer+Points; + + /* + * Butterfly: + * Ain-----Aout + * \ / + * / \ + * Bin-----Bout + */ + + while(ButterfliesPerGroup>0) + { + A=buffer; + B=buffer+ButterfliesPerGroup*2; + sptr=SinTable; + + while(A<endptr1) + { + register short sin=*sptr; + register short cos=*(sptr+1); + endptr2=B; + while(A<endptr2) + { + long v1=((long)*B*cos + (long)*(B+1)*sin) >> 15; + long v2=((long)*B*sin - (long)*(B+1)*cos) >> 15; + *B=(*A+v1)>>1; + *(A++)=*(B++)-v1; + *B=(*A-v2)>>1; + *(A++)=*(B++)+v2; + } + A=B; + B+=ButterfliesPerGroup*2; + sptr+=2; + } + ButterfliesPerGroup >>= 1; + } + /* + * Massage output to get the output for a real input sequence. + */ + br1=BitReversed+1; + br2=BitReversed+Points/2-1; + + while(br1<=br2) + { + register long temp1,temp2; + short sin=SinTable[*br1]; + short cos=SinTable[*br1+1]; + A=buffer+*br1; + B=buffer+*br2; + HRplus = (HRminus = *A - *B ) + (*B << 1); + HIplus = (HIminus = *(A+1) - *(B+1)) + (*(B+1) << 1); + temp1 = ((long)sin*HRminus - (long)cos*HIplus) >> 15; + temp2 = ((long)cos*HRminus + (long)sin*HIplus) >> 15; + *B = (*A = (HRplus + temp1) >> 1) - temp1; + *(B+1) = (*(A+1) = (HIminus + temp2) >> 1) - HIminus; + + br1++; + br2--; + } + /* + * Handle DC bin separately + */ + buffer[0]+=buffer[1]; + buffer[1]=0; +} + + +int* RealFFT::getBitReversed() { + return BitReversed; +} diff --git a/noatun/modules/winskin/vis/realFFT.h b/noatun/modules/winskin/vis/realFFT.h new file mode 100644 index 00000000..39c6dbfd --- /dev/null +++ b/noatun/modules/winskin/vis/realFFT.h @@ -0,0 +1,69 @@ +/* + a FFT class + Copyright (C) 1998 Martin Vogt;Philip VanBaren + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + + +#ifndef __REALFFT_H +#define __REALFFT_H + +#include <math.h> +#include <stdlib.h> +#include <stdio.h> + +/** + <pre> + * Program: REALFFTF.C + * Author: Philip VanBaren + * Date: 2 September 1993 + * + * Description: These routines perform an FFT on real data. + * On a 486/33 compiled using Borland C++ 3.1 with full + * speed optimization and a small memory model, a 1024 point + * FFT takes about 16ms. + * This code is for floating point data. + * + * Note: Output is BIT-REVERSED! so you must use the BitReversed to + * get legible output, (i.e. Real_i = buffer[ BitReversed[i] ] + * Imag_i = buffer[ BitReversed[i]+1 ] ) + * Input is in normal order. + </pre> + */ + + + +class RealFFT { + + int* BitReversed; + short* SinTable; + int Points; + + public: + RealFFT(int fftlen); + ~RealFFT(); + + void fft(short* buffer); + int* getBitReversed(); + + private: + + short *A,*B; + short *sptr; + short *endptr1,*endptr2; + int *br1,*br2; + long HRplus,HRminus,HIplus,HIminus; + + +}; + + +#endif diff --git a/noatun/modules/winskin/vis/realFFTFilter.cpp b/noatun/modules/winskin/vis/realFFTFilter.cpp new file mode 100644 index 00000000..13343bce --- /dev/null +++ b/noatun/modules/winskin/vis/realFFTFilter.cpp @@ -0,0 +1,88 @@ +/* + a FFT filter + Copyright (C) 1998 Martin Vogt;Philip VanBaren, 2 September 1993 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "realFFTFilter.h" + +RealFFTFilter::RealFFTFilter(int fftPoints) { + this->fftPoints = fftPoints; + data=new short[fftPoints*4]; + realFFT= new RealFFT(fftPoints*2); +} + + +RealFFTFilter::~RealFFTFilter() { + delete data; + delete realFFT; +} + + +int RealFFTFilter::getPoints() { + return fftPoints; +} + + +short* RealFFTFilter::getPointPtr() { + return data; +} + + +/* + the array is expected to be a PCM stream (real data) +*/ +int RealFFTFilter::fft16(float* left,float* right,int len) { + int i; + + len=len/4; + + + int mixTmp; + + // take care for no array overflows: + int n=min(len,fftPoints); + + // copy things into fftArray. + + for (i = 0 ; i < n; i++) { + mixTmp=(int) (16384.0*(left[i]+right[i])); + + if (mixTmp < SHRT_MIN) { + data[i]= SHRT_MIN; + } else { + if (mixTmp > SHRT_MAX) { + data[i] = SHRT_MAX; + } else { + data[i]=(short)mixTmp; + } + } + } + + realFFT->fft(data); + return true; +} + + + +int* RealFFTFilter::getBitReversed() { + return realFFT->getBitReversed(); +} + + + +int RealFFTFilter::min(int x1,int x2) { + if (x1 < x2) { + return x1; + } + return x2; +} + + diff --git a/noatun/modules/winskin/vis/realFFTFilter.h b/noatun/modules/winskin/vis/realFFTFilter.h new file mode 100644 index 00000000..255e5191 --- /dev/null +++ b/noatun/modules/winskin/vis/realFFTFilter.h @@ -0,0 +1,49 @@ +/* + a FFT filter + Copyright (C) 1998 Martin Vogt;Philip VanBaren, 2 September 1993 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + + +#ifndef __REALFFTFILTER_H +#define __REALFFTFILTER_H + + + +#include "realFFT.h" +#include <limits.h> + + + +class RealFFTFilter { + + int fftPoints; + RealFFT* realFFT; + + short* data; + + + public: + RealFFTFilter(int points); + ~RealFFTFilter(); + int fft16(float* left,float* right,int len); + + int* getBitReversed(); + int getPoints(); + short* getPointPtr(); + + private: + int min(int x1,int x2); + +}; + + +#endif diff --git a/noatun/modules/winskin/vis/visQueue.cpp b/noatun/modules/winskin/vis/visQueue.cpp new file mode 100644 index 00000000..370930d2 --- /dev/null +++ b/noatun/modules/winskin/vis/visQueue.cpp @@ -0,0 +1,43 @@ +/* + queue fft samples + Copyright (C) 2001 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "visQueue.h" + + +VISQueue::VISQueue(int elements) { + this->elements=elements; + + visArrayQueue = new std::vector<float>*[elements]; + for(int i=0;i<elements;i++) + { + visArrayQueue[i]=new std::vector<float>; + } + +} + +VISQueue::~VISQueue() { + for(int i=0;i<elements;i++) { + delete visArrayQueue[i]; + } + delete [] visArrayQueue; +} + +std::vector<float>* VISQueue::getElement(int i) +{ + if ( (i < 0) || (i>elements) ) { + return visArrayQueue[0]; + } + return visArrayQueue[i]; +} + + diff --git a/noatun/modules/winskin/vis/visQueue.h b/noatun/modules/winskin/vis/visQueue.h new file mode 100644 index 00000000..2f737fd1 --- /dev/null +++ b/noatun/modules/winskin/vis/visQueue.h @@ -0,0 +1,32 @@ +/* + queue fft samples + Copyright (C) 2001 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef __VISQUEUE_H +#define __VISQUEUE_H + + +#include <vector> + +class VISQueue { + + int elements; + std::vector<float> **visArrayQueue; + + public: + VISQueue(int elements); + ~VISQueue(); + + std::vector<float>* getElement(int i); + +}; +#endif diff --git a/noatun/modules/winskin/vis/winSkinFFT_impl.cpp b/noatun/modules/winskin/vis/winSkinFFT_impl.cpp new file mode 100644 index 00000000..5396ac3c --- /dev/null +++ b/noatun/modules/winskin/vis/winSkinFFT_impl.cpp @@ -0,0 +1,148 @@ +/* + implementation for winskin fft + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#include "winSkinFFT_impl.h" +#include <audiosubsys.h> +#include <cstring> + +#define __BANDS 75 + +namespace Noatun { + +WinSkinFFT_impl::WinSkinFFT_impl() { + fftBands_short=256; + realFFTFilter= new RealFFTFilter(fftBands_short); + fftArray=new int[fftBands_short]; + bands=0; + + fragCnt=(int)(AudioSubSystem::the()->fragmentCount()); + visQueue=new VISQueue(fragCnt); + writePos=0; + +} + +WinSkinFFT_impl::~WinSkinFFT_impl(){ + delete realFFTFilter; + delete fftArray; + delete visQueue; +} + +void WinSkinFFT_impl::streamInit() { +} + + +void WinSkinFFT_impl::streamStart() { +} + + +void WinSkinFFT_impl::calculateBlock(unsigned long samples) { + + + unsigned long i; + + // monitoring only tasks can't be done with that StereoEffect + // interface nicely - copy input to output until there is + // something better + // (when?) + int n=sizeof(float)*samples; + memcpy(outleft,inleft,n); + memcpy(outright,inright,n); + + + if (realFFTFilter->fft16(inleft,inright,samples) == false) { + return; + } + + + + // + // The following modifications have nothing to do + // with an fft, they only make the output look nice. + // (mostly scaling) + + short* fftPtr; + int* bitReversed; + + fftPtr=realFFTFilter->getPointPtr(); + bitReversed=realFFTFilter->getBitReversed(); + + int pos=0; + int step=realFFTFilter->getPoints()/__BANDS; + + + int re; + int im; + int tmp; + + float max=0.0; + float avg=0.0; + + + + for (i=0;i<__BANDS;i++) { + re=(int)fftPtr[bitReversed[pos]]; + im=(int)fftPtr[bitReversed[pos]+1]; + + tmp=re*re+im*im; + // Here I check a new idea. We remove all low values + // and all values over xyz to xyz. + fftArray[pos]=(int)(::sqrt(::sqrt(tmp))); + + if (fftArray[pos]<=15) { + max+=fftArray[pos]; + } else { + max+=15+fftArray[pos]/2; + } + pos=pos+step; + } + avg=0.65*max/(float)__BANDS; + + pos=0; + vector<float>* visAnalyserArray=visQueue->getElement(writePos); + visAnalyserArray->clear(); + visAnalyserArray->reserve(__BANDS); + for (i=0;i<__BANDS;i++) { + float val=(float)(fftArray[pos]-avg); + visAnalyserArray->push_back(val); + pos=pos+step; + } + writePos++; + if (writePos >= fragCnt) writePos=0; + +} + + +void WinSkinFFT_impl::bandResolution(float res) { + bands=(int)res; +} + +float WinSkinFFT_impl::bandResolution() { + return (float)bands; +} + + +vector<float>* WinSkinFFT_impl::scope() { + int delay=writePos+1; + if (delay >= fragCnt) delay=0; + + + vector<float>* visAnalyserArray=visQueue->getElement(delay); + + return new vector<float>(*visAnalyserArray); +} + + +REGISTER_IMPLEMENTATION(WinSkinFFT_impl); + +} diff --git a/noatun/modules/winskin/vis/winSkinFFT_impl.h b/noatun/modules/winskin/vis/winSkinFFT_impl.h new file mode 100644 index 00000000..c1a77e45 --- /dev/null +++ b/noatun/modules/winskin/vis/winSkinFFT_impl.h @@ -0,0 +1,62 @@ +/* + implementation for winskin fft + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef __WINSKINFFT_IMPL_H +#define __WINSKINFFT_IMPL_H + +#include <artsflow.h> +#include <stdsynthmodule.h> +#include "winskinvis.h" +#include "realFFTFilter.h" +#include "visQueue.h" + + +using namespace std; +using namespace Arts; + +namespace Noatun { + +class WinSkinFFT_impl : public WinSkinFFT_skel, public StdSynthModule { + + public: + + WinSkinFFT_impl(); + ~WinSkinFFT_impl(); + + void streamInit(); + void streamStart(); + + // in: audio stream inleft, inright; + // out: audio stream outleft, outright; + void calculateBlock(unsigned long samples); + + void bandResolution(float res); + float bandResolution(); + vector<float> *scope(); + + private: + RealFFTFilter* realFFTFilter; + int fftBands_short; + int* fftArray; + VISQueue* visQueue; + int bands; + + int fragCnt; + int writePos; + int readPos; +}; + + +} + +#endif diff --git a/noatun/modules/winskin/vis/winskinvis.idl b/noatun/modules/winskin/vis/winskinvis.idl new file mode 100644 index 00000000..9b6564f4 --- /dev/null +++ b/noatun/modules/winskin/vis/winskinvis.idl @@ -0,0 +1,12 @@ +#include <artsflow.idl> + +module Noatun +{ + +interface WinSkinFFT : Arts::StereoEffect +{ + attribute float bandResolution; + sequence<float> scope(); +}; + +};
\ No newline at end of file diff --git a/noatun/modules/winskin/waBalanceSlider.cpp b/noatun/modules/winskin/waBalanceSlider.cpp new file mode 100644 index 00000000..1ac1b562 --- /dev/null +++ b/noatun/modules/winskin/waBalanceSlider.cpp @@ -0,0 +1,56 @@ +/* + balanceslider for winamp skins + Copyright (C) 1998 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include <waBalanceSlider.h> + + +WaBalanceSlider::WaBalanceSlider() : WaWidget(_WA_MAPPING_BALANCE_BAR) +{ +} + + +WaBalanceSlider::~WaBalanceSlider() +{ +} + + +void WaBalanceSlider::buildGui() +{ + ws = new WaSlider(_WA_MAPPING_BALANCE_BAR, + _WA_MAPPING_BALANCE_SLIDER, true); + + ws->setRange(-100, 100); + + + ws->setPixmapSliderButtonUp(_WA_SKIN_BALANCE_SLIDER_NORM); + ws->setPixmapSliderButtonDown(_WA_SKIN_BALANCE_SLIDER_PRES); + ws->setPixmapSliderBar(_WA_SKIN_BALANCE_BAR); + + ws->setValue(0); + + connect(ws, SIGNAL(valueChanged(int)), this, + SIGNAL(balanceSetValue(int))); + connect(ws, SIGNAL(sliderPressed()), SIGNAL(sliderPressed())); + connect(ws, SIGNAL(sliderReleased()), SIGNAL(sliderReleased())); +} + + +void WaBalanceSlider::setBalanceValue(int val) +{ + int currVal = ws->value(); + if (currVal != val) { + ws->setValue(val); + } +} + +#include "waBalanceSlider.moc" diff --git a/noatun/modules/winskin/waBalanceSlider.h b/noatun/modules/winskin/waBalanceSlider.h new file mode 100644 index 00000000..d120bcc7 --- /dev/null +++ b/noatun/modules/winskin/waBalanceSlider.h @@ -0,0 +1,42 @@ +/* + balanceslider for winamp skins + Copyright (C) 1999 Martin Vogt + Copyright (C) 2001 Ryan Cumming + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#ifndef __WABALANCESLIDER_H +#define __WABALANCESLIDER_H + +#include <waSlider.h> +#include "waWidget.h" + +class WaBalanceSlider : public WaWidget { + Q_OBJECT + + public: + WaBalanceSlider(); + ~WaBalanceSlider(); + void buildGui(); + + void setBalanceValue(int val); + + private: + WaSlider *ws; + + signals: + void balanceSetValue(int val); + void sliderPressed(); + void sliderReleased(); +}; + + +#endif diff --git a/noatun/modules/winskin/waButton.cpp b/noatun/modules/winskin/waButton.cpp new file mode 100644 index 00000000..cac0275a --- /dev/null +++ b/noatun/modules/winskin/waButton.cpp @@ -0,0 +1,101 @@ +/* + standard Button fo winamp Skin + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + +#include <qbitmap.h> + +#include "waButton.h" + +WaButton::WaButton(int mapId) : WaWidget(mapId) +{ + _togglable = false; + _toggled = false; + pressed = false; +} + + +WaButton::~WaButton() { +} + +void WaButton::setPixmapUp(int pixId) { + nUpId=pixId; +} + + +void WaButton::setPixmapDown(int pixId) { + nDownId=pixId; +} + + +void WaButton::setPixmapUpSelected(int pixId) { + nUpIdSelected=pixId; +} + + +void WaButton::setPixmapDownSelected(int pixId) { + nDownIdSelected=pixId; +} + +void WaButton::paintEvent(QPaintEvent *) { + paintPixmap(getPixmapId()); +} + + +void WaButton::mousePressEvent(QMouseEvent* e) { + if (e->button() != LeftButton) { + // We can't deal with it, but maybe the widget can do something clever + WaWidget::mousePressEvent(e); + } + else { + pressed = true; + update(); + } +} + +void WaButton::mouseReleaseEvent(QMouseEvent* e) { + if (!pressed) { + // We're not pressed, so just pass along the mouse event, it's not ours + WaWidget::mouseReleaseEvent(e); + } + else { + pressed = false; + + if (this->rect().contains(e->pos())){ + if (_togglable) { + _toggled = !_toggled; + emit(toggleEvent(_toggled)); + } + + emit(clicked()); + } + } + + update(); +} + +int WaButton::getPixmapId() { + if (_toggled == true) { + if (pressed) + return nDownIdSelected; + else + return nUpIdSelected; + } + else { + if (pressed) + return nDownId; + else + return nUpId; + } + + return -1; +} + +#include "waButton.moc" diff --git a/noatun/modules/winskin/waButton.h b/noatun/modules/winskin/waButton.h new file mode 100644 index 00000000..50947216 --- /dev/null +++ b/noatun/modules/winskin/waButton.h @@ -0,0 +1,62 @@ +/* + standard Button for winamp Skin + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + + +#ifndef __WABUTTON_H +#define __WABUTTON_H + +#include <qpainter.h> +#include "waWidget.h" + +class WaButton : public WaWidget { + Q_OBJECT + public: + WaButton(int mapId); + ~WaButton(); + + void setPixmapDown(int pixId); + void setPixmapUp(int pixId); + void setPixmapUpSelected(int pixId); + void setPixmapDownSelected(int pixId); + + void setToggled(bool toggled_flag) { _toggled = toggled_flag; update(); } + bool toggled() const { return _toggled; } + + void setTogglable(bool togglable_flag) { _togglable = togglable_flag; update(); } + bool togglable() const { return _togglable; } + + int getPixmapId(); + void paintEvent(QPaintEvent*); + + private: + void mousePressEvent (QMouseEvent* e); + void mouseReleaseEvent (QMouseEvent* e); + + int nUpId; + int nDownId; + int nDownIdSelected; + int nUpIdSelected; + + QPoint currentLocation; + + bool _toggled; + bool _togglable; + + bool pressed; + + signals: + void toggleEvent(bool val); + void clicked(); +}; +#endif diff --git a/noatun/modules/winskin/waClutterbar.cpp b/noatun/modules/winskin/waClutterbar.cpp new file mode 100644 index 00000000..6ceb7d04 --- /dev/null +++ b/noatun/modules/winskin/waClutterbar.cpp @@ -0,0 +1,11 @@ +#include "waClutterbar.h" +#include "waClutterbar.moc" +WaClutterbar::WaClutterbar() : WaWidget(_WA_MAPPING_CLUTTERBAR) { +} + +WaClutterbar::~WaClutterbar() { +} + +void WaClutterbar::paintEvent(QPaintEvent *) { + paintPixmap(_WA_SKIN_CLUTTERBAR_DISABLED); +} diff --git a/noatun/modules/winskin/waClutterbar.h b/noatun/modules/winskin/waClutterbar.h new file mode 100644 index 00000000..69339c37 --- /dev/null +++ b/noatun/modules/winskin/waClutterbar.h @@ -0,0 +1,18 @@ +#ifndef __WACLUTTERBAR_H +#define __WACLUTTERBAR_H + +#include <qpainter.h> +#include "waWidget.h" + +class WaClutterbar : public WaWidget { + Q_OBJECT + + public: + WaClutterbar(); + ~WaClutterbar(); + + public slots: + void paintEvent(QPaintEvent *); +}; + +#endif diff --git a/noatun/modules/winskin/waColor.cpp b/noatun/modules/winskin/waColor.cpp new file mode 100644 index 00000000..e06b38bc --- /dev/null +++ b/noatun/modules/winskin/waColor.cpp @@ -0,0 +1,73 @@ +#include <fstream> +#include <qfile.h> + +#include "waColor.h" + +WaColor *colorScheme = NULL; + +WaColor::WaColor(QString filename) { + int r, g, b; + char comma; + + skinColors[0].setRgb(0, 0, 0); + skinColors[1].setRgb(24, 33, 41); + skinColors[2].setRgb(239, 49, 16); + skinColors[3].setRgb(206, 41, 16); + skinColors[4].setRgb(214, 90, 0); + skinColors[5].setRgb(214, 102, 0); + skinColors[6].setRgb(214, 115, 0); + skinColors[7].setRgb(198, 123, 8); + skinColors[8].setRgb(222, 165, 24); + skinColors[9].setRgb(214, 181, 33); + skinColors[10].setRgb(189, 222, 41); + skinColors[11].setRgb(148, 222, 33); + skinColors[12].setRgb(41, 206, 16); + skinColors[13].setRgb(50, 190, 16); + skinColors[14].setRgb(57, 181, 16); + skinColors[15].setRgb(49, 156, 8); + skinColors[16].setRgb(41, 148, 0); + skinColors[17].setRgb(24, 132, 8); + skinColors[18].setRgb(255, 255, 255); + skinColors[19].setRgb(214, 214, 222); + skinColors[20].setRgb(181, 189, 189); + skinColors[21].setRgb(160, 170, 175); + skinColors[22].setRgb(148, 156, 165); + skinColors[23].setRgb(150, 150, 150); + + if (filename.isEmpty()) { + return; + } + + std::ifstream viscolor(QFile::encodeName(filename)); + + if (!viscolor) + return; + + for (int index = 0;index < 24;index++) { + viscolor >> r; + viscolor >> std::ws; + viscolor >> comma; + viscolor >> std::ws; + viscolor >> g; + viscolor >> std::ws; + viscolor >> comma; + viscolor >> std::ws; + viscolor >> b; + + while(1) { + char c; + + if (!viscolor.get(c)) + return; + + if (c == '\n') + break; + } + + skinColors[index].setRgb(r, g, b); + } + +} + +WaColor::~WaColor() { +} diff --git a/noatun/modules/winskin/waColor.h b/noatun/modules/winskin/waColor.h new file mode 100644 index 00000000..a0e18484 --- /dev/null +++ b/noatun/modules/winskin/waColor.h @@ -0,0 +1,26 @@ + + +#ifndef WACOLOR_H +#define WACOLOR_H + +#include <qcolor.h> +#include <qstring.h> + +#define INDEX_BACKGROUND_COLOR 0 +#define INDEX_GRID_COLOR 1 +#define INDEX_SPEC_BASE 2 +#define INDEX_OSC_BASE 18 +#define INDEX_PEAKS 23 + +class WaColor { +public: + WaColor(QString filename); + ~WaColor(); + + QColor skinColors[24]; +}; + +extern WaColor *colorScheme; + +#endif + diff --git a/noatun/modules/winskin/waDigit.cpp b/noatun/modules/winskin/waDigit.cpp new file mode 100644 index 00000000..b775d7cf --- /dev/null +++ b/noatun/modules/winskin/waDigit.cpp @@ -0,0 +1,89 @@ +/* + The digit for the time + Copyright (C) 1999 Martin Vogt + Copyright (C) 2002 Ryan Cumming + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "waDigit.h" +#include "waSkinModel.h" + +#include <kconfig.h> +#include <kglobal.h> + +WaDigit::WaDigit() : WaWidget(_WA_MAPPING_DIGITS) +{ + KConfig *config = KGlobal::config(); + config->setGroup("Winskin"); + + reverse_time = config->readNumEntry("timeReversed", false); +} + + +WaDigit::~WaDigit() +{ + KConfig *config = KGlobal::config(); + config->setGroup("Winskin"); + config->writeEntry("timeReversed", reverse_time); +} + +void WaDigit::paintEvent(QPaintEvent *) +{ + paintBackground(); + + const char *time = timeString.latin1(); + int len = strlen(time); + if (len == 0) + return; + + // Declare all these variables after we check for zero-length + WaSkinModel *waSkinModel = WaSkinModel::instance(); + + int x = waSkinModel->getMapGeometry(mapping).x(); + int y = waSkinModel->getMapGeometry(mapping).y(); + + QRect mapRect; + + // We expect strings either in the form "xx:yy", or "-xx:yy" + // If the string length is 6, we have it in the form of "-xx:yy" + // Remove the -, move the string forward one character, and + // continue parsing + mapRect = waSkinModel->getMapGeometry(_WA_MAPPING_MINUS); + if (len == 6) { + waSkinModel->getDigit('-', this, mapRect.x() - x, mapRect.y() - y); + time++; + } + else { + waSkinModel->getDigit(' ', this, mapRect.x() - x, mapRect.y() - y); + } + + mapRect = waSkinModel->getMapGeometry(_WA_MAPPING_DIGIT_1); + waSkinModel->getDigit(time[0], this, mapRect.x() - x, mapRect.y() - y); + + mapRect = waSkinModel->getMapGeometry(_WA_MAPPING_DIGIT_2); + waSkinModel->getDigit(time[1], this, mapRect.x() - x, mapRect.y() - y); + + mapRect = waSkinModel->getMapGeometry(_WA_MAPPING_DIGIT_3); + waSkinModel->getDigit(time[3], this, mapRect.x() - x, mapRect.y() - y); + + mapRect = waSkinModel->getMapGeometry(_WA_MAPPING_DIGIT_4); + waSkinModel->getDigit(time[4], this, mapRect.x() - x, mapRect.y() - y); +} + +void WaDigit::mousePressEvent(QMouseEvent* e) { + if (e->button() == LeftButton) { + reverse_time = !reverse_time; + emit digitsClicked(); + } + else + WaWidget::mousePressEvent(e); +} + +#include "waDigit.moc" diff --git a/noatun/modules/winskin/waDigit.h b/noatun/modules/winskin/waDigit.h new file mode 100644 index 00000000..cefbfeb3 --- /dev/null +++ b/noatun/modules/winskin/waDigit.h @@ -0,0 +1,48 @@ +/* + The digit for the time + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + + +#ifndef __WADIGIT_H +#define __WADIGIT_H + +#include <qpainter.h> + +#include "waWidget.h" + +class WaDigit : public WaWidget { + Q_OBJECT + + public: + WaDigit(); + ~WaDigit(); + + void setTime(QString time) { timeString = time; update(); } + QString time() const { return timeString; } + + bool timeReversed() const { return reverse_time; } + + public slots: + void paintEvent(QPaintEvent * paintEvent); + + private: + void mousePressEvent(QMouseEvent* e); + bool reverse_time; + + WaSkinModel *waSkinModel; + QString timeString; + + signals: + void digitsClicked(); +}; +#endif diff --git a/noatun/modules/winskin/waIndicator.cpp b/noatun/modules/winskin/waIndicator.cpp new file mode 100644 index 00000000..9c5efa84 --- /dev/null +++ b/noatun/modules/winskin/waIndicator.cpp @@ -0,0 +1,34 @@ +/* + State indicator for Winamp Skin + Copyright (C) 2002 Ryan Cumming + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include <waIndicator.h> + +WaIndicator::WaIndicator(int widget_mapping, int enabled_mapping, int disabled_mapping) + : WaWidget(widget_mapping) +{ + _state = false; + _enabled_mapping = enabled_mapping; + _disabled_mapping = disabled_mapping; +} + +WaIndicator::~WaIndicator() +{ +} + +void WaIndicator::paintEvent(QPaintEvent *) +{ + paintPixmap( _state ? _enabled_mapping : _disabled_mapping ); +} + + +#include "waIndicator.moc" diff --git a/noatun/modules/winskin/waIndicator.h b/noatun/modules/winskin/waIndicator.h new file mode 100644 index 00000000..f367fe84 --- /dev/null +++ b/noatun/modules/winskin/waIndicator.h @@ -0,0 +1,41 @@ +/* + Standard state indicator for Winamp skin + Copyright (C) 2002 Ryan Cumming + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + + +#ifndef __WAINDICATOR_H +#define __WAINDICATOR_H + +#include <qpainter.h> + +#include "waWidget.h" + +class WaIndicator : public WaWidget { + Q_OBJECT + + public: + WaIndicator(int widget_mapping, int enabled_mapping, int disabled_mapping); + ~WaIndicator(); + + void setState(bool state) { _state = state; update(); } + bool state() const { return _state; } + + public slots: + void paintEvent(QPaintEvent *); + + private: + int _enabled_mapping; + int _disabled_mapping; + bool _state; +}; +#endif diff --git a/noatun/modules/winskin/waInfo.cpp b/noatun/modules/winskin/waInfo.cpp new file mode 100644 index 00000000..c735a8e4 --- /dev/null +++ b/noatun/modules/winskin/waInfo.cpp @@ -0,0 +1,173 @@ +/* + Scrolling song title for winamp Skin + Copyright (C) 1999 Martin Vogt + Copyright (C) 2001 Ryan Cumming + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include <qpainter.h> +#include <qpixmap.h> + +#include <stdlib.h> + +#include <kconfig.h> +#include <kglobal.h> + +#include "waInfo.h" +#include "waSkinModel.h" + +WaInfo::WaInfo() : WaWidget(_WA_MAPPING_INFO) +{ + connect(WaSkinModel::instance(), SIGNAL(skinChanged()), + this, SLOT(pixmapChange())); + + completePixmap = new QPixmap(); + + QSize size = sizeHint(); + completePixmap->resize(size.width(), size.height()); + + xGrabbedPos = -1; + + timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(timeEvent())); +} + +WaInfo::~WaInfo() +{ + delete completePixmap; +} + + +void WaInfo::timeEvent() +{ + if ((xGrabbedPos == -1) && (xScrollDirection)) { + xScrollPos += xScrollDirection; + + if (abs(xScrollPos) > completePixmap->width()) { + xScrollPos = 0; + } + + if (isVisible()) + repaint(false); + } +} + + +void WaInfo::scrollerSetup() +{ + xScrollPos = 0; + xScrollDirection = 0; + timer->stop(); + QSize size = sizeHint(); + if (completePixmap->width() > size.width()) { + xScrollDirection = 1; + + KConfig *config=KGlobal::config(); + config->setGroup("Winskin"); + int s = config->readNumEntry("ScrollDelay", 15); + if (s!=0) + timer->start(50-s); + } +} + +void WaInfo::paintEvent(QPaintEvent *) +{ + QSize size = sizeHint(); + + if (completePixmap->width() <= size.width()) { + bitBlt(this, 0, 0, completePixmap); + return; + } + + // pixmap widther than window: + int xDrawWidth; + int xRestWidth; + + xDrawWidth = completePixmap->width() - xScrollPos; + if (xDrawWidth > size.width()) { + xDrawWidth = size.width(); + } + + + bitBlt(this, 0, 0, completePixmap, xScrollPos, 0, xDrawWidth); + + if (xDrawWidth < size.width()) { + xRestWidth = size.width() - xDrawWidth; + bitBlt(this, xDrawWidth, 0, completePixmap, 0, 0, xRestWidth); + } +} + + +void WaInfo::setText(QString song) +{ + if (_text != song) { + _text = song; + pixmapChange(); + } +} + +QString WaInfo::text() const +{ + return _text; +} + + +void WaInfo::pixmapChange() +{ + int i; + const char *infoString = _text.latin1(); + + int x = 0; + int n=infoString ? strlen(infoString) : 0; + + QSize size = sizeHint(); + + completePixmap->resize(QMAX(n * _WA_TEXT_WIDTH, size.width()), _WA_TEXT_HEIGHT); + + for (i = 0; i < n; i++) { + WaSkinModel::instance()->getText(infoString[i], completePixmap, x, 0); + x += _WA_TEXT_WIDTH; + } + + // if the size is now smaller than the with of this widget, we + // fill the pixmap with spaces + if (x < size.width()) { + while (x < size.width()) { + WaSkinModel::instance()->getText(' ', completePixmap, x, 0); + x += _WA_TEXT_WIDTH; + } + } + + scrollerSetup(); + update(); +} + +void WaInfo::mousePressEvent (QMouseEvent *e) { + if (e->button() == LeftButton) + xGrabbedPos = (e->x() + xScrollPos) % completePixmap->width(); +} + +void WaInfo::mouseMoveEvent (QMouseEvent * e) { + xScrollPos = -e->x() + xGrabbedPos; + + if (xScrollPos < 0) + xScrollPos = completePixmap->width() - (-xScrollPos % completePixmap->width()); + else + xScrollPos %= completePixmap->width(); + + update(); +} + +void WaInfo::mouseReleaseEvent (QMouseEvent *) { + xGrabbedPos = -1; +} + + +#include "waInfo.moc" diff --git a/noatun/modules/winskin/waInfo.h b/noatun/modules/winskin/waInfo.h new file mode 100644 index 00000000..513ff3cc --- /dev/null +++ b/noatun/modules/winskin/waInfo.h @@ -0,0 +1,53 @@ +/* + standard Button for winamp Skin + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + + +#ifndef __WAINFO_H +#define __WAINFO_H + +#include <qpainter.h> +#include <qtimer.h> + +#include "waWidget.h" + +class WaInfo : public WaWidget { + Q_OBJECT + + public: + WaInfo(); + ~WaInfo(); + + void setText(QString song); + QString text() const; + void scrollerSetup(); + + protected: + void paintEvent(QPaintEvent * paintEvent); + + void mousePressEvent (QMouseEvent * e); + void mouseMoveEvent (QMouseEvent * e); + void mouseReleaseEvent (QMouseEvent * e); + + QPixmap *completePixmap; + QString _text; + QTimer *timer; + int xScrollPos; + int xScrollDirection; + int xGrabbedPos; + + protected slots: + void pixmapChange(); + void timeEvent(); +}; +#endif diff --git a/noatun/modules/winskin/waJumpSlider.cpp b/noatun/modules/winskin/waJumpSlider.cpp new file mode 100644 index 00000000..51633300 --- /dev/null +++ b/noatun/modules/winskin/waJumpSlider.cpp @@ -0,0 +1,78 @@ +/* + jumpslider for winamp skins + Copyright (C) 1998 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "waJumpSlider.h" + +WaJumpSlider::WaJumpSlider() : WaWidget(_WA_MAPPING_POS_BAR) +{ +} + +WaJumpSlider::~WaJumpSlider() +{ +} + +void WaJumpSlider::buildGui() +{ + ws = new WaSlider(_WA_MAPPING_POS_BAR, _WA_MAPPING_POS_BAR_SLIDER); + ws->setPixmapSliderButtonUp(_WA_SKIN_POS_BAR_SLIDER_NORM); + ws->setPixmapSliderButtonDown(_WA_SKIN_POS_BAR_SLIDER_PRES); + ws->setPixmapSliderBar(_WA_SKIN_POS_BAR); + ws->setRange(0, 100); + ws->setValue(0); + + connect(ws, SIGNAL(sliderPressed()), this, SIGNAL(sliderPressed())); + connect(ws, SIGNAL(sliderReleased()), this, SLOT(releasedSlider())); + connect(ws, SIGNAL(valueChanged(int)), this, SIGNAL(valueChanged(int))); +} + +void WaJumpSlider::setJumpRange(int val) +{ + if (val == -1) + ws->hideButton(); + else { + ws->showButton(); + ws->setRange(0, val); + } +} + +int WaJumpSlider::jumpValue() { + return ws->value(); +} + +void WaJumpSlider::setJumpValue(int val) +{ + int currVal = ws->value(); + + if (currVal != val) { + ws->setValue(val); + } +} + +void WaJumpSlider::releasedSlider() { + emit(jump(ws->value())); + emit(sliderReleased()); +} + +void WaJumpSlider::showEvent (QShowEvent *) { + ws->show(); +} + +void WaJumpSlider::hideEvent (QHideEvent *) { + ws->hide(); +} + +void WaJumpSlider::cancelDrag() { + ws->cancelDrag(); +} + +#include "waJumpSlider.moc" diff --git a/noatun/modules/winskin/waJumpSlider.h b/noatun/modules/winskin/waJumpSlider.h new file mode 100644 index 00000000..12c07808 --- /dev/null +++ b/noatun/modules/winskin/waJumpSlider.h @@ -0,0 +1,52 @@ +/* + jumpslider for winamp skins + Copyright (C) 1998 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#ifndef __WAJUMPSLIDER_H +#define __WAJUMPSLIDER_H + +#include "waSlider.h" +#include "waWidget.h" + +class WaJumpSlider : public WaWidget { + Q_OBJECT + + public: + WaJumpSlider(); + ~WaJumpSlider(); + void buildGui(); + + void setJumpRange(int val); + + void setJumpValue(int val); + int jumpValue(); + + void cancelDrag(); + + protected: + WaSlider *ws; + void showEvent (QShowEvent *); + void hideEvent (QHideEvent *); + + private slots: + void releasedSlider(); + + signals: + void jump(int seconds); + void sliderPressed(); + void sliderReleased(); + void valueChanged(int); +}; + + +#endif diff --git a/noatun/modules/winskin/waLabel.cpp b/noatun/modules/winskin/waLabel.cpp new file mode 100644 index 00000000..8f3ddb60 --- /dev/null +++ b/noatun/modules/winskin/waLabel.cpp @@ -0,0 +1,65 @@ +/* + Standard label for Winskin + Copyright (C) 1999 Martin Vogt + Copyright (C) 2001 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + +#include <qpainter.h> +#include <qpixmap.h> + +#include "waLabel.h" +#include "waSkinModel.h" + +WaLabel::WaLabel(int mapping) : WaWidget(mapping) +{ + connect(WaSkinModel::instance(), SIGNAL(skinChanged()), + this, SLOT(pixmapChange())); + + completePixmap = new QPixmap(); + + QSize size = sizeHint(); + + completePixmap->resize(size.width(), size.height()); +} + +WaLabel::~WaLabel() +{ + delete completePixmap; +} + +void WaLabel::paintEvent(QPaintEvent *) +{ + bitBlt(this, 0, 0, completePixmap); +} + +void WaLabel::setText(const QString &new_text) +{ + int width = WaSkinModel::instance()->getMapGeometry(mapping).width(); + + // Fit the text to the widget + // This should always be three characters, but we generate its value anyway + _text = new_text.rightJustify(width / _WA_TEXT_WIDTH, ' '); + + pixmapChange(); + + update(); +} + +void WaLabel::pixmapChange() +{ + const char *label_text = _text.latin1(); + int n = label_text ? strlen(label_text) : 0; + + for (int i = 0; i < n; i++) + WaSkinModel::instance()->getText(label_text[i], completePixmap, + i * _WA_TEXT_WIDTH, 0); +} + +#include "waLabel.moc" diff --git a/noatun/modules/winskin/waLabel.h b/noatun/modules/winskin/waLabel.h new file mode 100644 index 00000000..f1470902 --- /dev/null +++ b/noatun/modules/winskin/waLabel.h @@ -0,0 +1,39 @@ +/* + standard Button for winamp Skin + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + +#ifndef __WABPS_H +#define __WABPS_H + +#include <qpainter.h> +#include "waWidget.h" + +class WaLabel : public WaWidget { + Q_OBJECT + + public: + WaLabel(int mapping); + ~WaLabel(); + + void setText(const QString &text); + QString text() const { return _text; } + + private: + void paintEvent(QPaintEvent *); + + QPixmap *completePixmap; + QString _text; + + + private slots: + void pixmapChange(); +}; +#endif diff --git a/noatun/modules/winskin/waMain.cpp b/noatun/modules/winskin/waMain.cpp new file mode 100644 index 00000000..a5bb7fdc --- /dev/null +++ b/noatun/modules/winskin/waMain.cpp @@ -0,0 +1,13 @@ +#include "waMain.h" + +WaMain::WaMain() : WaWidget(_WA_MAPPING_MAIN) { +} + +WaMain::~WaMain() { +} + +void WaMain::paintEvent(QPaintEvent *) { + paintPixmap(_WA_SKIN_MAIN); +} + +#include "waMain.moc" diff --git a/noatun/modules/winskin/waMain.h b/noatun/modules/winskin/waMain.h new file mode 100644 index 00000000..06bcfe5d --- /dev/null +++ b/noatun/modules/winskin/waMain.h @@ -0,0 +1,16 @@ +#ifndef __WAMAIN_H +#define __WAMAIN_H + +#include "waWidget.h" + +class WaMain : WaWidget { + Q_OBJECT +public: + WaMain(); + ~WaMain(); + +protected: + void paintEvent(QPaintEvent *); +}; + +#endif diff --git a/noatun/modules/winskin/waRegion.cpp b/noatun/modules/winskin/waRegion.cpp new file mode 100644 index 00000000..ab4d2e57 --- /dev/null +++ b/noatun/modules/winskin/waRegion.cpp @@ -0,0 +1,126 @@ +/* + Winamp Skin + Copyright (C) 2002 Ryan Cumming + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + +#include <ksimpleconfig.h> +#include <qbitmap.h> +#include <qpainter.h> +#include <qregexp.h> + +#include "waSkinModel.h" +#include "waSkins.h" +#include "waRegion.h" + +WaRegion *windowRegion = NULL; + +// Hack around case-insensitivity in Winamp INI files by searching for common capitializations +// Needs to be replaced with an all-custom loader after 3.0 +const char *pointListNames[] = {"PointList", "pointlist", "Pointlist", "pointList", "POINTLIST", 0}; +const char *numPointsNames[] = {"NumPoints", "numpoints", "Numpoints", "numPoints", "NUMPOINTS", 0}; + +WaRegion::WaRegion(QString filename) { + // Load the region file, which happens to be in KConfig format + KSimpleConfig regionFile(filename, true); + + // Clear our variables by default + window_mask = 0; + shade_mask = 0; + + // Make the new bitmaps, default window size + window_mask = new QBitmap(WaSkinModel::instance()->getMapGeometry(_WA_MAPPING_MAIN).size(), true); + shade_mask = new QBitmap(WaSkinModel::instance()->getMapGeometry(_WA_MAPPING_TITLE).size(), true); + + // Load the normal window mask data + regionFile.setGroup("Normal"); + + QValueList<int> num_points; + for (int x = 0;numPointsNames[x];x++) { + if (regionFile.hasKey(numPointsNames[x])) + num_points = parseList(regionFile.readEntry(numPointsNames[x])); + } + + QValueList<int> point_list; + for (int x = 0;pointListNames[x];x++) { + if (regionFile.hasKey(pointListNames[x])) + point_list = parseList(regionFile.readEntry(pointListNames[x])); + } + + // Now build the mask + buildPixmap(num_points, point_list, window_mask); + + // Load the windowshade mask data + regionFile.setGroup("WindowShade"); + + num_points = parseList(regionFile.readEntry("NumPoints")); + point_list = parseList(regionFile.readEntry("PointList")); + + // Now build the mask + buildPixmap(num_points, point_list, shade_mask); +} + +WaRegion::~WaRegion() { + delete window_mask; + delete shade_mask; +} + +void WaRegion::buildPixmap(const QValueList<int> &num_points_list, const QValueList<int> &points_list, QBitmap *dest) { + if (!num_points_list.count()) { + dest->fill(Qt::color1); + return; + } + + QValueList<int>::const_iterator points = points_list.begin(); + + QPainter p(dest); + + // Coordinates in REGION.TXT can go one pixel beyond the window size + QBitmap bm(dest->width()+1,dest->height()+1,true); + QPainter bmp(&bm); + + bmp.setBrush(Qt::color1); + bmp.setPen(Qt::NoPen); // The polygon border itself should not be part of the visible window + + // Go over each "region" in the file + for (QValueList<int>::const_iterator num_points = num_points_list.begin();num_points != num_points_list.end();num_points++) { + // Make a new point array + QPointArray point_array(*num_points); + + // Populate it + for (int i = 0;i < *num_points;i++) { + int x = (*points++); + int y = (*points++); + + point_array.setPoint(i, x, y); + } + + // Now draw it as a filled polygon on the mask + bmp.drawPolygon(point_array); + } + + p.drawPixmap(0,0,bm,0,0,dest->width(),dest->height()); +} + + +// The winamp list format is absolutely insane, it will accept either +// commas or whitespace as the delimiter. This function deals with +// that. +QValueList<int> WaRegion::parseList(const QString &list) const { + QValueList<int> temp_list; + + if (list.isEmpty()) + return temp_list; + + QStringList open=QStringList::split(QRegExp("[,\\s]+"), list); + for (QStringList::Iterator i=open.begin(); i != open.end(); ++i) + temp_list.append((*i).toInt()); + + return temp_list; +} diff --git a/noatun/modules/winskin/waRegion.h b/noatun/modules/winskin/waRegion.h new file mode 100644 index 00000000..853909c1 --- /dev/null +++ b/noatun/modules/winskin/waRegion.h @@ -0,0 +1,26 @@ +#ifndef WAREGION_H +#define WAREGION_H + +#include <qcolor.h> +#include <qstring.h> + +class WaRegion { +public: + WaRegion(QString filename); + ~WaRegion(); + + const QBitmap *mainWindowMask() const { return window_mask; } + const QBitmap *mainWindowShadeMask() const { return shade_mask; } + +private: + QValueList<int> parseList(const QString &list) const; + void buildPixmap(const QValueList<int> &num_points, const QValueList<int> &point_list, QBitmap *dest); + + QBitmap *window_mask; + QBitmap *shade_mask; +}; + +extern WaRegion *windowRegion; + +#endif + diff --git a/noatun/modules/winskin/waShadeMapping.h b/noatun/modules/winskin/waShadeMapping.h new file mode 100644 index 00000000..d28d4ca8 --- /dev/null +++ b/noatun/modules/winskin/waShadeMapping.h @@ -0,0 +1,148 @@ +/* + mapping from file and id to pixmap, and global player map + Copyright (C) 1999 Martin Vogt + Copyright (C) 2002 Ryan Cumming + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#ifndef __WASHADEMAPPING_H +#define __WASHADEMAPPING_H + + +/** + This file is not a header file in the normal sense. + It define _directly_ variables, which are used in the + WaSkinLoader class. + Its a bit black voodoo magic. +*/ + +/** + The Skin file format was downloaded from the web. + http://www.algonet.et.se/~daniel7 + + Author: unknown +*/ + +#include "skinMap.h" +#include "waSkins.h" + +static const SkinMap shadeMapToGui[] = { + {0, 0, 275, 14}, // _WA_MAPPING_MAIN + {168, 3, 9, 9}, // _WA_MAPPING_CBUTTONS_PREV + {177, 3, 9, 9}, // _WA_MAPPING_CBUTTONS_PLAY + {186, 3, 9, 9}, // _WA_MAPPING_CBUTTONS_PAUSE + {195, 3, 9, 9}, // _WA_MAPPING_CBUTTONS_STOP + {204, 3, 9, 9}, // _WA_MAPPING_CBUTTONS_NEXT + {215, 3, 9, 9}, // _WA_MAPPING_CBUTTONS_EJECT + {239, 41, 29, 12}, // _WA_MAPPING_MONOSTER_STEREO + {212, 41, 27, 12}, // _WA_MAPPING_MONOSTER_MONO + {210, 89, 28, 15}, // _WA_MAPPING_REPEAT + {164, 89, 46, 15}, // _WA_MAPPING_SHUFFLE + {242, 58, 23, 12}, // _WA_MAPPING_PLAYLIST + {219, 58, 23, 12}, // _WA_MAPPING_EQ + {107, 57, 68, 13}, // _WA_MAPPING_VOLUME_BAR + {0, 0, 13, 11}, // _WA_MAPPING_VOLUME_SLIDER + {177, 57, 38, 13}, // _WA_MAPPING_BALANCE_BAR + {0, 0, 13, 11}, // _WA_MAPPING_BALANCE_SLIDER + {24, 28, 11, 9}, // _WA_MAPPING_PLAYPAUS + {16, 72, 248, 10}, // _WA_MAPPING_POS_BAR + {0, 0, 29, 10}, // _WA_MAPPING_POS_BAR_SLIDER + {130, 4, 27, 6}, // _WA_MAPPING_DIGITS + {130, 4, 5, 6}, // _WA_MAPPING_MINUS + {135, 4, 5, 6}, // _WA_MAPPING_DIGIT_1 + {140, 4, 5, 6}, // _WA_MAPPING_DIGIT_2 + {147, 4, 5, 6}, // _WA_MAPPING_DIGIT_3 + {152, 4, 5, 6}, // _WA_MAPPING_DIGIT_4 + {24, 43, 75, 16}, // _WA_MAPPING_ANALYSER + {111, 43, 15, 6}, // _WA_MAPPING_BPS + {156, 43, 10, 6}, // _WA_MAPPING_FREQ + {112, 27, 152, 6}, // _WA_MAPPING_INFO + {0, 0, 274, 14}, // _WA_MAPPING_TITLE + {6, 3, 9, 9}, // _WA_MAPPING_TITLE_MENU + {244, 3, 9, 9}, // _WA_MAPPING_TITLE_MIN + {254, 3, 9, 9}, // _WA_MAPPING_TITLE_SHADE + {264, 3, 9, 9}, // _WA_MAPPING_TITLE_CLOSE + {10, 22, 8, 43} // _WA_MAPPING_CLUTTERBAR +}; + + +static const SkinDesc shadeMapFromFile[] = { + {_WA_FILE_TITLEBAR, 27, 29, 275, 14}, // _WA_SKIN_MAIN + {_WA_FILE_TITLEBAR, 195, 32, 9, 9}, // _WA_SKIN_CBUTTONS_PREV_NORM + {_WA_FILE_TITLEBAR, 195, 32, 9, 9}, // _WA_SKIN_CBUTTONS_PREV_PRES + {_WA_FILE_TITLEBAR, 204, 32, 9, 9}, //_WA_SKIN_CBUTTONS_PLAY_NORM, + {_WA_FILE_TITLEBAR, 204, 32, 9, 9}, // _WA_SKIN_CBUTTONS_PLAY_PRES + {_WA_FILE_TITLEBAR, 213, 32, 9, 9}, // _WA_SKIN_CBUTTONS_PAUSE_NORM + {_WA_FILE_TITLEBAR, 213, 32, 9, 9}, // _WA_SKIN_CBUTTONS_PAUSE_PRES + {_WA_FILE_TITLEBAR, 222, 32, 9, 9}, // _WA_SKIN_CBUTTONS_STOP_NORM + {_WA_FILE_TITLEBAR, 222, 32, 9, 9}, // _WA_SKIN_CBUTTONS_STOP_PRES + {_WA_FILE_TITLEBAR, 231, 32, 9, 9}, // _WA_SKIN_CBUTTONS_NEXT_NORM + {_WA_FILE_TITLEBAR, 231, 32, 9, 9}, // _WA_SKIN_CBUTTONS_NEXT_PRES + {_WA_FILE_TITLEBAR, 242, 32, 9, 9}, // _WA_SKIN_CBUTTONS_EJECT_NORM + {_WA_FILE_TITLEBAR, 242, 32, 9, 9}, // _WA_SKIN_CBUTTONS_EJECT_PRESS + {_WA_FILE_MONOSTER, 0, 0, 29, 12}, // _WA_SKIN_MONOSTER_STEREO_TRUE + {_WA_FILE_MONOSTER, 0, 12, 29, 12}, // _WA_SKIN_MONOSTER_STEREO_FALSE + {_WA_FILE_MONOSTER, 29, 0, 27, 12}, // _WA_SKIN_MONOSTER_MONO_TRUE + {_WA_FILE_MONOSTER, 29, 12, 27, 12}, // _WA_SKIN_MONOSTER_MONO_FALSE + {_WA_FILE_TEXT, 0, 6, 50, 6}, // _WA_SKIN_NUMBERS + {_WA_FILE_TEXT, 75, 6, 5, 6}, // _WA_SKIN_NUMBERS_MINUS + {_WA_FILE_TEXT, 50, 12, 5, 6}, // _WA_SKIN_NUMBERS_BLANK + {_WA_FILE_SHUFREP, 0, 0, 28, 15}, // _WA_SKIN_SHUFREP_REPEAT_NOT_SET_NORM + {_WA_FILE_SHUFREP, 0, 15, 28, 15}, // _WA_SKIN_SHUFREP_REPEAT_NOT_SET_PRES + {_WA_FILE_SHUFREP, 0, 30, 28, 15}, // _WA_SKIN_SHUFREP_REPEAT_SET_NORM + {_WA_FILE_SHUFREP, 0, 45, 28, 15}, // _WA_SKIN_SHUFREP_REPEAT_SET_PRES + {_WA_FILE_SHUFREP, 28, 0, 47, 15}, // _WA_SKIN_SHUFREP_SHUFFLE_NOT_SET_NORM + {_WA_FILE_SHUFREP, 28, 15, 47, 15}, // _WA_SKIN_SHUFREP_SHUFFLE_NOT_SET_PRES + {_WA_FILE_SHUFREP, 28, 30, 47, 15}, // _WA_SKIN_SHUFREP_SHUFFLE_SET_NORM + {_WA_FILE_SHUFREP, 28, 45, 47, 15}, // _WA_SKIN_SHUFREP_SHUFFLE_SET_PRES + {_WA_FILE_SHUFREP, 23, 61, 23, 12}, // _WA_SKIN_SHUFREP_PLAYLIST_NOT_SET_NORM + {_WA_FILE_SHUFREP, 69, 61, 23, 12}, // _WA_SKIN_SHUFREP_PLAYLIST_NOT_SET_PRES + {_WA_FILE_SHUFREP, 23, 73, 23, 12}, // _WA_SKIN_SHUFREP_PLAYLIST_SET_NORM + {_WA_FILE_SHUFREP, 73, 23, 12}, // _WA_SKIN_SHUFREP_PLAYLIST_SET_PRES + {_WA_FILE_SHUFREP, 0, 61, 23, 12}, // _WA_SKIN_SHUFREP_EQ_NOT_SET_NORM + {_WA_FILE_SHUFREP, 46, 61, 23, 12}, // _WA_SKIN_SHUFREP_EQ_NOT_SET_PRES + {_WA_FILE_SHUFREP, 0, 73, 23, 12}, // _WA_SKIN_SHUFREP_EQ_SET_NORM + {_WA_FILE_SHUFREP, 46, 73, 23, 12}, // _WA_SKIN_SHUFREP_EQ_SET_PRES + {_WA_FILE_TEXT, 0, 0, 155, 18}, // _WA_SKIN_TEXT + {_WA_FILE_VOLUME, 0, 0, 68, 421}, // _WA_SKIN_VOLUME_BAR_ALL_BARS + {_WA_FILE_VOLUME, 0, 0, 68, 13}, // _WA_SKIN_VOLUME_BAR + {_WA_FILE_VOLUME, 0, 422, 14, 11}, // _WA_SKIN_VOLUME_SLIDER_NORM + {_WA_FILE_VOLUME, 15, 422, 14, 11}, // _WA_SKIN_VOLUME_SLIDER_PRES + {_WA_FILE_BALANCE, 9, 0, 38, 421}, // _WA_SKIN_BALANCE_BAR_ALL_BARS + {_WA_FILE_BALANCE, 9, 0, 38, 13}, // _WA_SKIN_BALANCE_BAR + {_WA_FILE_BALANCE, 0, 422, 14, 11}, // _WA_SKIN_BALANCE_SLIDER_NORM + {_WA_FILE_BALANCE, 15, 422, 14, 11}, // _WA_SKIN_BALANCE_SLIDER_PRES + {_WA_FILE_POSBAR, 0, 0, 248, 10}, // _WA_SKIN_POS_BAR + {_WA_FILE_POSBAR, 278, 0, 29, 10}, // _WA_SKIN_POS_BAR_SLIDER_NORM + {_WA_FILE_POSBAR, 248, 0, 29, 10}, // _WA_SKIN_POS_BAR_SLIDER_PRES + {_WA_FILE_PLAYPAUS, 1, 0, 8, 9}, // _WA_SKIN_PLAYPAUS_PLAY + {_WA_FILE_PLAYPAUS, 9, 0, 9, 9}, // _WA_SKIN_PLAYPAUS_PAUSE + {_WA_FILE_PLAYPAUS, 18, 0, 9, 9}, // _WA_SKIN_PLAYPAUS_STOP + {_WA_FILE_PLAYPAUS, 27, 0, 2, 9}, // _WA_SKIN_PLAYPAUS_FILLER + {_WA_FILE_PLAYPAUS, 36, 0, 3, 9}, // _WA_SKIN_PLAYPAUS_WORK_INDICATOR + {_WA_FILE_TITLEBAR, 27, 29, 275, 14}, // _WA_SKIN_TITLE_ACTIVE + {_WA_FILE_TITLEBAR, 27, 42, 275, 14}, // _WA_SKIN_TITLE_INACTIVE + {_WA_FILE_TITLEBAR, 0, 9, 9, 9}, // _WA_SKIN_TITLE_MENU_PRES + {_WA_FILE_TITLEBAR, 33, 32, 9, 9}, // _WA_SKIN_TITLE_MENU_NORM + {_WA_FILE_TITLEBAR, 33, 45, 9, 9}, // _WA_SKIN_TITLE_MENU_INACTIVE + {_WA_FILE_TITLEBAR, 9, 9, 9, 9}, // _WA_SKIN_TITLE_MIN_PRES + {_WA_FILE_TITLEBAR, 271, 32, 9, 9}, // _WA_SKIN_TITLE_MIN_NORM + {_WA_FILE_TITLEBAR, 271, 45, 9, 9}, // _WA_SKIN_TITLE_MIN_INACTIVE + {_WA_FILE_TITLEBAR, 9, 27, 9, 9}, // _WA_SKIN_TITLE_SHADE_PRES + {_WA_FILE_TITLEBAR, 281, 32, 9, 9}, // _WA_SKIN_TITLE_SHADE_NORM + {_WA_FILE_TITLEBAR, 281, 45, 9, 9}, // _WA_SKIN_TITLE_SHADE_INACTIVE + {_WA_FILE_TITLEBAR, 18, 9, 9, 9}, // _WA_SKIN_TITLE_CLOSE_PRES + {_WA_FILE_TITLEBAR, 291, 32, 9, 9}, // _WA_SKIN_TITLE_CLOSE_NORM + {_WA_FILE_TITLEBAR, 291, 45, 9, 9}, // _WA_SKIN_TITLE_CLOSE_INACTIVE + {_WA_FILE_TITLEBAR, 304, 0, 8, 43} // _WA_SKIN_CLUTTERBAR_DISABLED +}; + +#endif diff --git a/noatun/modules/winskin/waSkin.cpp b/noatun/modules/winskin/waSkin.cpp new file mode 100644 index 00000000..7d95047d --- /dev/null +++ b/noatun/modules/winskin/waSkin.cpp @@ -0,0 +1,800 @@ +/* + Winamp Skin + Copyright (C) 1999 Martin Vogt + Copyright (C) 2001-2002 Ryan Cumming + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + +#include <kconfig.h> +#include <qstringlist.h> +#include <kglobal.h> +#include <klocale.h> +#include <kiconloader.h> +#include <khelpmenu.h> +#include <kpopupmenu.h> +#include <kurldrag.h> +#include <kstdaction.h> +#include <kaction.h> +#include <qdragobject.h> +#include <kstandarddirs.h> +#include <kwin.h> +#include <time.h> + +#include <noatun/playlist.h> +#include <noatun/app.h> +#include <noatun/stdaction.h> + +#include "waSkin.h" + +#include "waRegion.h" + +#include "waMain.h" +#include "waClutterbar.h" +#include "waDigit.h" +#include "waInfo.h" +#include "waButton.h" +#include "waLabel.h" +#include "waIndicator.h" +#include "waTitleBar.h" + +#include "waJumpSlider.h" +#include "waBalanceSlider.h" +#include "waVolumeSlider.h" + +#include "waStatus.h" + +#include "waSkinManager.h" +#include "waSkinModel.h" + +#include "guiSpectrumAnalyser.h" +#include "fileInfo.h" + +WaSkin *_waskin_instance = NULL; + +WaSkin::WaSkin() : QWidget(0, "NoatunWinampSkin"), UserInterface() +{ + mJumpPressed = false; + mVolumePressed = false; + mBalancePressed = false; + + _waskin_instance = this; + + // Our really low-level render-y sort of stuff + waSkinModel = new WaSkinModel(); + // Skin management stuff + waSkinManager = new WaSkinManager(); + + createHighLevelElements(); + createButtons(); + setMinimumSize(sizeHint()); + setMaximumSize(sizeHint()); + + KWin::setType(this->winId(), NET::Override); + setBackgroundMode(NoBackground); + + setAcceptDrops(true); + + title_shaded = false; + + // These slots make Young Hickory love us + connect( napp, SIGNAL(hideYourself()), this, SLOT(hide()) ); + connect( napp, SIGNAL(showYourself()), this, SLOT(show()) ); + + connect(napp->player(), SIGNAL(playlistShown()), this, + SLOT(playlistShown())); + connect(napp->player(), SIGNAL(playlistHidden()), this, + SLOT(playlistHidden())); + connect(napp->player(), SIGNAL(loopTypeChange(int)), this, + SLOT(loopChange(int))); + connect(napp->player(), SIGNAL(newSong()), this, SLOT(newSong())); + + connect(napp->player(), SIGNAL(timeout()), this, SLOT(timetick())); + KConfig *config=KGlobal::config(); + + config->setGroup("Winskin"); + QString skin = config->readEntry("CurrentSkin", WaSkin::defaultSkin()); + + loadSkin(skin); + + setCaption(i18n("Noatun")); + setIcon(SmallIcon("noatun")); + + + QObject::connect(waTitleBar, SIGNAL(shaded()), this, SLOT(shadeEvent())); + // connect to players signals - so we can update our display if someone else + // changes settings... + + connect(napp->player(), SIGNAL(stopped()), this, SLOT(slotStopped())); + connect(napp->player(), SIGNAL(playing()), this, SLOT(slotPlaying())); + connect(napp->player(), SIGNAL(paused()), this, SLOT(slotPaused())); + + napp->player()->handleButtons(); + + playlist->setToggled(napp->playlist()->listVisible()); + + shuffle->setToggled(false); + repeat->setToggled(false); + waBalanceSlider->setBalanceValue(0); + waVolumeSlider->setVolumeValue(napp->player()->volume()); + + newSong(); + + // HACK: We won't get focus events otherwise + setFocusPolicy(QWidget::ClickFocus); + + show(); +} + + +WaSkin::~WaSkin() +{ + delete waSkinManager; + waSkinManager = 0L; +} + +void WaSkin::loadSkin(QString newSkinDir) +{ + waSkinManager->loadSkin(newSkinDir); + + setMinimumSize(sizeHint()); + + if (title_shaded) { + // waSkinModel::load() resets our skin model :( + waSkinModel->setSkinModel(WA_MODEL_WINDOWSHADE); + setMask(*windowRegion->mainWindowShadeMask()); + } + else { + setMask(*windowRegion->mainWindowMask()); + } +} + +QSize WaSkin::sizeHint() const +{ + QRect temp_rect; + + temp_rect = waSkinModel->getGeometry(_WA_SKIN_MAIN); + + return temp_rect.size(); +} + + +void WaSkin::createButtons() +{ + prev = new WaButton(_WA_MAPPING_CBUTTONS_PREV); + play = new WaButton(_WA_MAPPING_CBUTTONS_PLAY); + pause = new WaButton(_WA_MAPPING_CBUTTONS_PAUSE); + stop = new WaButton(_WA_MAPPING_CBUTTONS_STOP); + next = new WaButton(_WA_MAPPING_CBUTTONS_NEXT); + eject = new WaButton(_WA_MAPPING_CBUTTONS_EJECT); + shuffle = new WaButton(_WA_MAPPING_SHUFFLE); + repeat = new WaButton(_WA_MAPPING_REPEAT); + playlist = new WaButton(_WA_MAPPING_PLAYLIST); + eq = new WaButton(_WA_MAPPING_EQ); + + menu = new WaButton(_WA_MAPPING_TITLE_MENU); + menu->setPixmapUp(_WA_SKIN_TITLE_MENU_NORM); + menu->setPixmapDown(_WA_SKIN_TITLE_MENU_PRES); + connect(menu, SIGNAL(clicked()), this, SLOT(menuEvent())); + + minimize = new WaButton(_WA_MAPPING_TITLE_MIN); + minimize->setPixmapUp(_WA_SKIN_TITLE_MIN_NORM); + minimize->setPixmapDown(_WA_SKIN_TITLE_MIN_PRES); + connect(minimize, SIGNAL(clicked()), this, SLOT(minimizeEvent())); + + titleshade = new WaButton(_WA_MAPPING_TITLE_SHADE); + titleshade->setPixmapUp(_WA_SKIN_TITLE_SHADE_NORM); + titleshade->setPixmapDown(_WA_SKIN_TITLE_SHADE_PRES); + connect(titleshade, SIGNAL(clicked()), this, SLOT(shadeEvent())); + + close = new WaButton(_WA_MAPPING_TITLE_CLOSE); + close->setPixmapUp(_WA_SKIN_TITLE_CLOSE_NORM); + close->setPixmapDown(_WA_SKIN_TITLE_CLOSE_PRES); + connect(close, SIGNAL(clicked()), this, SLOT(doClose())); + + shuffle->setTogglable(true); + shuffle->show(); + + repeat->setTogglable(true); + playlist->setTogglable(true); + + connect(shuffle, SIGNAL(toggleEvent(bool)), + this, SLOT(shuffleClickedEvent(bool))); + + connect(repeat, SIGNAL(toggleEvent(bool)), + this, SLOT(repeatClickedEvent(bool))); + + connect(playlist, SIGNAL(toggleEvent(bool)), + this, SLOT(playlistClickedEvent(bool))); + + connect(eq, SIGNAL(clicked()), + this, SLOT(eqClickedEvent())); + + prev->setPixmapUp(_WA_SKIN_CBUTTONS_PREV_NORM); + prev->setPixmapDown(_WA_SKIN_CBUTTONS_PREV_PRES); + connect(prev, SIGNAL(clicked()), napp->player(), SLOT(back())); + + play->setPixmapUp(_WA_SKIN_CBUTTONS_PLAY_NORM); + play->setPixmapDown(_WA_SKIN_CBUTTONS_PLAY_PRES); + connect(play, SIGNAL(clicked()), this, SLOT(playCurrentEvent())); + + pause->setPixmapUp(_WA_SKIN_CBUTTONS_PAUSE_NORM); + pause->setPixmapDown(_WA_SKIN_CBUTTONS_PAUSE_PRES); + connect(pause, SIGNAL(clicked()), this, SLOT(playPauseEvent())); + + + stop->setPixmapUp(_WA_SKIN_CBUTTONS_STOP_NORM); + stop->setPixmapDown(_WA_SKIN_CBUTTONS_STOP_PRES); + connect(stop, SIGNAL(clicked()), napp->player(), SLOT(stop())); + + + next->setPixmapUp(_WA_SKIN_CBUTTONS_NEXT_NORM); + next->setPixmapDown(_WA_SKIN_CBUTTONS_NEXT_PRES); + connect(next, SIGNAL(clicked()), napp->player(), SLOT(forward())); + + + eject->setPixmapUp(_WA_SKIN_CBUTTONS_EJECT_NORM); + eject->setPixmapDown(_WA_SKIN_CBUTTONS_EJECT_PRESS); + connect(eject, SIGNAL(clicked()), napp, SLOT(fileOpen())); + + shuffle->setPixmapUp(_WA_SKIN_SHUFREP_SHUFFLE_NOT_SET_NORM); + shuffle->setPixmapDown(_WA_SKIN_SHUFREP_SHUFFLE_NOT_SET_PRES); + shuffle->setPixmapUpSelected(_WA_SKIN_SHUFREP_SHUFFLE_SET_NORM); + shuffle->setPixmapDownSelected(_WA_SKIN_SHUFREP_SHUFFLE_SET_PRES); + shuffle->setToggled(true); + + repeat->setPixmapUp(_WA_SKIN_SHUFREP_REPEAT_NOT_SET_NORM); + repeat->setPixmapDown(_WA_SKIN_SHUFREP_REPEAT_NOT_SET_PRES); + repeat->setPixmapUpSelected(_WA_SKIN_SHUFREP_REPEAT_SET_NORM); + repeat->setPixmapDownSelected(_WA_SKIN_SHUFREP_REPEAT_SET_PRES); + + + eq->setPixmapUp(_WA_SKIN_SHUFREP_EQ_NOT_SET_NORM); + eq->setPixmapDown(_WA_SKIN_SHUFREP_EQ_NOT_SET_PRES); + + playlist->setPixmapUp(_WA_SKIN_SHUFREP_PLAYLIST_NOT_SET_NORM); + playlist->setPixmapDown( _WA_SKIN_SHUFREP_PLAYLIST_NOT_SET_PRES); + + playlist->setPixmapUpSelected(_WA_SKIN_SHUFREP_PLAYLIST_SET_NORM); + playlist->setPixmapDownSelected(_WA_SKIN_SHUFREP_PLAYLIST_SET_PRES); + + waClutterbar = new WaClutterbar(); +} + +void WaSkin::createHighLevelElements() +{ + // Two most top-level elements + main = new WaMain(); + waTitleBar = new WaTitleBar(); + + guiSpectrumAnalyser = new GuiSpectrumAnalyser(); + + waJumpSlider = new WaJumpSlider(); + waJumpSlider->buildGui(); + + waVolumeSlider = new WaVolumeSlider(); + waVolumeSlider->buildGui(); + + connect(waVolumeSlider, SIGNAL(volumeSetValue(int)), + this, SLOT(volumeSetValue(int))); + connect(waVolumeSlider, SIGNAL(sliderPressed()), + this, SLOT(volumeSliderPressed())); + connect(waVolumeSlider, SIGNAL(sliderReleased()), + this, SLOT(volumeSliderReleased())); + + waBalanceSlider = new WaBalanceSlider(); + waBalanceSlider->buildGui(); + + connect(waBalanceSlider, SIGNAL(balanceSetValue(int)), + this, SLOT(balanceSetValue(int))); + connect(waBalanceSlider, SIGNAL(sliderPressed()), + this, SLOT(balanceSliderPressed())); + connect(waBalanceSlider, SIGNAL(sliderReleased()), + this, SLOT(balanceSliderReleased())); + + waDigit = new WaDigit(); + connect(waDigit, SIGNAL(digitsClicked()), this, SLOT(digitsClicked())); + + waBPS = new WaLabel(_WA_MAPPING_BPS); + waFreq = new WaLabel(_WA_MAPPING_FREQ); + + waInfo = new WaInfo(); + + waStatus = new WaStatus(); + + waStereo = new WaIndicator(_WA_MAPPING_MONOSTER_STEREO, _WA_SKIN_MONOSTER_STEREO_TRUE, _WA_SKIN_MONOSTER_STEREO_FALSE); + waMono = new WaIndicator(_WA_MAPPING_MONOSTER_MONO, _WA_SKIN_MONOSTER_MONO_TRUE, _WA_SKIN_MONOSTER_MONO_FALSE); + + connect(waJumpSlider, SIGNAL(jump(int)), this, SLOT(jump(int))); + connect(waJumpSlider, SIGNAL(sliderPressed()), + this, SLOT(jumpSliderPressed())); + connect(waJumpSlider, SIGNAL(sliderReleased()), + this, SLOT(jumpSliderReleased())); + connect(waJumpSlider, SIGNAL(valueChanged(int)), + this, SLOT(jumpValueChanged(int))); +} + + +void WaSkin::setChannels(int val) +{ + if (val <= 0) { + waStereo->setState(false); + waMono->setState(false); + } else if (val == 1) { + waStereo->setState(false); + waMono->setState(true); + } else { + waStereo->setState(true); + waMono->setState(false); + } +} + +void WaSkin::shade() { + waSkinModel->setSkinModel(WA_MODEL_WINDOWSHADE); + + setMinimumSize(sizeHint()); + setMask(*windowRegion->mainWindowShadeMask()); + + title_shaded = true; +} + +void WaSkin::unshade() { + waSkinModel->setSkinModel(WA_MODEL_NORMAL); + + setMinimumSize(sizeHint()); + setMask(*windowRegion->mainWindowMask()); + + title_shaded = false; +} + +void WaSkin::focusOutEvent( QFocusEvent * ) { + menu->setPixmapUp(_WA_SKIN_TITLE_MENU_INACTIVE); + menu->update(); + + minimize->setPixmapUp(_WA_SKIN_TITLE_MIN_INACTIVE); + minimize->update(); + + titleshade->setPixmapUp(_WA_SKIN_TITLE_SHADE_INACTIVE); + titleshade->update(); + + close->setPixmapUp(_WA_SKIN_TITLE_CLOSE_INACTIVE); + close->update(); + + waTitleBar->setState(false); +} + +void WaSkin::focusInEvent( QFocusEvent * ) { + menu->setPixmapUp(_WA_SKIN_TITLE_MENU_NORM); + menu->update(); + + minimize->setPixmapUp(_WA_SKIN_TITLE_MIN_NORM); + minimize->update(); + + titleshade->setPixmapUp(_WA_SKIN_TITLE_SHADE_NORM); + titleshade->update(); + + close->setPixmapUp(_WA_SKIN_TITLE_CLOSE_NORM); + close->update(); + + waTitleBar->setState(true); +} + +void WaSkin::wheelEvent(QWheelEvent *e) { + // Get the current volume + int newVolume = napp->player()->volume(); + + // Wheel events return needlessly large "deltas", normalize it a bit + newVolume += e->delta() / 24; + napp->player()->setVolume(newVolume); +} + +void WaSkin::repeatClickedEvent(bool) +{ + updateLoopStyle(); +} + +void WaSkin::shuffleClickedEvent(bool) +{ + updateLoopStyle(); +} + +void WaSkin::updateLoopStyle() { + if (shuffle->toggled()) { + napp->player()->loop(Player::Random); + } + else { + int loopVal = repeat->toggled() ? Player::Playlist : Player::None; + napp->player()->loop(loopVal); + } +} + +void WaSkin::playlistClickedEvent(bool) +{ + napp->playlist()->toggleList(); +} + +void WaSkin::eqClickedEvent() +{ + napp->equalizerView(); +} + +void WaSkin::jump(int val) +{ + if (napp->player()->isStopped()) { + waJumpSlider->setJumpValue(0); + } else { + napp->player()->skipTo((int) (val * 1000)); + } +} + +void WaSkin::jumpSliderPressed() +{ + mJumpPressed = true; + jumpValueChanged(waJumpSlider->jumpValue()); +} + + +void WaSkin::jumpSliderReleased() +{ + mJumpPressed = false; + waInfo->setText(getTitleString()); +} + +void WaSkin::jumpValueChanged(int val) +{ + if (mJumpPressed && !napp->player()->isStopped()) { + QString timeStr = i18n("Seek to: %1/%2 (%3%)"). + arg(getTimeString(val * 1000)). + arg(getTimeString(napp->player()->getLength())). + arg((val * 1000 * 100) / napp->player()->getLength()); + waInfo->setText(timeStr); + } +} + +QString WaSkin::getTitleString() { + int length; + QString title = ""; + + if (!napp->playlist()->current()) { + title = "Noatun "; + title += QString::number(NOATUN_MAJOR) + "."; + title += QString::number(NOATUN_MINOR) + "."; + title += QString::number(NOATUN_PATCHLEVEL); + } + else { + length = napp->playlist()->current().length(); + + title = napp->playlist()->current().title(); + + if (length >= 0) + title += " (" + getTimeString(length) + ")"; + + if (title.length() > 30) { + // It's scrolling; provide the nice, friendly seperator. + title += " *** "; + } + } + + return title; +} + +QString WaSkin::getTimeString(int milliseconds, bool truncate) { + int seconds = abs(milliseconds / 1000); + QString ret = ""; + + // Do we need to convert to hours:minutes instead of minutes:seconds? + if (truncate && (abs(seconds) >= (100 * 60))) + seconds /= 60; + + // Print the optional minus sign, hours/minutes, a colon, and then minutes/seconds. + ret.sprintf("%s%.2d:%.2d", ((milliseconds < 0) ? "-" : ""), seconds / 60, seconds % 60); + + return ret; +} + +void WaSkin::menuEvent() { + NoatunStdAction::ContextMenu::showContextMenu(mapToGlobal(QPoint(0, 14))); +} + +void WaSkin::minimizeEvent() { + showMinimized(); +} + +void WaSkin::shadeEvent() +{ + if (!title_shaded) + shade(); + else + unshade(); +} + +void WaSkin::doUnload() { + unload(); +} + +void WaSkin::doClose() { + QTimer::singleShot(0, this, SLOT(doUnload())); +} + +void WaSkin::dragEnterEvent(QDragEnterEvent * event) +{ + // accept uri drops only + event->accept(KURLDrag::canDecode(event)); +} + +void WaSkin::dropEvent(QDropEvent * event) +{ + KURL::List uri; + if (KURLDrag::decode(event, uri)) + { + for (KURL::List::Iterator i = uri.begin(); i != uri.end(); ++i) + napp->player()->openFile(*i, false); + } +} + +void WaSkin::balanceSliderPressed() +{ + mBalancePressed = true; + balanceSetValue(0); +} + +void WaSkin::balanceSliderReleased() +{ + + mBalancePressed = false; + waBalanceSlider->setBalanceValue(0); + + waInfo->setText(getTitleString()); +} + +void WaSkin::balanceSetValue(int val) +{ + if (val == 0) { + waInfo->setText(i18n("Balance: Center")); + } + else if (val < 0) { + waInfo->setText(i18n("Balance: %1% Left").arg(-val)); + } else { + waInfo->setText(i18n("Balance: %1% Right").arg(val)); + } +} + +void WaSkin::playCurrentEvent() +{ + if (napp->player()->isPaused()) + napp->player()->playpause(); + else + napp->player()->playCurrent(); +} + +void WaSkin::playPauseEvent() +{ + if (!napp->player()->isStopped()) + napp->player()->playpause(); +} + + +void WaSkin::loopChange(int loopType) +{ + shuffle->setToggled(loopType == Player::Random); + + if (loopType != Player::Random) + repeat->setToggled(loopType != Player::None); +} + +void WaSkin::playlistShown() +{ + playlist->setToggled(true); +} + +void WaSkin::playlistHidden() +{ + playlist->setToggled(false); +} + +void WaSkin::newSong() +{ + if (napp->player()->getLength() == -1) + waJumpSlider->hide(); + else + waJumpSlider->show(); + + mJumpPressed = false; + waJumpSlider->cancelDrag(); + + timetick(); +} + +void WaSkin::timetick() +{ + int mLength; + + if (!mVolumePressed && !mBalancePressed && !mJumpPressed) + waInfo->setText(getTitleString()); + + if (!napp->player()->current()) + return; + + mLength = (int) napp->player()->getLength() / 1000; + if (mLength < 0) + mLength = 0; + + waJumpSlider->setJumpRange(mLength); + + digitsClicked(); + + int time = 0; + if (napp->player()->current()) + time = (int) napp->player()->getTime() / 1000; + + if (!mJumpPressed) + waJumpSlider->setJumpValue(time); + + waVolumeSlider->setVolumeValue(napp->player()->volume()); +} + +void WaSkin::digitsClicked() { + if (!waDigit->timeReversed() || (napp->player()->getLength() == -1)) { + // Setting truncate=true means we want setTime to return + // no more than 6 digits (-xx:yy) + + if (napp->player()->getTime() != -1) + waDigit->setTime(getTimeString(napp->player()->getTime(), true)); + else + waDigit->setTime(getTimeString(0, true)); + } + else { + int rem_time = napp->player()->getTime() - napp->player()->getLength(); + + // Setting truncate=true means we want setTime to return + // no more than 6 digits (-xx:yy) + waDigit->setTime(getTimeString(rem_time, true)); + } +} + +void WaSkin::volumeSliderPressed() +{ + mVolumePressed = true; + volumeSetValue(napp->player()->volume()); +} + +void WaSkin::volumeSliderReleased() +{ + mVolumePressed = false; + waInfo->setText(getTitleString()); +} + +void WaSkin::volumeSetValue(int val) +{ + if (mVolumePressed) + waInfo->setText(i18n("Volume: %1%").arg(val)); + + napp->player()->setVolume(val); +} + +void WaSkin::slotPlaying() +{ + waStatus->setStatus(STATUS_PLAYING); + + if (!napp->playlist()->current()) { + return; + } + + fileInfo info(napp->playlist()->current()); + + if (!info.bps()) + waBPS->setText(""); + else + waBPS->setText(QString::number(info.bps())); + + if (!info.KHz()) + waFreq->setText(""); + else + waFreq->setText(QString::number(info.KHz() / 1000)); + + setChannels(info.channelCount()); + guiSpectrumAnalyser->resumeVisualization(); + + if (napp->player()->getLength() == -1) + waJumpSlider->hide(); + else + waJumpSlider->show(); + + timetick(); +} + +void WaSkin::slotStopped() +{ + waStatus->setStatus(STATUS_STOPPED); + + waDigit->setTime(""); + + waBPS->setText(""); + waFreq->setText(""); + setChannels(0); + + waJumpSlider->setJumpValue(0); + // -1 == disable jump bar + waJumpSlider->setJumpRange(-1); + + + mJumpPressed = false; + waJumpSlider->cancelDrag(); + + waJumpSlider->hide(); + + guiSpectrumAnalyser->pauseVisualization(); +} + +void WaSkin::slotPaused() +{ + waStatus->setStatus(STATUS_PAUSED); +} + +void WaSkin::keyPressEvent(QKeyEvent *e) { + switch(e->key()) { + case Key_Up: + napp->player()->setVolume(napp->player()->volume() + 5); + break; + case Key_Down: + napp->player()->setVolume(napp->player()->volume() - 5); + break; + case Key_Left: + if (napp->player()->current()) + napp->player()->skipTo(napp->player()->getTime() - 5000); + + break; + case Key_Right: + if (napp->player()->current()) + napp->player()->skipTo(napp->player()->getTime() + 5000); + + break; + + case Key_Z: + napp->player()->back(); + break; + + case Key_X: + if (napp->player()->isPaused()) + napp->player()->playpause(); + else + napp->player()->playCurrent(); + + break; + + case Key_C: + if (!napp->player()->isStopped()) + napp->player()->playpause(); + + break; + + case Key_V: + napp->player()->stop(); + break; + + case Key_B: + napp->player()->forward(); + break; + + case Key_R: + repeat->setToggled(!repeat->toggled()); + updateLoopStyle(); + break; + + case Key_S: + shuffle->setToggled(!shuffle->toggled()); + updateLoopStyle(); + break; + } +} + +QString WaSkin::defaultSkin() { + return "Winamp"; +} + +#include "waSkin.moc" diff --git a/noatun/modules/winskin/waSkin.h b/noatun/modules/winskin/waSkin.h new file mode 100644 index 00000000..7a2db9e1 --- /dev/null +++ b/noatun/modules/winskin/waSkin.h @@ -0,0 +1,177 @@ +/* + Winamp Skin + Copyright (C) 1999 Martin Vogt + Copyright (C) 2001 Ryan Cumming + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#ifndef __WASKIN_H +#define __WASKIN_H + +#include <noatun/plugin.h> +#include <noatun/app.h> +#include <noatun/player.h> +#include <qwidget.h> + +// Use forward declarations so we compile in a finite time +class WaSkinModel; +class WaSkinManager; + +class WaButton; +class WaDigit; +class WaLabel; +class WaInfo; +class WaMain; +class WaIndicator; +class WaTitleBar; +class WaClutterbar; +class WaStatus; + +class WaJumpSlider; +class WaVolumeSlider; +class WaBalanceSlider; + +class GuiSpectrumAnalyser; + +class WaSkin; +extern WaSkin *_waskin_instance; + +class WaSkin : public QWidget, public UserInterface { + Q_OBJECT + NOATUNPLUGIND + WaSkinModel *waSkinModel; + WaSkinManager *waSkinManager; + + public: + WaSkin(); + ~WaSkin(); + + int getSkinId(); + + void loadSkin(QString skinDir); + void setChannels(int val); + + QSize sizeHint() const; + + static QString defaultSkin(); + static WaSkin *instance() { return _waskin_instance; } + + public slots: + void repeatClickedEvent(bool); + void shuffleClickedEvent(bool); + void playlistClickedEvent(bool); + void eqClickedEvent(); + + // seek bar + void jump(int second); + void jumpSliderPressed(); + void jumpSliderReleased(); + void jumpValueChanged(int); + + void menuEvent(); + void minimizeEvent(); + void shadeEvent(); + void doUnload(); + void doClose(); + + // balance + void balanceSliderPressed(); + void balanceSetValue(int val); + void balanceSliderReleased(); + + // volume + void volumeSliderPressed(); + void volumeSetValue(int val); + void volumeSliderReleased(); + + void playCurrentEvent(); + void playPauseEvent(); + + void loopChange(int loopType); + void playlistShown(); + void playlistHidden(); + void newSong(); + + void timetick(); + void digitsClicked(); + + void slotPlaying(); + void slotStopped(); + void slotPaused(); + + WaSkinModel *skinModel() { return waSkinModel; } + WaSkinManager *skinManager() { return waSkinManager; } + WaInfo *skinInfo() { return waInfo; } + + protected: + void updateLoopStyle(); + + void createButtons(); + void createHighLevelElements(); + + void keyPressEvent(QKeyEvent *); + + void shade(); + void unshade(); + + QString getTitleString(); + QString getTimeString(int milliseconds, bool truncate = false); + + void focusOutEvent ( QFocusEvent * ); + void focusInEvent ( QFocusEvent * ); + + void dragEnterEvent(QDragEnterEvent * event); + void dropEvent(QDropEvent * event); + + void wheelEvent(QWheelEvent *e); + + WaButton *prev; + WaButton *play; + WaButton *pause; + WaButton *stop; + WaButton *next; + WaButton *eject; + WaButton *shuffle; + WaButton *repeat; + WaButton *playlist; + WaButton *eq; + + WaButton *menu; + WaButton *minimize; + WaButton *titleshade; + WaButton *close; + + WaJumpSlider *waJumpSlider; + WaVolumeSlider *waVolumeSlider; + WaBalanceSlider *waBalanceSlider; + WaDigit *waDigit; + + WaLabel *waBPS; + WaLabel *waFreq; + + WaInfo *waInfo; + WaStatus *waStatus; + WaIndicator *waStereo; + WaIndicator *waMono; + + WaMain *main; + WaTitleBar *waTitleBar; + WaClutterbar *waClutterbar; + + GuiSpectrumAnalyser *guiSpectrumAnalyser; + + bool title_shaded; + + bool mJumpPressed; + bool mBalancePressed; + bool mVolumePressed; +}; +#endif diff --git a/noatun/modules/winskin/waSkinManager.cpp b/noatun/modules/winskin/waSkinManager.cpp new file mode 100644 index 00000000..5cde117b --- /dev/null +++ b/noatun/modules/winskin/waSkinManager.cpp @@ -0,0 +1,127 @@ +#include <kglobal.h> +#include <qfileinfo.h> +#include <qregexp.h> +#include <kstandarddirs.h> +#include <qdir.h> +#include <kdebug.h> +#include <kmimetype.h> +#include <kio/job.h> +#include <kurl.h> +#include <kio/netaccess.h> +#include <kzip.h> + +#include "waSkinManager.h" +#include "waSkinModel.h" + +WaSkinManager::WaSkinManager() : DCOPObject("WaSkinManager") { +} + +WaSkinManager::~WaSkinManager() { +} + +QStringList WaSkinManager::availableSkins() { + QStringList skinDirs = KGlobal::dirs()->findDirs("data", "noatun/skins/winamp"); + QStringList skin_list; + + // This loop adds them all to our skin list + for(unsigned int x = 0;x < skinDirs.count();x++) { + QDir skinQDir(skinDirs[x]); + + // We only want directories, although there shouldn't be anything else + skinQDir.setFilter( QDir::Dirs ); + // I guess name is as good as any + skinQDir.setSorting( QDir::Name ); + + for (unsigned int y = 0;y < skinQDir.count();y++) { + QStringList skins = skinQDir.entryList(QDir::Dirs, QDir::Name); + + // We really don't care for '.' and '..' + if (skinQDir[y][0] != (char)'.') { + // Add ourselves to the list, using our directory name + skin_list += skinQDir[y]; + } + } + } + + return skin_list; +} + +QString WaSkinManager::currentSkin() { + return mCurrentSkin; +} + +QString WaSkinManager::defaultSkin() { + return "Winamp"; +} + +bool WaSkinManager::loadSkin(QString skinName) { + QStringList skins = KGlobal::dirs()->findDirs("data", "noatun/skins/winamp/" + skinName); + + if (!skins.count()) + mCurrentSkin = defaultSkin(); + else + mCurrentSkin = skinName; + + return _waskinmodel_instance->load(skins[0]); +} + +bool WaSkinManager::installSkin(QString _url) { + QString location = KGlobal::dirs()->saveLocation("data", "noatun/skins/winamp"); + KURL url(_url); + QString mimetype = KMimeType::findByURL(_url)->name(); + + if (mimetype == "inode/directory") + { + KIO::Job *job = KIO::copy(url, location, !url.isLocalFile()); + connect(job, SIGNAL(result(KIO::Job *)), this, SIGNAL(updateSkinList())); + return true; + } + else if ((mimetype == "interface/x-winamp-skin") || (mimetype == "application/x-zip")) + { + if (!url.isLocalFile()) + return false; + + QString base_path; + base_path = location + "/" + QFileInfo(url.path()).baseName().replace(QRegExp("_"), " "); + KIO::Job *job = KIO::copy("zip:" + url.path(), base_path); + connect(job, SIGNAL(result(KIO::Job *)), this, SIGNAL(updateSkinList())); + + return true; + } + + return false; +} + +bool WaSkinManager::removeSkin(QString skinName) { + if (!skinRemovable(skinName)) + return false; + + QStringList skins = KGlobal::dirs()->findDirs("data", "noatun/skins/winamp/" + skinName); + + KIO::Job *job = KIO::del(KURL(skins[0]), false, false); + connect(job, SIGNAL(result(KIO::Job *)), this, SIGNAL(updateSkinList())); + + return true; +} + +bool WaSkinManager::skinRemovable(QString skinName) { + QStringList skins = KGlobal::dirs()->findDirs("data", "noatun/skins/winamp/" + skinName); + + if (!skins.count()) + return false; + + QFileInfo info(skins[0]); + return info.isWritable(); +} + +QStringList WaSkinManager::skinMimeTypes() { + QStringList temp; + + temp.append("interface/x-winamp-skin"); + temp.append("application/x-zip"); + temp.append("inode/directory"); + + return temp; +} + +#include "waSkinManager.moc" diff --git a/noatun/modules/winskin/waSkinManager.h b/noatun/modules/winskin/waSkinManager.h new file mode 100644 index 00000000..17b21daf --- /dev/null +++ b/noatun/modules/winskin/waSkinManager.h @@ -0,0 +1,39 @@ +#ifndef _WASKINMANAGER_H +#define _WASKINMANAGER_H + +#include <dcopobject.h> +#include <qobject.h> +#include <qstringlist.h> +#include <qstring.h> +#include <qmap.h> + +class WaSkinManager : public QObject, public DCOPObject { +Q_OBJECT +K_DCOP + +public: + WaSkinManager(); + ~WaSkinManager(); + +k_dcop: + QStringList availableSkins(); + QString currentSkin(); + bool loadSkin(QString skinName); + + QString defaultSkin(); + + bool installSkin(QString url); + + bool skinRemovable(QString skinName); + bool removeSkin(QString skinName); + + QStringList skinMimeTypes(); + +signals: + void updateSkinList(); + +private: + QString mCurrentSkin; +}; + +#endif diff --git a/noatun/modules/winskin/waSkinMapping.h b/noatun/modules/winskin/waSkinMapping.h new file mode 100644 index 00000000..a3dfc9c5 --- /dev/null +++ b/noatun/modules/winskin/waSkinMapping.h @@ -0,0 +1,148 @@ +/* + mapping from file and id to pixmap, and global player map + Copyright (C) 1999 Martin Vogt + Copyright (C) 2002 Ryan Cumming + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#ifndef __WASKINMAPPING_H +#define __WASKINMAPPING_H + + +/** + This file is not a header file in the normal sense. + It define _directly_ variables, which are used in the + WaSkinLoader class. + Its a bit black voodoo magic. +*/ + +/** + The Skin file format was downloaded from the web. + http://www.algonet.et.se/~daniel7 + + Author: unknown +*/ + +#include "skinMap.h" +#include "waSkins.h" + +static const SkinMap normalMapToGui[] = { + {0, 0, 275, 116}, // _WA_MAPPING_MAIN + {16, 88, 23, 18}, // _WA_MAPPING_CBUTTONS_PREV + {16 + 1 * 23, 88, 23, 18}, // _WA_MAPPING_CBUTTONS_PLAY + {16 + 2 * 23, 88, 23, 18}, // _WA_MAPPING_CBUTTONS_PAUSE + {16 + 3 * 23, 88, 23, 18}, // _WA_MAPPING_CBUTTONS_STOP + {16 + 4 * 23, 88, 22, 18}, // _WA_MAPPING_CBUTTONS_NEXT + {136, 89, 22, 16}, // _WA_MAPPING_CBUTTONS_EJECT + {239, 41, 29, 12}, // _WA_MAPPING_MONOSTER_STEREO + {212, 41, 27, 12}, // _WA_MAPPING_MONOSTER_MONO + {210, 89, 28, 15}, // _WA_MAPPING_REPEAT + {164, 89, 46, 15}, // _WA_MAPPING_SHUFFLE + {242, 58, 23, 12}, // _WA_MAPPING_PLAYLIST + {219, 58, 23, 12}, // _WA_MAPPING_EQ + {107, 57, 68, 13}, // _WA_MAPPING_VOLUME_BAR + {0, 0, 14, 11}, // _WA_MAPPING_VOLUME_SLIDER + {177, 57, 38, 13}, // _WA_MAPPING_BALANCE_BAR + {0, 0, 14, 11}, // _WA_MAPPING_BALANCE_SLIDER + {24, 28, 11, 9}, // _WA_MAPPING_PLAYPAUS + {16, 72, 248, 10}, // _WA_MAPPING_POS_BAR + {0, 0, 29, 10}, // _WA_MAPPING_POS_BAR_SLIDER + {40, 26, 63, 13}, // _WA_MAPPING_DIGITS + {40, 32, 5, 1}, // _WA_MAPPING_MINUS + {48, 26, 9, 13}, // _WA_MAPPING_DIGIT_1 + {60, 26, 9, 13}, // _WA_MAPPING_DIGIT_2 + {78, 26, 9, 13}, // _WA_MAPPING_DIGIT_3 + {90, 26, 9, 13}, // _WA_MAPPING_DIGIT_4 + {24, 43, 75, 16}, // _WA_MAPPING_ANALYSER + {111, 43, 15, 6}, // _WA_MAPPING_BPS + {156, 43, 10, 6}, // _WA_MAPPING_FREQ + {112, 27, 152, 6}, // _WA_MAPPING_INFO + {0, 0, 274, 14}, // _WA_MAPPING_TITLE + {6, 3, 9, 9}, // _WA_MAPPING_TITLE_MENU + {244, 3, 9, 9}, // _WA_MAPPING_TITLE_MIN + {254, 3, 9, 9}, // _WA_MAPPING_TITLE_SHADE + {264, 3, 9, 9}, // _WA_MAPPING_TITLE_CLOSE + {10, 22, 8, 43} // _WA_MAPPING_CLUTTERBAR +}; + + +static const SkinDesc normalMapFromFile[] = { + {_WA_FILE_MAIN, 0, 0, 275, 116}, // _WA_SKIN_MAIN + {_WA_FILE_CBUTTONS, 0, 0, 23, 18}, // _WA_SKIN_CBUTTONS_PREV_NORM + {_WA_FILE_CBUTTONS, 0, 18, 23, 18}, // _WA_SKIN_CBUTTONS_PREV_PRES + {_WA_FILE_CBUTTONS, 23, 0, 23, 18}, //_WA_SKIN_CBUTTONS_PLAY_NORM, + {_WA_FILE_CBUTTONS, 23, 18, 23, 18}, // _WA_SKIN_CBUTTONS_PLAY_PRES + {_WA_FILE_CBUTTONS, 46, 0, 23, 18}, // _WA_SKIN_CBUTTONS_PAUSE_NORM + {_WA_FILE_CBUTTONS, 46, 18, 23, 18}, // _WA_SKIN_CBUTTONS_PAUSE_PRES + {_WA_FILE_CBUTTONS, 69, 0, 23, 18}, // _WA_SKIN_CBUTTONS_STOP_NORM + {_WA_FILE_CBUTTONS, 69, 18, 23, 18}, // _WA_SKIN_CBUTTONS_STOP_PRES + {_WA_FILE_CBUTTONS, 92, 0, 22, 18}, // _WA_SKIN_CBUTTONS_NEXT_NORM + {_WA_FILE_CBUTTONS, 92, 18, 22, 18}, // _WA_SKIN_CBUTTONS_NEXT_PRES + {_WA_FILE_CBUTTONS, 114, 0, 22, 16}, // _WA_SKIN_CBUTTONS_EJECT_NORM + {_WA_FILE_CBUTTONS, 114, 16, 22, 16}, // _WA_SKIN_CBUTTONS_EJECT_PRESS + {_WA_FILE_MONOSTER, 0, 0, 29, 12}, // _WA_SKIN_MONOSTER_STEREO_TRUE + {_WA_FILE_MONOSTER, 0, 12, 29, 12}, // _WA_SKIN_MONOSTER_STEREO_FALSE + {_WA_FILE_MONOSTER, 29, 0, 27, 12}, // _WA_SKIN_MONOSTER_MONO_TRUE + {_WA_FILE_MONOSTER, 29, 12, 27, 12}, // _WA_SKIN_MONOSTER_MONO_FALSE + {_WA_FILE_NUMBERS, 0, 0, 99, 13}, // _WA_SKIN_NUMBERS + {_WA_FILE_NUMBERS, 20, 6, 5, 1}, // _WA_SKIN_NUMBERS_MINUS + {_WA_FILE_NUMBERS, 90, 6, 5, 1}, // _WA_SKIN_NUMBERS_BLANK + {_WA_FILE_SHUFREP, 0, 0, 28, 15}, // _WA_SKIN_SHUFREP_REPEAT_NOT_SET_NORM + {_WA_FILE_SHUFREP, 0, 15, 28, 15}, // _WA_SKIN_SHUFREP_REPEAT_NOT_SET_PRES + {_WA_FILE_SHUFREP, 0, 30, 28, 15}, // _WA_SKIN_SHUFREP_REPEAT_SET_NORM + {_WA_FILE_SHUFREP, 0, 45, 28, 15}, // _WA_SKIN_SHUFREP_REPEAT_SET_PRES + {_WA_FILE_SHUFREP, 28, 0, 47, 15}, // _WA_SKIN_SHUFREP_SHUFFLE_NOT_SET_NORM + {_WA_FILE_SHUFREP, 28, 15, 47, 15}, // _WA_SKIN_SHUFREP_SHUFFLE_NOT_SET_PRES + {_WA_FILE_SHUFREP, 28, 30, 47, 15}, // _WA_SKIN_SHUFREP_SHUFFLE_SET_NORM + {_WA_FILE_SHUFREP, 28, 45, 47, 15}, // _WA_SKIN_SHUFREP_SHUFFLE_SET_PRES + {_WA_FILE_SHUFREP, 23, 61, 23, 12}, // _WA_SKIN_SHUFREP_PLAYLIST_NOT_SET_NORM + {_WA_FILE_SHUFREP, 69, 61, 23, 12}, // _WA_SKIN_SHUFREP_PLAYLIST_NOT_SET_PRES + {_WA_FILE_SHUFREP, 23, 73, 23, 12}, // _WA_SKIN_SHUFREP_PLAYLIST_SET_NORM + {_WA_FILE_SHUFREP, 73, 23, 12}, // _WA_SKIN_SHUFREP_PLAYLIST_SET_PRES + {_WA_FILE_SHUFREP, 0, 61, 23, 12}, // _WA_SKIN_SHUFREP_EQ_NOT_SET_NORM + {_WA_FILE_SHUFREP, 46, 61, 23, 12}, // _WA_SKIN_SHUFREP_EQ_NOT_SET_PRES + {_WA_FILE_SHUFREP, 0, 73, 23, 12}, // _WA_SKIN_SHUFREP_EQ_SET_NORM + {_WA_FILE_SHUFREP, 46, 73, 23, 12}, // _WA_SKIN_SHUFREP_EQ_SET_PRES + {_WA_FILE_TEXT, 0, 0, 155, 18}, // _WA_SKIN_TEXT + {_WA_FILE_VOLUME, 0, 0, 68, 421}, // _WA_SKIN_VOLUME_BAR_ALL_BARS + {_WA_FILE_VOLUME, 0, 0, 68, 13}, // _WA_SKIN_VOLUME_BAR + {_WA_FILE_VOLUME, 0, 422, 14, 11}, // _WA_SKIN_VOLUME_SLIDER_NORM + {_WA_FILE_VOLUME, 15, 422, 14, 11}, // _WA_SKIN_VOLUME_SLIDER_PRES + {_WA_FILE_BALANCE, 9, 0, 38, 421}, // _WA_SKIN_BALANCE_BAR_ALL_BARS + {_WA_FILE_BALANCE, 9, 0, 38, 13}, // _WA_SKIN_BALANCE_BAR + {_WA_FILE_BALANCE, 0, 422, 14, 11}, // _WA_SKIN_BALANCE_SLIDER_NORM + {_WA_FILE_BALANCE, 15, 422, 14, 11}, // _WA_SKIN_BALANCE_SLIDER_PRES + {_WA_FILE_POSBAR, 0, 0, 248, 10}, // _WA_SKIN_POS_BAR + {_WA_FILE_POSBAR, 278, 0, 29, 10}, // _WA_SKIN_POS_BAR_SLIDER_NORM + {_WA_FILE_POSBAR, 248, 0, 29, 10}, // _WA_SKIN_POS_BAR_SLIDER_PRES + {_WA_FILE_PLAYPAUS, 1, 0, 8, 9}, // _WA_SKIN_PLAYPAUS_PLAY + {_WA_FILE_PLAYPAUS, 9, 0, 9, 9}, // _WA_SKIN_PLAYPAUS_PAUSE + {_WA_FILE_PLAYPAUS, 18, 0, 9, 9}, // _WA_SKIN_PLAYPAUS_STOP + {_WA_FILE_PLAYPAUS, 27, 0, 2, 9}, // _WA_SKIN_PLAYPAUS_FILLER + {_WA_FILE_PLAYPAUS, 36, 0, 3, 9}, // _WA_SKIN_PLAYPAUS_WORK_INDICATOR + {_WA_FILE_TITLEBAR, 27, 0, 275, 14}, // _WA_SKIN_TITLE_ACTIVE + {_WA_FILE_TITLEBAR, 27, 15, 275, 14}, // _WA_SKIN_TITLE_INACTIVE + {_WA_FILE_TITLEBAR, 0, 9, 9, 9}, // _WA_SKIN_TITLE_MENU_PRES + {_WA_FILE_TITLEBAR, 0, 0, 9, 9}, // _WA_SKIN_TITLE_MENU_NORM + {_WA_FILE_TITLEBAR, 33, 18, 9, 9}, // _WA_SKIN_TITLE_MENU_INACTIVE + {_WA_FILE_TITLEBAR, 9, 9, 9, 9}, // _WA_SKIN_TITLE_MIN_PRES + {_WA_FILE_TITLEBAR, 9, 0, 9, 9}, // _WA_SKIN_TITLE_MIN_NORM + {_WA_FILE_TITLEBAR, 271, 18, 9, 9}, // _WA_SKIN_TITLE_MIN_INACTIVE + {_WA_FILE_TITLEBAR, 9, 18, 9, 9}, // _WA_SKIN_TITLE_SHADE_PRES + {_WA_FILE_TITLEBAR, 0, 18, 9, 9}, // _WA_SKIN_TITLE_SHADE_NORM + {_WA_FILE_TITLEBAR, 281, 18, 9, 9}, // _WA_SKIN_TITLE_SHADE_INACTIVE + {_WA_FILE_TITLEBAR, 18, 9, 9, 9}, // _WA_SKIN_TITLE_CLOSE_PRES + {_WA_FILE_TITLEBAR, 18, 0, 9, 9}, // _WA_SKIN_TITLE_CLOSE_NORM + {_WA_FILE_TITLEBAR, 291, 18, 9, 9}, // _WA_SKIN_TITLE_CLOSE_INACTIVE + {_WA_FILE_TITLEBAR, 312, 0, 8, 43} // _WA_SKIN_CLUTTERBAR_DISABLED +}; + +#endif diff --git a/noatun/modules/winskin/waSkinModel.cpp b/noatun/modules/winskin/waSkinModel.cpp new file mode 100644 index 00000000..ff53b4e6 --- /dev/null +++ b/noatun/modules/winskin/waSkinModel.cpp @@ -0,0 +1,458 @@ +/* + operations with skinset. + Copyright (C) 1999 Martin Vogt + Copyright (C) 2001 Ryan Cumming + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include <config.h> +#include <qdir.h> +#include <qstringlist.h> +#include <qbitmap.h> +#include <kdebug.h> +#include <kstandarddirs.h> + +#include "waSkinMapping.h" +#include "waShadeMapping.h" + +#include "waSkinModel.h" +#include "waColor.h" +#include "waRegion.h" +#include "waSkin.h" + +WaSkinModel *_waskinmodel_instance = NULL; + +// Our current skin map +// Can switch between normal and windowshade maps +const SkinMap *mapToGui; +const SkinDesc *mapFromFile; +int digit_width; +int digit_height; + + +struct WaPixmapEntry { + const char *filename; + QPixmap *pixmap; +}; + +WaPixmapEntry waPixmapEntries[11] = { + {"main.bmp", NULL}, + {"cbuttons.bmp", NULL}, + {"monoster.bmp", NULL}, + {"numbers.bmp", NULL}, + {"shufrep.bmp", NULL}, + {"text.bmp", NULL}, + {"volume.bmp", NULL}, + {"balance.bmp", NULL}, + {"posbar.bmp", NULL}, + {"playpaus.bmp", NULL}, + {"titlebar.bmp", NULL} + }; + +WaSkinModel::WaSkinModel() +{ + for (int x = 0;x < 11;x++) + waPixmapEntries[x].pixmap = new QPixmap; + + resetSkinModel(); + _waskinmodel_instance = this; +} + +WaSkinModel::~WaSkinModel() +{ + for (int x = 0;x < 11;x++) + delete waPixmapEntries[x].pixmap; + + delete windowRegion; + delete colorScheme; +} + +bool WaSkinModel::load(QString skinDir) +{ + bool success = true; + + QDir dir(skinDir); + + if (findFile(dir, "main.bmp").isEmpty()) { + // Ack, our skin dir doesn't exist, fall back to the default + dir = QDir(KGlobal::dirs()->findDirs("data", "noatun/skins/winamp/" + WaSkin::defaultSkin())[0]); + success = false; + } + + for (int x = 0;x < 11;x++) { + getPixmap(dir, waPixmapEntries[x].filename, + waPixmapEntries[x].pixmap); + } + + resetSkinModel(); + + loadColors(dir); + loadRegion(dir); + + emit(skinChanged()); + + return success; +} + +// Does a case-insenstive file search (like DOS/Windows) +// Filename -must- be lowercase, which is an nice optimization, since +// this is a private API, and all our filenames are internally lowercase +// anyway +QString WaSkinModel::findFile(const QDir &dir, const QString &filename) { + QFileInfo fileInfo; + QString ret = ""; + + QStringList strList = dir.entryList(); + + for (QStringList::iterator file = strList.begin(); file != strList.end(); file++) { + QFileInfo fileInfo(*file); + + if (fileInfo.isDir()) + continue; + + if (fileInfo.filePath().lower() == filename) + return dir.absPath() + "/" + QString(fileInfo.filePath()); + } + + return ""; +} + +void WaSkinModel::loadColors(const QDir &dir) { + QString colorFile = findFile(dir, "viscolor.txt"); + + if (colorScheme) { + delete colorScheme; + } + + colorScheme = new WaColor(colorFile); +} + +void WaSkinModel::loadRegion(const QDir &dir) { + QString regionFile = findFile(dir, "region.txt"); + + if (windowRegion) { + delete windowRegion; + windowRegion = 0; + } + + windowRegion = new WaRegion(regionFile); +} + +int WaSkinModel::getPixmap(const QDir &dir, QString fname, + QPixmap *target) +{ + QFileInfo fileInfo; + QStringList strList = dir.entryList(); + QString abspath; + + abspath = findFile(dir, fname); + + if (!abspath.isEmpty()) { + target->load(abspath); + return true; + } + + // now the filename mapping 1.8x -> 2.0 + if (fname == "volume.bmp") + return WaSkinModel::getPixmap(dir, QString("volbar.bmp"), target); + + if (fname == "numbers.bmp") + return WaSkinModel::getPixmap(dir, QString("nums_ex.bmp"), target); + + // Even 2.x themes can omit BALANCE, in which case we use VOLUME + if (fname == "balance.bmp") + return WaSkinModel::getPixmap(dir, QString("volume.bmp"), target); + + return false; +} + + +QRect WaSkinModel::getGeometry(int id) { + if ( (id < 0) || (id >= _WA_SKIN_ENTRIES) ) { + kdDebug() << "Array index out of range. WaSkinModel::getGeometry"<<endl; + exit(-1); + } + return QRect(mapFromFile[id].x, mapFromFile[id].y, + mapFromFile[id].width, mapFromFile[id].height); +} + +QRect WaSkinModel::getMapGeometry(int id) { + if ( (id < 0) || (id >= _WA_MAPPING_ENTRIES) ) { + kdDebug() << "Array index out of range. WaSkinModel::getMapGeometry"<<endl; + exit(-1); + } + return QRect(mapToGui[id].x, mapToGui[id].y, + mapToGui[id].width, mapToGui[id].height); +} + +void WaSkinModel::bltTo(int id, QPaintDevice *dest, int x, int y) { + bitBlt(dest, x, y, waPixmapEntries[mapFromFile[id].fileId].pixmap, + mapFromFile[id].x, mapFromFile[id].y, + mapFromFile[id].width, mapFromFile[id].height); +} + +void WaSkinModel::bltTo(int id, QPaintDevice *dest, int x, int y, int argument) { + if (id == _WA_SKIN_VOLUME_BAR) { + QPixmap *pix = waPixmapEntries[_WA_FILE_VOLUME].pixmap; + + int nBar = int((float)argument * 27.0 / 100.0); + bitBlt(dest, x, y, pix, 0, 15 * nBar, 68, 13); + + return; + } + + if (id == _WA_SKIN_BALANCE_BAR) { + QPixmap *pix = waPixmapEntries[_WA_FILE_BALANCE].pixmap; + + argument = abs(argument); + + int nBar = int((float)argument * 27.0 / 100.0); + bitBlt(dest, x, y, pix, 9, 15 * nBar, 38, 13); + + return; + } + + bltTo(id, dest, x, y); +} + +void WaSkinModel::getDigit(char number, QPaintDevice *dest, int x, int y) { + if (number=='-') { + bltTo(_WA_SKIN_NUMBERS_MINUS, dest, x, y); + return; + } + + // empty number ? + if (number == ' ') { + bltTo(_WA_SKIN_NUMBERS_BLANK, dest, x, y); + return; + } + + // number + QPixmap *pix = waPixmapEntries[mapFromFile[_WA_SKIN_NUMBERS].fileId].pixmap; + + // ordinary number: + int index = number - '0'; + if ((index < 0) || (index > 9)) + return; + + bitBlt(dest, x, y, pix , (index * digit_width) + mapFromFile[_WA_SKIN_NUMBERS].x, mapFromFile[_WA_SKIN_NUMBERS].y, digit_width, digit_height); + + return; +} + +void WaSkinModel::getText(char text, QPaintDevice * dest, int x, int y) { + QPixmap *pix = waPixmapEntries[_WA_FILE_TEXT].pixmap; + + text = deaccent(text); + + if (('A' <= text) && (text <= 'Z')) { + bitBlt(dest, x, y,pix,(text-'A')*5,0,5,6); + return; + } + if (('a' <= text) && (text <= 'z')) { + bitBlt(dest, x, y,pix,(text-'a')*5,0,5,6); + return; + } + if (('0' <= text) && (text <= '9')) { + bitBlt(dest, x, y,pix,(text-'0')*5,6,5,6); + return; + } + if ('"' == text) { + bitBlt(dest, x, y,pix,27*5,0,5,6); + return; + } + if ('@' == text) { + bitBlt(dest, x, y,pix,28*5,0,5,6); + return; + } + + + if ('.' == text) { + bitBlt(dest, x, y,pix,11*5,6,5,6); + return; + } + if (':' == text) { + bitBlt(dest, x, y,pix,12*5,6,5,6); + return; + } + if (('(' == text) || ('<' == text) || ('{' == text)) { + bitBlt(dest, x, y,pix,13*5,6,5,6); + return; + } + if ((')' == text) || ('>' == text) || ('}' == text)) { + bitBlt(dest, x, y,pix,14*5,6,5,6); + return; + } + if ('-' == text) { + bitBlt(dest, x, y,pix,15*5,6,5,6); + return; + } + if (('`' == text) || ('\'' == text)) { + bitBlt(dest, x, y,pix,16*5,6,5,6); + return; + } + if ('!' == text) { + bitBlt(dest, x, y,pix,17*5,6,5,6); + return; + } + if ('_' == text) { + bitBlt(dest, x, y,pix,18*5,6,5,6); + return; + } + if ('+' == text) { + bitBlt(dest, x, y,pix,19*5,6,5,6); + return; + } + if ('\\' == text) { + bitBlt(dest, x, y,pix,20*5,6,5,6); + return; + } + if ('/' == text) { + bitBlt(dest, x, y,pix,21*5,6,5,6); + return; + } + if ('[' == text) { + bitBlt(dest, x, y,pix,22*5,6,5,6); + return; + } + if (']' == text) { + bitBlt(dest, x, y,pix,23*5,6,5,6); + return; + } + if ('^' == text) { + bitBlt(dest, x, y,pix,24*5,6,5,6); + return; + } + if ('&' == text) { + bitBlt(dest, x, y,pix,25*5,6,5,6); + return; + } + if ('%' == text) { + bitBlt(dest, x, y,pix,26*5,6,5,6); + return; + } + if (',' == text) { + bitBlt(dest, x, y,pix,27*5,6,5,6); + return; + } + if ('=' == text) { + bitBlt(dest, x, y,pix,28*5,6,5,6); + return; + } + if ('$' == text) { + bitBlt(dest, x, y,pix,29*5,6,5,6); + return; + } + if ('#' == text) { + bitBlt(dest, x, y,pix,30*5,6,5,6); + return; + } + if (('' == text) || ('' == text)) { + bitBlt(dest, x, y,pix,0*5,12,5,6); + return; + } + if (('' == text) || ('' == text)) { + bitBlt(dest, x, y,pix,1*5,12,5,6); + return; + } + if (('' == text) || ('' == text)) { + bitBlt(dest, x, y,pix,2*5,12,5,6); + return; + } + if ('?' == text) { + bitBlt(dest, x, y,pix,3*5,12,5,6); + return; + } + if ('*' == text) { + bitBlt(dest, x, y,pix,4*5,12,5,6); + return; + } + // default back is space char + bitBlt(dest, x, y,pix,(10*5),12,5,6); +} + +void WaSkinModel::paintBackgroundTo(int mapping, QPaintDevice *dest, int x, int y) +{ + QPixmap *pix = waPixmapEntries[mapFromFile[_WA_SKIN_MAIN].fileId].pixmap; + QRect main_rect = getGeometry(_WA_SKIN_MAIN); + QRect dest_rect = getMapGeometry(mapping); + + int source_x = main_rect.x() + dest_rect.x() + x; + int source_y = main_rect.y() + dest_rect.y() + y; + + int width = dest_rect.width() - x; + int height = dest_rect.height() - y; + + bitBlt(dest, x, y, pix, source_x, source_y, width, height); +} + +void WaSkinModel::setSkinModel(skin_models new_model) { + if (new_model == WA_MODEL_NORMAL) { + mapToGui = normalMapToGui; + mapFromFile = normalMapFromFile; + digit_width = 9; + digit_height = 13; + } + else if (new_model == WA_MODEL_WINDOWSHADE) { + mapToGui = shadeMapToGui; + mapFromFile = shadeMapFromFile; + digit_width = 5; + digit_height = 6; + } + + emit(skinChanged()); +} + +void WaSkinModel::resetSkinModel() { + mapToGui = normalMapToGui; + mapFromFile = normalMapFromFile; + digit_width = 9; + digit_height = 13; +} + + +QChar WaSkinModel::deaccent(QChar input) { + if (QString("").contains(input)) + return 'A'; + + if (QString("").contains(input)) + return 'E'; + + if (QString("").contains(input)) + return 'I'; + + if (QString("").contains(input)) + return 'O'; + + if (QString("").contains(input)) + return 'U'; + + if (input == '') + return 'Y'; + + if (QString("").contains(input)) + return 'a'; + + if (QString("").contains(input)) + return 'e'; + + if (QString("").contains(input)) + return 'i'; + + if (QString("").contains(input)) + return 'o'; + + if (QString("").contains(input)) + return 'u'; + + return input; +} + +#include "waSkinModel.moc" diff --git a/noatun/modules/winskin/waSkinModel.h b/noatun/modules/winskin/waSkinModel.h new file mode 100644 index 00000000..9447f8ae --- /dev/null +++ b/noatun/modules/winskin/waSkinModel.h @@ -0,0 +1,64 @@ +/* + Model for winamp skins + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + +#ifndef __WASKINMODEL_H +#define __WASKINMODEL_H + +#include <qstring.h> +#include <qobject.h> +#include <qdir.h> + +#include "waSkins.h" + +enum skin_models { WA_MODEL_NORMAL, WA_MODEL_WINDOWSHADE }; + +class QChar; +class WaSkinModel; +extern WaSkinModel *_waskinmodel_instance; + +class WaSkinModel : public QObject { + Q_OBJECT + + public: + WaSkinModel(); + ~WaSkinModel(); + + void getDigit(char number, QPaintDevice *dest, int x, int y); + void getText(char text, QPaintDevice *dest, int x, int y); + + void bltTo(int id, QPaintDevice *dest, int x, int y); + void bltTo(int id, QPaintDevice *dest, int x, int y, int argument); + + void paintBackgroundTo(int mapping, QPaintDevice *dest, int x, int y); + + QRect getGeometry(int id); + QRect getMapGeometry(int id); + + bool load(QString skinDir); + + void setSkinModel(skin_models new_model); + static WaSkinModel *instance() { return _waskinmodel_instance; } + + private: + void resetSkinModel(); + + QString findFile(const QDir &dir, const QString &filename); + QChar deaccent(QChar input); + + int getPixmap(const QDir &dir, QString fname, QPixmap * target); + void loadColors(const QDir &dir); + void loadRegion(const QDir &dir); + + signals: + void skinChanged(); +}; +#endif diff --git a/noatun/modules/winskin/waSkins.h b/noatun/modules/winskin/waSkins.h new file mode 100644 index 00000000..f8d5f623 --- /dev/null +++ b/noatun/modules/winskin/waSkins.h @@ -0,0 +1,161 @@ +/* + names for the different skins in winamp + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef _WASKINS_H +#define _WASKINS_H + + + +/** + The Skin file format was downloaded from the web. + http://www.algonet.et.se/~daniel7 + + Author: unknown +*/ + + +#define _WA_SKIN_MAIN 0 +#define _WA_SKIN_CBUTTONS_PREV_NORM 1 +#define _WA_SKIN_CBUTTONS_PREV_PRES 2 +#define _WA_SKIN_CBUTTONS_PLAY_NORM 3 +#define _WA_SKIN_CBUTTONS_PLAY_PRES 4 +#define _WA_SKIN_CBUTTONS_PAUSE_NORM 5 +#define _WA_SKIN_CBUTTONS_PAUSE_PRES 6 +#define _WA_SKIN_CBUTTONS_STOP_NORM 7 +#define _WA_SKIN_CBUTTONS_STOP_PRES 8 +#define _WA_SKIN_CBUTTONS_NEXT_NORM 9 +#define _WA_SKIN_CBUTTONS_NEXT_PRES 10 +#define _WA_SKIN_CBUTTONS_EJECT_NORM 11 +#define _WA_SKIN_CBUTTONS_EJECT_PRESS 12 +#define _WA_SKIN_MONOSTER_STEREO_TRUE 13 +#define _WA_SKIN_MONOSTER_STEREO_FALSE 14 +#define _WA_SKIN_MONOSTER_MONO_TRUE 15 +#define _WA_SKIN_MONOSTER_MONO_FALSE 16 + +#define _WA_SKIN_NUMBERS 17 +#define _WA_SKIN_NUMBERS_MINUS 18 +#define _WA_SKIN_NUMBERS_BLANK 19 + +#define _WA_SKIN_SHUFREP_REPEAT_NOT_SET_NORM 20 +#define _WA_SKIN_SHUFREP_REPEAT_NOT_SET_PRES 21 +#define _WA_SKIN_SHUFREP_REPEAT_SET_NORM 22 +#define _WA_SKIN_SHUFREP_REPEAT_SET_PRES 23 +#define _WA_SKIN_SHUFREP_SHUFFLE_NOT_SET_NORM 24 +#define _WA_SKIN_SHUFREP_SHUFFLE_NOT_SET_PRES 25 +#define _WA_SKIN_SHUFREP_SHUFFLE_SET_NORM 26 +#define _WA_SKIN_SHUFREP_SHUFFLE_SET_PRES 27 +#define _WA_SKIN_SHUFREP_PLAYLIST_NOT_SET_NORM 28 +#define _WA_SKIN_SHUFREP_PLAYLIST_NOT_SET_PRES 29 +#define _WA_SKIN_SHUFREP_PLAYLIST_SET_NORM 30 +#define _WA_SKIN_SHUFREP_PLAYLIST_SET_PRES 31 +#define _WA_SKIN_SHUFREP_EQ_NOT_SET_NORM 32 +#define _WA_SKIN_SHUFREP_EQ_NOT_SET_PRES 33 +#define _WA_SKIN_SHUFREP_EQ_SET_NORM 34 +#define _WA_SKIN_SHUFREP_EQ_SET_PRES 35 + +#define _WA_SKIN_TEXT 36 + +#define _WA_SKIN_VOLUME_BAR_ALL_BARS 37 +#define _WA_SKIN_VOLUME_BAR 38 +#define _WA_SKIN_VOLUME_SLIDER_NORM 39 +#define _WA_SKIN_VOLUME_SLIDER_PRES 40 + +#define _WA_SKIN_BALANCE_BAR_ALL_BARS 41 +#define _WA_SKIN_BALANCE_BAR 42 +#define _WA_SKIN_BALANCE_SLIDER_NORM 43 +#define _WA_SKIN_BALANCE_SLIDER_PRES 44 + +#define _WA_SKIN_POS_BAR 45 +#define _WA_SKIN_POS_BAR_SLIDER_NORM 46 +#define _WA_SKIN_POS_BAR_SLIDER_PRES 47 + +#define _WA_SKIN_PLAYPAUS_PLAY 48 +#define _WA_SKIN_PLAYPAUS_PAUSE 49 +#define _WA_SKIN_PLAYPAUS_STOP 50 +#define _WA_SKIN_PLAYPAUS_FILLER 51 +#define _WA_SKIN_PLAYPAUS_WORK_INDICATOR 52 + +#define _WA_SKIN_TITLE_ACTIVE 53 +#define _WA_SKIN_TITLE_INACTIVE 54 + +#define _WA_SKIN_TITLE_MENU_PRES 55 +#define _WA_SKIN_TITLE_MENU_NORM 56 +#define _WA_SKIN_TITLE_MENU_INACTIVE 57 +#define _WA_SKIN_TITLE_MIN_PRES 58 +#define _WA_SKIN_TITLE_MIN_NORM 59 +#define _WA_SKIN_TITLE_MIN_INACTIVE 60 +#define _WA_SKIN_TITLE_SHADE_PRES 61 +#define _WA_SKIN_TITLE_SHADE_NORM 62 +#define _WA_SKIN_TITLE_SHADE_INACTIVE 63 +#define _WA_SKIN_TITLE_CLOSE_PRES 64 +#define _WA_SKIN_TITLE_CLOSE_NORM 65 +#define _WA_SKIN_TITLE_CLOSE_INACTIVE 66 + +#define _WA_SKIN_CLUTTERBAR_DISABLED 67 + +#define _WA_MAPPING_MAIN 0 +#define _WA_MAPPING_CBUTTONS_PREV 1 +#define _WA_MAPPING_CBUTTONS_PLAY 2 +#define _WA_MAPPING_CBUTTONS_PAUSE 3 +#define _WA_MAPPING_CBUTTONS_STOP 4 +#define _WA_MAPPING_CBUTTONS_NEXT 5 +#define _WA_MAPPING_CBUTTONS_EJECT 6 +#define _WA_MAPPING_MONOSTER_STEREO 7 +#define _WA_MAPPING_MONOSTER_MONO 8 +#define _WA_MAPPING_REPEAT 9 +#define _WA_MAPPING_SHUFFLE 10 +#define _WA_MAPPING_PLAYLIST 11 +#define _WA_MAPPING_EQ 12 +#define _WA_MAPPING_VOLUME_BAR 13 +#define _WA_MAPPING_VOLUME_SLIDER 14 +#define _WA_MAPPING_BALANCE_BAR 15 +#define _WA_MAPPING_BALANCE_SLIDER 16 +#define _WA_MAPPING_PLAYPAUS 17 +#define _WA_MAPPING_POS_BAR 18 +#define _WA_MAPPING_POS_BAR_SLIDER 19 +#define _WA_MAPPING_DIGITS 20 +#define _WA_MAPPING_MINUS 21 +#define _WA_MAPPING_DIGIT_1 22 +#define _WA_MAPPING_DIGIT_2 23 +#define _WA_MAPPING_DIGIT_3 24 +#define _WA_MAPPING_DIGIT_4 25 +#define _WA_MAPPING_ANALYSER 26 +#define _WA_MAPPING_BPS 27 +#define _WA_MAPPING_FREQ 28 +#define _WA_MAPPING_INFO 29 +#define _WA_MAPPING_TITLE 30 +#define _WA_MAPPING_TITLE_MENU 31 +#define _WA_MAPPING_TITLE_MIN 32 +#define _WA_MAPPING_TITLE_SHADE 33 +#define _WA_MAPPING_TITLE_CLOSE 34 +#define _WA_MAPPING_CLUTTERBAR 35 + +#define _WA_FILE_MAIN 0 +#define _WA_FILE_CBUTTONS 1 +#define _WA_FILE_MONOSTER 2 +#define _WA_FILE_NUMBERS 3 +#define _WA_FILE_SHUFREP 4 +#define _WA_FILE_TEXT 5 +#define _WA_FILE_VOLUME 6 +#define _WA_FILE_BALANCE 7 +#define _WA_FILE_POSBAR 8 +#define _WA_FILE_PLAYPAUS 9 +#define _WA_FILE_TITLEBAR 10 + +#define _WA_MAPPING_ENTRIES 36 +#define _WA_SKIN_ENTRIES 68 + +#define _WA_TEXT_WIDTH 5 +#define _WA_TEXT_HEIGHT 6 + +#endif diff --git a/noatun/modules/winskin/waSlider.cpp b/noatun/modules/winskin/waSlider.cpp new file mode 100644 index 00000000..4fff1b0d --- /dev/null +++ b/noatun/modules/winskin/waSlider.cpp @@ -0,0 +1,209 @@ +/* + Standard slider for Winskin + Copyright (C) 1999 Martin Vogt + Copyright (C) 2002 Ryan Cumming + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + +#include <stdlib.h> + +#include "waSlider.h" +#include "waSkinModel.h" + +WaSlider::WaSlider(int sliderBarMapId, int sliderId, bool is_volume) : WaWidget(sliderBarMapId) +{ + this->sliderBarMapId = sliderBarMapId; + + lDragging = false; + + currentValue = 0; + setRange(0, 100); + + slider_y = is_volume ? 1 : 0; + slider_x = 0; + + slider_width = WaSkinModel::instance()->getMapGeometry(sliderId).width(); + + slider_visible = true; +} + + +WaSlider::~WaSlider() +{ +} + +void WaSlider::setPixmapSliderBar(int pixId) +{ + this->sliderBarId = pixId; + update(); +} + +void WaSlider::paintEvent(QPaintEvent *) +{ + // POSBAR.BMP does not have full height in all Winamp skins + // Paint background before painting slider to be on the safe side + if(sliderBarId == _WA_SKIN_POS_BAR) + paintPixmap(-1); + + paintPixmap(sliderBarId, value()); + + if (slider_visible) + paintPixmap(lDragging ? up_pixmap : down_pixmap, slider_x, slider_y); +} + + +void WaSlider::mouseMoveEvent(QMouseEvent * e) +{ + if (lDragging == false) { + WaWidget::mouseMoveEvent(e); + return; + } + + int newX = e->x() - pressPoint.x(); + + if (newX < 0) + newX = 0; + + QSize size = sizeHint(); + + int maxX = size.width() - slider_width; + + if(mapping == _WA_MAPPING_VOLUME_BAR) + maxX -= 3; + + if (newX > maxX) + newX = maxX; + + int value = pixel2Value(newX); + + setValue(value); +} + + +void WaSlider::updateSliderPos(int value) +{ + if (value > maxValue) { + value = maxValue; + } + if (value < minValue) { + value = minValue; + } + + int pixelPos = value2Pixel(value); + slider_x = (pixelPos); + + update(); +} + +void WaSlider::mousePressEvent(QMouseEvent *e) { + if (e->button() != LeftButton && e->button() != MidButton) { + WaWidget::mousePressEvent(e); + return; + } + + int maxX = slider_x - slider_width; + + if(mapping == _WA_MAPPING_VOLUME_BAR) + maxX -= 3; + + if ((e->x() < slider_x) || (e->x() > (maxX))) { + int newX = e->x(); + newX -= (slider_width / 2); + setValue(pixel2Value(newX)); + } + + + pressPoint.setX(e->x() - slider_x); + lDragging = true; + + update(); + + emit(sliderPressed()); +} + +void WaSlider::mouseReleaseEvent(QMouseEvent *e) +{ + if (!lDragging) { + WaWidget::mouseReleaseEvent(e); + return; + } + + lDragging = false; + update(); + + emit(sliderReleased()); +} + + +int WaSlider::pixel2Value(int xpos) +{ + QSize size = sizeHint(); + int min = abs(minValue); + int max = abs(maxValue); + + int valuerange = min + max; + int pixelrange = size.width() - slider_width; + + if(mapping == _WA_MAPPING_VOLUME_BAR) + pixelrange -= 3; + + return ((xpos * valuerange) / pixelrange) + minValue; +} + +int WaSlider::value2Pixel(int value) +{ + QSize size = sizeHint(); + float min = (float) minValue; + float max = (float) maxValue; + float fmin = min; + float fmax = max; + if (min < 0) { + fmin = -1 * fmin; + } + if (max < 0) { + fmax = -1 * fmax; + } + float valuerange = fmin + fmax; + float verhaeltnis = fmin / valuerange; + float pixelrange = (float) (size.width() - slider_width); + + if(mapping == _WA_MAPPING_VOLUME_BAR) + pixelrange -= 3; + + float zeropoint = verhaeltnis * pixelrange; + float anstieg = pixelrange / valuerange; + + float pixel = (float) value * anstieg + zeropoint; + return (int) (pixel+0.5); // add 0.5 to round upwards if larger than x.5 +} + +void WaSlider::setRange(int min, int max) { + minValue = min; + maxValue = max; + + if (currentValue < min) + currentValue = min; + + if (currentValue > max) + currentValue = max; +} + +void WaSlider::setValue(int value) { + currentValue = value; + + updateSliderPos(currentValue); + emit(valueChanged(value)); +} + +void WaSlider::cancelDrag() { + lDragging = false; + update(); +} + +#include "waSlider.moc" diff --git a/noatun/modules/winskin/waSlider.h b/noatun/modules/winskin/waSlider.h new file mode 100644 index 00000000..0003afd2 --- /dev/null +++ b/noatun/modules/winskin/waSlider.h @@ -0,0 +1,82 @@ +/* + standard Slider for winamp Skin + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + + +#ifndef __WASLIDER_H +#define __WASLIDER_H + +#include <qpainter.h> + +#include "waWidget.h" +#include "waButton.h" + +class WaSlider : public WaWidget { + Q_OBJECT + + public: + WaSlider(int sliderBarMapId, int sliderId, bool is_volume = false); + ~WaSlider(); + + void setRange(int min, int max); + + void setValue(int value); + int value() const { return currentValue; } + + void hideButton() { slider_visible = false; } + void showButton() { slider_visible = true; } + + void cancelDrag(); + + public slots: + void setPixmapSliderButtonDown(int pixId) { down_pixmap = pixId; } + void setPixmapSliderButtonUp(int pixId) { up_pixmap = pixId; } + void setPixmapSliderBar(int pixId); + + private: + void paintEvent(QPaintEvent *); + int pixel2Value(int xpos); + int value2Pixel(int value); + + int slider_x; + int slider_y; + int slider_width; + bool slider_visible; + + int up_pixmap; + int down_pixmap; + + int sliderBarId; + int sliderBarMapId; + + bool lDragging; + QPoint pressPoint; + + int currentValue; + + int minValue; + int maxValue; + + void mousePressEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + + private slots: + void updateSliderPos(int value); + + signals: + void sliderPressed(); + void sliderReleased(); + void valueChanged(int); +}; +#endif diff --git a/noatun/modules/winskin/waStatus.cpp b/noatun/modules/winskin/waStatus.cpp new file mode 100644 index 00000000..e028b7f0 --- /dev/null +++ b/noatun/modules/winskin/waStatus.cpp @@ -0,0 +1,42 @@ +/* + standard Button for winamp Skin + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "waStatus.h" +#include "waSkinModel.h" + +WaStatus::WaStatus() : WaWidget(_WA_MAPPING_PLAYPAUS) +{ + _status = STATUS_STOPPED; +} + +WaStatus::~WaStatus() +{ +} + +void WaStatus::paintEvent(QPaintEvent *) +{ + if (_status == STATUS_PLAYING) { + paintPixmap(_WA_SKIN_PLAYPAUS_WORK_INDICATOR); + paintPixmap(_WA_SKIN_PLAYPAUS_PLAY, 3, 0); + } + else if (_status == STATUS_STOPPED) { + paintPixmap(_WA_SKIN_PLAYPAUS_FILLER); + paintPixmap(_WA_SKIN_PLAYPAUS_STOP, 2 ,0); + } + else if (_status == STATUS_PAUSED) { + paintPixmap(_WA_SKIN_PLAYPAUS_FILLER); + paintPixmap(_WA_SKIN_PLAYPAUS_PAUSE, 2, 0); + } +} + +#include "waStatus.moc" diff --git a/noatun/modules/winskin/waStatus.h b/noatun/modules/winskin/waStatus.h new file mode 100644 index 00000000..a3fe1bc8 --- /dev/null +++ b/noatun/modules/winskin/waStatus.h @@ -0,0 +1,40 @@ +/* + standard Button for winamp Skin + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + + +#ifndef __WASTATUS_H +#define __WASTATUS_H + +#include <qpainter.h> + +#include "waWidget.h" + +enum status_enum {STATUS_PLAYING, STATUS_STOPPED, STATUS_PAUSED}; + +class WaStatus : public WaWidget { + Q_OBJECT + + public: + WaStatus(); + ~WaStatus(); + + void setStatus(status_enum status) { _status = status; update(); } + status_enum status() const { return _status; } + + private: + void paintEvent(QPaintEvent * paintEvent); + + status_enum _status; +}; +#endif diff --git a/noatun/modules/winskin/waTitleBar.cpp b/noatun/modules/winskin/waTitleBar.cpp new file mode 100644 index 00000000..82b603f5 --- /dev/null +++ b/noatun/modules/winskin/waTitleBar.cpp @@ -0,0 +1,79 @@ +/* + Titlebar for winamp Skin + Copyright (C) 1999 Martin Vogt + Copyright (C) 2001 Ryan Cumming + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include <qwidget.h> +#include <qpixmap.h> + +#include "waTitleBar.h" +#include "waSkinModel.h" + +#include <stdlib.h> + +#include <iostream> + +WaTitleBar::WaTitleBar() : WaIndicator(_WA_MAPPING_TITLE, _WA_SKIN_TITLE_ACTIVE, _WA_SKIN_TITLE_INACTIVE) +{ + moving = false; + setState(parentWidget()->isActiveWindow()); +} + +WaTitleBar::~WaTitleBar() +{ +} + +void WaTitleBar::mousePressEvent(QMouseEvent * e) +{ + if (e->button() != RightButton) { + if (!moving) { + moving = true; + mDragStart = e->pos(); + mLastPos = e->globalPos(); + } + + setState(true); + update(); + return; + } + else + WaWidget::mousePressEvent(e); +} + +void WaTitleBar::mouseDoubleClickEvent(QMouseEvent *) { + emit(shaded()); +} + +void WaTitleBar::mouseReleaseEvent(QMouseEvent * e) +{ + if (e->button() != RightButton) { + moving = false; + update(); + return; + } + else + WaWidget::mouseReleaseEvent(e); +} + +void WaTitleBar::mouseMoveEvent(QMouseEvent * e) +{ + QPoint diff = e->globalPos() - mLastPos; + if (abs(diff.x()) > 10 || abs(diff.y()) > 10) { + // Moving starts only, when passing a drag border + moving = true; + } + + if (moving) + parentWidget()->move(e->globalPos() - mDragStart); +} + +#include <waTitleBar.moc> diff --git a/noatun/modules/winskin/waTitleBar.h b/noatun/modules/winskin/waTitleBar.h new file mode 100644 index 00000000..4e001394 --- /dev/null +++ b/noatun/modules/winskin/waTitleBar.h @@ -0,0 +1,51 @@ +/* + standard Button for winamp Skin + Copyright (C) 1999 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + + +#ifndef __WATITLEBAR_H +#define __WATITLEBAR_H + +#include <qpainter.h> + +#include "waIndicator.h" + + +/** + A titlebar is similar to a button only that we move + the whole widget, when pressed +*/ + + +class WaTitleBar : public WaIndicator { + Q_OBJECT + + public: + WaTitleBar(); + ~WaTitleBar(); + + private: + void mouseDoubleClickEvent (QMouseEvent * e); + void mousePressEvent(QMouseEvent * e); + void mouseReleaseEvent(QMouseEvent * e); + void mouseMoveEvent(QMouseEvent * e); + + bool moving; + QPoint mLastPos; + QPoint mDragStart; + + signals: + void shaded(); + +}; +#endif diff --git a/noatun/modules/winskin/waVolumeSlider.cpp b/noatun/modules/winskin/waVolumeSlider.cpp new file mode 100644 index 00000000..d0a934d7 --- /dev/null +++ b/noatun/modules/winskin/waVolumeSlider.cpp @@ -0,0 +1,51 @@ +/* + jumpslider for winamp skins + Copyright (C) 1998 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include <waVolumeSlider.h> + + +WaVolumeSlider::WaVolumeSlider() : WaWidget(_WA_MAPPING_VOLUME_BAR) +{ + +} + + +WaVolumeSlider::~WaVolumeSlider() +{ +} + + +void WaVolumeSlider::buildGui() +{ + ws = new WaSlider(_WA_MAPPING_VOLUME_BAR, _WA_MAPPING_VOLUME_SLIDER, true); + + ws->setPixmapSliderButtonUp(_WA_SKIN_VOLUME_SLIDER_NORM); + ws->setPixmapSliderButtonDown(_WA_SKIN_VOLUME_SLIDER_PRES); + ws->setPixmapSliderBar(_WA_SKIN_VOLUME_BAR); + + connect(ws, SIGNAL(valueChanged(int)), this, + SIGNAL(volumeSetValue(int))); + connect(ws, SIGNAL(sliderPressed()), SIGNAL(sliderPressed())); + connect(ws, SIGNAL(sliderReleased()), SIGNAL(sliderReleased())); +} + +void WaVolumeSlider::setVolumeValue(int val) +{ + int currVal = ws->value(); + if (currVal != val) { + ws->setValue(val); + } +} + + +#include "waVolumeSlider.moc" diff --git a/noatun/modules/winskin/waVolumeSlider.h b/noatun/modules/winskin/waVolumeSlider.h new file mode 100644 index 00000000..29030c65 --- /dev/null +++ b/noatun/modules/winskin/waVolumeSlider.h @@ -0,0 +1,41 @@ +/* + jumpslider for winamp skins + Copyright (C) 1998 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#ifndef __WAVOLUMESLIDER_H +#define __WAVOLUMESLIDER_H + +#include "waSlider.h" +#include "waWidget.h" + +class WaVolumeSlider:public WaWidget { + Q_OBJECT + + public: + WaVolumeSlider(); + ~WaVolumeSlider(); + void buildGui(); + + void setVolumeValue(int val); + + private: + WaSlider *ws; + + signals: + void volumeSetValue(int val); + void sliderPressed(); + void sliderReleased(); +}; + + +#endif diff --git a/noatun/modules/winskin/waWidget.cpp b/noatun/modules/winskin/waWidget.cpp new file mode 100644 index 00000000..ffe2d3b4 --- /dev/null +++ b/noatun/modules/winskin/waWidget.cpp @@ -0,0 +1,58 @@ +#include "waWidget.h" +#include "waSkinModel.h" +#include "noatun/stdaction.h" +#include "waSkin.h" + +WaWidget::WaWidget(int _mapping) : QWidget(WaSkin::instance()) { + mapping = _mapping; + setBackgroundMode(NoBackground); + connect (WaSkinModel::instance(), SIGNAL(skinChanged()), this, SLOT(skinChanged())); +} + +WaWidget::~WaWidget() { +} + +void WaWidget::paintPixmap(int pixmap_mapping) { + if (pixmap_mapping != -1) + WaSkinModel::instance()->bltTo(pixmap_mapping, this, 0, 0); + else + WaSkinModel::instance()->paintBackgroundTo(mapping, this, 0, 0); +} + +void WaWidget::paintPixmap(int pixmap_mapping, int x, int y) { + if (pixmap_mapping != -1) + WaSkinModel::instance()->bltTo(pixmap_mapping, this, x, y); + else + WaSkinModel::instance()->paintBackgroundTo(mapping, this, x, y); +} + +void WaWidget::paintPixmap(int pixmap_mapping, int argument) { + if (pixmap_mapping != -1) + WaSkinModel::instance()->bltTo(pixmap_mapping, this, 0, 0, argument); + else + WaSkinModel::instance()->paintBackgroundTo(mapping, this, 0, 0); + +} + +void WaWidget::paintPixmap(int pixmap_mapping, int argument, int x, int y) { + if (pixmap_mapping != -1) + WaSkinModel::instance()->bltTo(pixmap_mapping, this, x, y, argument); + else + WaSkinModel::instance()->paintBackgroundTo(mapping, this, x, y); +} + +QSize WaWidget::sizeHint() { + return WaSkinModel::instance()->getMapGeometry(mapping).size(); +} + +void WaWidget::mousePressEvent(QMouseEvent *e) { + if (e->button() == RightButton) + NoatunStdAction::ContextMenu::showContextMenu(); +} + +void WaWidget::skinChanged() { + setGeometry(WaSkinModel::instance()->getMapGeometry(mapping)); + update(); +} + +#include <waWidget.moc> diff --git a/noatun/modules/winskin/waWidget.h b/noatun/modules/winskin/waWidget.h new file mode 100644 index 00000000..f2a41c82 --- /dev/null +++ b/noatun/modules/winskin/waWidget.h @@ -0,0 +1,31 @@ +#ifndef _WAWIDGET_H +#define _WAWIDGET_H + +#include <qwidget.h> +#include "waSkinModel.h" + +class WaWidget : public QWidget { + Q_OBJECT +public: + WaWidget(int mapping); + virtual ~WaWidget(); + + QSize sizeHint(); + + void paintPixmap(int wa_mapping); + void paintPixmap(int wa_mapping, int number); + + void paintPixmap(int wa_mapping, int x, int y); + void paintPixmap(int wa_mapping, int number, int x, int y); + + void paintBackground() { WaSkinModel::instance()->paintBackgroundTo(mapping, this, 0, 0); } + +protected: + void mousePressEvent(QMouseEvent *); + int mapping; + +private slots: + void skinChanged(); +}; + +#endif diff --git a/noatun/modules/winskin/winSkinConfig.cpp b/noatun/modules/winskin/winSkinConfig.cpp new file mode 100644 index 00000000..649fd1fe --- /dev/null +++ b/noatun/modules/winskin/winSkinConfig.cpp @@ -0,0 +1,174 @@ +#include <noatun/pref.h> + +#include <klocale.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qpixmap.h> +#include <kglobal.h> +#include <kconfig.h> +#include <qslider.h> +#include <qframe.h> +#include <qstringlist.h> +#include <kfile.h> +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <kurlrequester.h> +#include <kurlrequesterdlg.h> +#include <qdir.h> + +#include "waSkin.h" +#include "waInfo.h" +#include "waSkinManager.h" +#include "winSkinConfig.h" + +WinSkinConfig::WinSkinConfig(QWidget * parent, WaSkinManager *waSkinManager) : + CModule(i18n("Winskin"), + i18n("Skin Selection for the Winskin Plugin"), + "style", + parent) +{ + // Make a token horizontal layout box + vbox = new QVBoxLayout(this); + vbox->setSpacing( 6 ); + vbox->setMargin( 0 ); + + // Add a simple list of skins, populated in WinSkinConfig::reopen() + skin_list = new QListBox(this, "skin_list"); + vbox->addWidget(skin_list); + + QHBoxLayout* hbox = new QHBoxLayout( 0, 6, 6 ); + + QPushButton* buttonInstall = new QPushButton( i18n("&Install New Skin..."), this ); + hbox->addWidget(buttonInstall); + + buttonRemove = new QPushButton( i18n("&Remove Skin"), this ); + buttonRemove->setEnabled(false); + hbox->addWidget(buttonRemove); + vbox->addLayout(hbox); + + connect( skin_list, SIGNAL(highlighted(const QString &)), this, SLOT(selected())); + connect( buttonInstall, SIGNAL(clicked()), this, SLOT(install())); + connect( buttonRemove, SIGNAL(clicked()), this, SLOT(remove())); + connect(waSkinManager, SIGNAL(updateSkinList()), this, SLOT(reopen())); + + mWaSkinManager = waSkinManager; + + QGroupBox *settingsBox = new QGroupBox( 1, Vertical, i18n("Settings"), this ); + vbox->addWidget(settingsBox); + + QHBox *box = new QHBox(settingsBox); + QLabel *label = new QLabel(i18n("T&itle scrolling speed:"), box); + new QLabel(i18n("None"), box); + + scrollSpeed = new QSlider(box); + label->setBuddy(scrollSpeed); + scrollSpeed->setMinimumSize( QSize( 80, 0 ) ); + scrollSpeed->setMinValue( 0 ); + scrollSpeed->setMaxValue( 50 ); + scrollSpeed->setPageStep( 1 ); + scrollSpeed->setOrientation( QSlider::Horizontal ); + scrollSpeed->setTickmarks( QSlider::NoMarks ); + + label = new QLabel(i18n("Fast"), box); + + reopen(); +} + +void WinSkinConfig::save() +{ + KConfig *config=KGlobal::config(); + config->setGroup("Winskin"); + config->writeEntry("CurrentSkin", skin_list->currentText()); + config->writeEntry("ScrollDelay", scrollSpeed->value()); + config->sync(); + + if (skin_list->currentText() != orig_skin) { + _waskin_instance->loadSkin(skin_list->currentText()); + orig_skin = skin_list->currentText(); + } + else + { + _waskin_instance->skinInfo()->scrollerSetup(); + } +} + +void WinSkinConfig::reopen() { + // Wipe out the old list + skin_list->clear(); + + // Get a list of skins + QStringList skins = mWaSkinManager->availableSkins(); + + // This loop adds them all to our skin list + for(unsigned int x = 0;x < skins.count();x++) { + // Add ourselves to the list + skin_list->insertItem(skins[x]); + } + + // Figure out our current skin + QString orig_skin = mWaSkinManager->currentSkin(); + + // Where is that skin in our big-list-o-skins? + QListBoxItem *item = skin_list->findItem(orig_skin); + + if (item) { + // Aha, found it... make it the currently selected skin + skin_list->setCurrentItem( item ); + } + else { + // Er, it's not there... select the current item + // Maybe this should emit a warning? Oh well, it's not harmful + skin_list->setCurrentItem( 0 ); + } + + KConfig *config=KGlobal::config(); + config->setGroup("Winskin"); + scrollSpeed->setValue(config->readNumEntry("ScrollDelay", 15)); +} + +void WinSkinConfig::selected() +{ + buttonRemove->setEnabled(mWaSkinManager->skinRemovable( skin_list->currentText() )); +} + +void WinSkinConfig::install() +{ + QString url; + + // Ask the user for directory containing a skin + KURLRequesterDlg* udlg = new KURLRequesterDlg( QString::null, this, "udlg", true ); + udlg->urlRequester()->setFilter(mWaSkinManager->skinMimeTypes().join(" ")); + udlg->urlRequester()->setMode( KFile::File | KFile::Directory | KFile::ExistingOnly ); + + if( udlg->exec() == QDialog::Accepted ) { + url = udlg->urlRequester()->url(); + mWaSkinManager->installSkin( url ); + } +} + +void WinSkinConfig::remove() +{ + // Is there any item selected ?? + if( skin_list->currentText().isEmpty() ) + return; + + // We can't remove every skin + if( !mWaSkinManager->skinRemovable( skin_list->currentText() ) ) { + KMessageBox::information( this, i18n("You cannot remove this skin.") ); + // Reload skin list, perhaps the skin is already removed! + return; + } + + // Ask the user first + if( KMessageBox::warningContinueCancel( this, + i18n("<qt>Are you sure you want to remove the <b>%1</b> skin?</qt>").arg( skin_list->currentText() ), QString::null, KStdGuiItem::del() ) + == KMessageBox::Continue ) { + + mWaSkinManager->removeSkin( skin_list->currentText() ); + reopen(); + } +} + +#include <winSkinConfig.moc> diff --git a/noatun/modules/winskin/winSkinConfig.h b/noatun/modules/winskin/winSkinConfig.h new file mode 100644 index 00000000..22dca884 --- /dev/null +++ b/noatun/modules/winskin/winSkinConfig.h @@ -0,0 +1,35 @@ +#ifndef __WINSKINCONFIG_H +#define __WINSKINCONFIG_H + +#include <noatun/pref.h> +#include <qwidget.h> + +class QVBoxLayout; +class WaSkinManager; +class QSlider; + +class WinSkinConfig:public CModule { + Q_OBJECT + public: + WinSkinConfig(QWidget * parent, WaSkinManager *waManager); + + void save(); + + public slots: + void reopen(); + + private slots: + void selected(); + void install(); + void remove(); + + private: + WaSkinManager *mWaSkinManager; + QListBox *skin_list; + QString orig_skin; + QVBoxLayout *vbox; + QPushButton *buttonRemove; + QSlider *scrollSpeed; +}; + +#endif diff --git a/noatun/modules/winskin/winSkinVis.cpp b/noatun/modules/winskin/winSkinVis.cpp new file mode 100644 index 00000000..f9937981 --- /dev/null +++ b/noatun/modules/winskin/winSkinVis.cpp @@ -0,0 +1,107 @@ +/* + noatun visualisation interface for winskin + Copyright (C) 2001 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#include "winSkinVis.h" + +#define __BANDS 75 +#define __SPAHEIGHT 15 + +WinSkinVis::WinSkinVis(QObject *parent, const char *name): + QObject(parent,name),Visualization(50) { + + m_currentPeaks=new float[__BANDS]; + + for(unsigned int i=0;i<__BANDS;i++) + m_currentPeaks[i]=0.0; + + // If we can create our server-side object, visualize away + if (initServerObject()) + { + start(); + } +} + + +WinSkinVis::~WinSkinVis() +{ + if (m_winSkinFFT != NULL) { + if (connected()) + { + visualizationStack().remove(m_id); + m_winSkinFFT->stop(); + delete m_winSkinFFT; + } + } + + delete[] m_currentPeaks; +} + + +bool WinSkinVis::initServerObject() +{ + // Create FFT on server + m_winSkinFFT = new Noatun::WinSkinFFT(); + *m_winSkinFFT = Arts::DynamicCast(server()->createObject("Noatun::WinSkinFFT")); + + if ( (*m_winSkinFFT).isNull() ) { + delete m_winSkinFFT; + m_winSkinFFT=NULL; + } + else + { + m_winSkinFFT->bandResolution(__BANDS); + m_winSkinFFT->start(); + m_id=visualizationStack().insertBottom(*m_winSkinFFT, "WinSkin FFT"); + } + + return (m_winSkinFFT != NULL); +} + +void WinSkinVis::timeout() +{ + std::vector<float> *data(m_winSkinFFT->scope()); + + float *f=&data->front(); + if (data->size()) + scopeEvent(f, data->size()); + + delete data; +} + +float* WinSkinVis::currentPeaks() +{ + return m_currentPeaks; +} + +void WinSkinVis::scopeEvent(float* bandPtr, unsigned int bands) +{ + for (unsigned int i = 0;i < bands;i++) { + float value=bandPtr[i]; + // if the peak is less we prefer the higher one + if (m_currentPeaks[i] < value) + m_currentPeaks[i] = value; + else + m_currentPeaks[i] = m_currentPeaks[i]-1.3; + + if (m_currentPeaks[i] < 0.0) + m_currentPeaks[i] = 0.0; + + if (m_currentPeaks[i] > __SPAHEIGHT) + m_currentPeaks[i]=__SPAHEIGHT; + } + emit(doRepaint()); +} + + +#include "winSkinVis.moc" diff --git a/noatun/modules/winskin/winSkinVis.h b/noatun/modules/winskin/winSkinVis.h new file mode 100644 index 00000000..7d139d0c --- /dev/null +++ b/noatun/modules/winskin/winSkinVis.h @@ -0,0 +1,54 @@ +/* + noatun visualisation interface for winskin + Copyright (C) 2001 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#ifndef __WINSKINVIS_H +#define __WINSKINVIS_H + +#include <qobject.h> + +// These are needed for the Visualisation class +#include <soundserver.h> +#include "noatunarts/noatunarts.h" +#include "noatun/plugin.h" + +#include "vis/winskinvis.h" + +class WinSkinVis : public QObject, public Visualization { + Q_OBJECT + + public: + WinSkinVis(QObject* parent,const char* name); + ~WinSkinVis(); + + /** + * reimplemented from class Visualization, you + * should never need to reimplement this yourself + **/ + void timeout(); + float* currentPeaks(); + + signals: + void doRepaint(); + + private: + bool initServerObject(); + void scopeEvent(float* spectrum, unsigned int size); + + Noatun::WinSkinFFT* m_winSkinFFT; + long m_id; + float* m_currentPeaks; + + +}; + +#endif diff --git a/noatun/modules/winskin/winskin.plugin b/noatun/modules/winskin/winskin.plugin new file mode 100644 index 00000000..0f8b1074 --- /dev/null +++ b/noatun/modules/winskin/winskin.plugin @@ -0,0 +1,122 @@ +Filename=noatun_winskin.la +Author=Ryan Cumming, Martin Vogt +Site=http://mpeglib.sf.net +Email=bodnar42@phalynx.dhs.org +Type=userinterface +License=LGPL +Name=WinAmp Interface +Name[af]=Winamp Koppelvlak +Name[ar]=واجهة WinAmp +Name[az]=WinAMP Ara üzü +Name[bn]=উইন-অ্যাম্প ইন্টারফেস +Name[br]=Talbenn evit WinAmp +Name[ca]=Interfície WinAmp +Name[cs]=Rozhraní WinAmpu +Name[cy]=Rhyngwyneb Winamp +Name[da]=Winamp-grænseflade +Name[de]=Winamp-Oberfläche +Name[el]=Περιβάλλον WinAmp +Name[eo]=WinAmp-interfaco +Name[es]=Interfaz de Winamp +Name[et]=WinAmp liides +Name[eu]=WinAmp interfazea +Name[fa]=واسط WinAmp +Name[fi]=WinAmp-käyttöliittymä +Name[fr]=Interface Winamp +Name[ga]=Comhéadan WinAmp +Name[gl]=Interface de WinAmp +Name[he]=ממשק WinAmp +Name[hi]= विनएम्प इंटरफेस +Name[hr]=WinAmp sučelje +Name[hu]=Winamp-felület +Name[id]=Interface winamp +Name[is]=WinAmp andlit +Name[it]=Interfaccia WinAmp +Name[ja]=WinAmp インターフェース +Name[kk]=WinAmp интерфейсі +Name[km]=ចំណុចប្រទាក់ WinAmp +Name[ko]=WinAmp 인터페이스 +Name[lt]=WinAmp sąsaja +Name[lv]=WinAmp Starpseja +Name[mk]=Интерфејс WinAmp +Name[ms]=Antaramuka WinAmp +Name[mt]=Interfaċċja WinAmp +Name[nb]=WinAmp-grensesnitt +Name[nds]=Winamp-Böversiet +Name[ne]=WinAmp इन्टरफेस +Name[nl]=WinAmp-interface +Name[nn]=WinAmp-grensesnitt +Name[pa]=WinAmp ਇੰਟਰਫੇਸ +Name[pl]=Motyw WinAmpa +Name[pt]=Interface do WinAmp +Name[pt_BR]=Interface WinAmp +Name[ro]=Interfaţă WinAmp +Name[ru]=Интерфейс WinAmp +Name[sk]=Rozhranie WinAmp +Name[sl]=Vmesnik WinAmp +Name[sr]=WinAmp интерфејс +Name[sr@Latn]=WinAmp interfejs +Name[sv]=Winamp-gränssnitt +Name[ta]=வின் ஆம்ப் முகப்பு +Name[tg]=Интерфейси WinAmp +Name[th]=ส่วนติดต่อแบบ WinAmp +Name[tr]=WinAmp Arayüzü +Name[uk]=Інтерфейс WinAmp +Name[ven]=Interface ya WinAmp +Name[wa]=Eterface po WinAmp +Name[xh]=Ujongano lwe WinAmp +Name[zh_CN]=WinAmp 界面 +Name[zh_HK]=WinAmp 界面 +Name[zh_TW]=WinAmp 界面 +Name[zu]=Uxhumano olubhekeneyo lwe WinAmp +Comment=A Winamp skin loader +Comment[bg]=Зареждане на теми за Winamp +Comment[bn]=একটি উইন-অ্যাম্প স্কিন লোডার +Comment[br]=Ur c'harger a groc'hen Winamp +Comment[bs]=Učitavanje Winamp skinova +Comment[ca]=Carregador d'aparences de Winamp +Comment[cs]=Zavaděč motivů WinAmpu +Comment[cy]=Llwythydd Crwyn Winamp +Comment[da]=En Winamp-forsideindlæser +Comment[de]=Import von Winamp-Designs +Comment[el]=Φόρτωση θεμάτων Winamp +Comment[eo]=WinAmp-etosŝargilo +Comment[es]=Un cargador de pieles de Winamp +Comment[et]=Winampi rüüde laadija +Comment[eu]=Winamp azal kargatzailea +Comment[fa]=یک بارکنندۀ Winamp skin +Comment[fi]=Winamp-nahkojen lataaja +Comment[fr]=Un chargeur de revêtement Winamp +Comment[gl]=Un cargador de peles de Winamp +Comment[he]=טוען Skins של Winamp +Comment[hu]=Betöltőprogram Winamp-kinézetekhez +Comment[is]=Les skinn fyrir WinAmp +Comment[it]=Caricatore di skin di Winamp +Comment[ja]=Winamp のスキンローダ +Comment[kk]=Winamp тысының жүктегіші +Comment[km]=កម្មវិធីផ្ទុកស្បែក Winamp +Comment[ko]=Winamp 스킨 로더 +Comment[lt]=Winamp pavidalų įkėliklis +Comment[mk]=Вчитувач на маски за Winamp +Comment[nb]=Laster WinAmp-drakt +Comment[nds]=En Winamp-Böversietlader +Comment[ne]=विन्याप स्किन लोडर +Comment[nl]=Een Winamp-skinlader +Comment[nn]=Lastar WinAmp-skal +Comment[pl]=Ładowarka skór Winampa +Comment[pt]=Um leitor de aspectos do WinAmp +Comment[pt_BR]=Um carregador de aparências (skins) do Winamp +Comment[ro]=Un încărcător de tematici WinAmp +Comment[ru]=Загрузчик тем Winamp +Comment[sk]=Načítavač tém WinAmp +Comment[sl]=Nalagalnik preoblek Winamp +Comment[sr]=Учитавач Winamp-ових кошуљица +Comment[sr@Latn]=Učitavač Winamp-ovih košuljica +Comment[sv]=Skalladdare för Winamp +Comment[ta]=வின் ஆம்ப் அலங்கார அமைப்பு ஏற்றி +Comment[th]=ตัวโหลดหน้ากากแบบวินแอมป์ +Comment[tr]=Winamp arayüz yükleyici +Comment[uk]=Завантажувач жупанів Winamp +Comment[zh_CN]=Winamp 外观载入器 +Comment[zh_HK]=Winamp Skin 載入器 +Comment[zh_TW]=Winamp 面板載入器 |