Log In
New Account
  
Home My Page Project Cloud Code Snippets Project Openings Pierogi
Summary Forums Tracker Lists Tasks Docs News SCM Files
authorJohn Pietrzak <john@pietrzak.org>
Fri, 10 Feb 2012 16:23:15 +0000 (11:23 -0500)
committerJohn Pietrzak <john@pietrzak.org>
Fri, 10 Feb 2012 16:23:15 +0000 (11:23 -0500)
Pierogi has reached a sufficient level of stability that I'd like to submit it
to Extras-Testing.  So, I'm again increasing the version number (to 0.6), and
working on any extra cleanup necessary.  Also in this update, new MCE keysets
and fixes to the Toshiba keysets.

15 files changed:
doc/about.html
keysets/bose.cpp
keysets/mce.cpp [new file with mode: 0644]
keysets/mce.h [new file with mode: 0644]
keysets/sony.cpp
keysets/toshiba.cpp
pierogi.pro
pierogi.pro.user
pirkeysetmanager.cpp
pirmakenames.cpp
pirmakenames.h
protocols/mceprotocol.cpp [new file with mode: 0644]
protocols/mceprotocol.h [new file with mode: 0644]
qtc_packaging/debian_fremantle/changelog
qtc_packaging/debian_fremantle/control

index f0a62be..6843f34 100644 (file)
@@ -9,18 +9,17 @@ Pierogi UIRC
 <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>
index dc07781..6ce7e1e 100644 (file)
@@ -58,12 +58,13 @@ BoseRadio2::BoseRadio2(
 
   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);
@@ -73,6 +74,7 @@ BoseRadio2::BoseRadio2(
   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);
 }
diff --git a/keysets/mce.cpp b/keysets/mce.cpp
new file mode 100644 (file)
index 0000000..8309a66
--- /dev/null
@@ -0,0 +1,165 @@
+#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);
+}
diff --git a/keysets/mce.h b/keysets/mce.h
new file mode 100644 (file)
index 0000000..406ecca
--- /dev/null
@@ -0,0 +1,72 @@
+#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
index 996dcde..ba1abfd 100644 (file)
@@ -467,6 +467,10 @@ SonyDVD1::SonyDVD1(
   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);
@@ -486,8 +490,8 @@ SonyDVD1::SonyDVD1(
   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);
 
@@ -518,11 +522,17 @@ SonyDVD1::SonyDVD1(
   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);
index c828c2f..8cac3e6 100644 (file)
@@ -29,17 +29,15 @@ ToshibaTV1::ToshibaTV1(
   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);
@@ -53,8 +51,6 @@ ToshibaTV1::ToshibaTV1(
   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);
@@ -66,18 +62,15 @@ ToshibaTV1::ToshibaTV1(
   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);
@@ -120,37 +113,39 @@ ToshibaTV1b::ToshibaTV1b(
 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);
 }
 
 
@@ -161,12 +156,12 @@ ToshibaTV1e::ToshibaTV1e(
 {
   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);
 }
 
 
@@ -179,10 +174,10 @@ ToshibaTV1f::ToshibaTV1f(
 
   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"
 }
 
 
@@ -200,6 +195,19 @@ ToshibaTV1g::ToshibaTV1g(
 }
 
 
+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)
index 6d624c6..92b1b24 100644 (file)
@@ -83,7 +83,9 @@ SOURCES += main.cpp mainwindow.cpp \
     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 \
@@ -143,7 +145,9 @@ HEADERS += mainwindow.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 \
index c6ba144..f703f80 100644 (file)
@@ -1,6 +1,6 @@
 <?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>
@@ -79,7 +79,7 @@
       <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>
index a57a398..c2bce33 100644 (file)
@@ -17,6 +17,7 @@
 #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"
@@ -170,6 +171,15 @@ PIRKeysetManager::PIRKeysetManager(
   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++));
index cacbecb..e272745 100644 (file)
@@ -18,6 +18,7 @@ PIRMakeMgr::PIRMakeMgr()
   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";
index cde6630..ff50d30 100644 (file)
@@ -19,6 +19,7 @@ enum PIRMakeName{
   JVC_Make,
   LG_Make,
   Magnavox_Make,
+  Microsoft_Make,
   Mitsubishi_Make,
   Nokia_Make,
   Panasonic_Make,
diff --git a/protocols/mceprotocol.cpp b/protocols/mceprotocol.cpp
new file mode 100644 (file)
index 0000000..9096c7e
--- /dev/null
@@ -0,0 +1,261 @@
+#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;
+}
diff --git a/protocols/mceprotocol.h b/protocols/mceprotocol.h
new file mode 100644 (file)
index 0000000..6f8dc24
--- /dev/null
@@ -0,0 +1,47 @@
+#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 
index c51b7de..f85d271 100644 (file)
@@ -1,3 +1,17 @@
+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.
index 15ce426..2f000e4 100644 (file)
@@ -11,8 +11,8 @@ Architecture: armel
 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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

Terms of Use    Privacy Policy    Contribution Guidelines    Feedback

Powered By GForge Collaborative Development Environment