<h1 align="center"><img src="qrc:///icons/PierogiIcon.png"> Pierogi</h1>
<h2 align="center">A Universal Infrared Remote Control</h2>
+<p align="center">
+Version 0.1 (Beta)
+</p>
+
+<p>
+Note: while this app is in a fairly usable state, the keysets are still
+incomplete and mostly untested. Many brands of device are not yet supported,
+and those which have keysets may only work in a limited manner.
+</p>
+
<p>Copyright (C) 2012 by John Pietrzak.
Released under the GPL version 2.0 or later.</p>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
ui(new Ui::MainWindow),
- mySelectionWindow(0),
+ selectKeysetForm(0),
documentationForm(0),
aboutForm(0),
currentKeyset(0)
myKeysets = new PIRKeysetManager(this);
// Set up the keyset selection window:
- mySelectionWindow = new SelectionWindow(this);
+ selectKeysetForm = new PIRSelectKeysetForm(this);
- myKeysets->populateGuiWidget(mySelectionWindow);
+ myKeysets->populateGuiWidget(selectKeysetForm);
// Remember any favorites the user has already set:
populateFavorites();
Qt::QueuedConnection);
// Make sure the two selection lists don't show different selections:
+ QListWidget *klw = selectKeysetForm->getKeysetListWidget();
connect(
ui->favoriteKeysetsWidget,
SIGNAL(itemActivated(QListWidgetItem *)),
- mySelectionWindow->nameListWidget,
+ klw,
SLOT(clearSelection()),
Qt::QueuedConnection);
connect(
- mySelectionWindow->nameListWidget,
+ klw,
SIGNAL(itemActivated(QListWidgetItem *)),
ui->favoriteKeysetsWidget,
SLOT(clearSelection()),
MainWindow::~MainWindow()
{
delete myKeysets;
- delete mySelectionWindow;
+ if (selectKeysetForm) delete selectKeysetForm;
if (documentationForm) delete documentationForm;
if (aboutForm) delete aboutForm;
delete ui;
void MainWindow::on_actionSelectKeyset_triggered()
{
- mySelectionWindow->show();
+ selectKeysetForm->show();
}
void MainWindow::on_actionAbout_triggered()
PIRMakeName make;
QString name;
unsigned int id;
+ PIRKeysetWidgetItem *kwi;
while (index < size)
{
name = makeManager.getMakeString(make);
name.append(" ");
name.append(myKeysets->getDisplayName(id));
- ui->favoriteKeysetsWidget->addItem(
- new PIRKeysetWidgetItem(name, id, make));
+ kwi = new PIRKeysetWidgetItem(name, id, make);
+ myKeysets->populateDeviceTypes(kwi, id);
+ ui->favoriteKeysetsWidget->addItem(kwi);
++index;
}
#define MAINWINDOW_H
#include <QtGui/QMainWindow>
+#include <QListWidgetItem>
//#include <QThread>
-#include "selectionwindow.h"
+//#include "selectionwindow.h"
+#include "pirselectkeysetform.h"
#include "pirdocumentationform.h"
#include "piraboutform.h"
#include "pirkeysetmanager.h"
Ui::MainWindow *ui;
- SelectionWindow *mySelectionWindow;
+ PIRSelectKeysetForm *selectKeysetForm;
PIRDocumentationForm *documentationForm;
PIRAboutForm *aboutForm;
<x>0</x>
<y>0</y>
<width>800</width>
- <height>445</height>
+ <height>480</height>
</rect>
</property>
<property name="sizePolicy">
}
// construct the device:
- PIRDevice device(carrierFrequency, dutyCycle);
+ PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
int repeatCount = 0;
while (repeatCount < MAX_REPEAT_COUNT)
// use that signal. Otherwise, generate a normal command string.
if (hasRepeatPair && repeatCount)
{
- commandDuration = generateRepeatCommand(device);
+ commandDuration = generateRepeatCommand(rx51device);
}
else if (fullHeadlessRepeat && repeatCount)
{
- commandDuration = generateHeadlessCommand((*i).second, device);
+ commandDuration = generateHeadlessCommand((*i).second, rx51device);
}
else
{
- commandDuration = generateStandardCommand((*i).second, device);
+ commandDuration = generateStandardCommand((*i).second, rx51device);
}
// Now, tell the device to send the whole command:
- device.sendCommandToDevice();
+ rx51device.sendCommandToDevice();
// sleep until the next repetition of command:
sleepUntilRepeat(commandDuration);
int NECProtocol::generateStandardCommand(
const CommandSequence &bits,
- PIRDevice &device)
+ PIRRX51Hardware &rx51device)
{
int duration = 0;
// First, the "header" pulse (if any):
if (hasHeaderPair)
{
- device.addPair(headerPulse, headerSpace);
+ rx51device.addPair(headerPulse, headerSpace);
duration += (headerPulse + headerSpace);
}
// Next, the "pre" data:
- duration += pushBits(preData, device);
+ duration += pushBits(preData, rx51device);
// Next, add the actual command:
- duration += pushBits(bits, device);
+ duration += pushBits(bits, rx51device);
// Next, add the "post" data:
- duration += pushBits(postData, device);
+ duration += pushBits(postData, rx51device);
// Finally add the "trail":
if (hasTrailerPulse)
{
- device.addSingle(trailerPulse);
+ rx51device.addSingle(trailerPulse);
duration += trailerPulse;
}
int NECProtocol::generateHeadlessCommand(
const CommandSequence &bits,
- PIRDevice &device)
+ PIRRX51Hardware &rx51device)
{
int duration = 0;
// First, the "pre" data:
- duration += pushBits(preData, device);
+ duration += pushBits(preData, rx51device);
// Next, add the actual command:
- duration += pushBits(bits, device);
+ duration += pushBits(bits, rx51device);
// Next, add the "post" data:
- duration += pushBits(postData, device);
+ duration += pushBits(postData, rx51device);
// Finally add the "trail":
if (hasTrailerPulse)
{
- device.addSingle(trailerPulse);
+ rx51device.addSingle(trailerPulse);
duration += trailerPulse;
}
int NECProtocol::generateRepeatCommand(
- PIRDevice &device)
+ PIRRX51Hardware &rx51device)
{
int duration = 0;
if (hasHeaderPair)
{
// Ok, then add the header to the repeat:
- device.addPair(headerPulse, headerSpace);
+ rx51device.addPair(headerPulse, headerSpace);
duration += (headerPulse + headerSpace);
}
}
// Add the repeat pulse:
- device.addPair(repeatPulse, repeatSpace);
+ rx51device.addPair(repeatPulse, repeatSpace);
duration += (repeatPulse + repeatSpace);
// Finally add the trailer:
if (hasTrailerPulse)
{
- device.addSingle(trailerPulse);
+ rx51device.addSingle(trailerPulse);
duration += trailerPulse;
}
int NECProtocol::pushBits(
const CommandSequence &bits,
- PIRDevice &device)
+ PIRRX51Hardware &rx51device)
{
int duration = 0;
CommandSequence::const_iterator i = bits.begin();
if (*i)
{
// Send the pulse for "One":
- device.addPair(onePulse, oneSpace);
+ rx51device.addPair(onePulse, oneSpace);
duration += (onePulse + oneSpace);
}
else
{
// Send the pulse for "Zero":
- device.addPair(zeroPulse, zeroSpace);
+ rx51device.addPair(zeroPulse, zeroSpace);
duration += (zeroPulse + zeroSpace);
}
++i;
#define NECPROTOCOL_H
#include "pirprotocol.h"
-#include "pirdevice.h"
+#include "pirrx51hardware.h"
//
// The "NEC" Protocol is, more or less, followed by the majority of
int generateStandardCommand(
const CommandSequence &bits,
- PIRDevice &device);
+ PIRRX51Hardware &device);
int generateHeadlessCommand(
const CommandSequence &bits,
- PIRDevice &device);
+ PIRRX51Hardware &device);
int generateRepeatCommand(
- PIRDevice &device);
+ PIRRX51Hardware &device);
int pushBits(
const CommandSequence &bits,
- PIRDevice &device);
+ PIRRX51Hardware &device);
};
#endif // NECPROTOCOL_H
# MOBILITY +=
SOURCES += main.cpp mainwindow.cpp \
- pirdevice.cpp \
- selectionwindow.cpp \
necprotocol.cpp \
rc5protocol.cpp \
pirmakenames.cpp \
keysets/westinghouse.cpp \
keysets/mitsubishi.cpp \
pirmodprobe.cpp \
- keysets/jvc.cpp
+ keysets/jvc.cpp \
+ pirselectkeysetform.cpp \
+ pirrx51hardware.cpp \
+ pirdevicetypenames.cpp
HEADERS += mainwindow.h \
- pirdevice.h \
pirkeynames.h \
- selectionwindow.h \
necprotocol.h \
rc5protocol.h \
pirmakenames.h \
keysets/westinghouse.h \
keysets/mitsubishi.h \
pirmodprobe.h \
- keysets/jvc.h
+ keysets/jvc.h \
+ pirselectkeysetform.h \
+ pirrx51hardware.h \
+ pirdevicetypenames.h
FORMS += mainwindow.ui \
pirdocumentationform.ui \
- piraboutform.ui
+ piraboutform.ui \
+ pirselectkeysetform.ui
# Please do not modify the following two lines. Required for deployment.
include(deployment.pri)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
-<!-- Written by Qt Creator 2.4.0, 2012-01-09T01:28:37. -->
+<!-- Written by Qt Creator 2.4.0, 2012-01-14T13:10:14. -->
<qtcreator>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="QString"></value>
</valuelist>
<valuelist type="QVariantList" key="Qt4ProjectManager.MaemoRunConfiguration.LastDeployedTimes">
- <value type="QDateTime">2012-01-06T10:31:10</value>
+ <value type="QDateTime">2012-01-14T12:58:57</value>
<value type="QDateTime">2012-01-01T15:35:35</value>
</valuelist>
</valuemap>
<x>0</x>
<y>0</y>
<width>800</width>
- <height>445</height>
+ <height>480</height>
</rect>
</property>
<property name="windowTitle">
<x>0</x>
<y>0</y>
<width>798</width>
- <height>443</height>
+ <height>478</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_2">
+++ /dev/null
-#include "pirdevice.h"
-
-//#define DEBUGGING
-
-// Needed system includes:
-#include <sys/ioctl.h>
-#ifdef DEBUGGING
-#include <iostream>
-#include <sys/time.h>
-timeval previousTime;
-#else
-//#ifndef DEBUGGING
-#include <linux/types.h>
-#include <linux/ioctl.h>
-#endif // DEBUGGING
-#include <fcntl.h>
-
-// Includes I'm using for error handling stuff:
-#include "pirexception.h"
-#include <errno.h>
-#include <sstream>
-
-// The N900's IR transmitter is controlled by a device driver created
-// specifically for the LIRC daemon:
-#define PATH_TO_LIRC_DEVICE "/dev/lirc0"
-
-// It appears that the frequency on this device can range between
-// 20000 on the low end and 500000 on the high end...
-// 38000 is the default for LIRC:
-//#define DEFAULT_FREQUENCY 38000
-
-// The duty cycle is a percentage (0-100), 50 is LIRC's default:
-//#define DEFAULT_DUTY_CYCLE 50
-
-
-PIRDevice::PIRDevice()
- : fileDescriptor(-1),
- index(0)
-{
- openLircDevice();
-}
-
-
-PIRDevice::PIRDevice(
- unsigned int frequency,
- unsigned int dutyCycle)
- : fileDescriptor(-1),
- index(0)
-{
- openLircDevice();
- setCarrierFrequency(frequency);
- setDutyCycle(dutyCycle);
-}
-
-
-PIRDevice::~PIRDevice()
-{
- if (fileDescriptor >= 0) close(fileDescriptor);
-}
-
-
-void PIRDevice::openLircDevice()
-{
-#ifdef DEBUGGING
- // check the current time:
- gettimeofday(&previousTime, NULL);
-#else
-//#ifndef DEBUGGING
- fileDescriptor = open(PATH_TO_LIRC_DEVICE, O_WRONLY);
-
- if (fileDescriptor == -1)
- {
- std::stringstream ss;
- ss << "Failed to connect to " << PATH_TO_LIRC_DEVICE << "\n";
- ss << "Error is " << strerror(errno) << "\n";
- throw PIRException(ss.str());
- }
-#endif // DEBUGGING
-}
-
-
-void PIRDevice::addPair(
- int pulse,
- int space)
-{
- if (index >= (BUFFER_SIZE - 1))
- {
- // Needed room for 2 ints, didn't have it.
- throw PIRException("Buffer overflow in PIRCommandBuffer object.\n");
- }
-
- buffer[index] = pulse;
- ++index;
- buffer[index] = space;
- ++index;
-}
-
-
-void PIRDevice::addSingle(
- int single)
-{
- if (index >= BUFFER_SIZE)
- {
- throw PIRException("Buffer overflow in PIRCommandBuffer object.\n");
- }
-
- buffer[index] = single;
- ++index;
-}
-
-
-void PIRDevice::sendCommandToDevice()
-{
- // Sanity check first:
- if (!index)
- {
- // We have no data!
- // We should probably complain here, but for now, just return.
- return;
- }
-
- // Note: if the generated command string ends on a "space", we'll just
- // go ahead and ignore that last value. Want the light switched off
- // permanently at the end of the command string, not temporarily.
- // So, only odd-numbered strings of commands are allowed:
- if ((index % 2) == 0)
- {
- --index;
- }
-
-#ifdef DEBUGGING
- timeval newTime;
- gettimeofday(&newTime, NULL);
- long microseconds = newTime.tv_usec - previousTime.tv_usec;
- microseconds += (newTime.tv_sec - previousTime.tv_sec) * 1000000;
- std::cout << "Time since last call to device: " << microseconds << std::endl;
- previousTime = newTime;
-//#ifdef DEBUGGING
- std::cout << "Sending array of ints to device:\n";
- int blah = 0;
- while (blah < index)
- {
- std::cout << "buffer[" << blah << "]: " << buffer[blah] << "\n";
- ++blah;
- }
- std::cout << std::endl;
-#else
- if (write(fileDescriptor, buffer, index * sizeof(int)) == -1)
- {
- std::stringstream ss;
- ss << "Failed to send command.\n";
- ss << "IR device returned error: " << strerror(errno) << "\n";
- throw PIRException(ss.str());
- }
-#endif // DEBUGGING
-
- // Reset the index:
- index = 0;
-}
-
-
-void PIRDevice::setCarrierFrequency(
- unsigned int frequency)
-{
-// if (!frequency) frequency = DEFAULT_FREQUENCY;
-
-#ifdef DEBUGGING
- std::cout << "Setting frequency to " << frequency << "\n";
-#else
- if (ioctl(fileDescriptor, _IOW('i', 0x13, __u32), &frequency) == -1)
- {
- std::stringstream ss;
- ss << "Failed to set carrier frequency.\n";
- ss << "IR device returned error: " << strerror(errno) << "\n";
- throw PIRException(ss.str());
- }
-#endif // DEBUGGING
-}
-
-
-void PIRDevice::setDutyCycle(
- unsigned int dutyCycle)
-{
-// if (dutyCycle > 100) dutyCycle = DEFAULT_DUTY_CYCLE;
-
-#ifdef DEBUGGING
- std::cout << "Setting duty cycle to " << dutyCycle << "\n";
-#else
- if (ioctl(fileDescriptor, _IOW('i', 0x15, __u32), &dutyCycle) == -1)
- {
- std::stringstream ss;
- ss << "Failed to set duty cycle percentage.\n";
- ss << "IR device returned error: " << strerror(errno) << "\n";
- throw PIRException(ss.str());
- }
-#endif // DEBUGGING
-}
+++ /dev/null
-#ifndef PIRDEVICE_H
-#define PIRDEVICE_H
-
-//
-// Encapsulates communication with the N900's IR hardware, using the LIRC
-// device that (hopefully) exists on all N900s.
-//
-
-// To my current knowledge, you can send a maximum of 256 integers to the
-// N900's IR device driver, so that's probably a good limit to set:
-#define BUFFER_SIZE 256
-
-class PIRDevice
-{
-public:
- PIRDevice();
-
- PIRDevice(
- unsigned int frequency,
- unsigned int dutyCycle);
-
- ~PIRDevice();
-
- // Most remotes will just want to append pairs of on/off times:
- void addPair(
- int pulse,
- int space);
-
- // Some remotes need to specify the switching values individually:
- void addSingle(
- int single);
-
- // Send the buffered pulses to the IR device:
- void sendCommandToDevice();
-
- void setCarrierFrequency(
- unsigned int frequency);
-
- void setDutyCycle(
- unsigned int dutyCycle);
-
-private:
- void openLircDevice();
-
- int fileDescriptor;
-
- int buffer[BUFFER_SIZE];
- int index;
-};
-
-#endif // PIRDEVICE_H
--- /dev/null
+#include "pirdevicetypenames.h"
+
+PIRDeviceTypeMgr::PIRDeviceTypeMgr()
+{
+ devices[Any_Device] = "Any";
+ devices[TV_Device] = "TV";
+ devices[VCR_Device] = "VCR";
+ devices[DVD_Device] = "DVD";
+ devices[Audio_Device] = "Audio";
+ devices[Computer_Device] = "Computer";
+}
+
+const char *PIRDeviceTypeMgr::getDeviceString(
+ PIRDeviceTypeName n)
+{
+ return devices[n];
+}
+
+void PIRDeviceTypeMgr::populateComboBox(
+ QComboBox *cb)
+{
+ PIRDeviceStringCollection::const_iterator i = devices.begin();
+ while (i != devices.end())
+ {
+ cb->insertItem(i->first, QString(i->second));
+ ++i;
+ }
+}
--- /dev/null
+#ifndef PIRDEVICETYPENAMES_H
+#define PIRDEVICETYPENAMES_H
+
+#include <set>
+#include <map>
+
+#include <QComboBox>
+
+enum PIRDeviceTypeName {
+ Any_Device,
+ TV_Device,
+ VCR_Device,
+ DVD_Device,
+ Audio_Device,
+ Computer_Device
+};
+
+typedef std::set<PIRDeviceTypeName> PIRDeviceTypeCollection;
+typedef std::map<PIRDeviceTypeName, const char *> PIRDeviceStringCollection;
+
+class PIRDeviceTypeMgr
+{
+public:
+ PIRDeviceTypeMgr();
+
+ const char *getDeviceString(
+ PIRDeviceTypeName n);
+
+ void populateComboBox(
+ QComboBox *cb);
+
+private:
+ PIRDeviceStringCollection devices;
+};
+
+#endif // PIRDEVICETYPENAMES_H
<x>0</x>
<y>0</y>
<width>800</width>
- <height>445</height>
+ <height>480</height>
</rect>
</property>
<property name="windowTitle">
<x>0</x>
<y>0</y>
<width>798</width>
- <height>443</height>
+ <height>478</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
bool stopRepeatingFlag;
QMutex stopRepeatingMutex;
-// Next, a global for helping out with Make names:
-
+// Global helper objects:
PIRMakeMgr makeManager;
+PIRDeviceTypeMgr deviceManager;
// Now, on to the actual method definitions:
void PIRKeysetManager::populateGuiWidget(
- SelectionWindow *widget)
+ PIRSelectKeysetForm *skf)
{
PIRKeysetCollection::const_iterator i = keysetsInfo.begin();
QString tempString = makeManager.getMakeString(make);
tempString.append(" ");
tempString.append(i->second->getKeysetName());
- widget->addNameToList(tempString, i->first, make);
+ skf->addNameToList(tempString, i->first, make);
++i;
}
}
+
+
+void PIRKeysetManager::populateDeviceTypes(
+ PIRKeysetWidgetItem *kwi,
+ int keysetID)
+{
+ // Pass the buck: (Need to check for bad keysetID here?)
+ keysetsInfo[keysetID]->populateDeviceTypes(kwi);
+}
#include "pirkeysetmetadata.h"
//#include "protocol.h"
#include "pirkeynames.h"
-#include "selectionwindow.h"
+//#include "selectionwindow.h"
+#include "pirselectkeysetform.h"
+#include "pirkeysetwidgetitem.h"
//#include <QtCore/QCoreApplication>
#include <QThread>
~PIRKeysetManager();
void populateGuiWidget(
- SelectionWindow *widget);
+ PIRSelectKeysetForm *widget);
void stopRepeating();
QString getDisplayName(
int keysetID);
+ void populateDeviceTypes(
+ PIRKeysetWidgetItem *kwi,
+ int keysetID);
+
private:
// This needs to be improved:
void populateKeyset(
}
+void PIRKeysetMetaData::populateDeviceTypes(
+ PIRKeysetWidgetItem *kwi)
+{
+ PIRDeviceTypeCollection::const_iterator i = deviceTypes.begin();
+ while (i != deviceTypes.end())
+ {
+ kwi->addDeviceType(*i);
+ ++i;
+ }
+}
+
+
unsigned int PIRKeysetMetaData::getID()
{
return id;
void PIRKeysetMetaData::addControlledDevice(
PIRMakeName make,
const char *model,
- DeviceType type)
+ PIRDeviceTypeName type)
{
controlledDevices.push_back(DeviceInfo(make, model, type));
+
+ deviceTypes.insert(type);
}
#ifndef PIRKEYSETMETADATA_H
#define PIRKEYSETMETADATA_H
-//#include <set>
#include <map>
#include <list>
//#include <string>
#include "pirkeynames.h"
#include "pirmakenames.h"
-
+#include "pirdevicetypenames.h"
+#include "pirkeysetwidgetitem.h"
#include "pirprotocol.h"
typedef std::map<PIRKeyName, const char *> KeyCollection;
-enum DeviceType
-{
- TV_Device,
- VCR_Device,
- DVD_Device,
- Audio_Device,
- Computer_Device
-};
-
class DeviceInfo
{
public:
DeviceInfo(
PIRMakeName ma,
const char *mo,
- DeviceType t)
+ PIRDeviceTypeName t)
: make(ma),
model(mo),
type(t)
PIRMakeName make;
const char *model;
- DeviceType type;
+ PIRDeviceTypeName type;
};
typedef std::list<DeviceInfo> DeviceCollection;
void moveProtocolToThread(
QThread &thread);
+ void populateDeviceTypes(
+ PIRKeysetWidgetItem *kwi);
+
protected:
void addControlledDevice(
PIRMakeName make,
const char *model,
- DeviceType type);
+ PIRDeviceTypeName type);
+
+ void addDeviceType(
+ PIRDeviceTypeName n);
void addKey(
const char *name,
private:
const char *keysetName;
PIRMakeName make;
+ PIRDeviceTypeCollection deviceTypes;
unsigned int id;
};
}
+void PIRKeysetWidgetItem::addDeviceType(
+ PIRDeviceTypeName dt)
+{
+ devices.insert(dt);
+}
+
+
unsigned int PIRKeysetWidgetItem::getID()
{
return id;
{
return make;
}
+
+
+bool PIRKeysetWidgetItem::supportsDeviceType(
+ PIRDeviceTypeName dt)
+{
+ return (devices.find(dt) != devices.end());
+}
#include <QListWidgetItem>
#include "pirmakenames.h"
+#include "pirdevicetypenames.h"
class PIRKeysetWidgetItem: public QListWidgetItem
{
unsigned int id,
PIRMakeName make);
+ void addDeviceType(
+ PIRDeviceTypeName dt);
+
unsigned int getID();
PIRMakeName getMake();
+ bool supportsDeviceType(
+ PIRDeviceTypeName dt);
+
private:
unsigned int id;
PIRMakeName make;
+ PIRDeviceTypeCollection devices;
};
#endif // PIRKEYSETWIDGETITEM_H
--- /dev/null
+#include "pirrx51hardware.h"
+
+//#define DEBUGGING
+
+// Needed system includes:
+#include <sys/ioctl.h>
+#ifdef DEBUGGING
+#include <iostream>
+#include <sys/time.h>
+timeval previousTime;
+#else
+//#ifndef DEBUGGING
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#endif // DEBUGGING
+#include <fcntl.h>
+
+// Includes I'm using for error handling stuff:
+#include "pirexception.h"
+#include <errno.h>
+#include <sstream>
+
+// The N900's IR transmitter is controlled by a device driver created
+// specifically for the LIRC daemon:
+#define PATH_TO_LIRC_DEVICE "/dev/lirc0"
+
+// It appears that the frequency on this device can range between
+// 20000 on the low end and 500000 on the high end...
+// 38000 is the default for LIRC:
+//#define DEFAULT_FREQUENCY 38000
+
+// The duty cycle is a percentage (0-100), 50 is LIRC's default:
+//#define DEFAULT_DUTY_CYCLE 50
+
+
+PIRRX51Hardware::PIRRX51Hardware()
+ : fileDescriptor(-1),
+ index(0)
+{
+ openLircDevice();
+}
+
+
+PIRRX51Hardware::PIRRX51Hardware(
+ unsigned int frequency,
+ unsigned int dutyCycle)
+ : fileDescriptor(-1),
+ index(0)
+{
+ openLircDevice();
+ setCarrierFrequency(frequency);
+ setDutyCycle(dutyCycle);
+}
+
+
+PIRRX51Hardware::~PIRRX51Hardware()
+{
+ if (fileDescriptor >= 0) close(fileDescriptor);
+}
+
+
+void PIRRX51Hardware::openLircDevice()
+{
+#ifdef DEBUGGING
+ // check the current time:
+ gettimeofday(&previousTime, NULL);
+#else
+//#ifndef DEBUGGING
+ fileDescriptor = open(PATH_TO_LIRC_DEVICE, O_WRONLY);
+
+ if (fileDescriptor == -1)
+ {
+ std::stringstream ss;
+ ss << "Failed to connect to " << PATH_TO_LIRC_DEVICE << "\n";
+ ss << "Error is " << strerror(errno) << "\n";
+ throw PIRException(ss.str());
+ }
+#endif // DEBUGGING
+}
+
+
+void PIRRX51Hardware::addPair(
+ int pulse,
+ int space)
+{
+ if (index >= (BUFFER_SIZE - 1))
+ {
+ // Needed room for 2 ints, didn't have it.
+ throw PIRException("Buffer overflow in PIRCommandBuffer object.\n");
+ }
+
+ buffer[index] = pulse;
+ ++index;
+ buffer[index] = space;
+ ++index;
+}
+
+
+void PIRRX51Hardware::addSingle(
+ int single)
+{
+ if (index >= BUFFER_SIZE)
+ {
+ throw PIRException("Buffer overflow in PIRCommandBuffer object.\n");
+ }
+
+ buffer[index] = single;
+ ++index;
+}
+
+
+void PIRRX51Hardware::sendCommandToDevice()
+{
+ // Sanity check first:
+ if (!index)
+ {
+ // We have no data!
+ // We should probably complain here, but for now, just return.
+ return;
+ }
+
+ // Note: if the generated command string ends on a "space", we'll just
+ // go ahead and ignore that last value. Want the light switched off
+ // permanently at the end of the command string, not temporarily.
+ // So, only odd-numbered strings of commands are allowed:
+ if ((index % 2) == 0)
+ {
+ --index;
+ }
+
+#ifdef DEBUGGING
+ timeval newTime;
+ gettimeofday(&newTime, NULL);
+ long microseconds = newTime.tv_usec - previousTime.tv_usec;
+ microseconds += (newTime.tv_sec - previousTime.tv_sec) * 1000000;
+ std::cout << "Time since last call to device: " << microseconds << std::endl;
+ previousTime = newTime;
+//#ifdef DEBUGGING
+ std::cout << "Sending array of ints to device:\n";
+ int blah = 0;
+ while (blah < index)
+ {
+ std::cout << "buffer[" << blah << "]: " << buffer[blah] << "\n";
+ ++blah;
+ }
+ std::cout << std::endl;
+#else
+ if (write(fileDescriptor, buffer, index * sizeof(int)) == -1)
+ {
+ std::stringstream ss;
+ ss << "Failed to send command.\n";
+ ss << "IR device returned error: " << strerror(errno) << "\n";
+ throw PIRException(ss.str());
+ }
+#endif // DEBUGGING
+
+ // Reset the index:
+ index = 0;
+}
+
+
+void PIRRX51Hardware::setCarrierFrequency(
+ unsigned int frequency)
+{
+// if (!frequency) frequency = DEFAULT_FREQUENCY;
+
+#ifdef DEBUGGING
+ std::cout << "Setting frequency to " << frequency << "\n";
+#else
+ if (ioctl(fileDescriptor, _IOW('i', 0x13, __u32), &frequency) == -1)
+ {
+ std::stringstream ss;
+ ss << "Failed to set carrier frequency.\n";
+ ss << "IR device returned error: " << strerror(errno) << "\n";
+ throw PIRException(ss.str());
+ }
+#endif // DEBUGGING
+}
+
+
+void PIRRX51Hardware::setDutyCycle(
+ unsigned int dutyCycle)
+{
+// if (dutyCycle > 100) dutyCycle = DEFAULT_DUTY_CYCLE;
+
+#ifdef DEBUGGING
+ std::cout << "Setting duty cycle to " << dutyCycle << "\n";
+#else
+ if (ioctl(fileDescriptor, _IOW('i', 0x15, __u32), &dutyCycle) == -1)
+ {
+ std::stringstream ss;
+ ss << "Failed to set duty cycle percentage.\n";
+ ss << "IR device returned error: " << strerror(errno) << "\n";
+ throw PIRException(ss.str());
+ }
+#endif // DEBUGGING
+}
--- /dev/null
+#ifndef PIRRX51HARDWARE_H
+#define PIRRX51HARDWARE_H
+
+//
+// Encapsulates communication with the N900's IR hardware, using the LIRC
+// device that (hopefully) exists on all N900s.
+//
+
+// To my current knowledge, you can send a maximum of 256 integers to the
+// N900's IR device driver, so that's probably a good limit to set:
+#define BUFFER_SIZE 256
+
+class PIRRX51Hardware
+{
+public:
+ PIRRX51Hardware();
+
+ PIRRX51Hardware(
+ unsigned int frequency,
+ unsigned int dutyCycle);
+
+ ~PIRRX51Hardware();
+
+ // Most remotes will just want to append pairs of on/off times:
+ void addPair(
+ int pulse,
+ int space);
+
+ // Some remotes need to specify the switching values individually:
+ void addSingle(
+ int single);
+
+ // Send the buffered pulses to the IR device:
+ void sendCommandToDevice();
+
+ void setCarrierFrequency(
+ unsigned int frequency);
+
+ void setDutyCycle(
+ unsigned int dutyCycle);
+
+private:
+ void openLircDevice();
+
+ int fileDescriptor;
+
+ int buffer[BUFFER_SIZE];
+ int index;
+};
+
+#endif // PIRRX51HARDWARE_H
--- /dev/null
+#include "pirselectkeysetform.h"
+#include "ui_pirselectkeysetform.h"
+#include "pirkeysetwidgetitem.h"
+
+extern PIRMakeMgr makeManager;
+extern PIRDeviceTypeMgr deviceManager;
+
+PIRSelectKeysetForm::PIRSelectKeysetForm(
+ QWidget *parent)
+ : QWidget(parent),
+ ui(new Ui::PIRSelectKeysetForm),
+ currentMake(Any_Make),
+ currentDevice(Any_Device)
+{
+ ui->setupUi(this);
+
+ setAttribute(Qt::WA_Maemo5StackedWindow);
+ setWindowFlags(windowFlags() | Qt::Window);
+
+ // push the list of makers into the make combo box:
+ makeManager.populateComboBox(ui->makeComboBox);
+ deviceManager.populateComboBox(ui->deviceComboBox);
+
+ // Connection telling main window that keyset has been selected:
+ connect(
+ ui->keysetListWidget,
+ SIGNAL(itemActivated(QListWidgetItem *)),
+ parent,
+ SLOT(keysetSelectionChanged(QListWidgetItem *)),
+ Qt::QueuedConnection);
+
+ // Connection used to filter keyset list:
+ connect(
+ ui->makeComboBox,
+ SIGNAL(currentIndexChanged(int)),
+ this,
+ SLOT(filterListByMake(int)),
+ Qt::QueuedConnection);
+
+ connect(
+ ui->deviceComboBox,
+ SIGNAL(currentIndexChanged(int)),
+ this,
+ SLOT(filterListByDeviceType(int)),
+ Qt::QueuedConnection);
+}
+
+PIRSelectKeysetForm::~PIRSelectKeysetForm()
+{
+ delete ui;
+}
+
+void PIRSelectKeysetForm::addNameToList(
+ QString name,
+ unsigned int index,
+ PIRMakeName make)
+{
+ ui->keysetListWidget->addItem(new PIRKeysetWidgetItem(name, index, make));
+}
+
+QListWidget *PIRSelectKeysetForm::getKeysetListWidget()
+{
+ return ui->keysetListWidget;
+}
+
+void PIRSelectKeysetForm::filterListByMake(
+ int make)
+{
+ currentMake = (PIRMakeName) make;
+ refilterList();
+}
+
+void PIRSelectKeysetForm::filterListByDeviceType(
+ int deviceType)
+{
+ currentDevice = (PIRDeviceTypeName) deviceType;
+ refilterList();
+}
+
+void PIRSelectKeysetForm::refilterList()
+{
+ int index = 0;
+ int count = ui->keysetListWidget->count();
+ PIRKeysetWidgetItem *item;
+ while (index < count)
+ {
+ item = dynamic_cast<PIRKeysetWidgetItem *>(
+ ui->keysetListWidget->item(index));
+
+ // Does the keylist have the required make?
+ if ((currentMake == Any_Make) || (item->getMake() == currentMake))
+ {
+ // And, does the keylist have the required device type?
+ if ((currentDevice == Any_Device)
+ || (item->supportsDeviceType(currentDevice)))
+ {
+ // Yes, we can show this keylist:
+ item->setHidden(false);
+ }
+ else
+ {
+ item->setHidden(true);
+ }
+ }
+ else
+ {
+ item->setHidden(true);
+ }
+
+ ++index;
+ }
+}
--- /dev/null
+#ifndef PIRSELECTKEYSETFORM_H
+#define PIRSELECTKEYSETFORM_H
+
+#include <QWidget>
+#include <QListWidget>
+#include <QString>
+
+#include "pirmakenames.h"
+#include "pirdevicetypenames.h"
+
+namespace Ui {
+class PIRSelectKeysetForm;
+}
+
+class PIRSelectKeysetForm : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit PIRSelectKeysetForm(QWidget *parent = 0);
+ ~PIRSelectKeysetForm();
+
+ void addNameToList(
+ QString name,
+ unsigned int index,
+ PIRMakeName make);
+
+ // This is a bit of a hack, but not sure how to create a connection otherwise.
+ QListWidget *getKeysetListWidget();
+
+private slots:
+ void filterListByMake(
+ int make);
+
+ void filterListByDeviceType(
+ int deviceType);
+
+private:
+ void refilterList();
+
+ Ui::PIRSelectKeysetForm *ui;
+
+ PIRMakeName currentMake;
+ PIRDeviceTypeName currentDevice;
+};
+
+#endif // PIRSELECTKEYSETFORM_H
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PIRSelectKeysetForm</class>
+ <widget class="QWidget" name="PIRSelectKeysetForm">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Select Keyset</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <item row="0" column="0">
+ <layout class="QHBoxLayout" name="makeHorizontalLayout">
+ <item>
+ <widget class="QLabel" name="makeLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Make</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="makeComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="1">
+ <layout class="QHBoxLayout" name="deviceHorizontalLayout">
+ <item>
+ <widget class="QLabel" name="deviceLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Device:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="deviceComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QListWidget" name="keysetListWidget"/>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
}
// Construct the object that communicates with the device driver:
- PIRDevice device(carrierFrequency, dutyCycle);
+ PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
int repeatCount = 0;
while (repeatCount < MAX_REPEAT_COUNT)
}
// Encode the bits:
- commandDuration += pushBits((*i).second, device);
+ commandDuration += pushBits((*i).second, rx51device);
// Clear out the buffer, if necessary:
if (buffer)
{
- device.addSingle(buffer);
+ rx51device.addSingle(buffer);
commandDuration += buffer;
buffer = 0;
bufferContainsSpace = false;
}
// Now, tell the device to send the whole command:
- device.sendCommandToDevice();
+ rx51device.sendCommandToDevice();
// Sleep for an amount of time. (Need to make this interruptable!)
sleepUntilRepeat(commandDuration);
int RC5Protocol::pushBits(
const CommandSequence &bits,
- PIRDevice &device)
+ PIRRX51Hardware &rx51device)
{
int bitsDuration = 0;
{
// Merge our space with the previous space, and send them to
// the device.
- device.addSingle(buffer + biphaseSpace);
+ rx51device.addSingle(buffer + biphaseSpace);
bitsDuration += (buffer + biphaseSpace);
buffer = 0;
bufferContainsSpace = false;
if (bufferContainsPulse)
{
// Flush the buffer:
- device.addSingle(buffer);
+ rx51device.addSingle(buffer);
bitsDuration += buffer;
buffer = 0;
bufferContainsPulse = false;
}
// Add a space:
- device.addSingle(biphaseSpace);
+ rx51device.addSingle(biphaseSpace);
bitsDuration += biphaseSpace;
}
if (bufferContainsPulse)
{
// Merge our pulse with the previous one, and send them to the device:
- device.addSingle(buffer + biphasePulse);
+ rx51device.addSingle(buffer + biphasePulse);
bitsDuration += (buffer + biphasePulse);
buffer = 0;
bufferContainsPulse = false;
if (bufferContainsSpace)
{
// Flush out the buffer:
- device.addSingle(buffer);
+ rx51device.addSingle(buffer);
bitsDuration += buffer;
buffer = 0;
bufferContainsSpace = false;
}
// Add a pulse:
- device.addSingle(biphasePulse);
+ rx51device.addSingle(biphasePulse);
bitsDuration += biphasePulse;
}
#define RC5PROTOCOL_H
#include "pirprotocol.h"
-#include "pirdevice.h"
+#include "pirrx51hardware.h"
//
// The RC5 protocol is apparently quite a bit older than the NEC protocol, but
private:
int pushBits(
const CommandSequence &bits,
- PIRDevice &device);
+ PIRRX51Hardware &device);
unsigned int buffer;
int keypressCount;
+++ /dev/null
-#include "selectionwindow.h"
-#include "pirkeysetwidgetitem.h"
-
-#include <QString>
-
-#include "pirexception.h"
-
-extern PIRMakeMgr makeManager;
-
-SelectionWindow::SelectionWindow(
- QWidget *parent)
- : QWidget(parent)
-{
- // This widget will be the window holding everything else.
- setAttribute(Qt::WA_Maemo5StackedWindow);
- setWindowFlags(windowFlags() | Qt::Window);
- setFixedSize(800, 445);
-
- // First things first, need a QList of some sort to display the names:
- nameListWidget = new QListWidget();
-
- // Now, some filters:
-// deviceTypeLabel = new QLabel("Filter by Device Type:");
-// deviceTypeComboBox = new QComboBox();
-// deviceTypeComboBox->insertItem(0, QString("Any"));
- makeLabel = new QLabel("Make:");
-// makeLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
- makeComboBox = new QComboBox();
- makeComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
- makeManager.populateComboBox(makeComboBox);
-// makeComboBox->insertItem(0, QString("Any"));
-
- layout = new QGridLayout;
-// layout->addWidget(deviceTypeLabel, 0, 0);
-// layout->addWidget(deviceTypeComboBox, 1, 0);
- layout->addWidget(makeLabel, 0, 0);
- layout->addWidget(makeComboBox, 0, 1);
- layout->addWidget(nameListWidget, 1, 0, 1, 2);
-
- setLayout(layout);
-
- connect(
- nameListWidget,
- SIGNAL(itemActivated(QListWidgetItem *)),
- parent,
- SLOT(keysetSelectionChanged(QListWidgetItem *)),
- Qt::QueuedConnection);
-
- connect(
- makeComboBox,
- SIGNAL(currentIndexChanged(int)),
- this,
- SLOT(filterListByMake(int)),
- Qt::QueuedConnection);
-}
-
-
-SelectionWindow::~SelectionWindow()
-{
-// if (deviceTypeLabel) delete deviceTypeLabel;
-// if (deviceTypeComboBox) delete deviceTypeComboBox;
- if (makeLabel) delete makeLabel;
- if (makeComboBox) delete makeComboBox;
- if (layout) delete layout;
- if (nameListWidget) delete nameListWidget;
-}
-
-
-void SelectionWindow::addNameToList(
- QString name,
- unsigned int index,
- PIRMakeName make)
-{
- nameListWidget->addItem(new PIRKeysetWidgetItem(name, index, make));
-}
-
-
-void SelectionWindow::filterListByMake(
- int make)
-{
- int index = 0;
- int count = nameListWidget->count();
- PIRKeysetWidgetItem *item;
- while (index < count)
- {
- item = dynamic_cast<PIRKeysetWidgetItem *>(nameListWidget->item(index));
- if ((make == Any_Make) || (item->getMake() == make))
- {
- item->setHidden(false);
- }
- else
- {
- item->setHidden(true);
- }
-
- ++index;
- }
-}
-
+++ /dev/null
-#ifndef SELECTIONWINDOW_H
-#define SELECTIONWINDOW_H
-
-#include "pirmakenames.h"
-
-#include <QWidget>
-#include <QListWidget>
-#include <QLabel>
-#include <QComboBox>
-#include <QGridLayout>
-#include <QString>
-
-
-class SelectionWindow : public QWidget
-{
- Q_OBJECT
-
-public:
- explicit SelectionWindow(
- QWidget *parent = 0);
-
- ~SelectionWindow();
-
- void addNameToList(
- QString name,
- unsigned int index,
- PIRMakeName make);
-
- // Public just for now, to get a quick hack working. (Actually, this whole
- // class should be replaced with a UI form eventually, to match the rest of
- // the code...)
- QListWidget *nameListWidget;
-
-private slots:
- void filterListByMake(
- int make);
-
-private:
- QLabel *makeLabel;
- QComboBox *makeComboBox;
- QGridLayout *layout;
-};
-
-
-#endif // SELECTIONWINDOW_H