Ticket #1772: ajm_multiple_recorders_v2.patch
| File ajm_multiple_recorders_v2.patch, 56.7 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); } … … 337 337 338 338 void SetOption(RecordingProfile &profile, const QString &name); 339 339 340 void DoneAddingRecording(); 341 340 342 // Various components TVRec coordinates 341 343 RecorderMuxBase *recorderMux; 342 RecorderBase *recorder;344 QMap<ProgramInfo *, RecorderBase *> recorders; 343 345 ChannelBase *channel; 344 346 SignalMonitor *signalMonitor; 345 347 EITScanner *scanner; … … 383 385 QWaitCondition triggerEventLoop; 384 386 QWaitCondition triggerEventSleep; 385 387 388 // Current recording info SPLIT 389 ProgramList curRecordings; 390 ProgramInfo *newRecording; 391 RecorderBase *newRecorder; 392 QMutex newRecordingLock; 393 386 394 // Current recording info 387 395 ProgramInfo *curRecording; 388 396 QDateTime recordEndTime; … … 399 407 // LiveTV file chain 400 408 LiveTVChain *tvchain; 401 409 410 // RingBuffer info SPLIT 411 RingBuffer *newRingBuffer; 412 QMap<ProgramInfo *, RingBuffer *> ringBuffers; 413 402 414 // RingBuffer info 403 415 RingBuffer *ringBuffer; 404 416 QString rbFilePrefix; -
libs/libmythtv/tv_rec.cpp
old new 94 94 static bool is_dishnet_eit(int cardid); 95 95 static QString load_profile(QString,void*,ProgramInfo*,RecordingProfile&); 96 96 97 static int comp_recend(ProgramInfo *a, ProgramInfo *b) 98 { 99 if (a->recendts != b->recendts) 100 { 101 if (a->recendts > b->recendts) 102 return 1; 103 else 104 return -1; 105 } 106 if (a->recstartts != b->recstartts) 107 { 108 if (a->recstartts > b->recstartts) 109 return 1; 110 else 111 return -1; 112 } 113 if (a->chansign != b->chansign) 114 { 115 if (a->chansign < b->chansign) 116 return 1; 117 else 118 return -1; 119 } 120 return 0; 121 } 122 97 123 /** \class TVRec 98 124 * \brief This is the coordinating class of the \ref recorder_subsystem. 99 125 * … … 120 146 */ 121 147 TVRec::TVRec(int capturecardnum) 122 148 // Various components TVRec coordinates 123 : recorderMux(NULL), recorder(NULL),channel(NULL), signalMonitor(NULL),149 : recorderMux(NULL), channel(NULL), signalMonitor(NULL), 124 150 scanner(NULL), dvbsiparser(NULL), 125 151 // Configuration variables from database 126 152 transcodeFirst(false), earlyCommFlag(false), runJobOnHostOnly(false), … … 133 159 internalState(kState_None), desiredNextState(kState_None), 134 160 changeState(false), pauseNotify(true), 135 161 stateFlags(0), lastTuningRequest(0), 162 // Current recording info SPLIT 163 curRecordings(false), newRecording(NULL), newRecorder(NULL), 136 164 // Current recording info 137 165 curRecording(NULL), autoRunJobs(JOB_NONE), 138 166 // Pending recording info … … 141 169 pseudoLiveTVRecording(NULL), 142 170 // tvchain 143 171 tvchain(NULL), 172 // RingBuffer info SPLIT 173 newRingBuffer(NULL), 144 174 // RingBuffer info 145 175 ringBuffer(NULL), rbFilePrefix(""), rbFileExt("mpg") 146 176 { … … 330 360 return internalState; 331 361 } 332 362 333 /** \fn TVRec::GetRecording (void)334 * \brief Allocates and returns a Program Info for the current recording.363 /** \fn TVRec::GetRecordings(void) 364 * \brief Allocates and returns a ProgramList for the current recordings. 335 365 * 336 * Note: The user of this function must free the %ProgramInfo this returns. 337 * \return %ProgramInfo for the current recording, if it exists, blank 338 * %ProgramInfo otherwise. 366 * Note: The user of this function must free the %ProgramInfo objects 367 * this returns. 368 * \return %ProgramList for the current recordings, an empty list is 369 * returned if there are no current recordings. 339 370 */ 340 Program Info *TVRec::GetRecording(void)371 ProgramList TVRec::GetRecordings(void) 341 372 { 342 373 QMutexLocker lock(&stateChangeLock); 343 374 344 ProgramInfo *tmppginfo = NULL; 375 ProgramList retlist(false); 376 377 if (changeState) 378 return retlist; 345 379 346 if (curRecording && !changeState) 380 for (ProgramInfo *rec = curRecordings.first(); 381 rec; rec = curRecordings.next()) 347 382 { 348 tmppginfo = new ProgramInfo(*curRecording);383 ProgramInfo *tmppginfo = new ProgramInfo(*rec); 349 384 tmppginfo->recstatus = rsRecording; 385 tmppginfo->cardid = cardid; 386 retlist.append(tmppginfo); 350 387 } 351 else352 tmppginfo = new ProgramInfo();353 tmppginfo->cardid = cardid;354 388 355 return tmppginfo;389 return retlist; 356 390 } 357 391 358 392 /** \fn TVRec::RecordPending(const ProgramInfo*, int) … … 419 453 * \return +1 if the recording started successfully, 420 454 * -1 if TVRec is busy doing something else, 0 otherwise. 421 455 * \sa EncoderLink::StartRecording(const ProgramInfo*) 422 * RecordPending(const ProgramInfo*, int), StopRecording( )456 * RecordPending(const ProgramInfo*, int), StopRecording(ProgramInfo *rec) 423 457 */ 424 458 RecStatusType TVRec::StartRecording(const ProgramInfo *rcinfo) 425 459 { … … 435 469 436 470 // We need to do this check early so we don't cancel an overrecord 437 471 // that we're trying to extend. 438 if (internalState != kState_WatchingLiveTV && 439 curRecording && 472 if (internalState != kState_WatchingLiveTV) 473 { 474 // change this to rec later 475 for (ProgramInfo *curRecording = curRecordings.first(); curRecording; 476 curRecording = curRecordings.next()) 477 { 478 if (curRecording && 440 479 curRecording->title == rcinfo->title && 441 480 curRecording->chanid == rcinfo->chanid && 442 481 curRecording->startts == rcinfo->startts) … … 449 488 MythEvent me("RECORDING_LIST_CHANGE"); 450 489 gContext->dispatch(me); 451 490 452 recordEndTime = curRecording->recendts.addSecs(post_roll_seconds); 491 // Resort the list of current recordings so that the recording 492 // that will end first is at the front of the list 493 curRecordings.Sort(comp_recend); 494 recordEndTime = curRecordings.getFirst()->recendts.addSecs(post_roll_seconds); 453 495 454 496 msg = QString("updating recording: %1 %2 %3 %4") 455 497 .arg(curRecording->title).arg(curRecording->chanid) … … 461 503 462 504 retval = rsRecording; 463 505 return retval; 506 } 507 } 464 508 } 465 509 466 510 if (pendingRecording) … … 474 518 // Flush out events... 475 519 WaitForEventThreadSleep(); 476 520 521 // SPLIT how does this test if recording is in post-roll? 477 522 // If in post-roll, end recording 523 #if 0 478 524 if (GetState() == kState_RecordingOnly && 479 525 !HasFlags(kFlagCancelNextRecording)) 480 526 { … … 482 528 StopRecording(); 483 529 stateChangeLock.lock(); 484 530 } 531 #endif 485 532 486 533 if (internalState == kState_None) 487 534 { … … 493 540 tvchain = NULL; 494 541 } 495 542 496 recordEndTime = GetRecordEndTime(rcinfo);497 498 543 // Tell event loop to begin recording. 499 curRecording = new ProgramInfo(*rcinfo); 500 curRecording->MarkAsInUse(true, "recorder"); 501 StartedRecording(curRecording); 544 newRecordingLock.lock(); 545 newRecording = new ProgramInfo(*rcinfo); 546 newRecording->MarkAsInUse(true, "recorder"); 547 StartedRecording(newRecording); 502 548 503 549 // Make sure scheduler is allowed to end this recording 504 550 ClearFlags(kFlagCancelNextRecording); … … 524 570 525 571 retval = rsRecording; 526 572 } 573 else if (!HasFlags(kFlagCancelNextRecording) && true /* OnSameMux (this should be true if the scheduler is working right)*/) 574 { 575 // Haven't integrated with LiveTV yet 576 newRecordingLock.lock(); 577 newRecording = new ProgramInfo(*rcinfo); 578 newRecording->MarkAsInUse(true, "recorder"); 579 StartedRecording(newRecording); 580 581 retval = rsRecording; 582 } 527 583 else if (!HasFlags(kFlagCancelNextRecording)) 528 584 { 529 585 msg = QString("Wanted to record: %1 %2 %3 %4\n" … … 532 588 .arg(rcinfo->recstartts.toString()) 533 589 .arg(rcinfo->recendts.toString()) 534 590 .arg(StateToString(internalState)); 535 if (curRecording && internalState == kState_RecordingOnly) 591 if (!curRecordings.isEmpty() && internalState == kState_RecordingOnly) 592 { 593 // Change this to rec later 594 for (ProgramInfo *curRecording = curRecordings.first(); 595 curRecording; curRecording = curRecordings.next()) 596 { 536 597 msg += QString("\n\t\t\tCurrently recording: %1 %2 %3 %4") 537 598 .arg(curRecording->title).arg(curRecording->chanid) 538 599 .arg(curRecording->recstartts.toString()) 539 600 .arg(curRecording->recendts.toString()); 601 } 602 } 540 603 VERBOSE(VB_IMPORTANT, LOC + msg); 541 604 542 605 retval = rsTunerBusy; … … 547 610 return retval; 548 611 } 549 612 550 /** \fn TVRec::StopRecording( void)613 /** \fn TVRec::StopRecording(ProgramInfo *rec) 551 614 * \brief Changes from kState_RecordingOnly to kState_None. 552 615 * \sa StartRecording(const ProgramInfo *rec), FinishRecording() 553 616 */ 554 void TVRec::StopRecording( void)617 void TVRec::StopRecording(ProgramInfo *rec) 555 618 { 556 if (StateIsRecording(GetState())) 619 if (curRecordings.contains(rec)) 620 { 621 recorders[rec]->StopRecording(); 622 FinishedRecording(rec); 623 curRecordings.remove(rec); 624 625 if (!curRecordings.isEmpty()) 626 recordEndTime = GetRecordEndTime(curRecordings.getFirst()); 627 } 628 629 if (curRecordings.isEmpty() && StateIsRecording(GetState())) 557 630 { 558 631 QMutexLocker lock(&stateChangeLock); 559 632 ChangeState(RemoveRecording(GetState())); … … 750 823 else if (TRANSITION(kState_None, kState_RecordingOnly)) 751 824 { 752 825 SetPseudoLiveTVRecording(NULL); 753 tuningRequests.enqueue(TuningRequest(kFlagRecording, curRecording));826 tuningRequests.enqueue(TuningRequest(kFlagRecording, newRecording)); 754 827 SET_NEXT(); 755 828 } 756 829 else if (TRANSITION(kState_RecordingOnly, kState_None)) … … 805 878 void TVRec::SetOption(RecordingProfile &profile, const QString &name) 806 879 { 807 880 int value = profile.byName(name)->getValue().toInt(); 808 recorder->SetOption(name, value);881 newRecorder->SetOption(name, value); 809 882 } 810 883 811 884 /** \fn TVRec::SetupRecorderMux(RecordingProfile&) … … 943 1016 */ 944 1017 bool TVRec::SetupNewRecorder(RecordingProfile &profile) 945 1018 { 946 recorder = recorderMux->CreateNewRecorder(this);1019 newRecorder = recorderMux->CreateNewRecorder(this); 947 1020 if (genOpt.cardtype == "MPEG") 948 1021 { 949 1022 #ifdef USING_IVTV … … 954 1027 { 955 1028 #ifdef USING_V4L 956 1029 VERBOSE(VB_RECORD, LOC + QString("Creating new HDTVRecorder")); 957 ringBuffer->SetWriteBufferSize(4*1024*1024);958 recorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);1030 newRingBuffer->SetWriteBufferSize(4*1024*1024); 1031 newRecorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart); 959 1032 #endif // USING_V4L 960 1033 } 961 1034 else if (genOpt.cardtype == "FIREWIRE") … … 965 1038 VERBOSE(VB_RECORD, LOC + QString("Creating new DarwinFirewireRecorder")); 966 1039 # else 967 1040 VERBOSE(VB_RECORD, LOC + QString("Creating new FirewireRecorder")); 968 recorder->SetOption("port", fwOpt.port);969 recorder->SetOption("node", fwOpt.node);970 recorder->SetOption("speed", fwOpt.speed);971 recorder->SetOption("model", fwOpt.model);972 recorder->SetOption("connection", fwOpt.connection);1041 newRecorder->SetOption("port", fwOpt.port); 1042 newRecorder->SetOption("node", fwOpt.node); 1043 newRecorder->SetOption("speed", fwOpt.speed); 1044 newRecorder->SetOption("model", fwOpt.model); 1045 newRecorder->SetOption("connection", fwOpt.connection); 973 1046 # endif // !CONFIG_DARWIN 974 1047 #endif // USING_FIREWIRE 975 1048 } … … 977 1050 { 978 1051 #ifdef USING_DBOX2 979 1052 VERBOSE(VB_RECORD, LOC + QString("Creating new DBox2Recorder")); 980 recorder->SetOption("port", dboxOpt.port);981 recorder->SetOption("host", dboxOpt.host);982 recorder->SetOption("httpport", dboxOpt.httpport);1053 newRecorder->SetOption("port", dboxOpt.port); 1054 newRecorder->SetOption("host", dboxOpt.host); 1055 newRecorder->SetOption("httpport", dboxOpt.httpport); 983 1056 #endif // USING_DBOX2 984 1057 } 985 1058 else if (genOpt.cardtype == "HDHOMERUN") 986 1059 { 987 1060 #ifdef USING_HDHOMERUN 988 1061 VERBOSE(VB_RECORD, LOC + QString("Creating new HDHRRecorder")); 989 ringBuffer->SetWriteBufferSize(4*1024*1024);990 recorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);1062 newRingBuffer->SetWriteBufferSize(4*1024*1024); 1063 newRecorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart); 991 1064 #endif // USING_HDHOMERUN 992 1065 } 993 1066 else if (genOpt.cardtype == "DVB") 994 1067 { 995 1068 #ifdef USING_DVB 996 1069 VERBOSE(VB_RECORD, LOC + QString("Creating new DVBRecorder")); 997 ringBuffer->SetWriteBufferSize(4*1024*1024);998 recorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);999 recorder->SetOption("dvb_on_demand", dvbOpt.dvb_on_demand);1070 newRingBuffer->SetWriteBufferSize(4*1024*1024); 1071 newRecorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart); 1072 newRecorder->SetOption("dvb_on_demand", dvbOpt.dvb_on_demand); 1000 1073 #endif // USING_DVB 1001 1074 } 1002 1075 else … … 1004 1077 #ifdef USING_V4L 1005 1078 // V4L/MJPEG/GO7007 from here on 1006 1079 VERBOSE(VB_RECORD, LOC + QString("Creating new NuppelVideoRecorder")); 1007 recorder->SetOption("skipbtaudio", genOpt.skip_btaudio);1080 newRecorder->SetOption("skipbtaudio", genOpt.skip_btaudio); 1008 1081 #endif // USING_V4L 1009 1082 } 1010 1083 1011 if ( recorder)1084 if (newRecorder) 1012 1085 { 1013 recorder->SetOptionsFromProfile(1086 newRecorder->SetOptionsFromProfile( 1014 1087 &profile, genOpt.videodev, genOpt.audiodev, genOpt.vbidev); 1015 recorder->SetRingBuffer(ringBuffer);1016 recorder->Initialize();1088 newRecorder->SetRingBuffer(newRingBuffer); 1089 newRecorder->Initialize(); 1017 1090 1018 1091 return true; 1019 1092 } … … 1052 1125 1053 1126 VERBOSE(VB_RECORD, LOC + "TeardownRecorder - Start"); 1054 1127 1128 // SPLIT This should shutdown each recorder 1129 if (!recorders.isEmpty()) 1130 { 1131 VERBOSE(VB_RECORD, LOC + "There are still recorders attached to mux"); 1132 } 1133 1055 1134 if (recorderMux && HasFlags(kFlagRecorderRunning)) 1056 1135 { 1057 1136 // This is a bad way to calculate this, the framerate … … 1083 1162 1084 1163 delete recorderMux; 1085 1164 recorderMux = NULL; 1086 delete recorder;1087 recorder = NULL;1088 1165 } 1089 1166 1167 // SPLIT this should be deleted 1090 1168 if (ringBuffer) 1091 1169 ringBuffer->StopReads(); 1092 1170 1171 // SPLIT this should be deleted, or atleast move to where each recording 1172 // is stoped 1093 1173 if (curRecording) 1094 1174 { 1095 1175 if (!killFile) … … 1155 1235 DVBRecorder *TVRec::GetDVBRecorder(void) 1156 1236 { 1157 1237 #ifdef USING_DVB 1158 return dynamic_cast<DVBRecorder*>( recorder);1238 return dynamic_cast<DVBRecorder*>(newRecorder); 1159 1239 #else // if !USING_DVB 1160 1240 return NULL; 1161 1241 #endif // !USING_DVB … … 1164 1244 HDTVRecorder *TVRec::GetHDTVRecorder(void) 1165 1245 { 1166 1246 #ifdef USING_V4L 1167 return dynamic_cast<HDTVRecorder*>( recorder);1247 return dynamic_cast<HDTVRecorder*>(newRecorder); 1168 1248 #else // if !USING_V4L 1169 1249 return NULL; 1170 1250 #endif // USING_V4L … … 1173 1253 HDHRRecorder *TVRec::GetHDHRRecorder(void) 1174 1254 { 1175 1255 #ifdef USING_HDHOMERUN 1176 return dynamic_cast<HDHRRecorder*>( recorder);1256 return dynamic_cast<HDHRRecorder*>(newRecorder); 1177 1257 #else // if !USING_HDHOMERUN 1178 1258 return NULL; 1179 1259 #endif // !USING_HDHOMERUN … … 1388 1468 1389 1469 while (HasFlags(kFlagRunMainLoop)) 1390 1470 { 1471 if (newRecording) 1472 VERBOSE(VB_RECORD, LOC + QString("Noticed newRecording(%1)").arg(newRecording->title)); 1473 1391 1474 // If there is a state change queued up, do it... 1392 1475 if (changeState) 1393 1476 { 1477 VERBOSE(VB_RECORD, LOC + "SPLIT: changeState"); 1394 1478 HandleStateChange(); 1395 1479 ClearFlags(kFlagFrontendReady | kFlagCancelNextRecording); 1396 1480 SetFlags(kFlagAskAllowRecording); … … 1408 1492 // Handle any tuning events.. 1409 1493 HandleTuning(); 1410 1494 1495 // SPLIT 1496 // Additional new recordings on the same mux are added here 1497 // Setup the recorder 1498 if (recorderMux && newRecording) 1499 { 1500 VERBOSE(VB_RECORD, LOC + "Adding additional recorders"); 1501 1502 RecordingProfile profile; 1503 QString profileName = load_profile(genOpt.cardtype, NULL, newRecording, profile); 1504 1505 SetRingBuffer(new RingBuffer(newRecording->GetFileName(), true)); 1506 1507 if (!SetupNewRecorder(profile)) 1508 VERBOSE(VB_RECORD, LOC_ERR + "Failed to add an additional recorder!"); 1509 1510 newRecorder->SetRecording(newRecording); 1511 1512 DoneAddingRecording(); 1513 } 1514 // End add additional new recordings on the same mux 1515 // new recordings should be added to the list by now 1516 1411 1517 // If we have a pending recording and AskAllowRecording is set 1412 1518 // and the frontend is ready send an ASK_RECORDING query to frontend. 1413 1519 if (pendingRecording && HasFlags(kFlagAskAllowRecording)) 1414 1520 { 1521 VERBOSE(VB_RECORD, LOC + "SPLIT: Ask Allow Recording"); 1415 1522 ClearFlags(kFlagAskAllowRecording); 1416 1523 1417 1524 if (GetState() == kState_WatchingLiveTV) … … 1441 1548 1442 1549 // If we are recording a program, check if the recording is 1443 1550 // over or someone has asked us to finish the recording. 1444 if ( GetState() == kState_RecordingOnly &&1551 if (recorderMux && GetState() == kState_RecordingOnly && 1445 1552 (QDateTime::currentDateTime() > recordEndTime || 1446 1553 HasFlags(kFlagFinishRecording))) 1447 1554 { 1448 ChangeState(kState_None); 1555 VERBOSE(VB_RECORD, LOC + "SPLIT: Finishing Previous Recording"); 1556 StopRecording(curRecordings.first()); 1557 if (curRecordings.isEmpty()) 1558 ChangeState(kState_None); 1449 1559 ClearFlags(kFlagFinishRecording); 1450 1560 } 1451 1561 1452 if (curRecording) 1453 curRecording->UpdateInUseMark(); 1562 for (ProgramInfo *rec = curRecordings.first(); 1563 rec; rec = curRecordings.next()) 1564 { 1565 rec->UpdateInUseMark(); 1566 } 1454 1567 1455 1568 // Check for the end of the current program.. 1456 1569 if (GetState() == kState_WatchingLiveTV) 1457 1570 { 1571 VERBOSE(VB_RECORD, LOC + "SPLIT: Watching LiveTV"); 1458 1572 #define LIVETV_END (now >= curRecording->endts) 1459 1573 // use the following instead to test ringbuffer switching 1460 1574 //static QDateTime last = QDateTime::currentDateTime(); … … 1498 1612 // state (either kState_RecordingOnly or kState_None). 1499 1613 if (HasFlags(kFlagExitPlayer)) 1500 1614 { 1615 VERBOSE(VB_RECORD, LOC + "SPLIT: Exit Player"); 1501 1616 if (internalState == kState_WatchingLiveTV) 1502 1617 ChangeState(kState_None); 1503 1618 else if (StateIsPlaying(internalState)) … … 1539 1654 } 1540 1655 } 1541 1656 1657 VERBOSE(VB_RECORD, LOC + "SPLIT: RunTV exited while loop"); 1658 1542 1659 if (GetState() != kState_None) 1543 1660 { 1544 1661 ChangeState(kState_None); … … 2316 2433 bool TVRec::SetVideoFiltersForChannel(uint sourceid, 2317 2434 const QString &channum) 2318 2435 { 2319 if (! recorder)2436 if (!newRecorder) 2320 2437 return false; 2321 2438 2322 2439 QString videoFilters = ChannelUtil::GetVideoFilters(sourceid, channum); 2323 2440 if (!videoFilters.isEmpty()) 2324 2441 { 2325 recorder->SetVideoFilters(videoFilters);2442 newRecorder->SetVideoFilters(videoFilters); 2326 2443 return true; 2327 2444 } 2328 2445 … … 2380 2497 * \sa EncoderLink::GetFramesWritten(), RemoteEncoder::GetFramesWritten() 2381 2498 * \return Number of frames if query succeeds, -1 otherwise. 2382 2499 */ 2500 // SPLIT this should take in a ProgramInfo * 2383 2501 long long TVRec::GetFramesWritten(void) 2384 2502 { 2385 2503 QMutexLocker lock(&stateChangeLock); 2386 2504 2387 if ( recorder)2388 return recorder->GetFramesWritten();2505 if (newRecorder) 2506 return newRecorder->GetFramesWritten(); 2389 2507 return -1; 2390 2508 } 2391 2509 … … 2411 2529 * RemoteEncoder::GetKeyframePosition(long long) 2412 2530 * \return Byte position of keyframe if query succeeds, -1 otherwise. 2413 2531 */ 2532 // SPLIT this thould take in a ProgramInfo * 2414 2533 long long TVRec::GetKeyframePosition(long long desired) 2415 2534 { 2416 2535 QMutexLocker lock(&stateChangeLock); 2417 2536 2418 if ( recorder)2419 return recorder->GetKeyframePosition(desired);2537 if (newRecorder) 2538 return newRecorder->GetKeyframePosition(desired); 2420 2539 return -1; 2421 2540 } 2422 2541 … … 3159 3278 { 3160 3279 QMutexLocker lock(&stateChangeLock); 3161 3280 3162 RingBuffer *rb_old = ringBuffer;3163 ringBuffer = rb;3281 RingBuffer *rb_old = newRingBuffer; 3282 newRingBuffer = rb; 3164 3283 3165 3284 if (rb_old && (rb_old != rb)) 3166 3285 { … … 3229 3348 if (HasFlags(kFlagWaitingForRecPause)) 3230 3349 { 3231 3350 VERBOSE(VB_RECORD, LOC + "RaceTrace: 6"); 3351 VERBOSE(VB_RECORD, LOC + QString("RecorderMux = %1").arg((unsigned int)recorderMux)); 3232 3352 if (!recorderMux->IsPaused()) 3233 3353 return; 3234 3354 3235 3355 ClearFlags(kFlagWaitingForRecPause); 3236 3356 #ifdef USING_DVB 3237 if (GetDVBRecorder ())3357 if (GetDVBRecorderMux() && GetDVBRecorder()) 3238 3358 { 3239 3359 // We currently need to close the file descriptor for 3240 3360 // DVB signal monitoring to work with some drivers … … 3525 3645 3526 3646 if (use_dr) 3527 3647 { 3648 VERBOSE(VB_RECORD, LOC + "SPLIT: Using Dummy Recorder"); 3528 3649 // We need there to be a ringbuffer for these modes 3529 3650 bool ok; 3530 3651 ProgramInfo *tmp = pseudoLiveTVRecording; … … 3747 3868 3748 3869 if (tvchain) 3749 3870 { 3871 VERBOSE(VB_RECORD, LOC + "SPLIT: Creating LiveTV RingBuffer"); 3750 3872 bool ok; 3751 3873 if (!ringBuffer) 3752 3874 { … … 3754 3876 SetFlags(kFlagRingBufferReady); 3755 3877 } 3756 3878 else 3757 ok = SwitchLiveTVRingBuffer(true, !had_dummyrec && recorder);3879 ok = SwitchLiveTVRingBuffer(true, !had_dummyrec && newRecorder); 3758 3880 if (!ok) 3759 3881 { 3760 3882 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create RingBuffer 2"); … … 3766 3888 if (lastTuningRequest.flags & kFlagRecording) 3767 3889 { 3768 3890 SetRingBuffer(new RingBuffer(rec->GetFileName(), true)); 3769 if (! ringBuffer->IsOpen())3891 if (!newRingBuffer->IsOpen()) 3770 3892 { 3771 3893 VERBOSE(VB_IMPORTANT, LOC_ERR + 3772 3894 QString("RingBuffer '%1' not open...") … … 3777 3899 } 3778 3900 } 3779 3901 3780 if (! ringBuffer)3902 if (!newRingBuffer) 3781 3903 { 3782 3904 VERBOSE(VB_IMPORTANT, LOC_ERR + QString( 3783 "Failed to start recorder! ringBuffer is NULL\n"3905 "Failed to start recorder! newRingBuffer is NULL\n" 3784 3906 "\t\t\t\t Tuning request was %1\n") 3785 3907 .arg(lastTuningRequest.toString())); 3786 3908 … … 3835 3957 channel->Open(); // Needed because of NVR::MJPEGInit() 3836 3958 3837 3959 if (rec) 3838 recorder->SetRecording(rec); 3960 newRecorder->SetRecording(rec); 3961 3962 DoneAddingRecording(); 3839 3963 3840 3964 // Setup for framebuffer capture devices.. 3841 3965 if (channel) … … 3905 4029 3906 4030 SwitchLiveTVRingBuffer(true, !had_dummyrec); 3907 4031 3908 recorderMux->Reset();4032 newRecorder->Reset(); 3909 4033 if (had_dummyrec) 3910 4034 { 3911 recorder->SetRingBuffer(ringBuffer);4035 newRecorder->SetRingBuffer(newRingBuffer); 3912 4036 ProgramInfo *progInfo = tvchain->GetProgramAt(-1); 3913 recorder->SetRecording(progInfo);4037 newRecorder->SetRecording(progInfo); 3914 4038 delete progInfo; 3915 4039 } 3916 4040 … … 4190 4314 tvchain->AppendNewProgram(pginfo, channel->GetCurrentName(), 4191 4315 channel->GetCurrentInput(), discont); 4192 4316 4193 if (set_rec && recorder)4317 if (set_rec && newRecorder) 4194 4318 { 4195 recorder->SetNextRecording(pginfo, rb);4319 newRecorder->SetNextRecording(pginfo, rb); 4196 4320 if (discont) 4197 recorder->CheckForRingBufferSwitch();4321 newRecorder->CheckForRingBufferSwitch(); 4198 4322 delete pginfo; 4199 4323 SetFlags(kFlagRingBufferReady); 4200 4324 } … … 4209 4333 return true; 4210 4334 } 4211 4335 4336 void TVRec::DoneAddingRecording() 4337 { 4338 VERBOSE(VB_RECORD, LOC + QString("Unlocking newRecordingLock for %1") 4339 .arg(newRecording->title)); 4340 curRecordings.append(newRecording); 4341 curRecordings.Sort(comp_recend); 4342 recordEndTime = GetRecordEndTime(curRecordings.getFirst()); 4343 ringBuffers[newRecording] = newRingBuffer; 4344 recorders[newRecording] = newRecorder; 4345 newRecording = NULL; 4346 newRingBuffer = NULL; 4347 newRecorder = NULL; 4348 newRecordingLock.unlock(); 4349 } 4350 4212 4351 QString TuningRequest::toString(void) const 4213 4352 { 4214 4353 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_WARN QString("MPEGRec(%1) Warning: ").arg( videodevice)45 #define LOC_ERR QString("MPEGRec(%1) Error: ").arg( videodevice)43 #define LOC QString("MPEGRec(%1): ").arg((unsigned int)this) 44 #define LOC_WARN QString("MPEGRec(%1) Warning: ").arg((unsigned int)this) 45 #define LOC_ERR QString("MPEGRec(%1) Error: ").arg((unsigned int)this) 46 46 47 47 MpegRecorder::MpegRecorder(TVRec *rec, MpegRecorderMux *mux) : 48 48 RecorderBase(rec, mux), … … 54 54 // Position map support 55 55 positionMapLock(false) 56 56 { 57 VERBOSE(VB_RECORD, LOC + QString("MpegRecorder ctor")); 57 58 } 58 59 59 60 MpegRecorder::~MpegRecorder() -
libs/libmythtv/mpegrecordermux.cpp
old new 486 486 if (PauseAndWait(100)) 487 487 continue; 488 488 489 if ((deviceIsMpegFile) && (dynamic_cast<MpegRecorder*>(recorder)->framesWritten)) 489 // This code limits the rate at which frames are written from an MPEG 490 // file. Use a local count of the total number of frames written by 491 // this mux thread. 492 if (deviceIsMpegFile && framesWritten) 490 493 { 491 494 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; 492 while (( dynamic_cast<MpegRecorder*>(recorder)->framesWritten / elapsed) > 30)495 while ((framesWritten / elapsed) > 30) 493 496 { 494 497 usleep(50000); 495 498 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; … … 557 560 } 558 561 } 559 562 560 recorder->FinishRecording();561 562 563 delete[] buffer; 563 564 recording = false; 564 565 … … 567 568 568 569 RecorderBase *MpegRecorderMux::CreateNewRecorder(TVRec *tvrec) 569 570 { 570 recorder = new MpegRecorder(tvrec, this); 571 return recorder; 571 MpegRecorder *rec = new MpegRecorder(tvrec, this); 572 recLock.lock(); 573 recorders.append(rec); 574 recLock.unlock(); 575 return rec; 572 576 } 573 577 574 578 bool MpegRecorderMux::SetupRecording(void) 575 579 { 576 580 leftovers = 0xFFFFFFFF; 577 VERBOSE(VB_RECORD, QString("recorder = %1").arg((int)recorder)); 578 dynamic_cast<MpegRecorder*>(recorder)->numgops = 0; 579 dynamic_cast<MpegRecorder*>(recorder)->lastseqstart = 0; 581 VERBOSE(VB_RECORD, QString("recorder = %1").arg((unsigned int)this)); 580 582 return true; 581 583 } 582 584 … … 594 596 595 597 while (bufptr < buffer + len) 596 598 { 599 recLock.lock(); 600 597 601 v = *bufptr++; 598 602 if (state == 0x000001) 599 603 { … … 601 605 602 606 if (state == PACK_HEADER) 603 607 { 604 long long startpos = recorder->ringBuffer->GetWritePosition(); 605 startpos += buildbuffersize + bufptr - bufstart - 4; 606 dynamic_cast<MpegRecorder*>(recorder)->lastpackheaderpos = startpos; 608 long long startpos = buildbuffersize + bufptr - bufstart - 4; 609 610 for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first()); rec; rec = dynamic_cast<MpegRecorder*>(recorders.next())) 611 { 612 rec->lastpackheaderpos = rec->ringBuffer->GetWritePosition() + startpos; 613 } 607 614 608 615 int curpos = bufptr - bufstart - 4; 609 616 if (curpos < 0) … … 611 618 // header was split 612 619 buildbuffersize += curpos; 613 620 if (buildbuffersize > 0) 614 recorder->ringBuffer->Write(buildbuffer, buildbuffersize); 621 { 622 for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first()); rec; rec = dynamic_cast<MpegRecorder*>(recorders.next())) 623 { 624 rec->ringBuffer->Write(buildbuffer, buildbuffersize); 625 } 626 } 615 627 616 628 buildbuffersize = 4; 617 629 memcpy(buildbuffer, &state, 4); … … 628 640 leftlen -= curpos; 629 641 630 642 if (buildbuffersize > 0) 631 recorder->ringBuffer->Write(buildbuffer, buildbuffersize); 643 { 644 for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first()); rec; rec = dynamic_cast<MpegRecorder*>(recorders.next())) 645 { 646 rec->ringBuffer->Write(buildbuffer, buildbuffersize); 647 } 648 } 632 649 633 650 buildbuffersize = 0; 634 651 } … … 636 653 637 654 if (state == SEQ_START) 638 655 { 639 dynamic_cast<MpegRecorder*>(recorder)->lastseqstart = dynamic_cast<MpegRecorder*>(recorder)->lastpackheaderpos; 656 for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first()); rec; rec = dynamic_cast<MpegRecorder*>(recorders.next())) 657 { 658 rec->lastseqstart = rec->lastpackheaderpos; 659 } 640 660 } 641 661 642 if (state == GOP_START && dynamic_cast<MpegRecorder*>(recorder)->lastseqstart == dynamic_cast<MpegRecorder*>(recorder)->lastpackheaderpos)662 for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first()); rec; rec = dynamic_cast<MpegRecorder*>(recorders.next())) 643 663 { 644 dynamic_cast<MpegRecorder*>(recorder)->framesWritten = dynamic_cast<MpegRecorder*>(recorder)->numgops * keyframedist; 645 dynamic_cast<MpegRecorder*>(recorder)->numgops++; 646 dynamic_cast<MpegRecorder*>(recorder)->HandleKeyframe(); 664 if (state == GOP_START && 665 rec->lastseqstart == rec->lastpackheaderpos) 666 { 667 if (rec == dynamic_cast<MpegRecorder*>(recorders.getFirst())) 668 { 669 // count the number of frames written by this mux 670 framesWritten = numgops * keyframedist; 671 numgops++; 672 } 673 674 rec->framesWritten = rec->numgops * keyframedist; 675 rec->numgops++; 676 rec->HandleKeyframe(); 677 } 647 678 } 648 679 } 649 680 else 650 681 state = ((state << 8) | v) & 0xFFFFFF; 682 683 recLock.unlock(); 651 684 } 652 685 653 686 leftovers = state; 654 687 655 688 if (buildbuffersize + leftlen > kBuildBufferMaxSize) 656 689 { 657 recorder->ringBuffer->Write(buildbuffer, buildbuffersize); 690 recLock.lock(); 691 for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first()); 692 rec; rec = dynamic_cast<MpegRecorder*>(recorders.next())) 693 { 694 rec->ringBuffer->Write(buildbuffer, buildbuffersize); 695 } 696 recLock.unlock(); 658 697 buildbuffersize = 0; 659 698 } 660 699 … … 670 709 671 710 void MpegRecorderMux::Reset(void) 672 711 { 673 dynamic_cast<MpegRecorder*>(recorder)->Reset(); 712 // reset all recorders 713 recLock.lock(); 714 for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first()); 715 rec; rec = dynamic_cast<MpegRecorder*>(recorders.next())) 716 { 717 rec->Reset(); 718 } 719 recLock.unlock(); 674 720 675 721 leftovers = 0xFFFFFFFF; 676 722 buildbuffersize = 0; -
libs/libmythtv/NuppelVideoRecorderMux.cpp
old new 125 125 126 126 go7007 = false; 127 127 resetcapture = false; 128 129 recorder = NULL; 128 130 } 129 131 130 132 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 61 61 bool MatchesRecording(const ProgramInfo *rec); 62 62 void RecordPending(const ProgramInfo *rec, int secsleft); 63 63 RecStatusType StartRecording(const ProgramInfo *rec); 64 void StopRecording( void);64 void StopRecording(ProgramInfo *rec); 65 65 void FinishRecording(void); 66 66 void FrontendReady(void); 67 67 void CancelNextRecording(bool); 68 68 bool WouldConflict(const ProgramInfo *rec); 69 69 70 70 bool IsReallyRecording(void); 71 Program Info *GetRecording(void);71 ProgramList GetRecordings(void); 72 72 float GetFramerate(void); 73 73 long long GetFramesWritten(void); 74 74 long long GetFilePosition(void); -
programs/mythbackend/mainserver.cpp
old new 1012 1012 "LEFT JOIN record ON recorded.recordid = record.recordid " 1013 1013 "LEFT JOIN channel ON recorded.chanid = channel.chanid " 1014 1014 "LEFT JOIN recordedprogram ON (recorded.chanid = recordedprogram.chanid " 1015 "AND recorded.starttime = recordedprogram.starttime) " 1015 "AND recorded.starttime = recordedprogram.starttime " 1016 "AND recorded.title = recordedprogram.title) " 1016 1017 "WHERE (recorded.deletepending = 0 OR " 1017 1018 "DATE_ADD(recorded.lastmodified, " 1018 1019 "INTERVAL 5 MINUTE) <= NOW()) " … … 1567 1568 1568 1569 if (num > 0) 1569 1570 { 1570 (*encoderList)[num]->StopRecording( );1571 (*encoderList)[num]->StopRecording(pginfo); 1571 1572 pginfo->recstatus = rsRecorded; 1572 1573 if (m_sched) 1573 1574 m_sched->UpdateRecStatus(pginfo); … … 1606 1607 { 1607 1608 recnum = iter.key(); 1608 1609 1609 elink->StopRecording( );1610 elink->StopRecording(pginfo); 1610 1611 1611 1612 while (elink->IsBusyRecording() || 1612 1613 elink->GetState() == kState_ChangingState) … … 1666 1667 1667 1668 if (num > 0) 1668 1669 { 1669 (*encoderList)[num]->StopRecording( );1670 (*encoderList)[num]->StopRecording(pginfo); 1670 1671 pginfo->recstatus = rsRecorded; 1671 1672 if (m_sched) 1672 1673 m_sched->UpdateRecStatus(pginfo); … … 1696 1697 { 1697 1698 resultCode = iter.key(); 1698 1699 1699 elink->StopRecording( );1700 elink->StopRecording(pginfo); 1700 1701 1701 1702 while (elink->IsBusyRecording() || 1702 1703 elink->GetState() == kState_ChangingState) … … 2438 2439 long long value = enc->GetMaxBitrate(); 2439 2440 encodeLongLong(retlist, value); 2440 2441 } 2441 else if (command == "GET_CURRENT_RECORDING ")2442 else if (command == "GET_CURRENT_RECORDINGS") 2442 2443 { 2443 ProgramInfo *info = enc->GetRecording(); 2444 info->ToStringList(retlist); 2445 delete info; 2444 ProgramList info = enc->GetRecordings(); 2445 info.ToStringList(retlist); 2446 2447 for (ProgramInfo *pginfo = info.first(); pginfo; pginfo = info.next()) 2448 delete pginfo; 2446 2449 } 2447 2450 else if (command == "GET_KEYFRAME_POS") 2448 2451 { … … 2469 2472 if (!retlist.size()) 2470 2473 retlist << "ok"; 2471 2474 } 2472 else if (command == "GET_RECORDING ")2475 else if (command == "GET_RECORDINGS") 2473 2476 { 2474 Program Info *pginfo = enc->GetRecording();2475 i f (pginfo)2476 { 2477 pginfo->ToStringList(retlist);2477 ProgramList info = enc->GetRecordings(); 2478 info.ToStringList(retlist); 2479 2480 for (ProgramInfo *pginfo = info.first(); pginfo; pginfo = info.next()) 2478 2481 delete pginfo; 2479 }2480 else2481 {2482 ProgramInfo dummy;2483 dummy.ToStringList(retlist);2484 }2485 2482 } 2486 2483 else if (command == "FRONTEND_READY") 2487 2484 { … … 2787 2784 long long value = enc->GetMaxBitrate(); 2788 2785 encodeLongLong(retlist, value); 2789 2786 } 2790 else if (command == "GET_CURRENT_RECORDING ")2787 else if (command == "GET_CURRENT_RECORDINGS") 2791 2788 { 2792 ProgramInfo *info = enc->GetRecording(); 2793 info->ToStringList(retlist); 2794 delete info; 2789 ProgramList info = enc->GetRecordings(); 2790 info.ToStringList(retlist); 2791 2792 for (ProgramInfo *pginfo = info.first(); pginfo; pginfo = info.next()) 2793 delete pginfo; 2795 2794 } 2796 2795 2797 2796 SendResponse(pbssock, retlist); … … 3699 3698 { 3700 3699 EncoderLink *elink = iter.data(); 3701 3700 elink->CancelNextRecording(true); 3702 ProgramInfo *pinfo = elink->GetRecording(); 3703 pinfo->ToStringList(strlist); 3704 delete pinfo; 3701 ProgramList info = elink->GetRecordings(); 3702 info.ToStringList(strlist); 3703 3704 for (ProgramInfo *pginfo = info.first(); pginfo; pginfo = info.next()) 3705 delete pginfo; 3705 3706 } 3706 3707 3707 3708 WriteStringList(masterServerSock, strlist); … … 3871 3872 case kState_RecordingOnly: 3872 3873 case kState_WatchingRecording: 3873 3874 { 3874 Program Info *pInfo = elink->GetRecording();3875 ProgramList info = elink->GetRecordings(); 3875 3876 3876 if (pInfo)3877 for (ProgramInfo *pInfo = info.first(); pInfo; pInfo = info.next()) 3877 3878 { 3878 3879 FillProgramInfo(pDoc, encoder, pInfo); 3879 3880 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); -
libs/libmythtv/dtvrecordermux.cpp
old new 11 11 #include "programinfo.h" 12 12 #include "mpegtables.h" 13 13 #include "dtvrecordermux.h" 14 #include "dtvrecorder.h" 14 15 #include "recorderbase.h" 15 16 #include "tv_rec.h" 16 17 … … 90 91 // documented in recorderbase.h 91 92 void DTVRecorderMux::Reset(void) 92 93 { 93 recorder->Reset(); 94 // reset all recorders 95 recLock.lock(); 96 for (DTVRecorder *rec = dynamic_cast<DTVRecorder*>(recorders.first()); 97 rec; rec = dynamic_cast<DTVRecorder*>(recorders.next())) 98 { 99 rec->Reset(); 100 } 94 101 95 102 //_recording 96 103 _error = false; -
libs/libmythtv/dvbrecordermux.cpp
old new 243 243 244 244 RecorderBase *DVBRecorderMux::CreateNewRecorder(TVRec *tvrec) 245 245 { 246 recorder = new DVBRecorder(tvrec, this); 247 return recorder; 246 DVBRecorder *rec = new DVBRecorder(tvrec, this); 247 recLock.lock(); 248 recorders.append(rec); 249 recLock.unlock(); 250 return rec; 248 251 } 249 252 250 253 void DVBRecorderMux::CloseFilters(void) … … 475 478 476 479 Close(); 477 480 478 recorder->FinishRecording();479 480 481 _recording = false; 481 482 } 482 483 … … 486 487 { 487 488 QMutexLocker read_lock(&_pid_lock); 488 489 uint next_cc; 489 if (_pat && _pmt && recorder)490 if (_pat && _pmt) 490 491 { 492 recLock.lock(); 493 491 494 next_cc = (_pat->tsheader()->ContinuityCounter()+1)&0xf; 492 495 _pat->tsheader()->SetContinuityCounter(next_cc); 493 dynamic_cast<DVBRecorder*>(recorder)->BufferedWrite(*(reinterpret_cast<TSPacket*>(_pat->tsheader()))); 496 for (DVBRecorder *rec = dynamic_cast<DVBRecorder*>(recorders.first()); 497 rec; rec = dynamic_cast<DVBRecorder*>(recorders.next())) 498 { 499 rec->BufferedWrite(*(reinterpret_cast<TSPacket*>(_pat->tsheader()))); 500 } 494 501 495 502 unsigned char buf[8 * 1024]; 496 503 uint cc = _pmt->tsheader()->ContinuityCounter(); 497 504 uint size = _pmt->WriteAsTSPackets(buf, cc); 498 505 _pmt->tsheader()->SetContinuityCounter(cc); 499 506 500 for (uint i = 0; i < size ; i += TSPacket::SIZE) 501 dynamic_cast<DVBRecorder*>(recorder)->BufferedWrite(*(reinterpret_cast<TSPacket*>(&buf[i]))); 507 for (DVBRecorder *rec = dynamic_cast<DVBRecorder*>(recorders.first()); 508 rec; rec = dynamic_cast<DVBRecorder*>(recorders.next())) 509 { 510 for (uint i = 0; i < size ; i += TSPacket::SIZE) 511 rec->BufferedWrite(*(reinterpret_cast<TSPacket*>(&buf[i]))); 512 } 502 513 503 514 _ts_packets_until_psip_sync = TSPACKETS_BETWEEN_PSIP_SYNC; 515 516 recLock.unlock(); 504 517 } 505 518 } 506 519 else … … 750 763 751 764 // Check for keyframes and count frames 752 765 if (info->isVideo) 753 dynamic_cast<DVBRecorder*>(recorder)->_buffer_packets = !dynamic_cast<DVBRecorder*>(recorder)->FindKeyframes(&tspacket); 766 { 767 recLock.lock(); 768 for (DVBRecorder *rec = dynamic_cast<DVBRecorder*>(recorders.first()); 769 rec; rec = dynamic_cast<DVBRecorder*>(recorders.next())) 770 { 771 rec->_buffer_packets = !rec->FindKeyframes(&tspacket); 772 } 773 recLock.unlock(); 774 } 754 775 776 // SPLIT this needs to be modified 755 777 // Sync recording start to first keyframe 778 #if 0 756 779 if (_wait_for_keyframe_option && dynamic_cast<DVBRecorder*>(recorder)->_first_keyframe<0) 757 780 return; 781 #endif 758 782 759 783 // Sync streams to the first Payload Unit Start Indicator 760 784 // _after_ first keyframe iff _wait_for_keyframe_option is true … … 772 796 WritePATPMT(); 773 797 774 798 // Write Data 775 dynamic_cast<DVBRecorder*>(recorder)->BufferedWrite(tspacket); 799 recLock.lock(); 800 for (DVBRecorder *rec = dynamic_cast<DVBRecorder*>(recorders.first()); 801 rec; rec = dynamic_cast<DVBRecorder*>(recorders.next())) 802 { 803 rec->BufferedWrite(tspacket); 804 } 805 recLock.unlock(); 776 806 } 777 807 778 808 void DVBRecorderMux::GetTimeStamp(const TSPacket& tspacket) -
libs/libmythtv/hdtvrecordermux.cpp
old new 115 115 _atsc_stream_data(NULL), 116 116 _resync_count(0) 117 117 { 118 recorder = NULL; 118 119 SetStreamData(new ATSCStreamData(-1, DEFAULT_SUBCHANNEL)); 119 120 120 121 _buffer_size = TSPacket::SIZE * 1500; -
libs/libmythtv/hdtvrecordermux.h
old new 106 106 unsigned char * writePtr; 107 107 unsigned char * endPtr; 108 108 } ringbuf; 109 110 RecorderBase *recorder; 109 111 }; 110 112 111 113 #endif
