Possible Uninstall Fix, plus cleanup, more keysets
[pierogi] / protocols / lircprotocol.cpp
1 #include "lircprotocol.h"
2
3 #include "pirrx51hardware.h"
4
5 #include "pirexception.h"
6 #include <string>
7 //#include <iostream>
8
9 // Some global communications stuff:
10 #include <QMutex>
11 extern bool commandInFlight;
12 extern QMutex commandIFMutex;
13
14 LIRCProtocol::LIRCProtocol(
15   QObject *guiObject,
16   unsigned int index,
17   unsigned int zPulse,
18   unsigned int zSpace,
19   unsigned int oPulse,
20   unsigned int oSpace,
21   unsigned int gSpace,
22   bool iclflag)
23   : SpaceProtocol(
24       guiObject, index,
25       zPulse, zSpace,
26       oPulse, oSpace,
27       0, 0,
28       0,
29       gSpace, iclflag),
30     hasHeaderPair(false),
31     hasTrailerPulse(false),
32     hasRepeatPair(false),
33     repeatNeedsHeader(false),
34     fullHeadlessRepeat(false)
35 {
36 }
37
38 void LIRCProtocol::setHeaderPair(
39   unsigned int pulse,
40   unsigned int space)
41 {
42   headerPulse = pulse;
43   headerSpace = space;
44   hasHeaderPair = true;
45 }
46
47 void LIRCProtocol::setTrailerPulse(
48   unsigned int pulse)
49 {
50   trailerPulse = pulse;
51   hasTrailerPulse = true;
52 }
53
54 void LIRCProtocol::setRepeatPair(
55   unsigned int pulse,
56   unsigned int space)
57 {
58   repeatPulse = pulse;
59   repeatSpace = space;
60   hasRepeatPair = true;
61 }
62
63 void LIRCProtocol::setRepeatNeedsHeader(
64   bool flag)
65 {
66   repeatNeedsHeader = flag;
67 }
68
69 void LIRCProtocol::setFullHeadlessRepeat(
70   bool flag)
71 {
72   fullHeadlessRepeat = flag;
73 }
74
75 void LIRCProtocol::startSendingCommand(
76   unsigned int threadableID,
77   PIRKeyName command)
78 {
79   // Exceptions here are problematic; I'll try to weed them out by putting the
80   // whole thing in a try/catch block:
81   try
82   {
83     // First, check if we are meant to be the recipient of this command:
84     if (threadableID != id) return;
85
86     clearRepeatFlag();
87
88     KeycodeCollection::const_iterator i = keycodes.find(command);
89
90     // Do we even have this key defined?
91     if (i == keycodes.end())
92     {
93       std::string s = "Tried to send a non-existent command.\n";
94       throw PIRException(s);
95     }
96
97     // construct the device:
98     PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
99
100     int repeatCount = 0;
101     int commandDuration = 0;
102     while (repeatCount < MAX_REPEAT_COUNT)
103     {
104       // If we are currently repeating, and have a special "repeat signal",
105       // use that signal.  Otherwise, generate a normal command string.
106       if (hasRepeatPair && repeatCount)
107       {
108         commandDuration = generateRepeatCommand(rx51device);
109       }
110       else if (fullHeadlessRepeat && repeatCount)
111       {
112         commandDuration = generateHeadlessCommand((*i).second, rx51device);
113       }
114       else
115       {
116         commandDuration = generateStandardCommand((*i).second, rx51device);
117       }
118
119       // Now, tell the device to send the whole command:
120       rx51device.sendCommandToDevice();
121
122       // sleep until the next repetition of command:
123       sleepUntilRepeat(commandDuration);
124
125       // Check whether we've reached the minimum required number of repetitons:
126       if (repeatCount >= minimumRepetitions)
127       {
128         // Check whether we've been asked to stop:
129         if (checkRepeatFlag())
130         {
131           QMutexLocker cifLocker(&commandIFMutex);
132           commandInFlight = false;
133           return;
134         }
135       }
136
137       ++repeatCount;
138     }
139   }
140   catch (PIRException e)
141   {
142     // inform the gui:
143     emit commandFailed(e.getError().c_str());
144   }
145
146   QMutexLocker cifLocker(&commandIFMutex);
147   commandInFlight = false;
148 }
149
150
151 int LIRCProtocol::generateStandardCommand(
152   const PIRKeyBits &pkb,
153   PIRRX51Hardware &rx51device)
154 {
155   int duration = 0;
156
157   // First, the "header" pulse (if any):
158   if (hasHeaderPair)
159   {
160     rx51device.addPair(headerPulse, headerSpace);
161     duration += (headerPulse + headerSpace);
162   }
163
164   // For LIRC, just dump the bits straight into the device, one by one:
165   duration += pushBits(preData, rx51device);
166   duration += pushBits(pkb.firstCode, rx51device);
167   duration += pushBits(postData, rx51device);
168
169   // Finally add the "trail":
170   if (hasTrailerPulse)
171   {
172     rx51device.addSingle(trailerPulse);
173     duration += trailerPulse;
174   }
175
176   return duration;
177 }
178
179
180 int LIRCProtocol::generateHeadlessCommand(
181   const PIRKeyBits &pkb,
182   PIRRX51Hardware &rx51device)
183 {
184   int duration = 0;
185
186   // First, the "pre" data:
187   duration += pushBits(preData, rx51device);
188
189   // Next, add the actual command:
190   duration += pushBits(pkb.firstCode, rx51device);
191
192   // Next, add the "post" data:
193   duration += pushBits(postData, rx51device);
194
195   // Finally add the "trail":
196   if (hasTrailerPulse)
197   {
198     rx51device.addSingle(trailerPulse);
199     duration += trailerPulse;
200   }
201
202   return duration;
203 }
204
205
206 int LIRCProtocol::generateRepeatCommand(
207   PIRRX51Hardware &rx51device)
208 {
209   int duration = 0;
210
211   // Do we need the header?
212   if (repeatNeedsHeader)
213   {
214     // Do we even have a header?
215     if (hasHeaderPair)
216     {
217       // Ok, then add the header to the repeat:
218       rx51device.addPair(headerPulse, headerSpace);
219       duration += (headerPulse + headerSpace);
220     }
221   }
222
223   // Add the repeat pulse:
224   rx51device.addPair(repeatPulse, repeatSpace);
225   duration += (repeatPulse + repeatSpace);
226
227   // Finally add the trailer:
228   if (hasTrailerPulse)
229   {
230     rx51device.addSingle(trailerPulse);
231     duration += trailerPulse;
232   }
233
234   return duration;
235 }