CPPMyth
Library to interoperate with MythTV server
mythprotobase.cpp
1 /*
2  * Copyright (C) 2014 Jean-Luc Barriere
3  *
4  * This Program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2, or (at your option)
7  * any later version.
8  *
9  * This Program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; see the file COPYING. If not, write to
16  * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
17  * MA 02110-1301 USA
18  * http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21 
22 #include "mythprotobase.h"
23 #include "../private/debug.h"
24 #include "../private/socket.h"
25 #include "../private/os/threads/mutex.h"
26 #include "../private/cppdef.h"
27 #include "../private/builtin.h"
28 
29 #include <limits>
30 #include <cstdio>
31 
32 using namespace Myth;
33 
34 typedef struct
35 {
36  unsigned version;
37  char token[44]; // up to 43 chars used in v87 + the terminating NULL character
39 
40 static myth_protomap_t protomap[] = {
41  {91, "BuzzOff"},
42  {90, "BuzzCut"},
43  {89, "BuzzKill"},
44  {88, "XmasGift"},
45  {87, "(ノಠ益ಠ)ノ彡┻━┻_No_entiendo!)"},
46  {86, "(ノಠ益ಠ)ノ彡┻━┻"},
47  {85, "BluePool"},
48  {84, "CanaryCoalmine"},
49  {83, "BreakingGlass"},
50  {82, "IdIdO"},
51  {81, "MultiRecDos"},
52  {80, "TaDah!"},
53  {79, "BasaltGiant"},
54  {77, "WindMark"},
55  {76, "FireWilde"},
56  {75, "SweetRock"},
57  {0, ""}
58 };
59 
60 ProtoBase::ProtoBase(const std::string& server, unsigned port)
61 : m_mutex(new OS::CMutex)
62 , m_socket(new TcpSocket())
63 , m_protoVersion(0)
64 , m_server(server)
65 , m_port(port)
66 , m_hang(false)
67 , m_tainted(false)
68 , m_msgLength(0)
69 , m_msgConsumed(0)
70 , m_isOpen(false)
71 , m_protoError(ERROR_NO_ERROR)
72 {
73  m_socket->SetReadAttempt(6); // 60 sec to hang up
74 }
75 
76 ProtoBase::~ProtoBase()
77 {
78  this->Close();
79  SAFE_DELETE(m_socket);
80  SAFE_DELETE(m_mutex);
81 }
82 
83 void ProtoBase::HangException()
84 {
85  DBG(DBG_ERROR, "%s: protocol connection hang with error %d\n", __FUNCTION__, m_socket->GetErrNo());
86  m_tainted = m_hang = true;
87  ProtoBase::Close();
88  // Note: Opening connection successfully will reset m_hang
89 }
90 
91 bool ProtoBase::SendCommand(const char *cmd, bool feedback)
92 {
93  size_t l = strlen(cmd);
94 
95  if (m_msgConsumed != m_msgLength)
96  {
97  DBG(DBG_ERROR, "%s: did not consume everything\n", __FUNCTION__);
98  FlushMessage();
99  }
100 
101  if (l > 0 && l < PROTO_SENDMSG_MAXSIZE)
102  {
103  char buf[9];
104  std::string msg;
105  msg.reserve(l + 8);
106  sprintf(buf, "%-8u", (unsigned)l);
107  msg.append(buf).append(cmd);
108  DBG(DBG_PROTO, "%s: %s\n", __FUNCTION__, cmd);
109  if (m_socket->SendData(msg.c_str(), msg.size()))
110  {
111  if (feedback)
112  return RcvMessageLength();
113  return true;
114  }
115  DBG(DBG_ERROR, "%s: failed (%d)\n", __FUNCTION__, m_socket->GetErrNo());
116  HangException();
117  return false;
118  }
119  DBG(DBG_ERROR, "%s: message size out of bound (%d)\n", __FUNCTION__, (int)l);
120  return false;
121 }
122 
123 size_t ProtoBase::GetMessageLength() const
124 {
125  return m_msgLength;
126 }
127 
133 bool ProtoBase::ReadField(std::string& field)
134 {
135  const char *str_sep = PROTO_STR_SEPARATOR;
136  size_t str_sep_len = PROTO_STR_SEPARATOR_LEN;
137  char buf[PROTO_BUFFER_SIZE];
138  size_t p = 0, p_ss = 0, l = m_msgLength, c = m_msgConsumed;
139 
140  field.clear();
141  if ( c >= l)
142  return false;
143 
144  for (;;)
145  {
146  if (l > c)
147  {
148  if (m_socket->ReceiveData(&buf[p], 1) < 1)
149  {
150  HangException();
151  return false;
152  }
153  ++c;
154  if (buf[p++] == str_sep[p_ss])
155  {
156  if (++p_ss >= str_sep_len)
157  {
158  // Append data until separator before exit
159  buf[p - str_sep_len] = '\0';
160  field.append(buf);
161  break;
162  }
163  }
164  else
165  {
166  p_ss = 0;
167  if (p > (PROTO_BUFFER_SIZE - 2 - str_sep_len))
168  {
169  // Append data before flushing to refill the following
170  buf[p] = '\0';
171  field.append(buf);
172  p = 0;
173  }
174  }
175  }
176  else
177  {
178  // All is consumed. Append rest of data before exit
179  buf[p] = '\0';
180  field.append(buf);
181  break;
182  }
183  }
184  // Renew consumed or reset when no more data
185  if (l > c)
186  m_msgConsumed = c;
187  else
188  m_msgConsumed = m_msgLength = 0;
189  return true;
190 }
191 
192 bool ProtoBase::IsMessageOK(const std::string& field) const
193 {
194  if (field.size() == 2)
195  {
196  if ((field[0] == 'O' || field[0] == 'o') && (field[1] == 'K' || field[1] == 'k'))
197  return true;
198  }
199  return false;
200 }
201 
202 size_t ProtoBase::FlushMessage()
203 {
204  char buf[PROTO_BUFFER_SIZE];
205  size_t r, n = 0, f = m_msgLength - m_msgConsumed;
206 
207  while (f > 0)
208  {
209  r = (f > PROTO_BUFFER_SIZE ? PROTO_BUFFER_SIZE : f);
210  if (m_socket->ReceiveData(buf, r) != r)
211  {
212  HangException();
213  break;
214  }
215  f -= r;
216  n += r;
217  }
218  m_msgLength = m_msgConsumed = 0;
219  return n;
220 }
221 
222 bool ProtoBase::RcvMessageLength()
223 {
224  char buf[9];
225  uint32_t val = 0;
226 
227  // If not placed on head of new response then break
228  if (m_msgLength > 0)
229  return false;
230 
231  if (m_socket->ReceiveData(buf, 8) == 8)
232  {
233  if (0 == string_to_uint32(buf, &val))
234  {
235  DBG(DBG_PROTO, "%s: %" PRIu32 "\n", __FUNCTION__, val);
236  m_msgLength = (size_t)val;
237  m_msgConsumed = 0;
238  return true;
239  }
240  DBG(DBG_ERROR, "%s: failed ('%s')\n", __FUNCTION__, buf);
241  }
242  HangException();
243  return false;
244 }
245 
252 bool ProtoBase::RcvVersion(unsigned *version)
253 {
254  std::string field;
255  uint32_t val = 0;
256 
257  /*
258  * The string we just consumed was either "ACCEPT" or "REJECT". In
259  * either case, the number following it is the correct version, and
260  * we use it as an unsigned.
261  */
262  if (!ReadField(field))
263  goto out;
264  if (!ReadField(field))
265  goto out;
266  if (FlushMessage())
267  {
268  DBG(DBG_ERROR, "%s: did not consume everything\n", __FUNCTION__);
269  return false;
270  }
271  if (0 != string_to_uint32(field.c_str(), &val))
272  goto out;
273  *version = (unsigned)val;
274  return true;
275 
276 out:
277  DBG(DBG_ERROR, "%s: failed ('%s')\n", __FUNCTION__, field.c_str());
278  FlushMessage();
279  return false;
280 }
281 
282 bool ProtoBase::OpenConnection(int rcvbuf)
283 {
284  static unsigned my_version = 0;
285  char cmd[256];
286  myth_protomap_t *map;
287  unsigned tmp_ver;
288 
289  OS::CLockGuard lock(*m_mutex);
290 
291  if (!my_version)
292  // try first version of the map
293  tmp_ver = protomap->version;
294  else
295  // try previously agreed version
296  tmp_ver = my_version;
297 
298  if (m_isOpen)
299  ProtoBase::Close();
300  // Reset error status
301  m_protoError = ERROR_NO_ERROR;
302  for (;;)
303  {
304  // Reset to allow downgrade/upgrade
305  map = protomap;
306  while (map->version != 0 && map->version != tmp_ver)
307  ++map;
308 
309  if (map->version == 0)
310  {
311  m_protoError = ERROR_UNKNOWN_VERSION;
312  DBG(DBG_ERROR, "%s: failed to connect with any version\n", __FUNCTION__);
313  break;
314  }
315 
316  if (!m_socket->Connect(m_server.c_str(), m_port, rcvbuf))
317  {
318  // hang will remain up allowing retry
319  m_hang = true;
320  m_protoError = ERROR_SERVER_UNREACHABLE;
321  break;
322  }
323  // Now socket is connected: Reset hang
324  m_hang = false;
325 
326  sprintf(cmd, "MYTH_PROTO_VERSION %" PRIu32 " %s", map->version, map->token);
327 
328  if (!SendCommand(cmd) || !RcvVersion(&tmp_ver))
329  {
330  m_protoError = ERROR_SOCKET_ERROR;
331  break;
332  }
333 
334  DBG(DBG_DEBUG, "%s: asked for version %" PRIu32 ", got version %" PRIu32 "\n",
335  __FUNCTION__, map->version, tmp_ver);
336 
337  if (map->version == tmp_ver)
338  {
339  DBG(DBG_DEBUG, "%s: agreed on version %u\n", __FUNCTION__, tmp_ver);
340  if (tmp_ver != my_version)
341  my_version = tmp_ver; // Store agreed version for next time
342  m_isOpen = true;
343  m_protoVersion = tmp_ver;
344  return true;
345  }
346  // Retry with the returned version
347  m_socket->Disconnect();
348  }
349 
350  m_socket->Disconnect();
351  m_isOpen = false;
352  m_protoVersion = 0;
353  return false;
354 }
355 
356 void ProtoBase::Close()
357 {
358  OS::CLockGuard lock(*m_mutex);
359 
360  if (m_socket->IsValid())
361  {
362  // Close gracefully by sending DONE message before disconnect
363  if (m_isOpen && !m_hang)
364  {
365  const char *cmd = "DONE";
366  if (SendCommand(cmd, false))
367  DBG(DBG_PROTO, "%s: done\n", __FUNCTION__);
368  else
369  DBG(DBG_WARN, "%s: gracefully failed (%d)\n", __FUNCTION__, m_socket->GetErrNo());
370  }
371  m_socket->Disconnect();
372  }
373  m_isOpen = false;
374  m_msgLength = m_msgConsumed = 0;
375 }
376 
377 unsigned ProtoBase::GetProtoVersion() const
378 {
379  if (m_isOpen)
380  return m_protoVersion;
381  return 0;
382 }
383 
384 std::string ProtoBase::GetServer() const
385 {
386  return m_server;
387 }
388 
389 unsigned ProtoBase::GetPort() const
390 {
391  return m_port;
392 }
393 
394 int ProtoBase::GetSocketErrNo() const
395 {
396  return m_socket->GetErrNo();
397 }
398 
399 int ProtoBase::GetSocket() const
400 {
401  return (int)(m_socket->GetHandle());
402 }
403 
404 bool ProtoBase::HasHanging() const
405 {
406  return m_tainted;
407 }
408 
409 void ProtoBase::CleanHanging()
410 {
411  m_tainted = false;
412 }
413 
414 ProtoBase::ERROR_t ProtoBase::GetProtoError() const
415 {
416  return m_protoError;
417 }
418 
419 ProgramPtr ProtoBase::RcvProgramInfo75()
420 {
421  int64_t tmpi;
422  std::string field;
423  ProgramPtr program(new Program());
424  int i = 0;
425 
426  ++i;
427  if (!ReadField(program->title))
428  goto out;
429  ++i;
430  if (!ReadField(program->subTitle))
431  goto out;
432  ++i;
433  if (!ReadField(program->description))
434  goto out;
435  ++i;
436  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->season)))
437  goto out;
438  ++i;
439  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->episode)))
440  goto out;
441  ++i;
442  if (!ReadField(program->category))
443  goto out;
444  ++i;
445  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.chanId)))
446  goto out;
447  ++i;
448  if (!ReadField(program->channel.chanNum))
449  goto out;
450  ++i;
451  if (!ReadField(program->channel.callSign))
452  goto out;
453  ++i;
454  if (!ReadField(program->channel.channelName))
455  goto out;
456  ++i;
457  if (!ReadField(program->fileName))
458  goto out;
459  ++i;
460  if (!ReadField(field) || string_to_int64(field.c_str(), &(program->fileSize)))
461  goto out;
462  ++i;
463  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
464  goto out;
465  program->startTime = (time_t)tmpi;
466  ++i;
467  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
468  goto out;
469  program->endTime = (time_t)tmpi;
470  ++i;
471  if (!ReadField(field)) // findid
472  goto out;
473  ++i;
474  if (!ReadField(program->hostName))
475  goto out;
476  ++i;
477  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.sourceId)))
478  goto out;
479  ++i;
480  if (!ReadField(field)) // cardid
481  goto out;
482  ++i;
483  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.inputId)))
484  goto out;
485  ++i;
486  if (!ReadField(field) || string_to_int32(field.c_str(), &(program->recording.priority)))
487  goto out;
488  ++i;
489  if (!ReadField(field) || string_to_int8(field.c_str(), &(program->recording.status)))
490  goto out;
491  ++i;
492  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->recording.recordId)))
493  goto out;
494  ++i;
495  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.recType)))
496  goto out;
497  ++i;
498  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupInType)))
499  goto out;
500  ++i;
501  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupMethod)))
502  goto out;
503  ++i;
504  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
505  goto out;
506  program->recording.startTs = (time_t)tmpi;
507  ++i;
508  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
509  goto out;
510  program->recording.endTs = (time_t)tmpi;
511  ++i;
512  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->programFlags)))
513  goto out;
514  ++i;
515  if (!ReadField(program->recording.recGroup))
516  goto out;
517  ++i;
518  if (!ReadField(program->channel.chanFilters))
519  goto out;
520  ++i;
521  if (!ReadField(program->seriesId))
522  goto out;
523  ++i;
524  if (!ReadField(program->programId))
525  goto out;
526  ++i;
527  if (!ReadField(program->inetref))
528  goto out;
529  ++i;
530  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
531  goto out;
532  program->lastModified = (time_t)tmpi;
533  ++i;
534  if (!ReadField(program->stars))
535  goto out;
536  ++i;
537  if (!ReadField(field) || string_to_time(field.c_str(), &(program->airdate)))
538  goto out;
539  ++i;
540  if (!ReadField(program->recording.playGroup))
541  goto out;
542  ++i;
543  if (!ReadField(field)) // recpriority2
544  goto out;
545  ++i;
546  if (!ReadField(field)) // parentid
547  goto out;
548  ++i;
549  if (!ReadField(program->recording.storageGroup))
550  goto out;
551  ++i;
552  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->audioProps)))
553  goto out;
554  ++i;
555  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->videoProps)))
556  goto out;
557  return program;
558 out:
559  DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str());
560  program.reset();
561  return program;
562 }
563 
564 ProgramPtr ProtoBase::RcvProgramInfo76()
565 {
566  int64_t tmpi;
567  std::string field;
568  ProgramPtr program(new Program());
569  int i = 0;
570 
571  ++i;
572  if (!ReadField(program->title))
573  goto out;
574  ++i;
575  if (!ReadField(program->subTitle))
576  goto out;
577  ++i;
578  if (!ReadField(program->description))
579  goto out;
580  ++i;
581  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->season)))
582  goto out;
583  ++i;
584  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->episode)))
585  goto out;
586  ++i;
587  if (!ReadField(field)) // syndicated episode
588  goto out;
589  ++i;
590  if (!ReadField(program->category))
591  goto out;
592  ++i;
593  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.chanId)))
594  goto out;
595  ++i;
596  if (!ReadField(program->channel.chanNum))
597  goto out;
598  ++i;
599  if (!ReadField(program->channel.callSign))
600  goto out;
601  ++i;
602  if (!ReadField(program->channel.channelName))
603  goto out;
604  ++i;
605  if (!ReadField(program->fileName))
606  goto out;
607  ++i;
608  if (!ReadField(field) || string_to_int64(field.c_str(), &(program->fileSize)))
609  goto out;
610  ++i;
611  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
612  goto out;
613  program->startTime = (time_t)tmpi;
614  ++i;
615  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
616  goto out;
617  program->endTime = (time_t)tmpi;
618  ++i;
619  if (!ReadField(field)) // findid
620  goto out;
621  ++i;
622  if (!ReadField(program->hostName))
623  goto out;
624  ++i;
625  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.sourceId)))
626  goto out;
627  ++i;
628  if (!ReadField(field)) // cardid
629  goto out;
630  ++i;
631  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.inputId)))
632  goto out;
633  ++i;
634  if (!ReadField(field) || string_to_int32(field.c_str(), &(program->recording.priority)))
635  goto out;
636  ++i;
637  if (!ReadField(field) || string_to_int8(field.c_str(), &(program->recording.status)))
638  goto out;
639  ++i;
640  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->recording.recordId)))
641  goto out;
642  ++i;
643  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.recType)))
644  goto out;
645  ++i;
646  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupInType)))
647  goto out;
648  ++i;
649  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupMethod)))
650  goto out;
651  ++i;
652  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
653  goto out;
654  program->recording.startTs = (time_t)tmpi;
655  ++i;
656  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
657  goto out;
658  program->recording.endTs = (time_t)tmpi;
659  ++i;
660  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->programFlags)))
661  goto out;
662  ++i;
663  if (!ReadField(program->recording.recGroup))
664  goto out;
665  ++i;
666  if (!ReadField(program->channel.chanFilters))
667  goto out;
668  ++i;
669  if (!ReadField(program->seriesId))
670  goto out;
671  ++i;
672  if (!ReadField(program->programId))
673  goto out;
674  ++i;
675  if (!ReadField(program->inetref))
676  goto out;
677  ++i;
678  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
679  goto out;
680  program->lastModified = (time_t)tmpi;
681  ++i;
682  if (!ReadField(program->stars))
683  goto out;
684  ++i;
685  if (!ReadField(field) || string_to_time(field.c_str(), &(program->airdate)))
686  goto out;
687  ++i;
688  if (!ReadField(program->recording.playGroup))
689  goto out;
690  ++i;
691  if (!ReadField(field)) // recpriority2
692  goto out;
693  ++i;
694  if (!ReadField(field)) // parentid
695  goto out;
696  ++i;
697  if (!ReadField(program->recording.storageGroup))
698  goto out;
699  ++i;
700  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->audioProps)))
701  goto out;
702  ++i;
703  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->videoProps)))
704  goto out;
705  ++i;
706  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->subProps)))
707  goto out;
708  ++i;
709  if (!ReadField(field)) // year
710  goto out;
711  ++i;
712  if (!ReadField(field)) // part number
713  goto out;
714  ++i;
715  if (!ReadField(field)) // part total
716  goto out;
717  return program;
718 out:
719  DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str());
720  program.reset();
721  return program;
722 }
723 
724 ProgramPtr ProtoBase::RcvProgramInfo79()
725 {
726  int64_t tmpi;
727  std::string field;
728  ProgramPtr program(new Program());
729  int i = 0;
730 
731  ++i;
732  if (!ReadField(program->title))
733  goto out;
734  ++i;
735  if (!ReadField(program->subTitle))
736  goto out;
737  ++i;
738  if (!ReadField(program->description))
739  goto out;
740  ++i;
741  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->season)))
742  goto out;
743  ++i;
744  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->episode)))
745  goto out;
746  ++i;
747  if (!ReadField(field)) // total episodes
748  goto out;
749  ++i;
750  if (!ReadField(field)) // syndicated episode
751  goto out;
752  ++i;
753  if (!ReadField(program->category))
754  goto out;
755  ++i;
756  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.chanId)))
757  goto out;
758  ++i;
759  if (!ReadField(program->channel.chanNum))
760  goto out;
761  ++i;
762  if (!ReadField(program->channel.callSign))
763  goto out;
764  ++i;
765  if (!ReadField(program->channel.channelName))
766  goto out;
767  ++i;
768  if (!ReadField(program->fileName))
769  goto out;
770  ++i;
771  if (!ReadField(field) || string_to_int64(field.c_str(), &(program->fileSize)))
772  goto out;
773  ++i;
774  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
775  goto out;
776  program->startTime = (time_t)tmpi;
777  ++i;
778  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
779  goto out;
780  program->endTime = (time_t)tmpi;
781  ++i;
782  if (!ReadField(field)) // findid
783  goto out;
784  ++i;
785  if (!ReadField(program->hostName))
786  goto out;
787  ++i;
788  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.sourceId)))
789  goto out;
790  ++i;
791  if (!ReadField(field)) // cardid
792  goto out;
793  ++i;
794  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.inputId)))
795  goto out;
796  ++i;
797  if (!ReadField(field) || string_to_int32(field.c_str(), &(program->recording.priority)))
798  goto out;
799  ++i;
800  if (!ReadField(field) || string_to_int8(field.c_str(), &(program->recording.status)))
801  goto out;
802  ++i;
803  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->recording.recordId)))
804  goto out;
805  ++i;
806  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.recType)))
807  goto out;
808  ++i;
809  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupInType)))
810  goto out;
811  ++i;
812  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupMethod)))
813  goto out;
814  ++i;
815  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
816  goto out;
817  program->recording.startTs = (time_t)tmpi;
818  ++i;
819  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
820  goto out;
821  program->recording.endTs = (time_t)tmpi;
822  ++i;
823  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->programFlags)))
824  goto out;
825  ++i;
826  if (!ReadField(program->recording.recGroup))
827  goto out;
828  ++i;
829  if (!ReadField(program->channel.chanFilters))
830  goto out;
831  ++i;
832  if (!ReadField(program->seriesId))
833  goto out;
834  ++i;
835  if (!ReadField(program->programId))
836  goto out;
837  ++i;
838  if (!ReadField(program->inetref))
839  goto out;
840  ++i;
841  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
842  goto out;
843  program->lastModified = (time_t)tmpi;
844  ++i;
845  if (!ReadField(program->stars))
846  goto out;
847  ++i;
848  if (!ReadField(field) || string_to_time(field.c_str(), &(program->airdate)))
849  goto out;
850  ++i;
851  if (!ReadField(program->recording.playGroup))
852  goto out;
853  ++i;
854  if (!ReadField(field)) // recpriority2
855  goto out;
856  ++i;
857  if (!ReadField(field)) // parentid
858  goto out;
859  ++i;
860  if (!ReadField(program->recording.storageGroup))
861  goto out;
862  ++i;
863  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->audioProps)))
864  goto out;
865  ++i;
866  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->videoProps)))
867  goto out;
868  ++i;
869  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->subProps)))
870  goto out;
871  ++i;
872  if (!ReadField(field)) // year
873  goto out;
874  ++i;
875  if (!ReadField(field)) // part number
876  goto out;
877  ++i;
878  if (!ReadField(field)) // part total
879  goto out;
880  ++i;
881  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
882  goto out;
883  program->catType = CategoryTypeToString(m_protoVersion, CategoryTypeFromNum(m_protoVersion, (int)tmpi));
884  return program;
885 out:
886  DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str());
887  program.reset();
888  return program;
889 }
890 
891 ProgramPtr ProtoBase::RcvProgramInfo82()
892 {
893  int64_t tmpi;
894  std::string field;
895  ProgramPtr program(new Program());
896  int i = 0;
897 
898  ++i;
899  if (!ReadField(program->title))
900  goto out;
901  ++i;
902  if (!ReadField(program->subTitle))
903  goto out;
904  ++i;
905  if (!ReadField(program->description))
906  goto out;
907  ++i;
908  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->season)))
909  goto out;
910  ++i;
911  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->episode)))
912  goto out;
913  ++i;
914  if (!ReadField(field)) // total episodes
915  goto out;
916  ++i;
917  if (!ReadField(field)) // syndicated episode
918  goto out;
919  ++i;
920  if (!ReadField(program->category))
921  goto out;
922  ++i;
923  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.chanId)))
924  goto out;
925  ++i;
926  if (!ReadField(program->channel.chanNum))
927  goto out;
928  ++i;
929  if (!ReadField(program->channel.callSign))
930  goto out;
931  ++i;
932  if (!ReadField(program->channel.channelName))
933  goto out;
934  ++i;
935  if (!ReadField(program->fileName))
936  goto out;
937  ++i;
938  if (!ReadField(field) || string_to_int64(field.c_str(), &(program->fileSize)))
939  goto out;
940  ++i;
941  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
942  goto out;
943  program->startTime = (time_t)tmpi;
944  ++i;
945  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
946  goto out;
947  program->endTime = (time_t)tmpi;
948  ++i;
949  if (!ReadField(field)) // findid
950  goto out;
951  ++i;
952  if (!ReadField(program->hostName))
953  goto out;
954  ++i;
955  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.sourceId)))
956  goto out;
957  ++i;
958  if (!ReadField(field)) // cardid
959  goto out;
960  ++i;
961  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.inputId)))
962  goto out;
963  ++i;
964  if (!ReadField(field) || string_to_int32(field.c_str(), &(program->recording.priority)))
965  goto out;
966  ++i;
967  if (!ReadField(field) || string_to_int8(field.c_str(), &(program->recording.status)))
968  goto out;
969  ++i;
970  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->recording.recordId)))
971  goto out;
972  ++i;
973  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.recType)))
974  goto out;
975  ++i;
976  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupInType)))
977  goto out;
978  ++i;
979  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupMethod)))
980  goto out;
981  ++i;
982  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
983  goto out;
984  program->recording.startTs = (time_t)tmpi;
985  ++i;
986  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
987  goto out;
988  program->recording.endTs = (time_t)tmpi;
989  ++i;
990  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->programFlags)))
991  goto out;
992  ++i;
993  if (!ReadField(program->recording.recGroup))
994  goto out;
995  ++i;
996  if (!ReadField(program->channel.chanFilters))
997  goto out;
998  ++i;
999  if (!ReadField(program->seriesId))
1000  goto out;
1001  ++i;
1002  if (!ReadField(program->programId))
1003  goto out;
1004  ++i;
1005  if (!ReadField(program->inetref))
1006  goto out;
1007  ++i;
1008  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
1009  goto out;
1010  program->lastModified = (time_t)tmpi;
1011  ++i;
1012  if (!ReadField(program->stars))
1013  goto out;
1014  ++i;
1015  if (!ReadField(field) || string_to_time(field.c_str(), &(program->airdate)))
1016  goto out;
1017  ++i;
1018  if (!ReadField(program->recording.playGroup))
1019  goto out;
1020  ++i;
1021  if (!ReadField(field)) // recpriority2
1022  goto out;
1023  ++i;
1024  if (!ReadField(field)) // parentid
1025  goto out;
1026  ++i;
1027  if (!ReadField(program->recording.storageGroup))
1028  goto out;
1029  ++i;
1030  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->audioProps)))
1031  goto out;
1032  ++i;
1033  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->videoProps)))
1034  goto out;
1035  ++i;
1036  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->subProps)))
1037  goto out;
1038  ++i;
1039  if (!ReadField(field)) // year
1040  goto out;
1041  ++i;
1042  if (!ReadField(field)) // part number
1043  goto out;
1044  ++i;
1045  if (!ReadField(field)) // part total
1046  goto out;
1047  ++i;
1048  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
1049  goto out;
1050  program->catType = CategoryTypeToString(m_protoVersion, CategoryTypeFromNum(m_protoVersion, (int)tmpi));
1051  ++i;
1052  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->recording.recordedId)))
1053  goto out;
1054  return program;
1055 out:
1056  DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str());
1057  program.reset();
1058  return program;
1059 }
1060 
1061 ProgramPtr ProtoBase::RcvProgramInfo86()
1062 {
1063  int64_t tmpi;
1064  std::string field;
1065  ProgramPtr program(new Program());
1066  int i = 0;
1067 
1068  ++i;
1069  if (!ReadField(program->title))
1070  goto out;
1071  ++i;
1072  if (!ReadField(program->subTitle))
1073  goto out;
1074  ++i;
1075  if (!ReadField(program->description))
1076  goto out;
1077  ++i;
1078  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->season)))
1079  goto out;
1080  ++i;
1081  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->episode)))
1082  goto out;
1083  ++i;
1084  if (!ReadField(field)) // total episodes
1085  goto out;
1086  ++i;
1087  if (!ReadField(field)) // syndicated episode
1088  goto out;
1089  ++i;
1090  if (!ReadField(program->category))
1091  goto out;
1092  ++i;
1093  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.chanId)))
1094  goto out;
1095  ++i;
1096  if (!ReadField(program->channel.chanNum))
1097  goto out;
1098  ++i;
1099  if (!ReadField(program->channel.callSign))
1100  goto out;
1101  ++i;
1102  if (!ReadField(program->channel.channelName))
1103  goto out;
1104  ++i;
1105  if (!ReadField(program->fileName))
1106  goto out;
1107  ++i;
1108  if (!ReadField(field) || string_to_int64(field.c_str(), &(program->fileSize)))
1109  goto out;
1110  ++i;
1111  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
1112  goto out;
1113  program->startTime = (time_t)tmpi;
1114  ++i;
1115  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
1116  goto out;
1117  program->endTime = (time_t)tmpi;
1118  ++i;
1119  if (!ReadField(field)) // findid
1120  goto out;
1121  ++i;
1122  if (!ReadField(program->hostName))
1123  goto out;
1124  ++i;
1125  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.sourceId)))
1126  goto out;
1127  ++i;
1128  if (!ReadField(field)) // cardid
1129  goto out;
1130  ++i;
1131  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.inputId)))
1132  goto out;
1133  ++i;
1134  if (!ReadField(field) || string_to_int32(field.c_str(), &(program->recording.priority)))
1135  goto out;
1136  ++i;
1137  if (!ReadField(field) || string_to_int8(field.c_str(), &(program->recording.status)))
1138  goto out;
1139  ++i;
1140  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->recording.recordId)))
1141  goto out;
1142  ++i;
1143  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.recType)))
1144  goto out;
1145  ++i;
1146  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupInType)))
1147  goto out;
1148  ++i;
1149  if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupMethod)))
1150  goto out;
1151  ++i;
1152  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
1153  goto out;
1154  program->recording.startTs = (time_t)tmpi;
1155  ++i;
1156  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
1157  goto out;
1158  program->recording.endTs = (time_t)tmpi;
1159  ++i;
1160  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->programFlags)))
1161  goto out;
1162  ++i;
1163  if (!ReadField(program->recording.recGroup))
1164  goto out;
1165  ++i;
1166  if (!ReadField(program->channel.chanFilters))
1167  goto out;
1168  ++i;
1169  if (!ReadField(program->seriesId))
1170  goto out;
1171  ++i;
1172  if (!ReadField(program->programId))
1173  goto out;
1174  ++i;
1175  if (!ReadField(program->inetref))
1176  goto out;
1177  ++i;
1178  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
1179  goto out;
1180  program->lastModified = (time_t)tmpi;
1181  ++i;
1182  if (!ReadField(program->stars))
1183  goto out;
1184  ++i;
1185  if (!ReadField(field) || string_to_time(field.c_str(), &(program->airdate)))
1186  goto out;
1187  ++i;
1188  if (!ReadField(program->recording.playGroup))
1189  goto out;
1190  ++i;
1191  if (!ReadField(field)) // recpriority2
1192  goto out;
1193  ++i;
1194  if (!ReadField(field)) // parentid
1195  goto out;
1196  ++i;
1197  if (!ReadField(program->recording.storageGroup))
1198  goto out;
1199  ++i;
1200  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->audioProps)))
1201  goto out;
1202  ++i;
1203  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->videoProps)))
1204  goto out;
1205  ++i;
1206  if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->subProps)))
1207  goto out;
1208  ++i;
1209  if (!ReadField(field)) // year
1210  goto out;
1211  ++i;
1212  if (!ReadField(field)) // part number
1213  goto out;
1214  ++i;
1215  if (!ReadField(field)) // part total
1216  goto out;
1217  ++i;
1218  if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi))
1219  goto out;
1220  program->catType = CategoryTypeToString(m_protoVersion, CategoryTypeFromNum(m_protoVersion, (int)tmpi));
1221  ++i;
1222  if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->recording.recordedId)))
1223  goto out;
1224  ++i;
1225  if (!ReadField(field)) // inputname
1226  goto out;
1227  ++i;
1228  if (!ReadField(field)) // bookmarkupdate
1229  goto out;
1230  return program;
1231 out:
1232  DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str());
1233  program.reset();
1234  return program;
1235 }
1236 
1237 void ProtoBase::MakeProgramInfo75(const Program& program, std::string& msg)
1238 {
1239  char buf[32];
1240  msg.clear();
1241 
1242  msg.append(program.title).append(PROTO_STR_SEPARATOR);
1243  msg.append(program.subTitle).append(PROTO_STR_SEPARATOR);
1244  msg.append(program.description).append(PROTO_STR_SEPARATOR);
1245  uint16_to_string(program.season, buf);
1246  msg.append(buf).append(PROTO_STR_SEPARATOR);
1247  uint16_to_string(program.episode, buf);
1248  msg.append(buf).append(PROTO_STR_SEPARATOR);
1249  msg.append(program.category).append(PROTO_STR_SEPARATOR);
1250  uint32_to_string(program.channel.chanId, buf);
1251  msg.append(buf).append(PROTO_STR_SEPARATOR);
1252  msg.append(program.channel.chanNum).append(PROTO_STR_SEPARATOR);
1253  msg.append(program.channel.callSign).append(PROTO_STR_SEPARATOR);
1254  msg.append(program.channel.channelName).append(PROTO_STR_SEPARATOR);
1255  msg.append(program.fileName).append(PROTO_STR_SEPARATOR);
1256  int64_to_string(program.fileSize, buf);
1257  msg.append(buf).append(PROTO_STR_SEPARATOR);
1258  int64_to_string((int64_t)program.startTime, buf);
1259  msg.append(buf).append(PROTO_STR_SEPARATOR);
1260  int64_to_string((int64_t)program.endTime, buf);
1261  msg.append(buf).append(PROTO_STR_SEPARATOR);
1262  msg.append("0").append(PROTO_STR_SEPARATOR); // findid
1263  msg.append(program.hostName).append(PROTO_STR_SEPARATOR);
1264  uint32_to_string(program.channel.sourceId, buf);
1265  msg.append(buf).append(PROTO_STR_SEPARATOR);
1266  msg.append("0").append(PROTO_STR_SEPARATOR); // cardid
1267  uint32_to_string(program.channel.inputId, buf);
1268  msg.append(buf).append(PROTO_STR_SEPARATOR);
1269  int32_to_string(program.recording.priority, buf);
1270  msg.append(buf).append(PROTO_STR_SEPARATOR);
1271  int8_to_string(program.recording.status, buf);
1272  msg.append(buf).append(PROTO_STR_SEPARATOR);
1273  uint32_to_string(program.recording.recordId, buf);
1274  msg.append(buf).append(PROTO_STR_SEPARATOR);
1275  uint8_to_string(program.recording.recType, buf);
1276  msg.append(buf).append(PROTO_STR_SEPARATOR);
1277  uint8_to_string(program.recording.dupInType, buf);
1278  msg.append(buf).append(PROTO_STR_SEPARATOR);
1279  uint8_to_string(program.recording.dupMethod, buf);
1280  msg.append(buf).append(PROTO_STR_SEPARATOR);
1281  int64_to_string((int64_t)program.recording.startTs, buf);
1282  msg.append(buf).append(PROTO_STR_SEPARATOR);
1283  int64_to_string((int64_t)program.recording.endTs, buf);
1284  msg.append(buf).append(PROTO_STR_SEPARATOR);
1285  uint32_to_string(program.programFlags, buf);
1286  msg.append(buf).append(PROTO_STR_SEPARATOR);
1287  msg.append(program.recording.recGroup).append(PROTO_STR_SEPARATOR);
1288  msg.append(program.channel.chanFilters).append(PROTO_STR_SEPARATOR);
1289  msg.append(program.seriesId).append(PROTO_STR_SEPARATOR);
1290  msg.append(program.programId).append(PROTO_STR_SEPARATOR);
1291  msg.append(program.inetref).append(PROTO_STR_SEPARATOR);
1292  int64_to_string((int64_t)program.lastModified, buf);
1293  msg.append(buf).append(PROTO_STR_SEPARATOR);
1294  msg.append(program.stars).append(PROTO_STR_SEPARATOR);
1295  time_to_isodate(program.airdate, buf);
1296  msg.append(buf).append(PROTO_STR_SEPARATOR);
1297  msg.append(program.recording.playGroup).append(PROTO_STR_SEPARATOR);
1298  msg.append("0").append(PROTO_STR_SEPARATOR); // recpriority2
1299  msg.append("0").append(PROTO_STR_SEPARATOR); // parentid
1300  msg.append(program.recording.storageGroup).append(PROTO_STR_SEPARATOR);
1301  uint16_to_string(program.audioProps, buf);
1302  msg.append(buf).append(PROTO_STR_SEPARATOR);
1303  uint16_to_string(program.videoProps, buf);
1304  msg.append(buf).append(PROTO_STR_SEPARATOR);
1305  uint16_to_string(program.subProps, buf);
1306  msg.append(buf).append(PROTO_STR_SEPARATOR);
1307  msg.append("0"); // year
1308 }
1309 
1310 void ProtoBase::MakeProgramInfo76(const Program& program, std::string& msg)
1311 {
1312  char buf[32];
1313  msg.clear();
1314 
1315  msg.append(program.title).append(PROTO_STR_SEPARATOR);
1316  msg.append(program.subTitle).append(PROTO_STR_SEPARATOR);
1317  msg.append(program.description).append(PROTO_STR_SEPARATOR);
1318  uint16_to_string(program.season, buf);
1319  msg.append(buf).append(PROTO_STR_SEPARATOR);
1320  uint16_to_string(program.episode, buf);
1321  msg.append(buf).append(PROTO_STR_SEPARATOR);
1322  msg.append(PROTO_STR_SEPARATOR); // syndicated episode
1323  msg.append(program.category).append(PROTO_STR_SEPARATOR);
1324  uint32_to_string(program.channel.chanId, buf);
1325  msg.append(buf).append(PROTO_STR_SEPARATOR);
1326  msg.append(program.channel.chanNum).append(PROTO_STR_SEPARATOR);
1327  msg.append(program.channel.callSign).append(PROTO_STR_SEPARATOR);
1328  msg.append(program.channel.channelName).append(PROTO_STR_SEPARATOR);
1329  msg.append(program.fileName).append(PROTO_STR_SEPARATOR);
1330  int64_to_string(program.fileSize, buf);
1331  msg.append(buf).append(PROTO_STR_SEPARATOR);
1332  int64_to_string((int64_t)program.startTime, buf);
1333  msg.append(buf).append(PROTO_STR_SEPARATOR);
1334  int64_to_string((int64_t)program.endTime, buf);
1335  msg.append(buf).append(PROTO_STR_SEPARATOR);
1336  msg.append("0").append(PROTO_STR_SEPARATOR); // findid
1337  msg.append(program.hostName).append(PROTO_STR_SEPARATOR);
1338  uint32_to_string(program.channel.sourceId, buf);
1339  msg.append(buf).append(PROTO_STR_SEPARATOR);
1340  msg.append("0").append(PROTO_STR_SEPARATOR); // cardid
1341  uint32_to_string(program.channel.inputId, buf);
1342  msg.append(buf).append(PROTO_STR_SEPARATOR);
1343  int32_to_string(program.recording.priority, buf);
1344  msg.append(buf).append(PROTO_STR_SEPARATOR);
1345  int8_to_string(program.recording.status, buf);
1346  msg.append(buf).append(PROTO_STR_SEPARATOR);
1347  uint32_to_string(program.recording.recordId, buf);
1348  msg.append(buf).append(PROTO_STR_SEPARATOR);
1349  uint8_to_string(program.recording.recType, buf);
1350  msg.append(buf).append(PROTO_STR_SEPARATOR);
1351  uint8_to_string(program.recording.dupInType, buf);
1352  msg.append(buf).append(PROTO_STR_SEPARATOR);
1353  uint8_to_string(program.recording.dupMethod, buf);
1354  msg.append(buf).append(PROTO_STR_SEPARATOR);
1355  int64_to_string((int64_t)program.recording.startTs, buf);
1356  msg.append(buf).append(PROTO_STR_SEPARATOR);
1357  int64_to_string((int64_t)program.recording.endTs, buf);
1358  msg.append(buf).append(PROTO_STR_SEPARATOR);
1359  uint32_to_string(program.programFlags, buf);
1360  msg.append(buf).append(PROTO_STR_SEPARATOR);
1361  msg.append(program.recording.recGroup).append(PROTO_STR_SEPARATOR);
1362  msg.append(program.channel.chanFilters).append(PROTO_STR_SEPARATOR);
1363  msg.append(program.seriesId).append(PROTO_STR_SEPARATOR);
1364  msg.append(program.programId).append(PROTO_STR_SEPARATOR);
1365  msg.append(program.inetref).append(PROTO_STR_SEPARATOR);
1366  int64_to_string((int64_t)program.lastModified, buf);
1367  msg.append(buf).append(PROTO_STR_SEPARATOR);
1368  msg.append(program.stars).append(PROTO_STR_SEPARATOR);
1369  time_to_isodate(program.airdate, buf);
1370  msg.append(buf).append(PROTO_STR_SEPARATOR);
1371  msg.append(program.recording.playGroup).append(PROTO_STR_SEPARATOR);
1372  msg.append("0").append(PROTO_STR_SEPARATOR); // recpriority2
1373  msg.append("0").append(PROTO_STR_SEPARATOR); // parentid
1374  msg.append(program.recording.storageGroup).append(PROTO_STR_SEPARATOR);
1375  uint16_to_string(program.audioProps, buf);
1376  msg.append(buf).append(PROTO_STR_SEPARATOR);
1377  uint16_to_string(program.videoProps, buf);
1378  msg.append(buf).append(PROTO_STR_SEPARATOR);
1379  uint16_to_string(program.subProps, buf);
1380  msg.append(buf).append(PROTO_STR_SEPARATOR);
1381  msg.append("0").append(PROTO_STR_SEPARATOR); // year
1382  msg.append("0").append(PROTO_STR_SEPARATOR); // part number
1383  msg.append("0"); // part total
1384 }
1385 
1386 void ProtoBase::MakeProgramInfo79(const Program& program, std::string& msg)
1387 {
1388  char buf[32];
1389  msg.clear();
1390 
1391  msg.append(program.title).append(PROTO_STR_SEPARATOR);
1392  msg.append(program.subTitle).append(PROTO_STR_SEPARATOR);
1393  msg.append(program.description).append(PROTO_STR_SEPARATOR);
1394  uint16_to_string(program.season, buf);
1395  msg.append(buf).append(PROTO_STR_SEPARATOR);
1396  uint16_to_string(program.episode, buf);
1397  msg.append(buf).append(PROTO_STR_SEPARATOR);
1398  msg.append("0").append(PROTO_STR_SEPARATOR); // total episodes
1399  msg.append(PROTO_STR_SEPARATOR); // syndicated episode
1400  msg.append(program.category).append(PROTO_STR_SEPARATOR);
1401  uint32_to_string(program.channel.chanId, buf);
1402  msg.append(buf).append(PROTO_STR_SEPARATOR);
1403  msg.append(program.channel.chanNum).append(PROTO_STR_SEPARATOR);
1404  msg.append(program.channel.callSign).append(PROTO_STR_SEPARATOR);
1405  msg.append(program.channel.channelName).append(PROTO_STR_SEPARATOR);
1406  msg.append(program.fileName).append(PROTO_STR_SEPARATOR);
1407  int64_to_string(program.fileSize, buf);
1408  msg.append(buf).append(PROTO_STR_SEPARATOR);
1409  int64_to_string((int64_t)program.startTime, buf);
1410  msg.append(buf).append(PROTO_STR_SEPARATOR);
1411  int64_to_string((int64_t)program.endTime, buf);
1412  msg.append(buf).append(PROTO_STR_SEPARATOR);
1413  msg.append("0").append(PROTO_STR_SEPARATOR); // findid
1414  msg.append(program.hostName).append(PROTO_STR_SEPARATOR);
1415  uint32_to_string(program.channel.sourceId, buf);
1416  msg.append(buf).append(PROTO_STR_SEPARATOR);
1417  msg.append("0").append(PROTO_STR_SEPARATOR); // cardid
1418  uint32_to_string(program.channel.inputId, buf);
1419  msg.append(buf).append(PROTO_STR_SEPARATOR);
1420  int32_to_string(program.recording.priority, buf);
1421  msg.append(buf).append(PROTO_STR_SEPARATOR);
1422  int8_to_string(program.recording.status, buf);
1423  msg.append(buf).append(PROTO_STR_SEPARATOR);
1424  uint32_to_string(program.recording.recordId, buf);
1425  msg.append(buf).append(PROTO_STR_SEPARATOR);
1426  uint8_to_string(program.recording.recType, buf);
1427  msg.append(buf).append(PROTO_STR_SEPARATOR);
1428  uint8_to_string(program.recording.dupInType, buf);
1429  msg.append(buf).append(PROTO_STR_SEPARATOR);
1430  uint8_to_string(program.recording.dupMethod, buf);
1431  msg.append(buf).append(PROTO_STR_SEPARATOR);
1432  int64_to_string((int64_t)program.recording.startTs, buf);
1433  msg.append(buf).append(PROTO_STR_SEPARATOR);
1434  int64_to_string((int64_t)program.recording.endTs, buf);
1435  msg.append(buf).append(PROTO_STR_SEPARATOR);
1436  uint32_to_string(program.programFlags, buf);
1437  msg.append(buf).append(PROTO_STR_SEPARATOR);
1438  msg.append(program.recording.recGroup).append(PROTO_STR_SEPARATOR);
1439  msg.append(program.channel.chanFilters).append(PROTO_STR_SEPARATOR);
1440  msg.append(program.seriesId).append(PROTO_STR_SEPARATOR);
1441  msg.append(program.programId).append(PROTO_STR_SEPARATOR);
1442  msg.append(program.inetref).append(PROTO_STR_SEPARATOR);
1443  int64_to_string((int64_t)program.lastModified, buf);
1444  msg.append(buf).append(PROTO_STR_SEPARATOR);
1445  msg.append(program.stars).append(PROTO_STR_SEPARATOR);
1446  time_to_isodate(program.airdate, buf);
1447  msg.append(buf).append(PROTO_STR_SEPARATOR);
1448  msg.append(program.recording.playGroup).append(PROTO_STR_SEPARATOR);
1449  msg.append("0").append(PROTO_STR_SEPARATOR); // recpriority2
1450  msg.append("0").append(PROTO_STR_SEPARATOR); // parentid
1451  msg.append(program.recording.storageGroup).append(PROTO_STR_SEPARATOR);
1452  uint16_to_string(program.audioProps, buf);
1453  msg.append(buf).append(PROTO_STR_SEPARATOR);
1454  uint16_to_string(program.videoProps, buf);
1455  msg.append(buf).append(PROTO_STR_SEPARATOR);
1456  uint16_to_string(program.subProps, buf);
1457  msg.append(buf).append(PROTO_STR_SEPARATOR);
1458  msg.append("0").append(PROTO_STR_SEPARATOR); // year
1459  msg.append("0").append(PROTO_STR_SEPARATOR); // part number
1460  msg.append("0").append(PROTO_STR_SEPARATOR); // part total
1461  uint8_to_string((uint8_t)CategoryTypeToNum(m_protoVersion, CategoryTypeFromString(m_protoVersion, program.catType)), buf);
1462  msg.append(buf);
1463 }
1464 
1465 void ProtoBase::MakeProgramInfo82(const Program& program, std::string& msg)
1466 {
1467  char buf[32];
1468  msg.clear();
1469 
1470  msg.append(program.title).append(PROTO_STR_SEPARATOR);
1471  msg.append(program.subTitle).append(PROTO_STR_SEPARATOR);
1472  msg.append(program.description).append(PROTO_STR_SEPARATOR);
1473  uint16_to_string(program.season, buf);
1474  msg.append(buf).append(PROTO_STR_SEPARATOR);
1475  uint16_to_string(program.episode, buf);
1476  msg.append(buf).append(PROTO_STR_SEPARATOR);
1477  msg.append("0").append(PROTO_STR_SEPARATOR); // total episodes
1478  msg.append(PROTO_STR_SEPARATOR); // syndicated episode
1479  msg.append(program.category).append(PROTO_STR_SEPARATOR);
1480  uint32_to_string(program.channel.chanId, buf);
1481  msg.append(buf).append(PROTO_STR_SEPARATOR);
1482  msg.append(program.channel.chanNum).append(PROTO_STR_SEPARATOR);
1483  msg.append(program.channel.callSign).append(PROTO_STR_SEPARATOR);
1484  msg.append(program.channel.channelName).append(PROTO_STR_SEPARATOR);
1485  msg.append(program.fileName).append(PROTO_STR_SEPARATOR);
1486  int64_to_string(program.fileSize, buf);
1487  msg.append(buf).append(PROTO_STR_SEPARATOR);
1488  int64_to_string((int64_t)program.startTime, buf);
1489  msg.append(buf).append(PROTO_STR_SEPARATOR);
1490  int64_to_string((int64_t)program.endTime, buf);
1491  msg.append(buf).append(PROTO_STR_SEPARATOR);
1492  msg.append("0").append(PROTO_STR_SEPARATOR); // findid
1493  msg.append(program.hostName).append(PROTO_STR_SEPARATOR);
1494  uint32_to_string(program.channel.sourceId, buf);
1495  msg.append(buf).append(PROTO_STR_SEPARATOR);
1496  msg.append("0").append(PROTO_STR_SEPARATOR); // cardid
1497  uint32_to_string(program.channel.inputId, buf);
1498  msg.append(buf).append(PROTO_STR_SEPARATOR);
1499  int32_to_string(program.recording.priority, buf);
1500  msg.append(buf).append(PROTO_STR_SEPARATOR);
1501  int8_to_string(program.recording.status, buf);
1502  msg.append(buf).append(PROTO_STR_SEPARATOR);
1503  uint32_to_string(program.recording.recordId, buf);
1504  msg.append(buf).append(PROTO_STR_SEPARATOR);
1505  uint8_to_string(program.recording.recType, buf);
1506  msg.append(buf).append(PROTO_STR_SEPARATOR);
1507  uint8_to_string(program.recording.dupInType, buf);
1508  msg.append(buf).append(PROTO_STR_SEPARATOR);
1509  uint8_to_string(program.recording.dupMethod, buf);
1510  msg.append(buf).append(PROTO_STR_SEPARATOR);
1511  int64_to_string((int64_t)program.recording.startTs, buf);
1512  msg.append(buf).append(PROTO_STR_SEPARATOR);
1513  int64_to_string((int64_t)program.recording.endTs, buf);
1514  msg.append(buf).append(PROTO_STR_SEPARATOR);
1515  uint32_to_string(program.programFlags, buf);
1516  msg.append(buf).append(PROTO_STR_SEPARATOR);
1517  msg.append(program.recording.recGroup).append(PROTO_STR_SEPARATOR);
1518  msg.append(program.channel.chanFilters).append(PROTO_STR_SEPARATOR);
1519  msg.append(program.seriesId).append(PROTO_STR_SEPARATOR);
1520  msg.append(program.programId).append(PROTO_STR_SEPARATOR);
1521  msg.append(program.inetref).append(PROTO_STR_SEPARATOR);
1522  int64_to_string((int64_t)program.lastModified, buf);
1523  msg.append(buf).append(PROTO_STR_SEPARATOR);
1524  msg.append(program.stars).append(PROTO_STR_SEPARATOR);
1525  time_to_isodate(program.airdate, buf);
1526  msg.append(buf).append(PROTO_STR_SEPARATOR);
1527  msg.append(program.recording.playGroup).append(PROTO_STR_SEPARATOR);
1528  msg.append("0").append(PROTO_STR_SEPARATOR); // recpriority2
1529  msg.append("0").append(PROTO_STR_SEPARATOR); // parentid
1530  msg.append(program.recording.storageGroup).append(PROTO_STR_SEPARATOR);
1531  uint16_to_string(program.audioProps, buf);
1532  msg.append(buf).append(PROTO_STR_SEPARATOR);
1533  uint16_to_string(program.videoProps, buf);
1534  msg.append(buf).append(PROTO_STR_SEPARATOR);
1535  uint16_to_string(program.subProps, buf);
1536  msg.append(buf).append(PROTO_STR_SEPARATOR);
1537  msg.append("0").append(PROTO_STR_SEPARATOR); // year
1538  msg.append("0").append(PROTO_STR_SEPARATOR); // part number
1539  msg.append("0").append(PROTO_STR_SEPARATOR); // part total
1540  uint8_to_string((uint8_t)CategoryTypeToNum(m_protoVersion, CategoryTypeFromString(m_protoVersion, program.catType)), buf);
1541  msg.append(buf).append(PROTO_STR_SEPARATOR);
1542  uint32_to_string(program.recording.recordedId, buf);
1543  msg.append(buf);
1544 }
1545 
1546 void ProtoBase::MakeProgramInfo86(const Program& program, std::string& msg)
1547 {
1548  char buf[32];
1549  msg.clear();
1550 
1551  msg.append(program.title).append(PROTO_STR_SEPARATOR);
1552  msg.append(program.subTitle).append(PROTO_STR_SEPARATOR);
1553  msg.append(program.description).append(PROTO_STR_SEPARATOR);
1554  uint16_to_string(program.season, buf);
1555  msg.append(buf).append(PROTO_STR_SEPARATOR);
1556  uint16_to_string(program.episode, buf);
1557  msg.append(buf).append(PROTO_STR_SEPARATOR);
1558  msg.append("0").append(PROTO_STR_SEPARATOR); // total episodes
1559  msg.append(PROTO_STR_SEPARATOR); // syndicated episode
1560  msg.append(program.category).append(PROTO_STR_SEPARATOR);
1561  uint32_to_string(program.channel.chanId, buf);
1562  msg.append(buf).append(PROTO_STR_SEPARATOR);
1563  msg.append(program.channel.chanNum).append(PROTO_STR_SEPARATOR);
1564  msg.append(program.channel.callSign).append(PROTO_STR_SEPARATOR);
1565  msg.append(program.channel.channelName).append(PROTO_STR_SEPARATOR);
1566  msg.append(program.fileName).append(PROTO_STR_SEPARATOR);
1567  int64_to_string(program.fileSize, buf);
1568  msg.append(buf).append(PROTO_STR_SEPARATOR);
1569  int64_to_string((int64_t)program.startTime, buf);
1570  msg.append(buf).append(PROTO_STR_SEPARATOR);
1571  int64_to_string((int64_t)program.endTime, buf);
1572  msg.append(buf).append(PROTO_STR_SEPARATOR);
1573  msg.append("0").append(PROTO_STR_SEPARATOR); // findid
1574  msg.append(program.hostName).append(PROTO_STR_SEPARATOR);
1575  uint32_to_string(program.channel.sourceId, buf);
1576  msg.append(buf).append(PROTO_STR_SEPARATOR);
1577  msg.append("0").append(PROTO_STR_SEPARATOR); // cardid
1578  uint32_to_string(program.channel.inputId, buf);
1579  msg.append(buf).append(PROTO_STR_SEPARATOR);
1580  int32_to_string(program.recording.priority, buf);
1581  msg.append(buf).append(PROTO_STR_SEPARATOR);
1582  int8_to_string(program.recording.status, buf);
1583  msg.append(buf).append(PROTO_STR_SEPARATOR);
1584  uint32_to_string(program.recording.recordId, buf);
1585  msg.append(buf).append(PROTO_STR_SEPARATOR);
1586  uint8_to_string(program.recording.recType, buf);
1587  msg.append(buf).append(PROTO_STR_SEPARATOR);
1588  uint8_to_string(program.recording.dupInType, buf);
1589  msg.append(buf).append(PROTO_STR_SEPARATOR);
1590  uint8_to_string(program.recording.dupMethod, buf);
1591  msg.append(buf).append(PROTO_STR_SEPARATOR);
1592  int64_to_string((int64_t)program.recording.startTs, buf);
1593  msg.append(buf).append(PROTO_STR_SEPARATOR);
1594  int64_to_string((int64_t)program.recording.endTs, buf);
1595  msg.append(buf).append(PROTO_STR_SEPARATOR);
1596  uint32_to_string(program.programFlags, buf);
1597  msg.append(buf).append(PROTO_STR_SEPARATOR);
1598  msg.append(program.recording.recGroup).append(PROTO_STR_SEPARATOR);
1599  msg.append(program.channel.chanFilters).append(PROTO_STR_SEPARATOR);
1600  msg.append(program.seriesId).append(PROTO_STR_SEPARATOR);
1601  msg.append(program.programId).append(PROTO_STR_SEPARATOR);
1602  msg.append(program.inetref).append(PROTO_STR_SEPARATOR);
1603  int64_to_string((int64_t)program.lastModified, buf);
1604  msg.append(buf).append(PROTO_STR_SEPARATOR);
1605  msg.append(program.stars).append(PROTO_STR_SEPARATOR);
1606  time_to_isodate(program.airdate, buf);
1607  msg.append(buf).append(PROTO_STR_SEPARATOR);
1608  msg.append(program.recording.playGroup).append(PROTO_STR_SEPARATOR);
1609  msg.append("0").append(PROTO_STR_SEPARATOR); // recpriority2
1610  msg.append("0").append(PROTO_STR_SEPARATOR); // parentid
1611  msg.append(program.recording.storageGroup).append(PROTO_STR_SEPARATOR);
1612  uint16_to_string(program.audioProps, buf);
1613  msg.append(buf).append(PROTO_STR_SEPARATOR);
1614  uint16_to_string(program.videoProps, buf);
1615  msg.append(buf).append(PROTO_STR_SEPARATOR);
1616  uint16_to_string(program.subProps, buf);
1617  msg.append(buf).append(PROTO_STR_SEPARATOR);
1618  msg.append("0").append(PROTO_STR_SEPARATOR); // year
1619  msg.append("0").append(PROTO_STR_SEPARATOR); // part number
1620  msg.append("0").append(PROTO_STR_SEPARATOR); // part total
1621  uint8_to_string((uint8_t)CategoryTypeToNum(m_protoVersion, CategoryTypeFromString(m_protoVersion, program.catType)), buf);
1622  msg.append(buf).append(PROTO_STR_SEPARATOR);
1623  uint32_to_string(program.recording.recordedId, buf);
1624  msg.append(buf);
1625  msg.append(PROTO_STR_SEPARATOR); // inputname
1626  msg.append(PROTO_STR_SEPARATOR); // bookmarkupdate
1627 }
bool RcvVersion(unsigned *version)
bool m_hang
Connection hang: while true allow retry.
Definition: mythprotobase.h:76
bool ReadField(std::string &field)
This is the main namespace that encloses all public classes.
Definition: mythcontrol.h:29
bool m_tainted
Connection has hung since last reset.
Definition: mythprotobase.h:77