<h2 align="center">A Universal Infrared Remote Control</h2>
<p align="center">
-Version 0.5 -- "Half-Way Usable"
+Version 0.6
</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. Please do
-post on the
-<a href="https://garage.maemo.org/forum/forum.php?forum_id=7316">Pierogi Forum Board</a>
-if you find bugs to fix, have suggestions on future enhancements, or have
-particular devices or brands you would like to see added to the list of
-keysets. Thank you!
+A tasty little app for controlling all your infrared devices. As of this
+version, the keysets are still limited and mostly untested. If you find
+problems or if you'd like to see keysets for more devices added, please send
+me a note at <a href="mailto:jpietrzak8@gmail.com">jpietrzak8@gmail.com</a>
+or leave a post on the
+<a href="https://garage.maemo.org/forum/forum.php?forum_id=7316">
+Pierogi message board</a>. Thank you!
</p>
<p>
addKey("on/off", Power_Key, 0x00, 8);
addKey("4", Four_Key, 0x08, 8);
- addKey("am", Unmapped_Key, 0x10, 8);
+ addKey("am", Red_Key, 0x10, 8); // sort of a hack to get AM in
addKey("6", Six_Key, 0x20, 8);
addKey("trackprev", Previous_Key, 0x30, 8);
+ addKey("trackprev", ChannelDown_Key, 0x30, 8);
addKey("volup", VolumeUp_Key, 0x40,8);
addKey("cdstop", Stop_Key, 0x50, 8);
- addKey("fm", Unmapped_Key, 0x60, 8);
+ addKey("fm", Green_Key, 0x60, 8); // also hack
addKey("2", Two_Key, 0x70, 8);
addKey("mute", Mute_Key, 0x80, 8);
addKey("5", Five_Key, 0x88, 8);
addKey("1", One_Key, 0xB0, 8);
addKey("voldown", VolumeDown_Key, 0xC0, 8);
addKey("tracknext", Next_Key, 0xD0, 8);
+ addKey("tracknext", ChannelUp_Key, 0xD0, 8);
addKey("aux", AuxInput_Key, 0xE0, 8);
addKey("3", Three_Key, 0xF0, 8);
}
--- /dev/null
+#include "mce.h"
+#include "protocols/mceprotocol.h"
+
+MCERemote1::MCERemote1(
+ QObject *guiObject,
+ unsigned int index)
+ : PIRKeysetMetaData(
+ "MCE Remote mode 1",
+ Microsoft_Make,
+ index)
+{
+ threadableProtocol = new MCEProtocol(guiObject, index, 0x800F);
+
+ setPreData(0x04, 7);
+
+ addKey("Zero", Zero_Key, 0x00, 8);
+ addKey("One", One_Key, 0x01, 8);
+ addKey("Two", Two_Key, 0x02, 8);
+ addKey("Three", Three_Key, 0x03, 8);
+ addKey("Four", Four_Key, 0x04, 8);
+ addKey("Five", Five_Key, 0x05, 8);
+ addKey("Six", Six_Key, 0x06, 8);
+ addKey("Seven", Seven_Key, 0x07, 8);
+ addKey("Eight", Eight_Key, 0x08, 8);
+ addKey("Nine", Nine_Key, 0x09, 8);
+ addKey("Clear", Clear_Key, 0x0A, 8);
+ addKey("Enter", Enter_Key, 0x0B, 8);
+
+ addKey("Power", Power_Key, 0x0C, 8);
+ addKey("Home", Menu_Key, 0x0D, 8);
+ addKey("Mute", Mute_Key, 0x0E, 8);
+ addKey("MoreInfo", Info_Key, 0x0F, 8);
+ addKey("VolUp", VolumeUp_Key, 0x10, 8);
+ addKey("VolDown", VolumeDown_Key, 0x11, 8);
+ addKey("ChanUp", ChannelUp_Key, 0x12, 8);
+ addKey("ChanDown", ChannelDown_Key, 0x13, 8);
+
+ addKey("Forward", FastForward_Key, 0x14, 8);
+ addKey("Rewind", Rewind_Key, 0x15, 8);
+ addKey("Play", Play_Key, 0x16, 8);
+ addKey("Record", Record_Key, 0x17, 8);
+ addKey("Pause", Pause_Key, 0x18, 8);
+ addKey("Stop", Stop_Key, 0x19, 8);
+ addKey("Skip", Advance_Key, 0x1A, 8);
+ addKey("Replay", Replay_Key, 0x1B, 8);
+
+ addKey("Hash", Unmapped_Key, 0x1C, 8); // "Caps Lock"
+ addKey("Star", Unmapped_Key, 0x1D, 8); // "Mouse"
+
+ addKey("Up", Up_Key, 0x1E, 8);
+ addKey("Down", Down_Key, 0x1F, 8);
+ addKey("Left", Left_Key, 0x20, 8);
+ addKey("Right", Right_Key, 0x21, 8);
+ addKey("OK", Select_Key, 0x22, 8);
+ addKey("Back", Exit_Key, 0x23, 8);
+ addKey("DVD", DiscMenu_Key, 0x24, 8);
+ addKey("LiveTV", LiveTV_Key, 0x25, 8);
+ addKey("Guide", Guide_Key, 0x26, 8);
+
+ addKey("Aspect", AspectRatio_Key, 0x27, 8);
+
+ addKey("Visualization", Unmapped_Key, 0x32, 8);
+ addKey("SlideShow", Unmapped_Key, 0x33, 8);
+ addKey("Eject", Eject_Key, 0x34, 8);
+
+ addKey("TV", Unmapped_Key, 0x46, 8); // "My TV"
+ addKey("Music", Unmapped_Key, 0x47, 8); // "My Music"
+ addKey("RecTV", Unmapped_Key, 0x48, 8); // "Recorded TV"
+ addKey("Pictures", Unmapped_Key, 0x49, 8); // "My Pictures"
+ addKey("Videos", Unmapped_Key, 0x4A, 8); // "My Videos"
+ addKey("DVD angle", Angle_Key, 0x4B, 8);
+ addKey("DVD audio", Audio_Key, 0x4C, 8);
+ addKey("DVD subtitle", Captions_Key, 0x4D, 8);
+
+ addKey("Print", Unmapped_Key, 0x4E, 8);
+ addKey("Radio", TunerInput_Key, 0x50, 8);
+
+ addKey("Teletext", Teletext_Key, 0x5A, 8);
+ addKey("Red", Red_Key, 0x5B, 8);
+ addKey("Green", Green_Key, 0x5C, 8);
+ addKey("Yellow", Yellow_Key, 0x5D, 8);
+ addKey("Blue", Blue_Key, 0x5E, 8);
+
+// addKey("PlayPause", Play_Key, 0x6E, 8);
+// addKey("PlayPause", Pause_Key, 0x6E, 8);
+
+ addKey("Media", Unmapped_Key, 0x80, 8); // "Write"
+}
+
+
+MCERemote1a::MCERemote1a(
+ QObject *guiObject,
+ unsigned int index)
+ : MCERemote1(guiObject, index)
+{
+ setKeysetName("MCE Remote mode 2");
+
+ setPreData(0x14, 7);
+}
+
+
+MCERemote1b::MCERemote1b(
+ QObject *guiObject,
+ unsigned int index)
+ : MCERemote1(guiObject, index)
+{
+ setKeysetName("MCE Remote mode 3");
+
+ setPreData(0x24, 7);
+}
+
+
+MCERemote1c::MCERemote1c(
+ QObject *guiObject,
+ unsigned int index)
+ : MCERemote1(guiObject, index)
+{
+ setKeysetName("MCE Remote mode 4");
+
+ setPreData(0x34, 7);
+}
+
+
+MCERemote1d::MCERemote1d(
+ QObject *guiObject,
+ unsigned int index)
+ : MCERemote1(guiObject, index)
+{
+ setKeysetName("MCE Remote mode 5");
+
+ setPreData(0x44, 7);
+}
+
+
+MCERemote1e::MCERemote1e(
+ QObject *guiObject,
+ unsigned int index)
+ : MCERemote1(guiObject, index)
+{
+ setKeysetName("MCE Remote mode 6");
+
+ setPreData(0x54, 7);
+}
+
+
+MCERemote1f::MCERemote1f(
+ QObject *guiObject,
+ unsigned int index)
+ : MCERemote1(guiObject, index)
+{
+ setKeysetName("MCE Remote mode 7");
+
+ setPreData(0x64, 7);
+}
+
+
+MCERemote1g::MCERemote1g(
+ QObject *guiObject,
+ unsigned int index)
+ : MCERemote1(guiObject, index)
+{
+ setKeysetName("MCE Remote mode 8");
+
+ setPreData(0x74, 7);
+}
--- /dev/null
+#ifndef MCE_H
+#define MCE_H
+
+#include "pirkeysetmetadata.h"
+
+class QObject;
+
+class MCERemote1: public PIRKeysetMetaData
+{
+public:
+ MCERemote1(
+ QObject *guiObject,
+ unsigned int index);
+};
+
+class MCERemote1a: public MCERemote1
+{
+public:
+ MCERemote1a(
+ QObject *guiObject,
+ unsigned int index);
+};
+
+class MCERemote1b: public MCERemote1
+{
+public:
+ MCERemote1b(
+ QObject *guiObject,
+ unsigned int index);
+};
+
+class MCERemote1c: public MCERemote1
+{
+public:
+ MCERemote1c(
+ QObject *guiObject,
+ unsigned int index);
+};
+
+class MCERemote1d: public MCERemote1
+{
+public:
+ MCERemote1d(
+ QObject *guiObject,
+ unsigned int index);
+};
+
+class MCERemote1e: public MCERemote1
+{
+public:
+ MCERemote1e(
+ QObject *guiObject,
+ unsigned int index);
+};
+
+class MCERemote1f: public MCERemote1
+{
+public:
+ MCERemote1f(
+ QObject *guiObject,
+ unsigned int index);
+};
+
+class MCERemote1g: public MCERemote1
+{
+public:
+ MCERemote1g(
+ QObject *guiObject,
+ unsigned int index);
+};
+
+#endif // MCE_H
addSIRC20Key("top_menu", DiscTitle_Key, 0x49, 0x1A, 0x1A); // "Title"
addSIRC20Key("dvd_menu", DiscMenu_Key, 0x49, 0x1A, 0x1B);
addSIRC20Key("program", Program_Key, 0x49, 0x1A, 0x1F);
+ addSIRC20Key("step/search -", StepBack_Key, 0x49, 0x1A, 0x20);
+ addSIRC20Key("step/search +", StepForward_Key, 0x49, 0x1A, 0x21);
+ addSIRC20Key("scan/slow -", SlowMinus_Key, 0x49, 0x1A, 0x22);
+ addSIRC20Key("scan/slow +", SlowPlus_Key, 0x49, 0x1A, 0x23);
addSIRC20Key("INDEX-", Unmapped_Key, 0x49, 0x1A, 0x26);
addSIRC20Key("INDEX+", Unmapped_Key, 0x49, 0x1A, 0x27);
addSIRC20Key("TIME", Unmapped_Key, 0x49, 0x1A, 0x28);
addSIRC20Key("X2_FORWARD", Unmapped_Key, 0x49, 0x1A, 0x37);
addSIRC20Key("stop", Stop_Key, 0x49, 0x1A, 0x38);
addSIRC20Key("pause", Pause_Key, 0x49, 0x1A, 0x39);
- addSIRC20Key("STEP_BACK", StepBack_Key, 0x49, 0x1A, 0x3A); // "Jog Rev"
- addSIRC20Key("STEP_FORWARD", StepForward_Key, 0x49, 0x1A, 0x3B); // "Jog Fwd"
+ addSIRC20Key("STEP_BACK", Unmapped_Key, 0x49, 0x1A, 0x3A); // "Jog Rev"
+ addSIRC20Key("STEP_FORWARD", Unmapped_Key, 0x49, 0x1A, 0x3B); // "Jog Fwd"
addSIRC20Key("RecStop", RecordStop_Key, 0x49, 0x1A, 0x3D);
addSIRC20Key("RecPause", RecordPause_Key, 0x49, 0x1A, 0x3E);
addSIRC20Key("Guide", Guide_Key, 0x62, 0x1A, 0x16);
addSIRC20Key("Options", Unmapped_Key, 0x62, 0x1A, 0x17); // "Tools"
addSIRC20Key("Dot", Unmapped_Key, 0x62, 0x1A, 0x1D);
+ addSIRC20Key("file", Unmapped_Key, 0x62, 0x1A, 0x20);
+ addSIRC20Key("sort", Unmapped_Key, 0x62, 0x1A, 0x21);
+ addSIRC20Key("edit", Unmapped_Key, 0x62, 0x1A, 0x22);
addSIRC20Key("ALBUM-MINUS", Unmapped_Key, 0x62, 0x1A, 0x29);
addSIRC20Key("ALBUM-PLUS", Unmapped_Key, 0x62, 0x1A, 0x2A);
addSIRC20Key("F1", Unmapped_Key, 0x62, 0x1A, 0x2E); // "HDD"
addSIRC20Key("F2", Unmapped_Key, 0x62, 0x1A, 0x2F); // "DVD"
- addSIRC20Key("DiscSkip", NextDisc_Key, 0x62, 0x1A, 0x3E);
+ addSIRC20Key("picture memory", Unmapped_Key, 0x62, 0x1A, 0x3C);
+ addSIRC20Key("disc skip -", PrevDisc_Key, 0x62, 0x1A, 0x3D);
+ addSIRC20Key("DiscSkip", NextDisc_Key, 0x62, 0x1A, 0x3E); // "disc skip +"
+ addSIRC20Key("folder", Unmapped_Key, 0x62, 0x1A, 0x40);
addSIRC20Key("Favorites", Favorites_Key, 0x62, 0x1A, 0x5E);
addSIRC20Key("Purple", Blue_Key, 0x62, 0x1A, 0x66);
addSIRC20Key("Red", Red_Key, 0x62, 0x1A, 0x67);
addKey("100", PlusOneHundred_Key, 0x0A, 8);
addKey("-/--", DoubleDigit_Key, 0x0B, 8);
addKey("reset", Reset_Key, 0x0C, 8);
- addKey("textzoom", TeletextSize_Key, 0x0D, 8); // "Enlarge"
addKey("tv/video", Unmapped_Key, 0x0F, 8); // "input"
addKey("MUTE", Mute_Key, 0x10, 8);
- addKey("BLANK", PictureMode_Key, 0x11, 8); // "Contrast", "picture_preset"
+ addKey("picturepref", PictureMode_Key, 0x11, 8); // "Contrast", "PP"
addKey("POWER", Power_Key, 0x12, 8);
- addKey("mts", FMMode_Key, 0x13, 8); // "audio_stereo_2channel"
+ addKey("mts", Audio_Key, 0x13, 8); // "audio_stereo_2channel"
addKey("SCART", Input_Key, 0x14, 8); // "AV", "inputs", "source"
- addKey("sleep", Sleep_Key, 0x15, 8); // Clock
+ addKey("sleep", Sleep_Key, 0x15, 8);
addKey("CALL", Call_Key, 0x16, 8);
addKey("ent", Enter_Key, 0x17, 8); // "ch_rtn"
- addKey("TXT/MIX", Teletext_Key, 0x17, 8);
addKey("fav+", Unmapped_Key, 0x19, 8);
addKey("V+", VolumeUp_Key, 0x1A, 8);
addKey("V+", Right_Key, 0x1A, 8);
addKey("P-", Down_Key, 0x1F, 8);
addKey("OK", Select_Key, 0x21, 8);
addKey("POP_DIR", Unmapped_Key, 0x26, 8);
- addKey("textindex", TeletextIndex_Key, 0x2B, 8);
- addKey("textpages", Unmapped_Key, 0x2C, 8);
addKey("a/d", Unmapped_Key, 0x44, 8);
addKey("RED", Red_Key, 0x48, 8);
addKey("GREEN", Green_Key, 0x49, 8);
addKey("locate", PIPMove_Key, 0x4E, 8);
addKey("source", PIPSource_Key, 0x4F, 8);
addKey("pip", PIP_Key, 0x51, 8);
- addKey("Double_Arrow", Unmapped_Key, 0x52, 8); // "swap", but not pip!; "back"
addKey("swap", PIPSwap_Key, 0x53, 8); // Reduce
- addKey("texthold", TeletextHold_Key, 0x53, 8);
addKey("PIC_SIZE", AspectRatio_Key, 0x54, 8); // "16:9"
- addKey("textanswer", TeletextReveal_Key, 0x54, 8); // "?"
addKey("Tone", Unmapped_Key, 0x55, 8);
addKey("cap/text", Captions_Key, 0x57, 8); // Image
addKey("exit", Exit_Key, 0x58, 8);
addKey("SIZE", AspectRatio_Key, 0x59, 8); // "WIDE"
addKey("DOULBY", NoiseReduction_Key, 0x5A, 8);
- addKey("1/2", Audio_Key, 0x63, 8); // "cap1/cap2"
addKey("MENU", Menu_Key, 0x5B, 8);
+ addKey("1/2", Unmapped_Key, 0x63, 8); // "cap1/cap2"
addKey("CLOCK", Timer_Key, 0x71, 8); // "TIMER"
addKey("TV", Unmapped_Key, 0x72, 8);
addKey("SEARCH", Unmapped_Key, 0x8F, 8);
ToshibaTV1c::ToshibaTV1c(
QObject *guiObject,
unsigned int index)
- : ToshibaTV1(guiObject, index)
+ : ToshibaTV1f(guiObject, index)
{
setKeysetName("TV Keyset 1c");
- addKey("exit", Exit_Key, 0xC23D, 16);
- addKey("pipswap", PIPSwap_Key, 0x1AE5, 16);
- addKey("osdinfo", Info_Key, 0x6897, 16);
+ addKey("textzoom", TeletextSize_Key, 0x0D, 8); // "Enlarge"
+ addKey("texttime", TeletextTime_Key, 0x15, 8);
+ addKey("TXT/MIX", Teletext_Key, 0x17, 8); // "teletext"
+ addKey("textindex", TeletextIndex_Key, 0x2B, 8);
+ addKey("textpages", Unmapped_Key, 0x2C, 8);
+ addKey("texthold", TeletextHold_Key, 0x53, 8);
+ addKey("textanswer", TeletextReveal_Key, 0x54, 8);
+ addKey("pipswap", PIPSwap_Key, 0x58, 8);
}
ToshibaTV1d::ToshibaTV1d(
QObject *guiObject,
unsigned int index)
- : ToshibaTV1(guiObject, index)
+ : ToshibaTV1f(guiObject, index)
{
setKeysetName("TV Keyset 1d");
- addKey("Left", Left_Key, 0x42BD, 16);
- addKey("Right", Right_Key, 0x02FD, 16);
- addKey("Down", Down_Key, 0xB847, 16);
- addKey("Up", Up_Key, 0x9867, 16);
- addKey("Back", Exit_Key, 0xC23D, 16);
- addKey("guide", Guide_Key, 0xA25D, 16);
- addKey("tv/fav/radio", Favorites_Key, 0xE21D, 16); // might be wrong
- addKey("info", Info_Key, 0x6897, 16); // might be wrong
- addKey("subtitle", Captions_Key, 0x30CF, 16);
- addKey("stillpicture", Pause_Key, 0x44BB, 16);
- addKey("24-", Unmapped_Key, 0x2AD5, 16);
- addKey("page-", PageUp_Key, 0xCA35, 16);
- addKey("page+", PageDown_Key, 0xB04F, 16);
- addKey("24+", Unmapped_Key, 0xA857, 16);
+ addKey("subtitle", Captions_Key, 0x0C, 8);
+ addKey("page+", PageDown_Key, 0x0D,8);
+ addKey("24+", Unmapped_Key, 0x15, 8);
+ addKey("Up", Up_Key, 0x19, 8);
+ addKey("Down", Down_Key, 0x1D, 8);
+ addKey("Right", Right_Key, 0x40, 8);
+ addKey("Left", Left_Key, 0x42, 8);
+ addKey("guide", Guide_Key, 0x45, 8);
+ addKey("tv/fav/radio", Favorites_Key, 0x47, 8); // might be wrong
+ addKey("page-", PageUp_Key, 0x53, 8);
+ addKey("24-", Unmapped_Key, 0x54, 8);
}
{
setKeysetName("TV Keyset 1e");
- addKey("STOP", Stop_Key, 0xF20D, 16);
- addKey("PLAY", Play_Key, 0x8A75, 16);
- addKey("SKIPPREV", Previous_Key, 0x8877, 16);
- addKey("SKIPNEXT", Next_Key, 0xCA35, 16);
- addKey("frev", Rewind_Key, 0xD22D, 16);
- addKey("FFWD", FastForward_Key, 0x52AD, 16);
+ addKey("SKIPPREV", Previous_Key, 0x11, 8);
+ addKey("FFWD", FastForward_Key, 0x2A, 8);
+ addKey("STOP", Stop_Key, 0x40, 8);
+ addKey("frev", Rewind_Key, 0x4B, 8);
+ addKey("PLAY", Play_Key, 0x51, 8);
+ addKey("SKIPNEXT", Next_Key, 0x53, 8);
}
addControlledDevice(Toshiba_Make, "Regza AV50*", TV_Device);
- addKey("back", PrevChannel_Key, 0x4AB5, 16);
- addKey("exit", Exit_Key, 0xC23D, 16);
- addKey("info", Info_Key, 0x6897, 16);
- addKey("stillpicture", Pause_Key, 0x44BB, 16);
+ addKey("info", Info_Key, 0x16, 8);
+ addKey("stillpicture", Pause_Key, 0x22, 8);
+ addKey("exit", Exit_Key, 0x43, 8);
+ addKey("back", PrevChannel_Key, 0x52, 8); // "Double_Arrow", "swap"
}
}
+ToshibaTV1h::ToshibaTV1h(
+ QObject *guiObject,
+ unsigned int index)
+ : ToshibaTV1b(guiObject, index)
+{
+ setKeysetName("TV Keyset 1h");
+
+ addKey("last (prev ch)", PrevChannel_Key, 0x17, 8);
+ addKey("program guide", Guide_Key, 0x1C, 8);
+ addKey("pip on/off", PIP_Key, 0x54, 8);
+}
+
+
ToshibaVCR1::ToshibaVCR1(
QObject *guiObject,
unsigned int index)
protocols/aiwaprotocol.cpp \
protocols/kaseikyoprotocol.cpp \
keysets/bose.cpp \
- protocols/boseprotocol.cpp
+ protocols/boseprotocol.cpp \
+ keysets/mce.cpp \
+ protocols/mceprotocol.cpp
HEADERS += mainwindow.h \
pirkeynames.h \
pirmakenames.h \
protocols/aiwaprotocol.h \
protocols/kaseikyoprotocol.h \
protocols/boseprotocol.h \
- keysets/bose.h
+ keysets/bose.h \
+ keysets/mce.h \
+ protocols/mceprotocol.h
FORMS += mainwindow.ui \
pirdocumentationform.ui \
piraboutform.ui \
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
-<!-- Written by Qt Creator 2.4.1, 2012-02-08T17:10:54. -->
+<!-- Written by Qt Creator 2.4.1, 2012-02-10T11:09:10. -->
<qtcreator>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="QString" key="ProjectExplorer.ProcessStep.Arguments">dpkg-buildpackage -sa -S -uc -us</value>
<value type="QString" key="ProjectExplorer.ProcessStep.Command">/Users/john/QtSDK/Maemo/4.6.2/bin/mad</value>
<value type="bool" key="ProjectExplorer.ProcessStep.Enabled">false</value>
- <value type="QString" key="ProjectExplorer.ProcessStep.WorkingDirectory">/Users/john/Develop/n900/pierogi-0.5.2</value>
+ <value type="QString" key="ProjectExplorer.ProcessStep.WorkingDirectory">/Users/john/Develop/n900/pierogi-0.6.0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Custom Process Step</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.ProcessStep</value>
<value type="QString">/Users/john/Develop/n900/pierogi-build-maemo-Qt_for_Fremantle_PR1_3_Devices__Qt_SDK__Release/pierogi_0_1_1_armel.deb</value>
<value type="QString">/Users/john/Develop/n900/pierogi-build-maemo-Qt_for_Fremantle_PR1_3_Devices__Qt_SDK__Release/pierogi_0_0_1_armel.deb</value>
<value type="QString">/Users/john/Develop/n900/pierogi-build-maemo-Qt_for_Fremantle_PR1_3_Devices__Qt_SDK__Release/pierogi_0_1_0_armel.deb</value>
+ <value type="QString">/Users/john/Develop/n900/pierogi-build-maemo-Qt_for_Fremantle_PR1_3_Devices__Qt_SDK__Release/pierogi_0_5_3_armel.deb</value>
<value type="QString">/Users/john/Develop/n900/pierogi-build-maemo-Qt_for_Fremantle_PR1_3_Devices__Qt_SDK__Release/pierogi_0_1_7_armel.deb</value>
<value type="QString">/Users/john/Develop/n900/pierogi-build-maemo-Qt_for_Fremantle_PR1_3_Devices__Qt_SDK__Release/pierogi_0_5_2_armel.deb</value>
<value type="QString">/Users/john/Develop/n900/pierogi-build-maemo-Qt_for_Fremantle_PR1_3_Devices__Qt_SDK__Release/pierogi_0_0_1_armel.deb</value>
<value type="QString">192.168.0.15</value>
<value type="QString">192.168.0.15</value>
<value type="QString">192.168.0.15</value>
+ <value type="QString">192.168.0.15</value>
<value type="QString">localhost</value>
<value type="QString">192.168.0.15</value>
<value type="QString">192.168.0.15</value>
<value type="QString"></value>
<value type="QString"></value>
<value type="QString"></value>
+ <value type="QString"></value>
</valuelist>
<valuelist type="QVariantList" key="Qt4ProjectManager.MaemoRunConfiguration.LastDeployedTimes">
<value type="QDateTime">2012-02-03T10:04:34</value>
<value type="QDateTime">2012-01-17T00:15:23</value>
<value type="QDateTime">2012-01-14T13:11:32</value>
<value type="QDateTime">2012-01-17T00:03:13</value>
+ <value type="QDateTime">2012-02-09T18:12:21</value>
<value type="QDateTime">2012-01-30T20:23:06</value>
- <value type="QDateTime">2012-02-08T11:55:19</value>
+ <value type="QDateTime">2012-02-08T20:29:28</value>
<value type="QDateTime">2012-01-01T15:35:35</value>
<value type="QDateTime">2012-01-25T13:42:55</value>
<value type="QDateTime">2012-02-06T17:22:16</value>
#include "keysets/jvc.h"
#include "keysets/lg.h"
#include "keysets/magnavox.h"
+#include "keysets/mce.h"
#include "keysets/mitsubishi.h"
#include "keysets/nokia.h"
#include "keysets/panasonic.h"
populateKeyset(new MagnavoxConverterBox1(guiObject, counter++));
populateKeyset(new MagnavoxTV1(guiObject, counter++));
+ populateKeyset(new MCERemote1(guiObject, counter++));
+ populateKeyset(new MCERemote1a(guiObject, counter++));
+ populateKeyset(new MCERemote1b(guiObject, counter++));
+ populateKeyset(new MCERemote1c(guiObject, counter++));
+ populateKeyset(new MCERemote1d(guiObject, counter++));
+ populateKeyset(new MCERemote1e(guiObject, counter++));
+ populateKeyset(new MCERemote1f(guiObject, counter++));
+ populateKeyset(new MCERemote1g(guiObject, counter++));
+
populateKeyset(new MitsubishiTV1(guiObject, counter++));
populateKeyset(new MitsubishiTV1a(guiObject, counter++));
populateKeyset(new MitsubishiVCR1(guiObject, counter++));
makes[JVC_Make] = "JVC";
makes[LG_Make] = "LG";
makes[Magnavox_Make] = "Magnavox";
+ makes[Microsoft_Make] = "Microsoft";
makes[Mitsubishi_Make] = "Mitsubishi";
makes[Nokia_Make] = "Nokia";
makes[Panasonic_Make] = "Panasonic";
JVC_Make,
LG_Make,
Magnavox_Make,
+ Microsoft_Make,
Mitsubishi_Make,
Nokia_Make,
Panasonic_Make,
--- /dev/null
+#include "mceprotocol.h"
+
+#include "pirrx51hardware.h"
+
+#include "pirexception.h"
+
+#include <QMutex>
+extern bool commandInFlight;
+extern QMutex commandIFMutex;
+
+// These defines might need to be turned into variables, for odd devices.
+#define HEADER_PULSE 2666
+#define HEADER_SPACE 888
+#define TRAILER_BIPHASE 888
+
+// Ok, what I've got on MCE protocol is this:
+// It is based on RC6 mode 6A, with a few odd tweaks.
+// The biphase unit of time is 444 usec.
+// The RC6 header block starts with the normal 2666 usec pulse, 888 usec space.
+// The next bit is fixed as a "1", as usual.
+// The next three bits are 110, marking this as a mode 6 protocol.
+// The trailer bit has an 888 usec biphase, is set to 0, and is _not_ toggled!
+// The next 16 bits I'm not sure about. Hopefully they will be a fixed value
+// for any given device...
+// Then, the next bit is the new toggle bit.
+// Following this, there are seven "device address" bits, and then eight
+// "command" bits.
+// A space of (at least) 2666 usec must follow any command.
+// The carrier frequency is 36 kHZ, duty cycle between 25 and 50 %.
+
+MCEProtocol::MCEProtocol(
+ QObject *guiObject,
+ unsigned int index,
+ unsigned int oemData)
+ : PIRProtocol(guiObject, index, 2666, false),
+ biphaseUnit(444),
+ buffer(0),
+ keypressCount(0)
+{
+ setCarrierFrequency(36000);
+ appendToBitSeq(oemBits, oemData, 16);
+}
+
+
+void MCEProtocol::startSendingCommand(
+ unsigned int threadableID,
+ PIRKeyName command)
+{
+ try
+ {
+ // Is this command meant for us?
+ if (threadableID != id) return;
+
+ clearRepeatFlag();
+
+ KeycodeCollection::const_iterator i = keycodes.find(command);
+
+ // Sanity check:
+ if (i == keycodes.end())
+ {
+ std::string s = "Tried to send a non-existent command.\n";
+ throw PIRException(s);
+ }
+
+ PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
+
+ int repeatCount = 0;
+ int duration = 0;
+ while (repeatCount < MAX_REPEAT_COUNT)
+ {
+ bufferContainsSpace = false;
+ bufferContainsPulse = false;
+ // First, construct the "Header" segment of the pulse train.
+ //
+ // The header involves:
+ // a) a "lead" of 2666 us pulse, 888 us space;
+ // b) a "start bit", value 1 (so 444 us pulse, 444 us space)
+ // c) three control bits, set to "110" (i.e., mode "6")
+ // d) the double-sized "trailer" bit, set to 0.
+
+ rx51device.addSingle(HEADER_PULSE); // lead pulse
+ duration += HEADER_PULSE;
+ rx51device.addSingle(HEADER_SPACE); // lead space
+ duration += HEADER_SPACE;
+ rx51device.addSingle(biphaseUnit); // start bit pulse
+ duration += biphaseUnit;
+ rx51device.addSingle(biphaseUnit); // start bit space
+ duration += biphaseUnit;
+ rx51device.addSingle(biphaseUnit); // bit 1 pulse;
+ duration += biphaseUnit;
+ rx51device.addSingle(biphaseUnit); // bit 1 space;
+ duration += biphaseUnit;
+ rx51device.addSingle(biphaseUnit); // bit 2 pulse;
+ duration += biphaseUnit;
+ rx51device.addSingle(2 * biphaseUnit); // bit 2 space + bit 3 space;
+ duration += 2 * biphaseUnit;
+ rx51device.addSingle(biphaseUnit); // bit 3 pulse;
+ duration += biphaseUnit;
+ rx51device.addSingle(2 * biphaseUnit); // trailer space
+ duration += 2 * biphaseUnit;
+ buffer = 2 * biphaseUnit; // trailer pulse goes into the buffer
+ bufferContainsPulse = true;
+
+ // Now, we can start the normal buffering process:
+
+ // push the "OEM" data:
+ duration += pushBits(oemBits, rx51device);
+
+ // The next bit is the MCE toggle bit:
+ if (keypressCount % 2)
+ {
+ pushOne(rx51device);
+ }
+ else
+ {
+ pushZero(rx51device);
+ }
+
+ // push the device address data:
+ duration += pushBits(preData, rx51device);
+
+ // push the command data:
+ duration += pushBits((*i).second.firstCode, rx51device);
+
+ // Flush out the buffer, if necessary:
+ if (buffer)
+ {
+ rx51device.addSingle(buffer);
+ duration += buffer;
+ buffer = 0;
+ }
+
+ // Actually send out the command:
+ rx51device.sendCommandToDevice();
+
+ // Sleep for an amount of time. (RC6 demands an addtional 6 unit space
+ // at the end of any command...)
+ sleepUntilRepeat(duration + 6 * biphaseUnit);
+
+ // Have we been told to stop yet?
+ if (checkRepeatFlag())
+ {
+ // Yes, we can now quit repeating:
+ ++keypressCount;
+ QMutexLocker ciflocker(&commandIFMutex);
+ commandInFlight = false;
+ return;
+ }
+ }
+ }
+ catch (PIRException e)
+ {
+ emit commandFailed(e.getError().c_str());
+ }
+
+ ++keypressCount;
+ QMutexLocker cifLocker(&commandIFMutex);
+ commandInFlight = false;
+}
+
+
+int MCEProtocol::pushBits(
+ const CommandSequence &bits,
+ PIRRX51Hardware &rx51device)
+{
+ int duration = 0;
+
+ CommandSequence::const_iterator i = bits.begin();
+
+ while (i != bits.end())
+ {
+ if (*i)
+ {
+ duration += pushOne(rx51device);
+ }
+ else
+ {
+ duration += pushZero(rx51device);
+ }
+
+ ++i;
+ }
+
+ return duration;
+}
+
+
+// This should be part of a general RC6 parent maybe?
+int MCEProtocol::pushZero(
+ PIRRX51Hardware &rx51device)
+{
+ // Need to add a space, then a pulse.
+ int duration = 0;
+
+ if (bufferContainsSpace)
+ {
+ // Merge this space and the previous one, and send to device:
+ rx51device.addSingle(buffer + biphaseUnit);
+ duration += (buffer + biphaseUnit);
+ buffer = 0;
+ bufferContainsSpace = false;
+ }
+ else
+ {
+ if (bufferContainsPulse)
+ {
+ // Flush out the buffer:
+ rx51device.addSingle(buffer);
+ duration += buffer;
+ buffer = 0;
+ bufferContainsPulse = false;
+ }
+
+ // push a space onto the device:
+ rx51device.addSingle(biphaseUnit);
+ duration += biphaseUnit;
+ }
+
+ // Put a pulse into the buffer to wait:
+ buffer = biphaseUnit;
+ bufferContainsPulse = true;
+
+ return duration;
+}
+
+
+int MCEProtocol::pushOne(
+ PIRRX51Hardware &rx51device)
+{
+ // Need to add a pulse, then a space.
+ int duration = 0;
+
+ // First, the pulse:
+ if (bufferContainsPulse)
+ {
+ rx51device.addSingle(buffer + biphaseUnit);
+ duration += (buffer + biphaseUnit);
+ buffer = 0;
+ bufferContainsPulse = false;
+ }
+ else
+ {
+ if (bufferContainsSpace)
+ {
+ // Flush the buffer:
+ rx51device.addSingle(buffer);
+ duration += buffer;
+ buffer = 0;
+ bufferContainsSpace = false;
+ }
+ // Now, add the pulse:
+ rx51device.addSingle(biphaseUnit);
+ duration += biphaseUnit;
+ }
+
+ // Next, push a space onto the buffer:
+ buffer = biphaseUnit;
+ bufferContainsSpace = true;
+
+ return duration;
+}
--- /dev/null
+#ifndef MCEPROTOCOL_H
+#define MCEPROTOCOL_H
+
+#include "pirprotocol.h"
+
+class PIRRX51Hardware;
+
+//
+// The MCE protocol is derived from (but does not exactly match) RC6 mode 6A.
+//
+
+class MCEProtocol: public PIRProtocol
+{
+public:
+ MCEProtocol(
+ QObject *guiObject,
+ unsigned int index,
+ unsigned int oemData);
+
+public slots:
+ void startSendingCommand(
+ unsigned int threadableID,
+ PIRKeyName command);
+
+private:
+ int pushBits(
+ const CommandSequence &bits,
+ PIRRX51Hardware &device);
+
+ int pushZero(
+ PIRRX51Hardware &device);
+
+ int pushOne(
+ PIRRX51Hardware &device);
+
+ unsigned int biphaseUnit;
+
+ CommandSequence oemBits;
+
+ unsigned int buffer;
+ int keypressCount;
+
+ bool bufferContainsSpace;
+ bool bufferContainsPulse;
+};
+
+#endif // MCEPROTOCOL_H
+pierogi (0.6.0) unstable; urgency=low
+ * My first candidate for Extras-Testing, so up to version 0.6
+ * Fixed some bugs in Toshiba keysets
+ * Added MCE (Media Center Edition) remote keysets
+
+ -- John Pietrzak <jpietrzak8@gmail.com> Fri, 10 Feb 2012 11:08:18 -0500
+
+pierogi (0.5.3) unstable; urgency=low
+ * Another "final" fix for the uninstall problem, this time for sure. :)
+ * Completely revamped Panasonic protocol, needs testing
+ * Created Bose keysets, added more Aiwa keysets
+
+ -- John Pietrzak <jpietrzak8@gmail.com> Wed, 08 Feb 2012 20:51:14 -0500
+
pierogi (0.5.2) unstable; urgency=low
* Finally, got a fix for the uninstall problem!
* Some general internal cleanup.
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Universal Infrared Remote Control for N900
Pierogi is a Universal Infrared Remote Control app for the Nokia N900. It is independent from the LIRC server, and stores all configuration info internally.
-XB-Maemo-Upgrade-Description: Continuing to work on installer
- New method for creating pierogi.sudoers file should finally allow uninstaller to cleanly remove it. Also, completely revamped Panasonic keysets (possibly breaking them), and added Bose and more Aiwa keysets.
+XB-Maemo-Upgrade-Description: First Extras-Testing Candidate
+ Pierogi is now somewhat stable, so I will start cleaning it up for submission to Extras-Testing. Also in this update, new MCE keysets, and cleanup of Toshiba keysets.
XSBC-Bugtracker: https://garage.maemo.org/tracker/?func=add&group_id=2286&atid=7641
XB-Maemo-Display-Name: Pierogi
XB-Maemo-Icon-26: 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