Ticket #1772: ajm_multiple_recorders.patch
| File ajm_multiple_recorders.patch, 51.6 KB (added by , 20 years ago) |
|---|
-
libs/libmythtv/tv_rec.h
old new 169 169 void RecordPending(const ProgramInfo *rcinfo, int secsleft); 170 170 RecStatusType StartRecording(const ProgramInfo *rcinfo); 171 171 172 void StopRecording( void);172 void StopRecording(ProgramInfo *rec); 173 173 /// \brief Tells TVRec to finish the current recording as soon as possible. 174 174 void FinishRecording(void) { SetFlags(kFlagFinishRecording); } 175 175 /// \brief Tells TVRec that the frontend's TV class is ready for messages. 176 176 void FrontendReady(void) { SetFlags(kFlagFrontendReady); } 177 177 void CancelNextRecording(bool cancel); 178 Program Info *GetRecording(void);178 ProgramList GetRecordings(void); 179 179 180 180 /// \brief Returns true if event loop has not been told to shut down 181 181 bool IsRunning(void) const { return HasFlags(kFlagRunMainLoop); } … … 346 346 347 347 void SetOption(RecordingProfile &profile, const QString &name); 348 348 349 void DoneAddingRecording(); 350 349 351 // Various components TVRec coordinates 350 352 RecorderMuxBase *recorderMux; 351 RecorderBase *recorder;353 QMap<ProgramInfo *, RecorderBase *> recorders; 352 354 ChannelBase *channel; 353 355 SignalMonitor *signalMonitor; 354 356 EITScanner *scanner; … … 392 394 QWaitCondition triggerEventLoop; 393 395 QWaitCondition triggerEventSleep; 394 396 397 // Current recording info SPLIT 398 ProgramList curRecordings; 399 ProgramInfo *newRecording; 400 RecorderBase *newRecorder; 401 QMutex newRecordingLock; 402 395 403 // Current recording info 396 404 ProgramInfo *curRecording; 397 405 QDateTime recordEndTime; … … 408 416 // LiveTV file chain 409 417 LiveTVChain *tvchain; 410 418 419 // RingBuffer info SPLIT 420 RingBuffer *newRingBuffer; 421 QMap<ProgramInfo *, RingBuffer *> ringBuffers; 422 411 423 // RingBuffer info 412 424 RingBuffer *ringBuffer; 413 425 QString rbFilePrefix; -
libs/libmythtv/tv_rec.cpp
old new 92 92 static bool is_dishnet_eit(int cardid); 93 93 static QString load_profile(QString,void*,ProgramInfo*,RecordingProfile&); 94 94 95 static int comp_recend(ProgramInfo *a, ProgramInfo *b) 96 { 97 if (a->recendts != b->recendts) 98 { 99 if (a->recendts > b->recendts) 100 return 1; 101 else 102 return -1; 103 } 104 if (a->recstartts != b->recstartts) 105 { 106 if (a->recstartts > b->recstartts) 107 return 1; 108 else 109 return -1; 110 } 111 if (a->chansign != b->chansign) 112 { 113 if (a->chansign < b->chansign) 114 return 1; 115 else 116 return -1; 117 } 118 return 0; 119 } 120 95 121 /** \class TVRec 96 122 * \brief This is the coordinating class of the \ref recorder_subsystem. 97 123 * … … 118 144 */ 119 145 TVRec::TVRec(int capturecardnum) 120 146 // Various components TVRec coordinates 121 : recorderMux(NULL), recorder(NULL),channel(NULL), signalMonitor(NULL),147 : recorderMux(NULL), channel(NULL), signalMonitor(NULL), 122 148 scanner(NULL), dvbsiparser(NULL), 123 149 // Configuration variables from database 124 150 transcodeFirst(false), earlyCommFlag(false), runJobOnHostOnly(false), … … 131 157 internalState(kState_None), desiredNextState(kState_None), 132 158 changeState(false), pauseNotify(true), 133 159 stateFlags(0), lastTuningRequest(0), 160 // Current recording info SPLIT 161 curRecordings(false), newRecording(NULL), newRecorder(NULL), 134 162 // Current recording info 135 163 curRecording(NULL), autoRunJobs(JOB_NONE), 136 164 // Pending recording info … … 139 167 pseudoLiveTVRecording(NULL), 140 168 // tvchain 141 169 tvchain(NULL), 170 // RingBuffer info SPLIT 171 newRingBuffer(NULL), 142 172 // RingBuffer info 143 173 ringBuffer(NULL), rbFilePrefix(""), rbFileExt("mpg") 144 174 { … … 328 358 return internalState; 329 359 } 330 360 331 /** \fn TVRec::GetRecording (void)332 * \brief Allocates and returns a Program Info for the current recording.361 /** \fn TVRec::GetRecordings(void) 362 * \brief Allocates and returns a ProgramList for the current recordings. 333 363 * 334 * Note: The user of this function must free the %ProgramInfo this returns. 335 * \return %ProgramInfo for the current recording, if it exists, blank 336 * %ProgramInfo otherwise. 364 * Note: The user of this function must free the %ProgramInfo objects 365 * this returns. 366 * \return %ProgramList for the current recordings, an empty list is 367 * returned if there are no current recordings. 337 368 */ 338 Program Info *TVRec::GetRecording(void)369 ProgramList TVRec::GetRecordings(void) 339 370 { 340 371 QMutexLocker lock(&stateChangeLock); 341 372 342 ProgramInfo *tmppginfo = NULL; 373 ProgramList retlist(false); 374 375 if (changeState) 376 return retlist; 343 377 344 if (curRecording && !changeState) 378 for (ProgramInfo *rec = curRecordings.first(); 379 rec; rec = curRecordings.next()) 345 380 { 346 tmppginfo = new ProgramInfo(*curRecording);381 ProgramInfo *tmppginfo = new ProgramInfo(*rec); 347 382 tmppginfo->recstatus = rsRecording; 383 tmppginfo->cardid = cardid; 384 retlist.append(tmppginfo); 348 385 } 349 else350 tmppginfo = new ProgramInfo();351 tmppginfo->cardid = cardid;352 386 353 return tmppginfo;387 return retlist; 354 388 } 355 389 356 390 /** \fn TVRec::RecordPending(const ProgramInfo*, int) … … 417 451 * \return +1 if the recording started successfully, 418 452 * -1 if TVRec is busy doing something else, 0 otherwise. 419 453 * \sa EncoderLink::StartRecording(const ProgramInfo*) 420 * RecordPending(const ProgramInfo*, int), StopRecording( )454 * RecordPending(const ProgramInfo*, int), StopRecording(ProgramInfo *rec) 421 455 */ 422 456 RecStatusType TVRec::StartRecording(const ProgramInfo *rcinfo) 423 457 { … … 433 467 434 468 // We need to do this check early so we don't cancel an overrecord 435 469 // that we're trying to extend. 436 if (internalState != kState_WatchingLiveTV && 437 curRecording && 470 if (internalState != kState_WatchingLiveTV) 471 { 472 // change this to rec later 473 for (ProgramInfo *curRecording = curRecordings.first(); curRecording; 474 curRecording = curRecordings.next()) 475 { 476 if (curRecording && 438 477 curRecording->title == rcinfo->title && 439 478 curRecording->chanid == rcinfo->chanid && 440 479 curRecording->startts == rcinfo->startts) … … 447 486 MythEvent me("RECORDING_LIST_CHANGE"); 448 487 gContext->dispatch(me); 449 488 450 recordEndTime = curRecording->recendts.addSecs(post_roll_seconds); 489 // Resort the list of current recordings so that the recording 490 // that will end first is at the front of the list 491 curRecordings.Sort(comp_recend); 492 recordEndTime = curRecordings.getFirst()->recendts.addSecs(post_roll_seconds); 451 493 452 494 msg = QString("updating recording: %1 %2 %3 %4") 453 495 .arg(curRecording->title).arg(curRecording->chanid) … … 459 501 460 502 retval = rsRecording; 461 503 return retval; 504 } 505 } 462 506 } 463 507 464 508 if (pendingRecording) … … 472 516 // Flush out events... 473 517 WaitForEventThreadSleep(); 474 518 519 // SPLIT how does this test if recording is in post-roll? 475 520 // If in post-roll, end recording 521 #if 0 476 522 if (GetState() == kState_RecordingOnly && 477 523 !HasFlags(kFlagCancelNextRecording)) 478 524 { … … 480 526 StopRecording(); 481 527 stateChangeLock.lock(); 482 528 } 529 #endif 483 530 484 531 if (internalState == kState_None) 485 532 { … … 491 538 tvchain = NULL; 492 539 } 493 540 494 recordEndTime = GetRecordEndTime(rcinfo);495 496 541 // Tell event loop to begin recording. 497 curRecording = new ProgramInfo(*rcinfo); 498 curRecording->MarkAsInUse(true, "recorder"); 499 StartedRecording(curRecording); 542 newRecordingLock.lock(); 543 newRecording = new ProgramInfo(*rcinfo); 544 newRecording->MarkAsInUse(true, "recorder"); 545 StartedRecording(newRecording); 500 546 501 547 // Make sure scheduler is allowed to end this recording 502 548 ClearFlags(kFlagCancelNextRecording); … … 522 568 523 569 retval = rsRecording; 524 570 } 571 else if (!HasFlags(kFlagCancelNextRecording) && true /* OnSameMux (this should be true if the scheduler is working right)*/) 572 { 573 // Haven't integrated with LiveTV yet 574 newRecordingLock.lock(); 575 newRecording = new ProgramInfo(*rcinfo); 576 newRecording->MarkAsInUse(true, "recorder"); 577 StartedRecording(newRecording); 578 579 retval = rsRecording; 580 } 525 581 else if (!HasFlags(kFlagCancelNextRecording)) 526 582 { 527 583 msg = QString("Wanted to record: %1 %2 %3 %4\n" … … 530 586 .arg(rcinfo->recstartts.toString()) 531 587 .arg(rcinfo->recendts.toString()) 532 588 .arg(StateToString(internalState)); 533 if (curRecording && internalState == kState_RecordingOnly) 589 if (!curRecordings.isEmpty() && internalState == kState_RecordingOnly) 590 { 591 // Change this to rec later 592 for (ProgramInfo *curRecording = curRecordings.first(); 593 curRecording; curRecording = curRecordings.next()) 594 { 534 595 msg += QString("\n\t\t\tCurrently recording: %1 %2 %3 %4") 535 596 .arg(curRecording->title).arg(curRecording->chanid) 536 597 .arg(curRecording->recstartts.toString()) 537 598 .arg(curRecording->recendts.toString()); 599 } 600 } 538 601 VERBOSE(VB_IMPORTANT, LOC + msg); 539 602 540 603 retval = rsTunerBusy; … … 545 608 return retval; 546 609 } 547 610 548 /** \fn TVRec::StopRecording( void)611 /** \fn TVRec::StopRecording(ProgramInfo *rec) 549 612 * \brief Changes from kState_RecordingOnly to kState_None. 550 613 * \sa StartRecording(const ProgramInfo *rec), FinishRecording() 551 614 */ 552 void TVRec::StopRecording( void)615 void TVRec::StopRecording(ProgramInfo *rec) 553 616 { 554 if (StateIsRecording(GetState())) 617 if (curRecordings.contains(rec)) 618 { 619 recorders[rec]->StopRecording(); 620 FinishedRecording(rec); 621 curRecordings.remove(rec); 622 623 if (!curRecordings.isEmpty()) 624 recordEndTime = GetRecordEndTime(curRecordings.getFirst()); 625 } 626 627 if (curRecordings.isEmpty() && StateIsRecording(GetState())) 555 628 { 556 629 QMutexLocker lock(&stateChangeLock); 557 630 ChangeState(RemoveRecording(GetState())); … … 748 821 else if (TRANSITION(kState_None, kState_RecordingOnly)) 749 822 { 750 823 SetPseudoLiveTVRecording(NULL); 751 tuningRequests.enqueue(TuningRequest(kFlagRecording, curRecording));824 tuningRequests.enqueue(TuningRequest(kFlagRecording, newRecording)); 752 825 SET_NEXT(); 753 826 } 754 827 else if (TRANSITION(kState_RecordingOnly, kState_None)) … … 803 876 void TVRec::SetOption(RecordingProfile &profile, const QString &name) 804 877 { 805 878 int value = profile.byName(name)->getValue().toInt(); 806 recorder->SetOption(name, value);879 newRecorder->SetOption(name, value); 807 880 } 808 881 809 882 /** \fn TVRec::SetupRecorderMux(RecordingProfile&) … … 941 1014 */ 942 1015 bool TVRec::SetupNewRecorder(RecordingProfile &profile) 943 1016 { 944 recorder = recorderMux->CreateNewRecorder(this);1017 newRecorder = recorderMux->CreateNewRecorder(this); 945 1018 if (genOpt.cardtype == "MPEG") 946 1019 { 947 1020 #ifdef USING_IVTV … … 952 1025 { 953 1026 #ifdef USING_V4L 954 1027 VERBOSE(VB_RECORD, LOC + QString("Creating new HDTVRecorder")); 955 ringBuffer->SetWriteBufferSize(4*1024*1024);956 recorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);1028 newRingBuffer->SetWriteBufferSize(4*1024*1024); 1029 newRecorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart); 957 1030 #endif // USING_V4L 958 1031 } 959 1032 else if (genOpt.cardtype == "FIREWIRE") … … 963 1036 VERBOSE(VB_RECORD, LOC + QString("Creating new DarwinFirewireRecorder")); 964 1037 # else 965 1038 VERBOSE(VB_RECORD, LOC + QString("Creating new FirewireRecorder")); 966 recorder->SetOption("port", fwOpt.port);967 recorder->SetOption("node", fwOpt.node);968 recorder->SetOption("speed", fwOpt.speed);969 recorder->SetOption("model", fwOpt.model);970 recorder->SetOption("connection", fwOpt.connection);1039 newRecorder->SetOption("port", fwOpt.port); 1040 newRecorder->SetOption("node", fwOpt.node); 1041 newRecorder->SetOption("speed", fwOpt.speed); 1042 newRecorder->SetOption("model", fwOpt.model); 1043 newRecorder->SetOption("connection", fwOpt.connection); 971 1044 # endif // !CONFIG_DARWIN 972 1045 #endif // USING_FIREWIRE 973 1046 } … … 975 1048 { 976 1049 #ifdef USING_DBOX2 977 1050 VERBOSE(VB_RECORD, LOC + QString("Creating new DBox2Recorder")); 978 recorder->SetOption("port", dboxOpt.port);979 recorder->SetOption("host", dboxOpt.host);980 recorder->SetOption("httpport", dboxOpt.httpport);1051 newRecorder->SetOption("port", dboxOpt.port); 1052 newRecorder->SetOption("host", dboxOpt.host); 1053 newRecorder->SetOption("httpport", dboxOpt.httpport); 981 1054 #endif // USING_DBOX2 982 1055 } 983 1056 else if (genOpt.cardtype == "HDHOMERUN") 984 1057 { 985 1058 #ifdef USING_HDHOMERUN 986 1059 VERBOSE(VB_RECORD, LOC + QString("Creating new HDHRRecorder")); 987 ringBuffer->SetWriteBufferSize(4*1024*1024);988 recorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);1060 newRingBuffer->SetWriteBufferSize(4*1024*1024); 1061 newRecorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart); 989 1062 #endif // USING_HDHOMERUN 990 1063 } 991 1064 else if (genOpt.cardtype == "DVB") 992 1065 { 993 1066 #ifdef USING_DVB 994 1067 VERBOSE(VB_RECORD, LOC + QString("Creating new DVBRecorder")); 995 ringBuffer->SetWriteBufferSize(4*1024*1024);996 recorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);997 recorder->SetOption("dvb_on_demand", dvbOpt.dvb_on_demand);1068 newRingBuffer->SetWriteBufferSize(4*1024*1024); 1069 newRecorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart); 1070 newRecorder->SetOption("dvb_on_demand", dvbOpt.dvb_on_demand); 998 1071 #endif // USING_DVB 999 1072 } 1000 1073 else … … 1002 1075 #ifdef USING_V4L 1003 1076 // V4L/MJPEG/GO7007 from here on 1004 1077 VERBOSE(VB_RECORD, LOC + QString("Creating new NuppelVideoRecorder")); 1005 recorder->SetOption("skipbtaudio", genOpt.skip_btaudio);1078 newRecorder->SetOption("skipbtaudio", genOpt.skip_btaudio); 1006 1079 #endif // USING_V4L 1007 1080 } 1008 1081 1009 if ( recorder)1082 if (newRecorder) 1010 1083 { 1011 recorder->SetOptionsFromProfile(1084 newRecorder->SetOptionsFromProfile( 1012 1085 &profile, genOpt.videodev, genOpt.audiodev, genOpt.vbidev); 1013 recorder->SetRingBuffer(ringBuffer);1014 recorder->Initialize();1086 newRecorder->SetRingBuffer(newRingBuffer); 1087 newRecorder->Initialize(); 1015 1088 1016 1089 return true; 1017 1090 } … … 1050 1123 1051 1124 VERBOSE(VB_RECORD, LOC + "TeardownRecorder - Start"); 1052 1125 1126 // SPLIT This should shutdown each recorder 1127 if (!recorders.isEmpty()) 1128 { 1129 VERBOSE(VB_RECORD, LOC + "There are still recorders attached to mux"); 1130 } 1131 1053 1132 if (recorderMux && HasFlags(kFlagRecorderRunning)) 1054 1133 { 1055 1134 // This is a bad way to calculate this, the framerate … … 1081 1160 1082 1161 delete recorderMux; 1083 1162 recorderMux = NULL; 1084 delete recorder;1085 recorder = NULL;1086 1163 } 1087 1164 1165 // SPLIT this should be deleted 1088 1166 if (ringBuffer) 1089 1167 ringBuffer->StopReads(); 1090 1168 1169 // SPLIT this should be deleted, or atleast move to where each recording 1170 // is stoped 1091 1171 if (curRecording) 1092 1172 { 1093 1173 if (!killFile) … … 1153 1233 DVBRecorder *TVRec::GetDVBRecorder(void) 1154 1234 { 1155 1235 #ifdef USING_DVB 1156 return dynamic_cast<DVBRecorder*>( recorder);1236 return dynamic_cast<DVBRecorder*>(newRecorder); 1157 1237 #else // if !USING_DVB 1158 1238 return NULL; 1159 1239 #endif // !USING_DVB … … 1162 1242 HDTVRecorder *TVRec::GetHDTVRecorder(void) 1163 1243 { 1164 1244 #ifdef USING_V4L 1165 return dynamic_cast<HDTVRecorder*>( recorder);1245 return dynamic_cast<HDTVRecorder*>(newRecorder); 1166 1246 #else // if !USING_V4L 1167 1247 return NULL; 1168 1248 #endif // USING_V4L … … 1171 1251 HDHRRecorder *TVRec::GetHDHRRecorder(void) 1172 1252 { 1173 1253 #ifdef USING_HDHOMERUN 1174 return dynamic_cast<HDHRRecorder*>( recorder);1254 return dynamic_cast<HDHRRecorder*>(newRecorder); 1175 1255 #else // if !USING_HDHOMERUN 1176 1256 return NULL; 1177 1257 #endif // !USING_HDHOMERUN … … 1387 1467 1388 1468 while (HasFlags(kFlagRunMainLoop)) 1389 1469 { 1470 if (newRecording) 1471 VERBOSE(VB_RECORD, LOC + QString("Noticed newRecording(%1)").arg(newRecording->title)); 1472 1390 1473 // If there is a state change queued up, do it... 1391 1474 if (changeState) 1392 1475 { 1476 VERBOSE(VB_RECORD, LOC + "SPLIT: changeState"); 1393 1477 HandleStateChange(); 1394 1478 ClearFlags(kFlagFrontendReady | kFlagCancelNextRecording); 1395 1479 SetFlags(kFlagAskAllowRecording); … … 1407 1491 // Handle any tuning events.. 1408 1492 HandleTuning(); 1409 1493 1494 // SPLIT 1495 // Additional new recordings on the same mux are added here 1496 // Setup the recorder 1497 if (newRecording) 1498 { 1499 VERBOSE(VB_RECORD, LOC + "Adding additional recorders"); 1500 1501 RecordingProfile profile; 1502 QString profileName = load_profile(genOpt.cardtype, NULL, newRecording, profile); 1503 1504 SetRingBuffer(new RingBuffer(newRecording->GetFileName(), true)); 1505 1506 if (!SetupNewRecorder(profile)) 1507 VERBOSE(VB_RECORD, LOC_ERR + "Failed to add an additional recorder!"); 1508 1509 newRecorder->SetRecording(newRecording); 1510 1511 DoneAddingRecording(); 1512 } 1513 // End add additional new recordings on the same mux 1514 // new recordings should be added to the list by now 1515 1410 1516 // If we have a pending recording and AskAllowRecording is set 1411 1517 // and the frontend is ready send an ASK_RECORDING query to frontend. 1412 1518 if (pendingRecording && HasFlags(kFlagAskAllowRecording)) 1413 1519 { 1520 VERBOSE(VB_RECORD, LOC + "SPLIT: Ask Allow Recording"); 1414 1521 ClearFlags(kFlagAskAllowRecording); 1415 1522 1416 1523 if (GetState() == kState_WatchingLiveTV) … … 1444 1551 (QDateTime::currentDateTime() > recordEndTime || 1445 1552 HasFlags(kFlagFinishRecording))) 1446 1553 { 1447 ChangeState(kState_None); 1554 VERBOSE(VB_RECORD, LOC + "SPLIT: Finishing Previous Recording"); 1555 StopRecording(curRecordings.first()); 1556 if (curRecordings.isEmpty()) 1557 ChangeState(kState_None); 1448 1558 ClearFlags(kFlagFinishRecording); 1449 1559 } 1450 1560 1451 if (curRecording) 1452 curRecording->UpdateInUseMark(); 1561 for (ProgramInfo *rec = curRecordings.first(); 1562 rec; rec = curRecordings.next()) 1563 { 1564 rec->UpdateInUseMark(); 1565 } 1453 1566 1454 1567 // Check for the end of the current program.. 1455 1568 if (GetState() == kState_WatchingLiveTV) 1456 1569 { 1570 VERBOSE(VB_RECORD, LOC + "SPLIT: Watching LiveTV"); 1457 1571 #define LIVETV_END (now >= curRecording->endts) 1458 1572 // use the following instead to test ringbuffer switching 1459 1573 //static QDateTime last = QDateTime::currentDateTime(); … … 1497 1611 // state (either kState_RecordingOnly or kState_None). 1498 1612 if (HasFlags(kFlagExitPlayer)) 1499 1613 { 1614 VERBOSE(VB_RECORD, LOC + "SPLIT: Exit Player"); 1500 1615 if (internalState == kState_WatchingLiveTV) 1501 1616 ChangeState(kState_None); 1502 1617 else if (StateIsPlaying(internalState)) … … 1538 1653 } 1539 1654 } 1540 1655 1656 VERBOSE(VB_RECORD, LOC + "SPLIT: RunTV exited while loop"); 1657 1541 1658 if (GetState() != kState_None) 1542 1659 { 1543 1660 ChangeState(kState_None); … … 2353 2470 2354 2471 videoFilters = query.value(0).toString(); 2355 2472 2356 if ( recorder != NULL)2473 if (newRecorder) 2357 2474 { 2358 recorder->SetVideoFilters(videoFilters);2475 newRecorder->SetVideoFilters(videoFilters); 2359 2476 } 2360 2477 2361 2478 return true; … … 2704 2821 * \sa EncoderLink::GetFramesWritten(), RemoteEncoder::GetFramesWritten() 2705 2822 * \return Number of frames if query succeeds, -1 otherwise. 2706 2823 */ 2824 // SPLIT this should take in a ProgramInfo * 2707 2825 long long TVRec::GetFramesWritten(void) 2708 2826 { 2709 2827 QMutexLocker lock(&stateChangeLock); 2710 2828 2711 if ( recorder)2712 return recorder->GetFramesWritten();2829 if (newRecorder) 2830 return newRecorder->GetFramesWritten(); 2713 2831 return -1; 2714 2832 } 2715 2833 … … 2735 2853 * RemoteEncoder::GetKeyframePosition(long long) 2736 2854 * \return Byte position of keyframe if query succeeds, -1 otherwise. 2737 2855 */ 2856 // SPLIT this thould take in a ProgramInfo * 2738 2857 long long TVRec::GetKeyframePosition(long long desired) 2739 2858 { 2740 2859 QMutexLocker lock(&stateChangeLock); 2741 2860 2742 if ( recorder)2743 return recorder->GetKeyframePosition(desired);2861 if (newRecorder) 2862 return newRecorder->GetKeyframePosition(desired); 2744 2863 return -1; 2745 2864 } 2746 2865 … … 3495 3614 { 3496 3615 QMutexLocker lock(&stateChangeLock); 3497 3616 3498 RingBuffer *rb_old = ringBuffer;3499 ringBuffer = rb;3617 RingBuffer *rb_old = newRingBuffer; 3618 newRingBuffer = rb; 3500 3619 3501 3620 if (rb_old && (rb_old != rb)) 3502 3621 { … … 3562 3681 3563 3682 if (HasFlags(kFlagWaitingForRecPause)) 3564 3683 { 3684 VERBOSE(VB_RECORD, LOC + QString("RecorderMux = %1").arg((unsigned int)recorderMux)); 3565 3685 if (!recorderMux->IsPaused()) 3566 3686 return; 3567 3687 3568 3688 ClearFlags(kFlagWaitingForRecPause); 3569 3689 #ifdef USING_DVB 3570 if (GetDVBRecorder ())3690 if (GetDVBRecorderMux() && GetDVBRecorder()) 3571 3691 { 3572 3692 // We currently need to close the file descriptor for 3573 3693 // DVB signal monitoring to work with some drivers … … 3846 3966 3847 3967 if (use_dr) 3848 3968 { 3969 VERBOSE(VB_RECORD, LOC + "SPLIT: Using Dummy Recorder"); 3849 3970 // We need there to be a ringbuffer for these modes 3850 3971 bool ok; 3851 3972 ProgramInfo *tmp = pseudoLiveTVRecording; … … 4064 4185 4065 4186 if (tvchain) 4066 4187 { 4188 VERBOSE(VB_RECORD, LOC + "SPLIT: Creating LiveTV RingBuffer"); 4067 4189 bool ok; 4068 4190 if (!ringBuffer) 4069 4191 { … … 4071 4193 SetFlags(kFlagRingBufferReady); 4072 4194 } 4073 4195 else 4074 ok = SwitchLiveTVRingBuffer(true, !had_dummyrec && recorder);4196 ok = SwitchLiveTVRingBuffer(true, !had_dummyrec && newRecorder); 4075 4197 if (!ok) 4076 4198 { 4077 4199 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create RingBuffer 2"); … … 4083 4205 if (lastTuningRequest.flags & kFlagRecording) 4084 4206 { 4085 4207 SetRingBuffer(new RingBuffer(rec->GetFileName(), true)); 4086 if (! ringBuffer->IsOpen())4208 if (!newRingBuffer->IsOpen()) 4087 4209 { 4088 4210 VERBOSE(VB_IMPORTANT, LOC_ERR + 4089 4211 QString("RingBuffer '%1' not open...") … … 4094 4216 } 4095 4217 } 4096 4218 4097 if (! ringBuffer)4219 if (!newRingBuffer) 4098 4220 { 4099 4221 VERBOSE(VB_IMPORTANT, LOC_ERR + QString( 4100 "Failed to start recorder! ringBuffer is NULL\n"4222 "Failed to start recorder! newRingBuffer is NULL\n" 4101 4223 "\t\t\t\t Tuning request was %1\n") 4102 4224 .arg(lastTuningRequest.toString())); 4103 4225 … … 4152 4274 channel->Open(); // Needed because of NVR::MJPEGInit() 4153 4275 4154 4276 if (rec) 4155 recorder->SetRecording(rec); 4277 newRecorder->SetRecording(rec); 4278 4279 DoneAddingRecording(); 4156 4280 4157 4281 // Setup for framebuffer capture devices.. 4158 4282 if (channel) … … 4219 4343 4220 4344 SwitchLiveTVRingBuffer(true, !had_dummyrec); 4221 4345 4222 recorderMux->Reset();4346 newRecorder->Reset(); 4223 4347 if (had_dummyrec) 4224 4348 { 4225 recorder->SetRingBuffer(ringBuffer);4349 newRecorder->SetRingBuffer(newRingBuffer); 4226 4350 ProgramInfo *progInfo = tvchain->GetProgramAt(-1); 4227 recorder->SetRecording(progInfo);4351 newRecorder->SetRecording(progInfo); 4228 4352 delete progInfo; 4229 4353 } 4230 4354 … … 4503 4627 tvchain->AppendNewProgram(pginfo, channel->GetCurrentName(), 4504 4628 channel->GetCurrentInput(), discont); 4505 4629 4506 if (set_rec && recorder)4630 if (set_rec && newRecorder) 4507 4631 { 4508 recorder->SetNextRecording(pginfo, rb);4632 newRecorder->SetNextRecording(pginfo, rb); 4509 4633 if (discont) 4510 recorder->CheckForRingBufferSwitch();4634 newRecorder->CheckForRingBufferSwitch(); 4511 4635 delete pginfo; 4512 4636 SetFlags(kFlagRingBufferReady); 4513 4637 } … … 4522 4646 return true; 4523 4647 } 4524 4648 4649 void TVRec::DoneAddingRecording() 4650 { 4651 VERBOSE(VB_RECORD, LOC + QString("Unlocking newRecordingLock for %1") 4652 .arg(newRecording->title)); 4653 curRecordings.append(newRecording); 4654 curRecordings.Sort(comp_recend); 4655 recordEndTime = GetRecordEndTime(curRecordings.getFirst()); 4656 ringBuffers[newRecording] = newRingBuffer; 4657 recorders[newRecording] = newRecorder; 4658 newRecording = NULL; 4659 newRingBuffer = NULL; 4660 newRecorder = NULL; 4661 newRecordingLock.unlock(); 4662 } 4663 4525 4664 QString TuningRequest::toString(void) const 4526 4665 { 4527 4666 return QString("Program(%1) channel(%2) input(%3) flags(%4)") -
libs/libmythtv/recorderbase.h
old new 57 57 */ 58 58 void SetRingBuffer(RingBuffer *rbuf); 59 59 60 /** \brief StopRecording() removes this recorder from the list of 61 * current recorders in RecorderMuxBase recorder list. 62 */ 63 virtual void StopRecording(); 64 60 65 /** \brief Set an specific option. 61 66 * 62 67 * Base options include: codec, audiodevice, videodevice, vbidevice, -
libs/libmythtv/recordermuxbase.h
old new 38 38 RecorderMuxBase(TVRec *rec); 39 39 virtual ~RecorderMuxBase(); 40 40 41 void RemoveRecording(RecorderBase *rec); 42 41 43 /// \brief Sets the video frame rate. 42 44 void SetFrameRate(double rate) 43 45 { … … 157 159 virtual bool PauseAndWait(int timeout = 100); 158 160 159 161 TVRec *tvrec; 160 RecorderBase *recorder; // SPLIT this should be a QPtrList<RecorderBase> 162 QPtrList<RecorderBase> recorders; 163 QMutex recLock; 161 164 162 165 QString audiodevice; 163 166 QString videodevice; -
libs/libmythtv/recorderbase.cpp
old new 101 101 "SetStrOption(...%1): Option not in profile.").arg(name)); 102 102 } 103 103 104 void RecorderBase::StopRecording() 105 { 106 recMux->RemoveRecording(this); 107 } 108 104 109 void RecorderBase::CheckForRingBufferSwitch(void) 105 110 { 106 111 nextRingBufferLock.lock(); -
libs/libmythtv/recordermuxbase.cpp
old new 13 13 #define LOC_ERR QString("RecMuxBase(%1) Error: ").arg(videodevice) 14 14 15 15 RecorderMuxBase::RecorderMuxBase(TVRec *rec) 16 : tvrec(rec), recorder(NULL),16 : tvrec(rec), 17 17 audiodevice("/dev/dsp"), videodevice("/dev/video"), vbidevice("/dev/vbi"), 18 18 vbimode(0), ntsc(true), ntsc_framerate(true), video_frame_rate(29.97), 19 19 request_pause(false), paused(false) … … 24 24 25 25 RecorderMuxBase::~RecorderMuxBase(void) 26 26 { 27 recLock.lock(); 28 recorders.setAutoDelete(true); 29 recLock.unlock(); 30 } 31 32 void RecorderMuxBase::RemoveRecording(RecorderBase *rec) 33 { 34 QMutexLocker locker(&recLock); 35 36 QString msg = QString("Trying to remove %1 from:").arg((unsigned int)rec); 37 for (RecorderBase *r = recorders.first(); r; r = recorders.next()) 38 msg += QString("\n%1").arg((unsigned int)r); 39 VERBOSE(VB_RECORD, msg); 40 41 rec->FinishRecording(); 42 recorders.remove(rec); 43 if (recorders.isEmpty()) 44 StopRecording(); 27 45 } 28 46 29 47 void RecorderMuxBase::SetOption(const QString &name, const QString &value) -
libs/libmythtv/programinfo.cpp
old new 1524 1524 const ProgramInfo *pg, 1525 1525 const ScheduledRecording *schd) 1526 1526 { 1527 VERBOSE(VB_RECORD, QString("Inserting \"%1\" into recorded").arg(pg->title)); 1527 1528 query.prepare("LOCK TABLES recorded WRITE"); 1528 1529 if (!query.exec()) 1529 1530 { … … 3893 3894 * * 3894 3895 * ************************************************************************* */ 3895 3896 3897 void ProgramList::ToStringList(QStringList &list) const 3898 { 3899 char tmp[64]; 3900 3901 // you can't iterate over a const QPtrList, copy it and iterate over 3902 // the copy to keep this function const 3903 ProgramList t(*this); 3904 3905 INT_TO_LIST(t.count()); 3906 for (ProgramInfo *pginfo = t.first(); pginfo; pginfo = t.next()) 3907 { 3908 pginfo->ToStringList(list); 3909 } 3910 } 3911 3912 bool ProgramList::FromStringList(QStringList &list, int offset) 3913 { 3914 QStringList::iterator it = list.at(offset); 3915 return FromStringList(list, it); 3916 } 3917 3918 bool ProgramList::FromStringList(QStringList &list, QStringList::iterator &it) 3919 { 3920 const char *listerror = "ProgramList::FromStringList, not enough items " 3921 "in list.\n"; 3922 QStringList::iterator listend = list.end(); 3923 QString ts; 3924 int progCount; 3925 3926 INT_FROM_LIST(progCount) 3927 3928 for (int i = 0; i < progCount; i++) 3929 { 3930 ProgramInfo *pginfo = new ProgramInfo; 3931 pginfo->FromStringList(list, it); 3932 append(pginfo); 3933 } 3934 3935 return true; 3936 } 3937 3896 3938 bool ProgramList::FromScheduler(bool &hasConflicts, QString rectable, 3897 3939 int recordid) 3898 3940 { -
libs/libmythtv/programinfo.h
old new 338 338 return at(index); 339 339 }; 340 340 341 void ToStringList(QStringList &list) const; 342 bool FromStringList(QStringList &list, int offset); 343 bool FromStringList(QStringList &list, QStringList::iterator &it); 344 341 345 bool FromScheduler(bool &hasConflicts, QString altTable = "", int recordid=-1); 342 346 bool FromScheduler(void) { 343 347 bool dummyConflicts; -
libs/libmythtv/mpegrecorder.cpp
old new 40 40 #endif 41 41 } 42 42 43 #define LOC QString("MPEGRec(%1): ").arg( videodevice)44 #define LOC_ERR QString("MPEGRec(%1) Error: ").arg( videodevice)43 #define LOC QString("MPEGRec(%1): ").arg((unsigned int)this) 44 #define LOC_ERR QString("MPEGRec(%1) Error: ").arg((unsigned int)this) 45 45 46 46 MpegRecorder::MpegRecorder(TVRec *rec, MpegRecorderMux *mux) : 47 47 RecorderBase(rec, mux), … … 53 53 // Position map support 54 54 positionMapLock(false) 55 55 { 56 VERBOSE(VB_RECORD, LOC + QString("MpegRecorder ctor")); 56 57 } 57 58 58 59 MpegRecorder::~MpegRecorder() -
libs/libmythtv/mpegrecordermux.cpp
old new 483 483 if (PauseAndWait(100)) 484 484 continue; 485 485 486 if ((deviceIsMpegFile) && (dynamic_cast<MpegRecorder*>(recorder)->framesWritten)) 486 // This code limits the rate at which frames are written from an MPEG 487 // file. Use a local count of the total number of frames written by 488 // this mux thread. 489 if (deviceIsMpegFile && framesWritten) 487 490 { 488 491 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; 489 while (( dynamic_cast<MpegRecorder*>(recorder)->framesWritten / elapsed) > 30)492 while ((framesWritten / elapsed) > 30) 490 493 { 491 494 usleep(50000); 492 495 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; … … 554 557 } 555 558 } 556 559 557 recorder->FinishRecording();558 559 560 delete[] buffer; 560 561 recording = false; 561 562 … … 564 565 565 566 RecorderBase *MpegRecorderMux::CreateNewRecorder(TVRec *tvrec) 566 567 { 567 recorder = new MpegRecorder(tvrec, this); 568 return recorder; 568 MpegRecorder *rec = new MpegRecorder(tvrec, this); 569 recLock.lock(); 570 recorders.append(rec); 571 recLock.unlock(); 572 return rec; 569 573 } 570 574 571 575 bool MpegRecorderMux::SetupRecording(void) 572 576 { 573 577 leftovers = 0xFFFFFFFF; 574 VERBOSE(VB_RECORD, QString("recorder = %1").arg((int)recorder)); 575 dynamic_cast<MpegRecorder*>(recorder)->numgops = 0; 576 dynamic_cast<MpegRecorder*>(recorder)->lastseqstart = 0; 578 VERBOSE(VB_RECORD, QString("recorder = %1").arg((unsigned int)this)); 577 579 return true; 578 580 } 579 581 … … 591 593 592 594 while (bufptr < buffer + len) 593 595 { 596 recLock.lock(); 597 594 598 v = *bufptr++; 595 599 if (state == 0x000001) 596 600 { … … 598 602 599 603 if (state == PACK_HEADER) 600 604 { 601 long long startpos = recorder->ringBuffer->GetWritePosition(); 602 startpos += buildbuffersize + bufptr - bufstart - 4; 603 dynamic_cast<MpegRecorder*>(recorder)->lastpackheaderpos = startpos; 605 long long startpos = buildbuffersize + bufptr - bufstart - 4; 606 607 for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first()); rec; rec = dynamic_cast<MpegRecorder*>(recorders.next())) 608 { 609 rec->lastpackheaderpos = rec->ringBuffer->GetWritePosition() + startpos; 610 } 604 611 605 612 int curpos = bufptr - bufstart - 4; 606 613 if (curpos < 0) … … 608 615 // header was split 609 616 buildbuffersize += curpos; 610 617 if (buildbuffersize > 0) 611 recorder->ringBuffer->Write(buildbuffer, buildbuffersize); 618 { 619 for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first()); rec; rec = dynamic_cast<MpegRecorder*>(recorders.next())) 620 { 621 rec->ringBuffer->Write(buildbuffer, buildbuffersize); 622 } 623 } 612 624 613 625 buildbuffersize = 4; 614 626 memcpy(buildbuffer, &state, 4); … … 625 637 leftlen -= curpos; 626 638 627 639 if (buildbuffersize > 0) 628 recorder->ringBuffer->Write(buildbuffer, buildbuffersize); 640 { 641 for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first()); rec; rec = dynamic_cast<MpegRecorder*>(recorders.next())) 642 { 643 rec->ringBuffer->Write(buildbuffer, buildbuffersize); 644 } 645 } 629 646 630 647 buildbuffersize = 0; 631 648 } … … 633 650 634 651 if (state == SEQ_START) 635 652 { 636 dynamic_cast<MpegRecorder*>(recorder)->lastseqstart = dynamic_cast<MpegRecorder*>(recorder)->lastpackheaderpos; 653 for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first()); rec; rec = dynamic_cast<MpegRecorder*>(recorders.next())) 654 { 655 rec->lastseqstart = rec->lastpackheaderpos; 656 } 637 657 } 638 658 639 if (state == GOP_START && dynamic_cast<MpegRecorder*>(recorder)->lastseqstart == dynamic_cast<MpegRecorder*>(recorder)->lastpackheaderpos)659 for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first()); rec; rec = dynamic_cast<MpegRecorder*>(recorders.next())) 640 660 { 641 dynamic_cast<MpegRecorder*>(recorder)->framesWritten = dynamic_cast<MpegRecorder*>(recorder)->numgops * keyframedist; 642 dynamic_cast<MpegRecorder*>(recorder)->numgops++; 643 dynamic_cast<MpegRecorder*>(recorder)->HandleKeyframe(); 661 if (state == GOP_START && 662 rec->lastseqstart == rec->lastpackheaderpos) 663 { 664 if (rec == dynamic_cast<MpegRecorder*>(recorders.getFirst())) 665 { 666 // count the number of frames written by this mux 667 framesWritten = numgops * keyframedist; 668 numgops++; 669 } 670 671 rec->framesWritten = rec->numgops * keyframedist; 672 rec->numgops++; 673 rec->HandleKeyframe(); 674 } 644 675 } 645 676 } 646 677 else 647 678 state = ((state << 8) | v) & 0xFFFFFF; 679 680 recLock.unlock(); 648 681 } 649 682 650 683 leftovers = state; 651 684 652 685 if (buildbuffersize + leftlen > kBuildBufferMaxSize) 653 686 { 654 recorder->ringBuffer->Write(buildbuffer, buildbuffersize); 687 recLock.lock(); 688 for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first()); 689 rec; rec = dynamic_cast<MpegRecorder*>(recorders.next())) 690 { 691 rec->ringBuffer->Write(buildbuffer, buildbuffersize); 692 } 693 recLock.unlock(); 655 694 buildbuffersize = 0; 656 695 } 657 696 … … 667 706 668 707 void MpegRecorderMux::Reset(void) 669 708 { 670 dynamic_cast<MpegRecorder*>(recorder)->Reset(); 709 // reset all recorders 710 recLock.lock(); 711 for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first()); 712 rec; rec = dynamic_cast<MpegRecorder*>(recorders.next())) 713 { 714 rec->Reset(); 715 } 716 recLock.unlock(); 671 717 672 718 leftovers = 0xFFFFFFFF; 673 719 buildbuffersize = 0; -
libs/libmythtv/dtvrecordermux.cpp
old new 44 44 // TS packet buffer 45 45 _buffer(0), _buffer_size(0) 46 46 { 47 recorder = NULL; 47 48 } 48 49 49 50 DTVRecorderMux::~DTVRecorderMux() -
libs/libmythtv/dtvrecordermux.h
old new 56 56 // packet buffer 57 57 unsigned char* _buffer; 58 58 int _buffer_size; 59 60 // SPLIT remove list once coverted 61 RecorderBase *recorder; 59 62 }; 60 63 61 64 #endif // DTVRECORDERMUX_H -
libs/libmythtv/NuppelVideoRecorderMux.cpp
old new 123 123 124 124 go7007 = false; 125 125 resetcapture = false; 126 127 recorder = NULL; 126 128 } 127 129 128 130 NuppelVideoRecorderMux::~NuppelVideoRecorderMux(void) -
libs/libmythtv/NuppelVideoRecorderMux.h
old new 195 195 196 196 bool go7007; 197 197 bool resetcapture; 198 199 // SPLIT delete this 200 RecorderBase *recorder; 198 201 }; 199 202 200 203 #endif -
programs/mythbackend/encoderlink.cpp
old new 162 162 * \brief Returns true if rec is actually being recorded by TVRec. 163 163 * 164 164 * This waits for TVRec to enter a state other than kState_ChangingState 165 * Then it checks TVRec::GetRecording () against rec.166 * \param rec Recording to check against TVRec::GetRecording ().165 * Then it checks TVRec::GetRecordings() against rec. 166 * \param rec Recording to check against TVRec::GetRecordings(). 167 167 * \sa IsRecording(const ProgramInfo*) 168 168 */ 169 169 bool EncoderLink::MatchesRecording(const ProgramInfo *rec) 170 170 { 171 171 bool retval = false; 172 Program Info *tvrec = NULL;172 ProgramList tvrecList; 173 173 174 174 if (local) 175 175 { … … 177 177 usleep(100); 178 178 179 179 if (IsBusyRecording()) 180 tvrec = tv->GetRecording();180 tvrecList = tv->GetRecordings(); 181 181 182 if (tvrec)182 for (ProgramInfo *tvrec = tvrecList.first(); tvrec; tvrec = tvrecList.current()) 183 183 { 184 184 if (tvrec->chanid == rec->chanid && 185 185 tvrec->recstartts == rec->recstartts) … … 187 187 retval = true; 188 188 } 189 189 190 tvrecList.removeFirst(); 190 191 delete tvrec; 191 192 } 192 193 } … … 394 395 * 395 396 * \return +1 if the recording started successfully, 396 397 * -1 if TVRec is busy doing something else, 0 otherwise. 397 * \sa RecordPending(const ProgramInfo*, int), StopRecording( )398 * \sa RecordPending(const ProgramInfo*, int), StopRecording(ProgramInfo *) 398 399 */ 399 400 RecStatusType EncoderLink::StartRecording(const ProgramInfo *rec) 400 401 { … … 424 425 return retval; 425 426 } 426 427 427 /** \fn EncoderLink::GetRecording ()428 * \brief Returns TVRec's current recording .428 /** \fn EncoderLink::GetRecordings() 429 * \brief Returns TVRec's current recordings. 429 430 * 430 * Caller is responsible for deleting the ProgramInfo when done with it. 431 * Caller is responsible for deleting the %ProgramInfo items in the 432 * %ProgramList when done with it. 431 433 * \return Returns TVRec's current recording if it succeeds, NULL otherwise. 432 434 */ 433 Program Info *EncoderLink::GetRecording(void)435 ProgramList EncoderLink::GetRecordings(void) 434 436 { 435 ProgramInfo *info = NULL;436 437 437 if (local) 438 info = tv->GetRecording();438 return tv->GetRecordings(); 439 439 else if (sock) 440 info = sock->GetRecording(m_capturecardnum);441 442 return info;440 return sock->GetRecordings(m_capturecardnum); 441 else 442 return ProgramList(false); 443 443 } 444 444 445 /** \fn EncoderLink::StopRecording( )445 /** \fn EncoderLink::StopRecording(ProgramInfo *) 446 446 * \brief Tells TVRec to stop recording immediately. 447 447 * <b>This only works on local recorders.</b> 448 448 * \sa StartRecording(const ProgramInfo *rec), FinishRecording() 449 449 */ 450 void EncoderLink::StopRecording( void)450 void EncoderLink::StopRecording(ProgramInfo *rec) 451 451 { 452 452 endRecordingTime = QDateTime::currentDateTime().addDays(-2); 453 453 startRecordingTime = endRecordingTime; … … 455 455 456 456 if (local) 457 457 { 458 tv->StopRecording( );458 tv->StopRecording(rec); 459 459 return; 460 460 } 461 461 } … … 463 463 /** \fn EncoderLink::FinishRecording() 464 464 * \brief Tells TVRec to stop recording, but only after "overrecord" seconds. 465 465 * <b>This only works on local recorders.</b> 466 * \sa StopRecording( )466 * \sa StopRecording(ProgramInfo *) 467 467 */ 468 468 void EncoderLink::FinishRecording(void) 469 469 { -
programs/mythbackend/encoderlink.h
old new 59 59 bool MatchesRecording(const ProgramInfo *rec); 60 60 void RecordPending(const ProgramInfo *rec, int secsleft); 61 61 RecStatusType StartRecording(const ProgramInfo *rec); 62 void StopRecording( void);62 void StopRecording(ProgramInfo *rec); 63 63 void FinishRecording(void); 64 64 void FrontendReady(void); 65 65 void CancelNextRecording(bool); 66 66 bool WouldConflict(const ProgramInfo *rec); 67 67 68 68 bool IsReallyRecording(void); 69 Program Info *GetRecording(void);69 ProgramList GetRecordings(void); 70 70 float GetFramerate(void); 71 71 long long GetFramesWritten(void); 72 72 long long GetFilePosition(void); -
programs/mythbackend/mainserver.cpp
old new 1011 1011 "LEFT JOIN record ON recorded.recordid = record.recordid " 1012 1012 "LEFT JOIN channel ON recorded.chanid = channel.chanid " 1013 1013 "LEFT JOIN recordedprogram ON (recorded.chanid = recordedprogram.chanid " 1014 "AND recorded.starttime = recordedprogram.starttime) " 1014 "AND recorded.starttime = recordedprogram.starttime " 1015 "AND recorded.title = recordedprogram.title) " 1015 1016 "WHERE (recorded.deletepending = 0 OR " 1016 1017 "DATE_ADD(recorded.lastmodified, " 1017 1018 "INTERVAL 5 MINUTE) <= NOW()) " … … 1566 1567 1567 1568 if (num > 0) 1568 1569 { 1569 (*encoderList)[num]->StopRecording( );1570 (*encoderList)[num]->StopRecording(pginfo); 1570 1571 pginfo->recstatus = rsRecorded; 1571 1572 if (m_sched) 1572 1573 m_sched->UpdateRecStatus(pginfo); … … 1605 1606 { 1606 1607 recnum = iter.key(); 1607 1608 1608 elink->StopRecording( );1609 elink->StopRecording(pginfo); 1609 1610 1610 1611 while (elink->IsBusyRecording() || 1611 1612 elink->GetState() == kState_ChangingState) … … 1665 1666 1666 1667 if (num > 0) 1667 1668 { 1668 (*encoderList)[num]->StopRecording( );1669 (*encoderList)[num]->StopRecording(pginfo); 1669 1670 pginfo->recstatus = rsRecorded; 1670 1671 if (m_sched) 1671 1672 m_sched->UpdateRecStatus(pginfo); … … 1695 1696 { 1696 1697 resultCode = iter.key(); 1697 1698 1698 elink->StopRecording( );1699 elink->StopRecording(pginfo); 1699 1700 1700 1701 while (elink->IsBusyRecording() || 1701 1702 elink->GetState() == kState_ChangingState) … … 2437 2438 long long value = enc->GetMaxBitrate(); 2438 2439 encodeLongLong(retlist, value); 2439 2440 } 2440 else if (command == "GET_CURRENT_RECORDING ")2441 else if (command == "GET_CURRENT_RECORDINGS") 2441 2442 { 2442 ProgramInfo *info = enc->GetRecording(); 2443 info->ToStringList(retlist); 2444 delete info; 2443 ProgramList info = enc->GetRecordings(); 2444 info.ToStringList(retlist); 2445 2446 for (ProgramInfo *pginfo = info.first(); pginfo; pginfo = info.next()) 2447 delete pginfo; 2445 2448 } 2446 2449 else if (command == "GET_KEYFRAME_POS") 2447 2450 { … … 2468 2471 if (!retlist.size()) 2469 2472 retlist << "ok"; 2470 2473 } 2471 else if (command == "GET_RECORDING ")2474 else if (command == "GET_RECORDINGS") 2472 2475 { 2473 Program Info *pginfo = enc->GetRecording();2474 i f (pginfo)2475 { 2476 pginfo->ToStringList(retlist);2476 ProgramList info = enc->GetRecordings(); 2477 info.ToStringList(retlist); 2478 2479 for (ProgramInfo *pginfo = info.first(); pginfo; pginfo = info.next()) 2477 2480 delete pginfo; 2478 }2479 else2480 {2481 ProgramInfo dummy;2482 dummy.ToStringList(retlist);2483 }2484 2481 } 2485 2482 else if (command == "FRONTEND_READY") 2486 2483 { … … 2786 2783 long long value = enc->GetMaxBitrate(); 2787 2784 encodeLongLong(retlist, value); 2788 2785 } 2789 else if (command == "GET_CURRENT_RECORDING ")2786 else if (command == "GET_CURRENT_RECORDINGS") 2790 2787 { 2791 ProgramInfo *info = enc->GetRecording(); 2792 info->ToStringList(retlist); 2793 delete info; 2788 ProgramList info = enc->GetRecordings(); 2789 info.ToStringList(retlist); 2790 2791 for (ProgramInfo *pginfo = info.first(); pginfo; pginfo = info.next()) 2792 delete pginfo; 2794 2793 } 2795 2794 2796 2795 SendResponse(pbssock, retlist); … … 3698 3697 { 3699 3698 EncoderLink *elink = iter.data(); 3700 3699 elink->CancelNextRecording(true); 3701 ProgramInfo *pinfo = elink->GetRecording(); 3702 pinfo->ToStringList(strlist); 3703 delete pinfo; 3700 ProgramList info = elink->GetRecordings(); 3701 info.ToStringList(strlist); 3702 3703 for (ProgramInfo *pginfo = info.first(); pginfo; pginfo = info.next()) 3704 delete pginfo; 3704 3705 } 3705 3706 3706 3707 WriteStringList(masterServerSock, strlist); … … 3870 3871 case kState_RecordingOnly: 3871 3872 case kState_WatchingRecording: 3872 3873 { 3873 Program Info *pInfo = elink->GetRecording();3874 ProgramList info = elink->GetRecordings(); 3874 3875 3875 if (pInfo)3876 for (ProgramInfo *pInfo = info.first(); pInfo; pInfo = info.next()) 3876 3877 { 3877 3878 FillProgramInfo(pDoc, encoder, pInfo); 3878 3879 delete pInfo; -
programs/mythbackend/playbacksock.cpp
old new 217 217 return ret; 218 218 } 219 219 220 /** \fn *PlaybackSock::GetRecording (int)221 * \brief Returns the Program Infobeing used by any current recording.220 /** \fn *PlaybackSock::GetRecordings(int) 221 * \brief Returns the ProgramList being used by any current recording. 222 222 * 223 * Caller is responsible for deleting the ProgramInfo when done with it. 223 * Caller is responsible for deleting the ProgramInfo in the ProgramList 224 * when done with it. 224 225 * \param capturecardnum cardid of recorder 225 226 */ 226 Program Info *PlaybackSock::GetRecording(int capturecardnum)227 ProgramList PlaybackSock::GetRecordings(int capturecardnum) 227 228 { 228 229 QStringList strlist = QString("QUERY_REMOTEENCODER %1") 229 230 .arg(capturecardnum); 230 231 231 strlist << "GET_CURRENT_RECORDING ";232 strlist << "GET_CURRENT_RECORDINGS"; 232 233 233 234 SendReceiveStringList(strlist); 234 235 235 Program Info *info = new ProgramInfo();236 info ->FromStringList(strlist, 0);236 ProgramList info(false); 237 info.FromStringList(strlist, 0); 237 238 return info; 238 239 } 239 240 -
programs/mythbackend/playbacksock.h
old new 54 54 bool IsBusy(int capturecardnum); 55 55 int GetEncoderState(int capturecardnum); 56 56 long long GetMaxBitrate(int capturecardnum); 57 Program Info *GetRecording(int capturecardnum);57 ProgramList GetRecordings(int capturecardnum); 58 58 bool EncoderIsRecording(int capturecardnum, const ProgramInfo *pginfo); 59 59 RecStatusType StartRecording(int capturecardnum, 60 60 const ProgramInfo *pginfo);
