summaryrefslogtreecommitdiffstats
path: root/noatun/modules/infrared
diff options
context:
space:
mode:
Diffstat (limited to 'noatun/modules/infrared')
-rw-r--r--noatun/modules/infrared/Makefile.am16
-rw-r--r--noatun/modules/infrared/README3
-rw-r--r--noatun/modules/infrared/infrared.cpp120
-rw-r--r--noatun/modules/infrared/infrared.h30
-rw-r--r--noatun/modules/infrared/infrared.plugin120
-rw-r--r--noatun/modules/infrared/irprefs.cpp311
-rw-r--r--noatun/modules/infrared/irprefs.h62
-rw-r--r--noatun/modules/infrared/lirc.cpp173
-rw-r--r--noatun/modules/infrared/lirc.h75
9 files changed, 910 insertions, 0 deletions
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
+