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