CPPMyth
Library to interoperate with MythTV server
Loading...
Searching...
No Matches
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/latch.h"
26#include "../private/cppdef.h"
27#include "../private/builtin.h"
28
29#include <limits>
30#include <cstdio>
31
32using namespace Myth;
33
34typedef struct
35{
36 unsigned version;
37 char token[44]; // up to 43 chars used in v87 + the terminating NULL character
39
40static 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
60ProtoBase::ProtoBase(const std::string& server, unsigned port)
61: m_latch(new OS::Latch)
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
76ProtoBase::~ProtoBase()
77{
78 this->Close();
79 SAFE_DELETE(m_socket);
80 SAFE_DELETE(m_latch);
81}
82
83void 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
91bool 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 snprintf(buf, sizeof(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
123size_t ProtoBase::GetMessageLength() const
124{
125 return m_msgLength;
126}
127
133bool 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
192bool 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
202size_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
222bool 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
252bool 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
276out:
277 DBG(DBG_ERROR, "%s: failed ('%s')\n", __FUNCTION__, field.c_str());
278 FlushMessage();
279 return false;
280}
281
282bool 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::WriteLock lock(*m_latch);
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 snprintf(cmd, sizeof(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
356void ProtoBase::Close()
357{
358 OS::WriteLock lock(*m_latch);
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
377unsigned ProtoBase::GetProtoVersion() const
378{
379 if (m_isOpen)
380 return m_protoVersion;
381 return 0;
382}
383
384std::string ProtoBase::GetServer() const
385{
386 return m_server;
387}
388
389unsigned ProtoBase::GetPort() const
390{
391 return m_port;
392}
393
394int ProtoBase::GetSocketErrNo() const
395{
396 return m_socket->GetErrNo();
397}
398
399int ProtoBase::GetSocket() const
400{
401 return (int)(m_socket->GetHandle());
402}
403
404bool ProtoBase::HasHanging() const
405{
406 return m_tainted;
407}
408
409void ProtoBase::CleanHanging()
410{
411 m_tainted = false;
412}
413
414ProtoBase::ERROR_t ProtoBase::GetProtoError() const
415{
416 return m_protoError;
417}
418
419ProgramPtr 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(field) || string_to_double(field.c_str(), &(program->stars)))
535 goto out;
536 ++i;
537 if (!ReadField(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;
558out:
559 DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str());
560 program.reset();
561 return program;
562}
563
564ProgramPtr 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(field) || string_to_double(field.c_str(), &(program->stars)))
683 goto out;
684 ++i;
685 if (!ReadField(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;
718out:
719 DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str());
720 program.reset();
721 return program;
722}
723
724ProgramPtr 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(field) || string_to_double(field.c_str(), &(program->stars)))
846 goto out;
847 ++i;
848 if (!ReadField(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;
885out:
886 DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str());
887 program.reset();
888 return program;
889}
890
891ProgramPtr 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(field) || string_to_double(field.c_str(), &(program->stars)))
1013 goto out;
1014 ++i;
1015 if (!ReadField(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;
1055out:
1056 DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str());
1057 program.reset();
1058 return program;
1059}
1060
1061ProgramPtr 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(field) || string_to_double(field.c_str(), &(program->stars)))
1183 goto out;
1184 ++i;
1185 if (!ReadField(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;
1231out:
1232 DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str());
1233 program.reset();
1234 return program;
1235}
1236
1237void ProtoBase::MakeProgramInfo75(const Program& program, std::string& msg)
1238{
1239 BUILTIN_BUFFER buf;
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.data).append(PROTO_STR_SEPARATOR);
1247 uint16_to_string(program.episode, &buf);
1248 msg.append(buf.data).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.data).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.data).append(PROTO_STR_SEPARATOR);
1258 int64_to_string((int64_t)program.startTime, &buf);
1259 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1260 int64_to_string((int64_t)program.endTime, &buf);
1261 msg.append(buf.data).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.data).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.data).append(PROTO_STR_SEPARATOR);
1269 int32_to_string(program.recording.priority, &buf);
1270 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1271 int8_to_string(program.recording.status, &buf);
1272 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1273 uint32_to_string(program.recording.recordId, &buf);
1274 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1275 uint8_to_string(program.recording.recType, &buf);
1276 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1277 uint8_to_string(program.recording.dupInType, &buf);
1278 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1279 uint8_to_string(program.recording.dupMethod, &buf);
1280 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1281 int64_to_string((int64_t)program.recording.startTs, &buf);
1282 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1283 int64_to_string((int64_t)program.recording.endTs, &buf);
1284 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1285 uint32_to_string(program.programFlags, &buf);
1286 msg.append(buf.data).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.data).append(PROTO_STR_SEPARATOR);
1294 double_to_string(program.stars, &buf);
1295 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1296 msg.append(program.airdate).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.data).append(PROTO_STR_SEPARATOR);
1303 uint16_to_string(program.videoProps, &buf);
1304 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1305 uint16_to_string(program.subProps, &buf);
1306 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1307 msg.append("0"); // year
1308}
1309
1310void ProtoBase::MakeProgramInfo76(const Program& program, std::string& msg)
1311{
1312 BUILTIN_BUFFER buf;
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.data).append(PROTO_STR_SEPARATOR);
1320 uint16_to_string(program.episode, &buf);
1321 msg.append(buf.data).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.data).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.data).append(PROTO_STR_SEPARATOR);
1332 int64_to_string((int64_t)program.startTime, &buf);
1333 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1334 int64_to_string((int64_t)program.endTime, &buf);
1335 msg.append(buf.data).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.data).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.data).append(PROTO_STR_SEPARATOR);
1343 int32_to_string(program.recording.priority, &buf);
1344 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1345 int8_to_string(program.recording.status, &buf);
1346 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1347 uint32_to_string(program.recording.recordId, &buf);
1348 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1349 uint8_to_string(program.recording.recType, &buf);
1350 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1351 uint8_to_string(program.recording.dupInType, &buf);
1352 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1353 uint8_to_string(program.recording.dupMethod, &buf);
1354 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1355 int64_to_string((int64_t)program.recording.startTs, &buf);
1356 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1357 int64_to_string((int64_t)program.recording.endTs, &buf);
1358 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1359 uint32_to_string(program.programFlags, &buf);
1360 msg.append(buf.data).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.data).append(PROTO_STR_SEPARATOR);
1368 double_to_string(program.stars, &buf);
1369 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1370 msg.append(program.airdate).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.data).append(PROTO_STR_SEPARATOR);
1377 uint16_to_string(program.videoProps, &buf);
1378 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1379 uint16_to_string(program.subProps, &buf);
1380 msg.append(buf.data).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
1386void ProtoBase::MakeProgramInfo79(const Program& program, std::string& msg)
1387{
1388 BUILTIN_BUFFER buf;
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.data).append(PROTO_STR_SEPARATOR);
1396 uint16_to_string(program.episode, &buf);
1397 msg.append(buf.data).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.data).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.data).append(PROTO_STR_SEPARATOR);
1409 int64_to_string((int64_t)program.startTime, &buf);
1410 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1411 int64_to_string((int64_t)program.endTime, &buf);
1412 msg.append(buf.data).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.data).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.data).append(PROTO_STR_SEPARATOR);
1420 int32_to_string(program.recording.priority, &buf);
1421 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1422 int8_to_string(program.recording.status, &buf);
1423 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1424 uint32_to_string(program.recording.recordId, &buf);
1425 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1426 uint8_to_string(program.recording.recType, &buf);
1427 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1428 uint8_to_string(program.recording.dupInType, &buf);
1429 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1430 uint8_to_string(program.recording.dupMethod, &buf);
1431 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1432 int64_to_string((int64_t)program.recording.startTs, &buf);
1433 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1434 int64_to_string((int64_t)program.recording.endTs, &buf);
1435 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1436 uint32_to_string(program.programFlags, &buf);
1437 msg.append(buf.data).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.data).append(PROTO_STR_SEPARATOR);
1445 double_to_string(program.stars, &buf);
1446 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1447 msg.append(program.airdate).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.data).append(PROTO_STR_SEPARATOR);
1454 uint16_to_string(program.videoProps, &buf);
1455 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1456 uint16_to_string(program.subProps, &buf);
1457 msg.append(buf.data).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.data);
1463}
1464
1465void ProtoBase::MakeProgramInfo82(const Program& program, std::string& msg)
1466{
1467 BUILTIN_BUFFER buf;
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.data).append(PROTO_STR_SEPARATOR);
1475 uint16_to_string(program.episode, &buf);
1476 msg.append(buf.data).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.data).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.data).append(PROTO_STR_SEPARATOR);
1488 int64_to_string((int64_t)program.startTime, &buf);
1489 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1490 int64_to_string((int64_t)program.endTime, &buf);
1491 msg.append(buf.data).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.data).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.data).append(PROTO_STR_SEPARATOR);
1499 int32_to_string(program.recording.priority, &buf);
1500 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1501 int8_to_string(program.recording.status, &buf);
1502 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1503 uint32_to_string(program.recording.recordId, &buf);
1504 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1505 uint8_to_string(program.recording.recType, &buf);
1506 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1507 uint8_to_string(program.recording.dupInType, &buf);
1508 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1509 uint8_to_string(program.recording.dupMethod, &buf);
1510 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1511 int64_to_string((int64_t)program.recording.startTs, &buf);
1512 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1513 int64_to_string((int64_t)program.recording.endTs, &buf);
1514 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1515 uint32_to_string(program.programFlags, &buf);
1516 msg.append(buf.data).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.data).append(PROTO_STR_SEPARATOR);
1524 double_to_string(program.stars, &buf);
1525 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1526 msg.append(program.airdate).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.data).append(PROTO_STR_SEPARATOR);
1533 uint16_to_string(program.videoProps, &buf);
1534 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1535 uint16_to_string(program.subProps, &buf);
1536 msg.append(buf.data).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.data).append(PROTO_STR_SEPARATOR);
1542 uint32_to_string(program.recording.recordedId, &buf);
1543 msg.append(buf.data);
1544}
1545
1546void ProtoBase::MakeProgramInfo86(const Program& program, std::string& msg)
1547{
1548 BUILTIN_BUFFER buf;
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.data).append(PROTO_STR_SEPARATOR);
1556 uint16_to_string(program.episode, &buf);
1557 msg.append(buf.data).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.data).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.data).append(PROTO_STR_SEPARATOR);
1569 int64_to_string((int64_t)program.startTime, &buf);
1570 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1571 int64_to_string((int64_t)program.endTime, &buf);
1572 msg.append(buf.data).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.data).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.data).append(PROTO_STR_SEPARATOR);
1580 int32_to_string(program.recording.priority, &buf);
1581 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1582 int8_to_string(program.recording.status, &buf);
1583 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1584 uint32_to_string(program.recording.recordId, &buf);
1585 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1586 uint8_to_string(program.recording.recType, &buf);
1587 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1588 uint8_to_string(program.recording.dupInType, &buf);
1589 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1590 uint8_to_string(program.recording.dupMethod, &buf);
1591 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1592 int64_to_string((int64_t)program.recording.startTs, &buf);
1593 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1594 int64_to_string((int64_t)program.recording.endTs, &buf);
1595 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1596 uint32_to_string(program.programFlags, &buf);
1597 msg.append(buf.data).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.data).append(PROTO_STR_SEPARATOR);
1605 double_to_string(program.stars, &buf);
1606 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1607 msg.append(program.airdate).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.data).append(PROTO_STR_SEPARATOR);
1614 uint16_to_string(program.videoProps, &buf);
1615 msg.append(buf.data).append(PROTO_STR_SEPARATOR);
1616 uint16_to_string(program.subProps, &buf);
1617 msg.append(buf.data).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.data).append(PROTO_STR_SEPARATOR);
1623 uint32_to_string(program.recording.recordedId, &buf);
1624 msg.append(buf.data);
1625 msg.append(PROTO_STR_SEPARATOR); // inputname
1626 msg.append(PROTO_STR_SEPARATOR); // bookmarkupdate
1627}
bool m_tainted
Connection has hung since last reset.
bool RcvVersion(unsigned *version)
bool ReadField(std::string &field)
bool m_hang
Connection hang: while true allow retry.
This is the main namespace that encloses all public classes.
Definition mythcontrol.h:30