Advertisement
Guest User

r5000 patch for mythtv linux 0.26

a guest
Jan 1st, 2013
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 57.89 KB | None | 0 0
  1. Index: libs/libmythtv/r5000recorder.cpp
  2. ===================================================================
  3. --- libs/libmythtv/r5000recorder.cpp    (revision 0)
  4. +++ libs/libmythtv/r5000recorder.cpp    (revision 4)
  5. @@ -0,0 +1,285 @@
  6. +/**
  7. + *  R5000Recorder
  8. + *  Copyright (c) 2005 by Jim Westfall and Dave Abrahams
  9. + *  Distributed as part of MythTV under GPL v2 and later.
  10. + */
  11. +
  12. +// MythTV includes
  13. +#include "r5000recorder.h"
  14. +#include "r5000channel.h"
  15. +#include "mythcontext.h"
  16. +#include "mpegtables.h"
  17. +#include "mpegstreamdata.h"
  18. +#include "tv_rec.h"
  19. +
  20. +#define LOC QString("R5000RecBase(%1): ").arg(channel->GetDevice())
  21. +#define LOC_ERR QString("R5000RecBase(%1), Error: ").arg(channel->GetDevice())
  22. +
  23. +R5000Recorder::R5000Recorder(TVRec *rec, R5000Channel *chan) :
  24. +    DTVRecorder(rec),
  25. +    channel(chan), isopen(false)
  26. +{
  27. +    //_wait_for_keyframe_option = false;
  28. +}
  29. +
  30. +R5000Recorder::~R5000Recorder()
  31. +{
  32. +    Close();
  33. +}
  34. +
  35. +bool R5000Recorder::Open(void)
  36. +{
  37. +    if (!isopen)
  38. +        isopen = channel->GetR5000Device()->OpenPort();
  39. +
  40. +    return isopen;
  41. +}
  42. +
  43. +void R5000Recorder::Close(void)
  44. +{
  45. +    if (isopen)
  46. +    {
  47. +        channel->GetR5000Device()->ClosePort();
  48. +        isopen = false;
  49. +    }
  50. +}
  51. +
  52. +void R5000Recorder::StartStreaming(void)
  53. +{
  54. +    channel->GetR5000Device()->AddListener(this);
  55. +}
  56. +
  57. +void R5000Recorder::StopStreaming(void)
  58. +{
  59. +    channel->GetR5000Device()->RemoveListener(this);
  60. +}
  61. +
  62. +void R5000Recorder::StartRecording(void)
  63. +{
  64. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "StartRecording");
  65. +
  66. +    if (!Open())
  67. +    {
  68. +        _error = true;
  69. +        return;
  70. +    }
  71. +
  72. +    request_recording = true;
  73. +    recording = true;
  74. +
  75. +    StartStreaming();
  76. +
  77. +    while (request_recording)
  78. +    {
  79. +        if (!PauseAndWait())
  80. +            usleep(50 * 1000);
  81. +    }
  82. +
  83. +    StopStreaming();
  84. +    FinishRecording();
  85. +
  86. +    recording = false;
  87. +}
  88. +
  89. +void R5000Recorder::run(void)
  90. +{
  91. +    LOG(VB_RECORD, LOG_INFO, LOC + "run");
  92. +
  93. +    if (!Open())
  94. +    {
  95. +        _error = "Failed to open R5000 device";
  96. +        LOG(VB_GENERAL, LOG_ERR, LOC + _error);
  97. +        return;
  98. +    }
  99. +
  100. +    {
  101. +        QMutexLocker locker(&pauseLock);
  102. +        request_recording = true;
  103. +        recording = true;
  104. +        recordingWait.wakeAll();
  105. +    }
  106. +
  107. +    StartStreaming();
  108. +
  109. +    while (IsRecordingRequested() && !IsErrored())
  110. +    {
  111. +        if (PauseAndWait())
  112. +            continue;
  113. +
  114. +        if (!IsRecordingRequested())
  115. +            break;
  116. +
  117. +        {   // sleep 1 seconds unless StopRecording() or Unpause() is called,
  118. +            // just to avoid running this too often.
  119. +            QMutexLocker locker(&pauseLock);
  120. +            if (!request_recording || request_pause)
  121. +                continue;
  122. +            unpauseWait.wait(&pauseLock, 1000);
  123. +        }
  124. +    }
  125. +
  126. +    StopStreaming();
  127. +    FinishRecording();
  128. +
  129. +    QMutexLocker locker(&pauseLock);
  130. +    recording = false;
  131. +    recordingWait.wakeAll();
  132. +}
  133. +
  134. +void R5000Recorder::AddData(const unsigned char *data, uint len)
  135. +{
  136. +    uint bufsz = buffer.size();
  137. +    if ((SYNC_BYTE == data[0]) && (TSPacket::kSize == len) &&
  138. +        (TSPacket::kSize > bufsz))
  139. +    {
  140. +        if (bufsz)
  141. +            buffer.clear();
  142. +
  143. +        ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(data)));
  144. +        return;
  145. +    }
  146. +
  147. +    buffer.insert(buffer.end(), data, data + len);
  148. +    bufsz += len;
  149. +
  150. +    int sync_at = -1;
  151. +    for (uint i = 0; (i < bufsz) && (sync_at < 0); i++)
  152. +    {
  153. +        if (buffer[i] == SYNC_BYTE)
  154. +            sync_at = i;
  155. +    }
  156. +
  157. +    if (sync_at < 0)
  158. +        return;
  159. +
  160. +    if (bufsz < 30 * TSPacket::kSize)
  161. +        return; // build up a little buffer
  162. +
  163. +    while (sync_at + TSPacket::kSize < bufsz)
  164. +    {
  165. +        ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(
  166. +                              &buffer[0] + sync_at)));
  167. +
  168. +        sync_at += TSPacket::kSize;
  169. +    }
  170. +
  171. +    buffer.erase(buffer.begin(), buffer.begin() + sync_at);
  172. +
  173. +    return;
  174. +}
  175. +
  176. +bool R5000Recorder::ProcessTSPacket(const TSPacket &tspacket)
  177. +{
  178. +    if (tspacket.TransportError())
  179. +        return true;
  180. +
  181. +    if (tspacket.Scrambled())
  182. +        return true;
  183. +
  184. +    if (! GetStreamData())
  185. +        return true;
  186. +    if (tspacket.HasAdaptationField())
  187. +        GetStreamData()->HandleAdaptationFieldControl(&tspacket);
  188. +
  189. +    if (tspacket.HasPayload())
  190. +    {
  191. +        const unsigned int lpid = tspacket.PID();
  192. +        // Pass or reject packets based on PID, and parse info from them
  193. +        if (lpid == GetStreamData()->VideoPIDSingleProgram())
  194. +        {
  195. +            ProgramMapTable *pmt = GetStreamData()->PMTSingleProgram();
  196. +            uint video_stream_type = pmt->StreamType(pmt->FindPID(lpid));
  197. +
  198. +            if (video_stream_type == StreamID::H264Video)
  199. +                _buffer_packets = !FindH264Keyframes(&tspacket);
  200. +            else if (StreamID::IsVideo(video_stream_type))
  201. +                _buffer_packets = !FindMPEG2Keyframes(&tspacket);
  202. +
  203. +            if ((video_stream_type != StreamID::H264Video) || _seen_sps)
  204. +                BufferedWrite(tspacket);
  205. +        }
  206. +        else if (GetStreamData()->IsAudioPID(lpid))
  207. +        {
  208. +            _buffer_packets = !FindAudioKeyframes(&tspacket);
  209. +            BufferedWrite(tspacket);
  210. +        }
  211. +        else if (GetStreamData()->IsListeningPID(lpid))
  212. +            GetStreamData()->HandleTSTables(&tspacket);
  213. +        else if (GetStreamData()->IsWritingPID(lpid))
  214. +            BufferedWrite(tspacket);
  215. +    }
  216. +
  217. +    return true;
  218. +}
  219. +
  220. +void R5000Recorder::SetOptionsFromProfile(RecordingProfile *profile,
  221. +                                                 const QString &videodev,
  222. +                                                 const QString &audiodev,
  223. +                                                 const QString &vbidev)
  224. +{
  225. +    (void)videodev;
  226. +    (void)audiodev;
  227. +    (void)vbidev;
  228. +    (void)profile;
  229. +}
  230. +
  231. +// documented in recorderbase.cpp
  232. +bool R5000Recorder::PauseAndWait(int timeout)
  233. +{
  234. +    if (request_pause)
  235. +    {
  236. +        LOG(VB_RECORD, LOG_INFO, LOC +
  237. +            QString("PauseAndWait(%1) -- pause").arg(timeout));
  238. +        if (!IsPaused(true))
  239. +        {
  240. +            StopStreaming();
  241. +            paused = true;
  242. +            pauseWait.wakeAll();
  243. +            if (tvrec)
  244. +                tvrec->RecorderPaused();
  245. +        }
  246. +        QMutex unpause_lock;
  247. +        unpause_lock.lock();
  248. +        unpauseWait.wait(&unpause_lock, timeout);
  249. +    }
  250. +    if (!request_pause && IsPaused(true))
  251. +    {
  252. +        LOG(VB_RECORD, LOG_INFO, LOC +
  253. +            QString("PauseAndWait(%1) -- unpause").arg(timeout));
  254. +        StartStreaming();
  255. +        paused = false;
  256. +    }
  257. +    return paused;
  258. +}
  259. +
  260. +void R5000Recorder::SetStreamData(void)
  261. +{
  262. +    _stream_data->AddMPEGSPListener(this);
  263. +
  264. +    if (_stream_data->DesiredProgram() >= 0)
  265. +        _stream_data->SetDesiredProgram(_stream_data->DesiredProgram());
  266. +}
  267. +
  268. +void R5000Recorder::HandleSingleProgramPAT(ProgramAssociationTable *pat)
  269. +{
  270. +    if (!pat)
  271. +    {
  272. +        LOG(VB_RECORD, LOG_DEBUG, LOC + "HandleSingleProgramPAT(NULL)");
  273. +        return;
  274. +    }
  275. +    int next = (pat->tsheader()->ContinuityCounter()+1)&0xf;
  276. +    pat->tsheader()->SetContinuityCounter(next);
  277. +    BufferedWrite(*(reinterpret_cast<const TSPacket*>(pat->tsheader())));
  278. +}
  279. +
  280. +void R5000Recorder::HandleSingleProgramPMT(ProgramMapTable *pmt)
  281. +{
  282. +    if (!pmt)
  283. +    {
  284. +        LOG(VB_RECORD, LOG_DEBUG, LOC + "HandleSingleProgramPMT(NULL)");
  285. +        return;
  286. +    }
  287. +    int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf;
  288. +    pmt->tsheader()->SetContinuityCounter(next);
  289. +    BufferedWrite(*(reinterpret_cast<const TSPacket*>(pmt->tsheader())));
  290. +}
  291. Index: libs/libmythtv/tv_rec.h
  292. ===================================================================
  293. --- libs/libmythtv/tv_rec.h (revision 1)
  294. +++ libs/libmythtv/tv_rec.h (revision 4)
  295. @@ -46,6 +46,7 @@
  296.  class V4LChannel;
  297.  class HDHRChannel;
  298.  class CetonChannel;
  299. +class R5000Channel;
  300.  
  301.  class MPEGStreamData;
  302.  class ProgramMapTable;
  303. @@ -264,6 +265,7 @@
  304.                         bool enter_power_save_mode);
  305.      void CloseChannel(void);
  306.      DTVChannel *GetDTVChannel(void);
  307. +    R5000Channel *GetR5000Channel(void);
  308.      V4LChannel *GetV4LChannel(void);
  309.  
  310.      bool SetupSignalMonitor(
  311. Index: libs/libmythtv/r5000signalmonitor.cpp
  312. ===================================================================
  313. --- libs/libmythtv/r5000signalmonitor.cpp   (revision 0)
  314. +++ libs/libmythtv/r5000signalmonitor.cpp   (revision 4)
  315. @@ -0,0 +1,294 @@
  316. +// -*- Mode: c++ -*-
  317. +// Copyright (c) 2006, Daniel Thor Kristjansson
  318. +
  319. +#include <pthread.h>
  320. +#include <fcntl.h>
  321. +#include <unistd.h>
  322. +#include <sys/select.h>
  323. +
  324. +#include "mythcontext.h"
  325. +#include "mythdbcon.h"
  326. +#include "atscstreamdata.h"
  327. +#include "mpegtables.h"
  328. +#include "atsctables.h"
  329. +#include "r5000channel.h"
  330. +#include "r5000signalmonitor.h"
  331. +
  332. +#define LOC QString("R5kSM(%1): ").arg(channel->GetDevice())
  333. +#define LOC_WARN QString("R5kSM(%1), Warning: ").arg(channel->GetDevice())
  334. +#define LOC_ERR QString("R5kSM(%1), Error: ").arg(channel->GetDevice())
  335. +
  336. +const uint R5000SignalMonitor::kPowerTimeout  = 3000; /* ms */
  337. +const uint R5000SignalMonitor::kBufferTimeout = 5000; /* ms */
  338. +
  339. +QMap<void*,uint> R5000SignalMonitor::pat_keys;
  340. +QMutex           R5000SignalMonitor::pat_keys_lock;
  341. +
  342. +/** \fn R5000SignalMonitor::R5000SignalMonitor(int,R5000Channel*,uint,const char*)
  343. + *  \brief Initializes signal lock and signal values.
  344. + *
  345. + *   Start() must be called to actually begin continuous
  346. + *   signal monitoring. The timeout is set to 3 seconds,
  347. + *   and the signal threshold is initialized to 0%.
  348. + *
  349. + *  \param db_cardnum Recorder number to monitor,
  350. + *                    if this is less than 0, SIGNAL events will not be
  351. + *                    sent to the frontend even if SetNotifyFrontend(true)
  352. + *                    is called.
  353. + *  \param _channel R5000Channel for card
  354. + *  \param _flags   Flags to start with
  355. + *  \param _name    Name for Qt signal debugging
  356. + */
  357. +R5000SignalMonitor::R5000SignalMonitor(
  358. +    int db_cardnum,
  359. +    R5000Channel *_channel,
  360. +    uint64_t _flags, const char *_name) :
  361. +    DTVSignalMonitor(db_cardnum, _channel, _flags),
  362. +    dtvMonitorRunning(false),
  363. +    stb_needs_retune(true),
  364. +    stb_needs_to_wait_for_pat(false),
  365. +    stb_needs_to_wait_for_power(false)
  366. +{
  367. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC + "ctor");
  368. +
  369. +    signalStrength.SetThreshold(65);
  370. +
  371. +    AddFlags(kSigMon_WaitForSig);
  372. +
  373. +    stb_needs_retune =
  374. +        (R5000Device::kAVCPowerOff == _channel->GetPowerState());
  375. +}
  376. +
  377. +/** \fn R5000SignalMonitor::~R5000SignalMonitor()
  378. + *  \brief Stops signal monitoring and table monitoring threads.
  379. + */
  380. +R5000SignalMonitor::~R5000SignalMonitor()
  381. +{
  382. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC + "dtor");
  383. +    Stop();
  384. +}
  385. +
  386. +/** \fn R5000SignalMonitor::Stop(void)
  387. + *  \brief Stop signal monitoring and table monitoring threads.
  388. + */
  389. +void R5000SignalMonitor::Stop(void)
  390. +{
  391. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC + "Stop() -- begin");
  392. +    SignalMonitor::Stop();
  393. +    if (dtvMonitorRunning)
  394. +    {
  395. +        dtvMonitorRunning = false;
  396. +        pthread_join(table_monitor_thread, NULL);
  397. +    }
  398. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC + "Stop() -- end");
  399. +}
  400. +
  401. +void R5000SignalMonitor::HandlePAT(const ProgramAssociationTable *pat)
  402. +{
  403. +    AddFlags(kDTVSigMon_PATSeen);
  404. +
  405. +    R5000Channel *fwchan = dynamic_cast<R5000Channel*>(channel);
  406. +    if (!fwchan)
  407. +        return;
  408. +
  409. +    bool crc_bogus = !fwchan->GetR5000Device()->IsSTBBufferCleared();
  410. +    if (crc_bogus && stb_needs_to_wait_for_pat &&
  411. +        (stb_wait_for_pat_timer.elapsed() < (int)kBufferTimeout))
  412. +    {
  413. +        LOG(VB_CHANNEL, LOG_DEBUG, LOC + "HandlePAT() ignoring PAT");
  414. +        uint tsid = pat->TransportStreamID();
  415. +        GetStreamData()->SetVersionPAT(tsid, -1,0);
  416. +        return;
  417. +    }
  418. +
  419. +    if (crc_bogus && stb_needs_to_wait_for_pat)
  420. +    {
  421. +        LOG(VB_GENERAL, LOG_DEBUG, LOC_WARN + "Wait for valid PAT timed out");
  422. +        stb_needs_to_wait_for_pat = false;
  423. +    }
  424. +
  425. +    DTVSignalMonitor::HandlePAT(pat);
  426. +}
  427. +
  428. +void R5000SignalMonitor::HandlePMT(uint pnum, const ProgramMapTable *pmt)
  429. +{
  430. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC + "HandlePMT()");
  431. +
  432. +    AddFlags(kDTVSigMon_PMTSeen);
  433. +
  434. +    if (!HasFlags(kDTVSigMon_PATMatch))
  435. +    {
  436. +        GetStreamData()->SetVersionPMT(pnum, -1,0);
  437. +        LOG(VB_CHANNEL, LOG_DEBUG, LOC + "HandlePMT() ignoring PMT");
  438. +        return;
  439. +    }
  440. +
  441. +    DTVSignalMonitor::HandlePMT(pnum, pmt);
  442. +}
  443. +
  444. +void *R5000SignalMonitor::TableMonitorThread(void *param)
  445. +{
  446. +    R5000SignalMonitor *mon = (R5000SignalMonitor*) param;
  447. +    mon->RunTableMonitor();
  448. +    return NULL;
  449. +}
  450. +
  451. +void R5000SignalMonitor::RunTableMonitor(void)
  452. +{
  453. +    stb_needs_to_wait_for_pat = true;
  454. +    stb_wait_for_pat_timer.start();
  455. +    dtvMonitorRunning = true;
  456. +
  457. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC + "RunTableMonitor(): -- begin");
  458. +
  459. +    R5000Channel *lchan = dynamic_cast<R5000Channel*>(channel);
  460. +    if (!lchan)
  461. +    {
  462. +        LOG(VB_CHANNEL, LOG_DEBUG, LOC + "RunTableMonitor(): -- err end");
  463. +        dtvMonitorRunning = false;
  464. +        return;
  465. +    }
  466. +
  467. +    R5000Device *dev = lchan->GetR5000Device();
  468. +
  469. +    dev->OpenPort();
  470. +    dev->AddListener(this);
  471. +
  472. +    while (dtvMonitorRunning && GetStreamData())
  473. +        usleep(100000);
  474. +
  475. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC + "RunTableMonitor(): -- shutdown ");
  476. +
  477. +    dev->RemoveListener(this);
  478. +    dev->ClosePort();
  479. +
  480. +    dtvMonitorRunning = false;
  481. +
  482. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC + "RunTableMonitor(): -- end");
  483. +}
  484. +
  485. +void R5000SignalMonitor::AddData(const unsigned char *data, uint len)
  486. +{
  487. +    if (!dtvMonitorRunning)
  488. +        return;
  489. +
  490. +    if (GetStreamData())
  491. +        GetStreamData()->ProcessData((unsigned char *)data, len);
  492. +}
  493. +
  494. +/** \fn R5000SignalMonitor::UpdateValues(void)
  495. + *  \brief Fills in frontend stats and emits status Qt signals.
  496. + *
  497. + *   This function uses five ioctl's FE_READ_SNR, FE_READ_SIGNAL_STRENGTH
  498. + *   FE_READ_BER, FE_READ_UNCORRECTED_BLOCKS, and FE_READ_STATUS to obtain
  499. + *   statistics from the frontend.
  500. + *
  501. + *   This is automatically called by MonitorLoop(), after Start()
  502. + *   has been used to start the signal monitoring thread.
  503. + */
  504. +void R5000SignalMonitor::UpdateValues(void)
  505. +{
  506. +    if (!running || exit)
  507. +        return;
  508. +
  509. +    //if (!IsChannelTuned())
  510. +      //  return;
  511. +
  512. +    if (dtvMonitorRunning)
  513. +    {
  514. +        EmitStatus();
  515. +        if (IsAllGood())
  516. +            SendMessageAllGood();
  517. +        // TODO dtv signals...
  518. +
  519. +        update_done = true;
  520. +        return;
  521. +    }
  522. +
  523. +    if (stb_needs_to_wait_for_power &&
  524. +        (stb_wait_for_power_timer.elapsed() < (int)kPowerTimeout))
  525. +    {
  526. +        return;
  527. +    }
  528. +    stb_needs_to_wait_for_power = false;
  529. +
  530. +    R5000Channel *fwchan = dynamic_cast<R5000Channel*>(channel);
  531. +    if (!fwchan)
  532. +        return;
  533. +
  534. +    if (HasFlags(kFWSigMon_WaitForPower) && !HasFlags(kFWSigMon_PowerMatch))
  535. +    {
  536. +        bool retried = false;
  537. +        while (true)
  538. +        {
  539. +            R5000Device::PowerState power = fwchan->GetPowerState();
  540. +            if (R5000Device::kAVCPowerOn == power)
  541. +            {
  542. +                AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch);
  543. +            }
  544. +            else if (R5000Device::kAVCPowerOff == power)
  545. +            {
  546. +                AddFlags(kFWSigMon_PowerSeen);
  547. +                fwchan->SetPowerState(true);
  548. +                stb_wait_for_power_timer.start();
  549. +                stb_needs_to_wait_for_power = true;
  550. +            }
  551. +            else
  552. +            {
  553. +                bool qfailed = (R5000Device::kAVCPowerQueryFailed == power);
  554. +                if (qfailed && !retried)
  555. +                {
  556. +                    retried = true;
  557. +                    continue;
  558. +                }
  559. +
  560. +                LOG(VB_RECORD, LOG_INFO, "Can't determine if STB is power on, "
  561. +                        "assuming it is...");
  562. +                AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch);
  563. +            }
  564. +            break;
  565. +        }
  566. +    }
  567. +
  568. +    bool isLocked = !HasFlags(kFWSigMon_WaitForPower) ||
  569. +        HasFlags(kFWSigMon_WaitForPower | kFWSigMon_PowerMatch);
  570. +
  571. +    if (isLocked && stb_needs_retune)
  572. +    {
  573. +        fwchan->Retune();
  574. +        isLocked = stb_needs_retune = false;
  575. +    }
  576. +
  577. +    // Set SignalMonitorValues from info from card.
  578. +    {
  579. +        QMutexLocker locker(&statusLock);
  580. +        signalStrength.SetValue(isLocked ? 100 : 0);
  581. +        signalLock.SetValue(isLocked ? 1 : 0);
  582. +    }
  583. +
  584. +    EmitStatus();
  585. +    if (IsAllGood())
  586. +        SendMessageAllGood();
  587. +
  588. +    // Start table monitoring if we are waiting on any table
  589. +    // and we have a lock.
  590. +    if (isLocked && GetStreamData() &&
  591. +        HasAnyFlag(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT |
  592. +                   kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT |
  593. +                   kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT))
  594. +    {
  595. +        pthread_create(&table_monitor_thread, NULL,
  596. +                       TableMonitorThread, this);
  597. +
  598. +        LOG(VB_CHANNEL, LOG_DEBUG, LOC + "UpdateValues() -- "
  599. +                "Waiting for table monitor to start");
  600. +
  601. +        while (!dtvMonitorRunning)
  602. +            usleep(50);
  603. +
  604. +        LOG(VB_CHANNEL, LOG_DEBUG, LOC + "UpdateValues() -- "
  605. +                "Table monitor started");
  606. +    }
  607. +
  608. +    update_done = true;
  609. +}
  610. Index: libs/libmythtv/tv_rec.cpp
  611. ===================================================================
  612. --- libs/libmythtv/tv_rec.cpp   (revision 1)
  613. +++ libs/libmythtv/tv_rec.cpp   (revision 4)
  614. @@ -29,6 +29,7 @@
  615.  #include "remoteutil.h"
  616.  #include "ringbuffer.h"
  617.  #include "mythlogging.h"
  618. +#include "r5000channel.h"
  619.  #include "v4lchannel.h"
  620.  #include "dialogbox.h"
  621.  #include "jobqueue.h"
  622. @@ -1155,6 +1156,15 @@
  623.      return dynamic_cast<DTVChannel*>(channel);
  624.  }
  625.  
  626. +R5000Channel *TVRec::GetR5000Channel(void)
  627. +{
  628. +#ifdef USING_R5000
  629. +    return dynamic_cast<R5000Channel*>(channel);
  630. +#else
  631. +    return NULL;
  632. +#endif // USING_R5000
  633. +}
  634. +
  635.  V4LChannel *TVRec::GetV4LChannel(void)
  636.  {
  637.  #ifdef USING_V4L2
  638. Index: libs/libmythtv/libmythtv.pro
  639. ===================================================================
  640. --- libs/libmythtv/libmythtv.pro    (revision 1)
  641. +++ libs/libmythtv/libmythtv.pro    (revision 4)
  642. @@ -664,6 +664,25 @@
  643.          DEFINES += USING_ASI
  644.      }
  645.  
  646. +    #Support for R5000 usb device
  647. +    using_r5000 {
  648. +        HEADERS += r5000channel.h           r5000recorder.h
  649. +        HEADERS += r5000signalmonitor.h     r5000device.h
  650. +   HEADERS += r5000/r5000.h            r5000/libusb_augment.h
  651. +   HEADERS += r5000/r5000_internal.h   r5000/r5000init.h
  652. +
  653. +        SOURCES += r5000channel.cpp         r5000recorder.cpp
  654. +        SOURCES += r5000signalmonitor.cpp   r5000device.cpp
  655. +   SOURCES += r5000/r5000.c            r5000/libusb_augment.c
  656. +   SOURCES += r5000/r5k_vip.c          r5000/r5k_pes.c
  657. +   SOURCES += r5000/r5k_sat.c          r5000/r5k_misc.c
  658. +   SOURCES += r5000/r5k_vip_buttons.c  r5000/r5k_directv_buttons.c
  659. +   SOURCES += r5000/r5k_dish6000_buttons.c
  660. +
  661. +   LIBS += -lusb
  662. +        DEFINES += USING_R5000
  663. +    }
  664. +
  665.      DEFINES += USING_BACKEND
  666.  }
  667.  
  668. Index: libs/libmythtv/transporteditor.cpp
  669. ===================================================================
  670. --- libs/libmythtv/transporteditor.cpp  (revision 1)
  671. +++ libs/libmythtv/transporteditor.cpp  (revision 4)
  672. @@ -739,7 +739,8 @@
  673.          left->addChild(new Modulation(id, nType));
  674.      }
  675.      else if ((CardUtil::FIREWIRE == nType) ||
  676. -             (CardUtil::FREEBOX  == nType))
  677. +             (CardUtil::FREEBOX  == nType) ||
  678. +             (CardUtil::R5000    == nType))
  679.      {
  680.          left->addChild(new DTVStandard(id, true, true));
  681.      }
  682. Index: libs/libmythtv/r5000device.cpp
  683. ===================================================================
  684. --- libs/libmythtv/r5000device.cpp  (revision 0)
  685. +++ libs/libmythtv/r5000device.cpp  (revision 4)
  686. @@ -0,0 +1,464 @@
  687. +/**
  688. + *  R5000Device
  689. + *  Copyright (c) 2008 by Alan Nisota
  690. + *  Copyright (c) 2005 by Jim Westfall
  691. + *  Distributed as part of MythTV under GPL v2 and later.
  692. + */
  693. +
  694. +// C++ headers
  695. +#include <algorithm>
  696. +
  697. +// Qt headers
  698. +#include <QMap>
  699. +
  700. +// for usleep
  701. +#include <unistd.h>
  702. +
  703. +// MythTV headers
  704. +#include "r5000device.h"
  705. +#include "mythcontext.h"
  706. +#include "mythlogging.h"
  707. +#include "pespacket.h"
  708. +#include "mthread.h"
  709. +#include "mythtimer.h"
  710. +
  711. +#define LOC      QString("R5kDev: ")
  712. +#define LOC_WARN QString("R5kDev, Warning: ")
  713. +#define LOC_ERR  QString("R5kDev, Error: ")
  714. +
  715. +static int r5k_init = 0;
  716. +QMap<uint64_t,QString> R5000Device::s_id_to_model;
  717. +QMutex                 R5000Device::s_static_lock;
  718. +
  719. +unsigned int r5000_device_tspacket_handler(unsigned char *tspacket, int len, void *callback_data)
  720. +{
  721. +    R5000Device *fw = (R5000Device*) callback_data;
  722. +    if (! fw)
  723. +        return 0;
  724. +    if (len > 0)
  725. +        fw->BroadcastToListeners(tspacket, len);
  726. +    return 1;
  727. +}
  728. +
  729. +void r5000_msg(char * msg)
  730. +{
  731. +    LOG(VB_GENERAL, LOG_INFO, LOC +
  732. +        QString("R5kLib: ") + msg);
  733. +}
  734. +
  735. +class R5kPriv
  736. +{
  737. +  public:
  738. +    R5kPriv() :
  739. +        reset_timer_on(false),
  740. +        run_port_handler(false), is_port_handler_running(false),
  741. +        channel(-1),
  742. +        is_streaming(false)
  743. +    {
  744. +    }
  745. +
  746. +    bool             reset_timer_on;
  747. +    MythTimer        reset_timer;
  748. +
  749. +    bool             run_port_handler;
  750. +    bool             is_port_handler_running;
  751. +    QMutex           start_stop_port_handler_lock;
  752. +
  753. +    int              channel;
  754. +
  755. +    bool             is_streaming;
  756. +
  757. +    QDateTime        stop_streaming_timer;
  758. +    pthread_t        port_handler_thread;
  759. +
  760. +    static QMutex           s_lock;
  761. +};
  762. +QMutex          R5kPriv::s_lock;
  763. +
  764. +//callback functions
  765. +void *r5000_device_port_handler_thunk(void *param);
  766. +
  767. +R5000Device::R5000Device(int type, QString serial) :
  768. +    m_type(type),
  769. +    m_serial(serial),
  770. +    m_last_channel(""),      m_last_crc(0),
  771. +    m_buffer_cleared(true), m_open_port_cnt(0),
  772. +    m_lock(),          m_priv(new R5kPriv())
  773. +{
  774. +    QMutexLocker locker(&s_static_lock);
  775. +    usbdev = NULL;
  776. +    if (! r5k_init)
  777. +      r5k_init = r5000_init(r5000_msg);
  778. +}
  779. +
  780. +R5000Device::~R5000Device()
  781. +{
  782. +    if (usbdev)
  783. +    {
  784. +        LOG(VB_GENERAL, LOG_DEBUG, LOC_ERR + "ctor called with open port");
  785. +        while (usbdev)
  786. +            ClosePort();
  787. +    }
  788. +
  789. +    if (m_priv)
  790. +    {
  791. +        delete m_priv;
  792. +        m_priv = NULL;
  793. +    }
  794. +}
  795. +
  796. +void R5000Device::AddListener(TSDataListener *listener)
  797. +{
  798. +    QMutexLocker locker(&m_lock);
  799. +    if (listener)
  800. +    {
  801. +        vector<TSDataListener*>::iterator it =
  802. +            find(m_listeners.begin(), m_listeners.end(), listener);
  803. +
  804. +        if (it == m_listeners.end())
  805. +            m_listeners.push_back(listener);
  806. +    }
  807. +
  808. +    LOG(VB_RECORD, LOG_INFO, LOC +
  809. +        QString("AddListener() %1").arg(m_listeners.size()));
  810. +    if (!m_listeners.empty())
  811. +    {
  812. +        StartStreaming();
  813. +    }
  814. +}
  815. +
  816. +void R5000Device::RemoveListener(TSDataListener *listener)
  817. +{
  818. +    QMutexLocker locker(&m_lock);
  819. +    vector<TSDataListener*>::iterator it = m_listeners.end();
  820. +
  821. +    do
  822. +    {
  823. +        it = find(m_listeners.begin(), m_listeners.end(), listener);
  824. +        if (it != m_listeners.end())
  825. +            m_listeners.erase(it);
  826. +    }
  827. +    while (it != m_listeners.end());
  828. +
  829. +    LOG(VB_RECORD, LOG_INFO, LOC +
  830. +        QString("RemoveListener() %1").arg(m_listeners.size()));
  831. +    if (m_listeners.empty())
  832. +    {
  833. +        StopStreaming();
  834. +    }
  835. +}
  836. +
  837. +bool R5000Device::StartStreaming(void)
  838. +{
  839. +    if (m_priv->is_streaming)
  840. +        return m_priv->is_streaming;
  841. +
  842. +    if (! usbdev)
  843. +    {
  844. +        LOG(VB_GENERAL, LOG_DEBUG, LOC_ERR + "Device not open");
  845. +        return false;
  846. +    }
  847. +    if (r5000_start_stream(usbdev))
  848. +    {
  849. +        m_priv->is_streaming = true;
  850. +    }
  851. +    else
  852. +    {
  853. +        LOG(VB_GENERAL, LOG_DEBUG, LOC_ERR + "Starting A/V streaming ");
  854. +    }
  855. +
  856. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "Starting A/V streaming -- done");
  857. +
  858. +    return m_priv->is_streaming;
  859. +}
  860. +
  861. +bool R5000Device::StopStreaming(void)
  862. +{
  863. +    if (m_priv->is_streaming)
  864. +    {
  865. +        LOG(VB_RECORD, LOG_DEBUG, LOC + "Stopping A/V streaming -- really");
  866. +
  867. +        m_priv->is_streaming = false;
  868. +
  869. +        r5000_stop_stream(usbdev);
  870. +    }
  871. +
  872. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "Stopped A/V streaming");
  873. +
  874. +    return true;
  875. +}
  876. +
  877. +bool R5000Device::SetPowerState(bool on)
  878. +{
  879. +    QMutexLocker locker(&m_lock);
  880. +    QString cmdStr = (on) ? "on" : "off";
  881. +    LOG(VB_RECORD, LOG_DEBUG, LOC + QString("Powering %1").arg(cmdStr));
  882. +    r5000_power_on_off(usbdev, on);
  883. +    return true;
  884. +}
  885. +
  886. +R5000Device::PowerState R5000Device::GetPowerState(void)
  887. +{
  888. +    QMutexLocker locker(&m_lock);
  889. +    int on_off;
  890. +
  891. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC + "Requesting STB Power State");
  892. +    on_off = r5000_get_power_state(usbdev);
  893. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC + (on_off ? "On" : "Off"));
  894. +    return on_off ? kAVCPowerOn : kAVCPowerOff;
  895. +}
  896. +
  897. +bool R5000Device::SetChannel(const QString &panel_model,
  898. +                                const QString &channel, uint mpeg_prog)
  899. +{
  900. +    LOG(VB_CHANNEL, LOG_DEBUG, QString("SetChannel(model %1, chan %2 mpeg_prog %3)")
  901. +            .arg(panel_model).arg(channel).arg(mpeg_prog));
  902. +
  903. +    QMutexLocker locker(&m_lock);
  904. +    LOG(VB_CHANNEL, LOG_DEBUG, "SetChannel() -- locked");
  905. +    if (! r5000_change_channel(usbdev, channel.toAscii().constData(), mpeg_prog))
  906. +        LOG(VB_GENERAL, LOG_DEBUG, LOC + "Failed to set channel");
  907. +    return true;
  908. +}
  909. +
  910. +void R5000Device::BroadcastToListeners(
  911. +    const unsigned char *data, uint dataSize)
  912. +{
  913. +    QMutexLocker locker(&m_lock);
  914. +    if ((dataSize >= TSPacket::kSize) && (data[0] == SYNC_BYTE) &&
  915. +        ((data[1] & 0x1f) == 0) && (data[2] == 0))
  916. +    {
  917. +        ProcessPATPacket(*((const TSPacket*)data));
  918. +    }
  919. +
  920. +    vector<TSDataListener*>::iterator it = m_listeners.begin();
  921. +    for (; it != m_listeners.end(); ++it)
  922. +        (*it)->AddData(data, dataSize);
  923. +}
  924. +
  925. +void R5000Device::SetLastChannel(const QString &channel)
  926. +{
  927. +    m_buffer_cleared = (channel == m_last_channel);
  928. +    m_last_channel   = channel;
  929. +
  930. +    LOG(VB_GENERAL, LOG_DEBUG, QString("SetLastChannel(%1): cleared: %2")
  931. +            .arg(channel).arg(m_buffer_cleared ? "yes" : "no"));
  932. +}
  933. +
  934. +void R5000Device::ProcessPATPacket(const TSPacket &tspacket)
  935. +{
  936. +    if (!tspacket.TransportError() && !tspacket.Scrambled() &&
  937. +        tspacket.HasPayload() && tspacket.PayloadStart() && !tspacket.PID())
  938. +    {
  939. +        PESPacket pes = PESPacket::View(tspacket);
  940. +        uint crc = pes.CalcCRC();
  941. +        m_buffer_cleared |= (crc != m_last_crc);
  942. +        m_last_crc = crc;
  943. +#if 0
  944. +        LOG(VB_RECORD, LOG_DEBUG, LOC +
  945. +                QString("ProcessPATPacket: CRC 0x%1 cleared: %2")
  946. +                .arg(crc,0,16).arg(m_buffer_cleared ? "yes" : "no"));
  947. +#endif
  948. +    }
  949. +    else
  950. +    {
  951. +        LOG(VB_GENERAL, LOG_DEBUG, LOC_ERR + "Can't handle large PAT's");
  952. +    }
  953. +}
  954. +
  955. +QString R5000Device::GetModelName(uint vendor_id, uint model_id)
  956. +{
  957. +    QMutexLocker locker(&s_static_lock);
  958. +/*
  959. +    if (s_id_to_model.empty())
  960. +        fw_init(s_id_to_model);
  961. +
  962. +    QString ret = s_id_to_model[(((uint64_t) vendor_id) << 32) | model_id];
  963. +
  964. +    if (ret.isEmpty())
  965. +        return "GENERIC";
  966. +*/
  967. +    return "R5000";
  968. +}
  969. +
  970. +bool R5000Device::IsSTBSupported(const QString &panel_model)
  971. +{
  972. +    return true;
  973. +}
  974. +
  975. +bool R5000Device::OpenPort(void)
  976. +{
  977. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "Starting Port Handler Thread");
  978. +    QMutexLocker mlocker(&m_lock);
  979. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "Starting Port Handler Thread -- locked");
  980. +    if (usbdev)
  981. +    {
  982. +        m_open_port_cnt++;
  983. +        return true;
  984. +    }
  985. +
  986. +    if (m_serial.length())
  987. +    {
  988. +      LOG(VB_RECORD, LOG_DEBUG, LOC + QString("Opening R5000 device type %1 with serial#: "+ m_serial).arg(m_type));
  989. +      usbdev = r5000_open((r5ktype_t)m_type, r5000_device_tspacket_handler, this, m_serial.toAscii().constData());
  990. +    }
  991. +    else
  992. +    {
  993. +      LOG(VB_RECORD, LOG_DEBUG, LOC + "Opening R5000 device with unknown serial#");
  994. +      usbdev = r5000_open((r5ktype_t)m_type, r5000_device_tspacket_handler, this, NULL);
  995. +    }
  996. +    if (! usbdev)
  997. +    {
  998. +        LOG(VB_GENERAL, LOG_DEBUG, LOC + "Failed to open R5000 device");
  999. +        return false;
  1000. +    }
  1001. +
  1002. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "Starting port handler thread");
  1003. +    m_priv->run_port_handler = true;
  1004. +    pthread_create(&m_priv->port_handler_thread, NULL,
  1005. +                   r5000_device_port_handler_thunk, this);
  1006. +
  1007. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "Waiting for port handler thread to start");
  1008. +    while (!m_priv->is_port_handler_running)
  1009. +    {
  1010. +        m_lock.unlock();
  1011. +        usleep(5000);
  1012. +        m_lock.lock();
  1013. +    }
  1014. +
  1015. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "Port handler thread started");
  1016. +
  1017. +    m_open_port_cnt++;
  1018. +
  1019. +    return true;
  1020. +}
  1021. +
  1022. +bool R5000Device::ClosePort(void)
  1023. +{
  1024. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "Stopping Port Handler Thread");
  1025. +    QMutexLocker locker(&m_priv->start_stop_port_handler_lock);
  1026. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "Stopping Port Handler Thread -- locked");
  1027. +
  1028. +    QMutexLocker mlocker(&m_lock);
  1029. +
  1030. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "ClosePort()");
  1031. +
  1032. +    if (m_open_port_cnt < 1)
  1033. +        return false;
  1034. +
  1035. +    m_open_port_cnt--;
  1036. +
  1037. +    if (m_open_port_cnt != 0)
  1038. +        return true;
  1039. +
  1040. +    if (!usbdev)
  1041. +        return false;
  1042. +
  1043. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "Waiting for port handler thread to stop");
  1044. +    m_priv->run_port_handler = false;
  1045. +    while (m_priv->is_port_handler_running)
  1046. +    {
  1047. +        m_lock.unlock();
  1048. +        usleep(5000);
  1049. +        m_lock.lock();
  1050. +    }
  1051. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "Joining port handler thread");
  1052. +    pthread_join(m_priv->port_handler_thread, NULL);
  1053. +
  1054. +    r5000_close(usbdev);
  1055. +    usbdev = NULL;
  1056. +
  1057. +    return true;
  1058. +}
  1059. +
  1060. +void *r5000_device_port_handler_thunk(void *param)
  1061. +{
  1062. +    R5000Device *mon = (R5000Device*) param;
  1063. +    mon->RunPortHandler();
  1064. +    return NULL;
  1065. +}
  1066. +
  1067. +void R5000Device::RunPortHandler(void)
  1068. +{
  1069. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "RunPortHandler -- start");
  1070. +    m_lock.lock();
  1071. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "RunPortHandler -- got first lock");
  1072. +    m_priv->is_port_handler_running = true;
  1073. +    m_lock.unlock();
  1074. +
  1075. +    while (m_priv->run_port_handler)
  1076. +    {
  1077. +        if (m_priv->is_streaming)
  1078. +        {
  1079. +            // This will timeout after 10ms regardless of data availability
  1080. +            r5000_loop_iterate(usbdev, 10);
  1081. +        }
  1082. +        else
  1083. +        {
  1084. +            usleep(10000);
  1085. +        }
  1086. +    }
  1087. +
  1088. +    m_lock.lock();
  1089. +    m_priv->is_port_handler_running = false;
  1090. +    m_lock.unlock();
  1091. +    LOG(VB_RECORD, LOG_DEBUG, LOC + "RunPortHandler -- end");
  1092. +}
  1093. +
  1094. +QStringList R5000Device::GetSTBList(void)
  1095. +{
  1096. +    QStringList STBList;
  1097. +    int i;
  1098. +    r5kenum_t r5k_stbs;
  1099. +    if (! r5k_init)
  1100. +    {
  1101. +        r5k_init = r5000_init(r5000_msg);
  1102. +        if (! r5k_init)
  1103. +            return STBList;
  1104. +    }
  1105. +    if (! r5000_find_stbs(&r5k_stbs))
  1106. +        LOG(VB_GENERAL, LOG_DEBUG, LOC + "Locating R5000 devices failed."
  1107. +                                    "  This may be a permission problem");
  1108. +
  1109. +    for (i = 0; i < r5k_stbs.count; i++)
  1110. +        STBList.append((char *)r5k_stbs.serial[i]);
  1111. +    return STBList;
  1112. +}
  1113. +
  1114. +int R5000Device::GetDeviceType(const QString &r5ktype)
  1115. +{
  1116. +    QString type = r5ktype.toUpper();
  1117. +    if (type == "DIRECTV")
  1118. +    {
  1119. +        return R5K_STB_DIRECTV;
  1120. +    }
  1121. +    else if ("VIP211/VIP622/DISH411" == type ||
  1122. +               "VIP211/VIP422"         == type ||
  1123. +               "VIP211"                == type ||
  1124. +               "VIP411"                == type)
  1125. +    {
  1126. +        return R5K_STB_VIP211;
  1127. +    }
  1128. +    else if ("STARCHOICE/DSR" == type)
  1129. +    {
  1130. +        return R5K_STB_DSR;
  1131. +    }
  1132. +    else if ("HDD-200" == type)
  1133. +    {
  1134. +        return R5K_STB_HDD;
  1135. +    }
  1136. +    else if ("VIP622"  == type ||
  1137. +               "VIP722"  == type ||
  1138. +               "BEV9242" == type)
  1139. +    {
  1140. +        return R5K_STB_VIP622;
  1141. +    }
  1142. +    else if ("DISH6000" == type)
  1143. +    {
  1144. +        return R5K_STB_DISH6000;
  1145. +    }
  1146. +    else
  1147. +    {
  1148. +      return R5K_STB_VIP211;
  1149. +    }
  1150. +}
  1151. Index: libs/libmythtv/cardutil.h
  1152. ===================================================================
  1153. --- libs/libmythtv/cardutil.h   (revision 1)
  1154. +++ libs/libmythtv/cardutil.h   (revision 4)
  1155. @@ -66,6 +66,7 @@
  1156.          DEMO      = 15,
  1157.          ASI       = 16,
  1158.          CETON     = 17,
  1159. +   R5000     = 18,
  1160.      };
  1161.  
  1162.      static enum CARD_TYPES toCardType(const QString &name)
  1163. @@ -106,6 +107,8 @@
  1164.              return ASI;
  1165.          if ("CETON" == name)
  1166.              return CETON;
  1167. +   if ("R5000" == name)
  1168. +            return R5000;
  1169.          return ERROR_UNKNOWN;
  1170.      }
  1171.  
  1172. @@ -115,7 +118,8 @@
  1173.              (rawtype != "DVB")       && (rawtype != "FIREWIRE") &&
  1174.              (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX")  &&
  1175.              (rawtype != "IMPORT")    && (rawtype != "DEMO")     &&
  1176. -            (rawtype != "ASI")       && (rawtype != "CETON");
  1177. +            (rawtype != "ASI")       && (rawtype != "CETON") &&
  1178. +            (rawtype != "R5000") ;
  1179.      }
  1180.  
  1181.      static bool         IsV4L(const QString &rawtype)
  1182. @@ -135,7 +139,8 @@
  1183.          return
  1184.              (rawtype == "FIREWIRE")  || (rawtype == "HDPVR") ||
  1185.              (rawtype == "IMPORT")    || (rawtype == "DEMO")  ||
  1186. -            (rawtype == "GO7007")    || (rawtype == "MJPEG");
  1187. +            (rawtype == "GO7007")    || (rawtype == "MJPEG") ||
  1188. +            (rawtype == "R5000");
  1189.      }
  1190.      static QString      GetScanableCardTypes(void);
  1191.  
  1192. @@ -182,7 +187,7 @@
  1193.              (rawtype == "FIREWIRE")  || (rawtype == "HDHOMERUN") ||
  1194.              (rawtype == "FREEBOX")   || (rawtype == "ASI")       ||
  1195.              (rawtype == "IMPORT")    || (rawtype == "DEMO")      ||
  1196. -            (rawtype == "CETON");
  1197. +            (rawtype == "CETON")     || (rawtype == "R5000");
  1198.      }
  1199.  
  1200.      // Card creation and deletion
  1201. Index: libs/libmythtv/r5000channel.cpp
  1202. ===================================================================
  1203. --- libs/libmythtv/r5000channel.cpp (revision 0)
  1204. +++ libs/libmythtv/r5000channel.cpp (revision 4)
  1205. @@ -0,0 +1,215 @@
  1206. +/**
  1207. + *  R5000Channel
  1208. + *  Copyright (c) 2005 by Jim Westfall, Dave Abrahams
  1209. + *  Copyright (c) 2006 by Daniel Kristjansson
  1210. + *  Distributed as part of MythTV under GPL v2 and later.
  1211. + */
  1212. +
  1213. +#include "mythcontext.h"
  1214. +#include "tv_rec.h"
  1215. +#include "r5000channel.h"
  1216. +
  1217. +#define LOC QString("R5kChan(%1): ").arg(GetDevice())
  1218. +#define LOC_WARN QString("R5kChan(%1), Warning: ").arg(GetDevice())
  1219. +#define LOC_ERR QString("R5kChan(%1), Error: ").arg(GetDevice())
  1220. +
  1221. +R5000Channel::R5000Channel(TVRec *parent, const QString &_videodevice,const QString &_r5ktype, bool pocc) :
  1222. +    DTVChannel(parent),
  1223. +    videodevice(_videodevice),
  1224. +    power_on_channel_change(pocc),
  1225. +    device(NULL),
  1226. +    current_channel(""),
  1227. +    current_mpeg_prog(0),
  1228. +    isopen(false),
  1229. +    tuning_delay(0)
  1230. +{
  1231. +    int type = R5000Device::GetDeviceType(_r5ktype);
  1232. +    device = new R5000Device(type, videodevice);
  1233. +
  1234. +    InitializeInputs();
  1235. +}
  1236. +
  1237. +bool R5000Channel::SetChannelByString(const QString &channum)
  1238. +{
  1239. +    QString loc = LOC + QString("SetChannelByString(%1)").arg(channum);
  1240. +    bool ok = false;
  1241. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC);
  1242. +
  1243. +    InputMap::const_iterator it = m_inputs.find(m_currentInputID);
  1244. +    if (it == m_inputs.end())
  1245. +        return false;
  1246. +
  1247. +    QString tvformat, modulation, freqtable, freqid, dtv_si_std;
  1248. +    int finetune;
  1249. +    uint64_t frequency;
  1250. +    int mpeg_prog_num;
  1251. +    uint atsc_major, atsc_minor, mplexid, tsid, netid;
  1252. +    if (!ChannelUtil::GetChannelData(
  1253. +        (*it)->sourceid, channum,
  1254. +        tvformat, modulation, freqtable, freqid,
  1255. +        finetune, frequency,
  1256. +        dtv_si_std, mpeg_prog_num, atsc_major, atsc_minor, tsid, netid,
  1257. +        mplexid, m_commfree))
  1258. +    {
  1259. +        LOG(VB_GENERAL, LOG_DEBUG, LOC + " " + QString(
  1260. +                    "Requested channel '%1' is on input '%2' "
  1261. +                    "which is in a busy input group")
  1262. +                .arg(channum).arg(m_currentInputID));
  1263. +
  1264. +        return false;
  1265. +    }
  1266. +    uint mplexid_restriction;
  1267. +    if (!IsInputAvailable(m_currentInputID, mplexid_restriction))
  1268. +    {
  1269. +        LOG(VB_GENERAL, LOG_DEBUG, LOC + " " + QString(
  1270. +                    "Requested channel '%1' is on input '%2' "
  1271. +                    "which is in a busy input group")
  1272. +                .arg(channum).arg(m_currentInputID));
  1273. +
  1274. +        return false;
  1275. +    }
  1276. +
  1277. +    if (!(*it)->externalChanger.isEmpty())
  1278. +    {
  1279. +        ok = ChangeExternalChannel((*it)->externalChanger, freqid);
  1280. +        // -1 resets any state without executing a channel change
  1281. +        device->SetChannel(fw_opts.model, 0, mpeg_prog_num);
  1282. +        SetSIStandard("mpeg");
  1283. +        SetDTVInfo(0,0,0,0,1);
  1284. +    }
  1285. +    else
  1286. +    {
  1287. +        ok = isopen && SetChannelByNumber(freqid, mpeg_prog_num);
  1288. +    }
  1289. +
  1290. +    if (ok)
  1291. +    {
  1292. +        if (tuning_delay) {
  1293. +            LOG(VB_CHANNEL, LOG_DEBUG, LOC + " " + QString(
  1294. +                    "Adding additional delay: %1ms").arg(tuning_delay));
  1295. +            usleep(tuning_delay * 1000);
  1296. +        }
  1297. +        // Set the current channum to the new channel's channum
  1298. +        QString tmp = channum;
  1299. +        tmp.detach();
  1300. +        m_curchannelname = tmp;
  1301. +        tmp.detach();
  1302. +        (*it)->startChanNum = tmp;
  1303. +    }
  1304. +
  1305. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC + " " + ((ok) ? "success" : "failure"));
  1306. +
  1307. +    return ok;
  1308. +}
  1309. +
  1310. +bool R5000Channel::Open(void)
  1311. +{
  1312. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC + "Open()");
  1313. +
  1314. +    if (m_inputs.find(m_currentInputID) == m_inputs.end())
  1315. +        return false;
  1316. +
  1317. +    if (!device)
  1318. +        return false;
  1319. +
  1320. +    if (isopen)
  1321. +        return true;
  1322. +
  1323. +    if (!device->OpenPort())
  1324. +        return false;
  1325. +
  1326. +    isopen = true;
  1327. +
  1328. +    return true;
  1329. +}
  1330. +
  1331. +void R5000Channel::Close(void)
  1332. +{
  1333. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC + "Close()");
  1334. +    if (isopen)
  1335. +    {
  1336. +        device->ClosePort();
  1337. +        isopen = false;
  1338. +    }
  1339. +}
  1340. +
  1341. +QString R5000Channel::GetDevice(void) const
  1342. +{
  1343. +    return videodevice;
  1344. +}
  1345. +
  1346. +bool R5000Channel::SetPowerState(bool on)
  1347. +{
  1348. +    if (!isopen)
  1349. +    {
  1350. +        LOG(VB_GENERAL, LOG_DEBUG, LOC_ERR +
  1351. +                "SetPowerState() called on closed R5000Channel.");
  1352. +
  1353. +        return false;
  1354. +    }
  1355. +    if (power_on_channel_change)
  1356. +        return R5000Device::kAVCPowerOn;
  1357. +
  1358. +    return device->SetPowerState(on);
  1359. +}
  1360. +
  1361. +R5000Device::PowerState R5000Channel::GetPowerState(void) const
  1362. +{
  1363. +    if (!isopen)
  1364. +    {
  1365. +        LOG(VB_GENERAL, LOG_DEBUG, LOC_ERR +
  1366. +                "GetPowerState() called on closed R5000Channel.");
  1367. +
  1368. +        return R5000Device::kAVCPowerQueryFailed;
  1369. +    }
  1370. +
  1371. +    if (power_on_channel_change)
  1372. +        return R5000Device::kAVCPowerOn;
  1373. +
  1374. +    return device->GetPowerState();
  1375. +}
  1376. +
  1377. +bool R5000Channel::Retune(void)
  1378. +{
  1379. +    LOG(VB_CHANNEL, LOG_DEBUG, LOC + "Retune()");
  1380. +
  1381. +    if (! power_on_channel_change && R5000Device::kAVCPowerOff == GetPowerState())
  1382. +    {
  1383. +        LOG(VB_GENERAL, LOG_DEBUG, LOC_ERR +
  1384. +                "STB is turned off, must be on to retune.");
  1385. +
  1386. +        return false;
  1387. +    }
  1388. +
  1389. +    if (current_channel.length())
  1390. +        return SetChannelByNumber(current_channel, current_mpeg_prog);
  1391. +
  1392. +    return false;
  1393. +}
  1394. +
  1395. +bool R5000Channel::SetChannelByNumber(const QString &channel, int mpeg_prog)
  1396. +{
  1397. +    LOG(VB_CHANNEL, LOG_DEBUG, QString("SetChannelByNumber(%1)").arg(channel));
  1398. +    current_channel = channel;
  1399. +    current_mpeg_prog = mpeg_prog;
  1400. +
  1401. +    if (! power_on_channel_change && R5000Device::kAVCPowerOff == GetPowerState())
  1402. +    {
  1403. +        LOG(VB_GENERAL, LOG_DEBUG, LOC_WARN +
  1404. +                "STB is turned off, must be on to set channel.");
  1405. +
  1406. +        SetSIStandard("mpeg");
  1407. +        SetDTVInfo(0,0,0,0,1);
  1408. +
  1409. +        return true; // signal monitor will call retune later...
  1410. +    }
  1411. +
  1412. +    QString tmpchan = (power_on_channel_change ? "P" : "") + channel;
  1413. +    if (! device->SetChannel(fw_opts.model, tmpchan, mpeg_prog))
  1414. +        return false;
  1415. +
  1416. +    SetSIStandard("mpeg");
  1417. +    SetDTVInfo(0,0,0,0,1);
  1418. +
  1419. +    return true;
  1420. +}
  1421. Index: libs/libmythtv/channelbase.cpp
  1422. ===================================================================
  1423. --- libs/libmythtv/channelbase.cpp  (revision 1)
  1424. +++ libs/libmythtv/channelbase.cpp  (revision 4)
  1425. @@ -26,6 +26,7 @@
  1426.  #include "firewirechannel.h"
  1427.  #include "mythcorecontext.h"
  1428.  #include "cetonchannel.h"
  1429. +#include "r5000channel.h"
  1430.  #include "dummychannel.h"
  1431.  #include "tvremoteutil.h"
  1432.  #include "channelutil.h"
  1433. @@ -1197,6 +1198,15 @@
  1434.          channel = new CetonChannel(tvrec, genOpt.videodev);
  1435.  #endif
  1436.      }
  1437. +    else if (genOpt.cardtype == "R5000")
  1438. +    {
  1439. +#ifdef USING_R5000
  1440. +        channel = new R5000Channel(tvrec, genOpt.videodev, fwOpt.model, dvbOpt.dvb_on_demand);
  1441. +        dynamic_cast<R5000Channel*>(channel)->SetSlowTuning(
  1442. +            dvbOpt.dvb_tuning_delay);
  1443. +#endif
  1444. +    }
  1445. +
  1446.      else if (CardUtil::IsV4L(genOpt.cardtype))
  1447.      {
  1448.  #ifdef USING_V4L2
  1449. Index: libs/libmythtv/r5000recorder.h
  1450. ===================================================================
  1451. --- libs/libmythtv/r5000recorder.h  (revision 0)
  1452. +++ libs/libmythtv/r5000recorder.h  (revision 4)
  1453. @@ -0,0 +1,69 @@
  1454. +/**
  1455. + *  R5000Recorder
  1456. + *  Copyright (c) 2005 by Jim Westfall
  1457. + *  Distributed as part of MythTV under GPL v2 and later.
  1458. + */
  1459. +
  1460. +#ifndef _R5000RECORDER_H_
  1461. +#define _R5000RECORDER_H_
  1462. +
  1463. +// MythTV headers
  1464. +#include "dtvrecorder.h"
  1465. +#include "tspacket.h"
  1466. +#include "streamlisteners.h"
  1467. +
  1468. +class TVRec;
  1469. +class R5000Channel;
  1470. +
  1471. +/** \class R5000Recorder
  1472. + *  \brief This is a specialization of DTVRecorder used to
  1473. + *         handle DVB and ATSC streams from a firewire input.
  1474. + *
  1475. + *  \sa DTVRecorder
  1476. + */
  1477. +class R5000Recorder : public DTVRecorder,
  1478. +//                         public MPEGSingleProgramStreamListener,
  1479. +                         public TSDataListener
  1480. +{
  1481. +    friend class MPEGStreamData;
  1482. +    friend class TSPacketProcessor;
  1483. +
  1484. +  public:
  1485. +    R5000Recorder(TVRec *rec, R5000Channel *chan);
  1486. +    virtual ~R5000Recorder();
  1487. +
  1488. +    // Commands
  1489. +    bool Open(void);
  1490. +    void Close(void);
  1491. +
  1492. +    void StartStreaming(void);
  1493. +    void StopStreaming(void);
  1494. +
  1495. +    void StartRecording(void);
  1496. +    void run(void);
  1497. +    bool PauseAndWait(int timeout = 100);
  1498. +
  1499. +    void AddData(const unsigned char *data, uint dataSize);
  1500. +    bool ProcessTSPacket(const TSPacket &tspacket);
  1501. +
  1502. +    // Sets
  1503. +    void SetOptionsFromProfile(RecordingProfile *profile,
  1504. +                               const QString &videodev,
  1505. +                               const QString &audiodev,
  1506. +                               const QString &vbidev);
  1507. +    void SetStreamData(void);
  1508. +
  1509. +    // MPEG Single Program
  1510. +    void HandleSingleProgramPAT(ProgramAssociationTable*);
  1511. +    void HandleSingleProgramPMT(ProgramMapTable*);
  1512. +
  1513. +  protected:
  1514. +    R5000Recorder(TVRec *rec);
  1515. +
  1516. +  private:
  1517. +    R5000Channel       *channel;
  1518. +    bool                   isopen;
  1519. +    vector<unsigned char>  buffer;
  1520. +};
  1521. +
  1522. +#endif //  _R5000RECORDER_H_
  1523. Index: libs/libmythtv/r5000channel.h
  1524. ===================================================================
  1525. --- libs/libmythtv/r5000channel.h   (revision 0)
  1526. +++ libs/libmythtv/r5000channel.h   (revision 4)
  1527. @@ -0,0 +1,56 @@
  1528. +/**
  1529. + *  R5000Channel
  1530. + *  Copyright (c) 2008 by Alan Nisota
  1531. + *  Copyright (c) 2005 by Jim Westfall and Dave Abrahams
  1532. + *  Distributed as part of MythTV under GPL v2 and later.
  1533. + */
  1534. +
  1535. +#ifndef _R5000CHANNEL_H_
  1536. +#define _R5000CHANNEL_H_
  1537. +
  1538. +#include "tv_rec.h"
  1539. +#include "dtvchannel.h"
  1540. +#include "r5000device.h"
  1541. +
  1542. +class R5000Channel : public DTVChannel
  1543. +{
  1544. +  public:
  1545. +    R5000Channel(TVRec *parent, const QString &videodevice,
  1546. +                    const QString &_r5ktype, bool pocc);
  1547. +    ~R5000Channel() { Close(); }
  1548. +
  1549. +    // Commands
  1550. +    virtual bool Open(void);
  1551. +    virtual void Close(void);
  1552. +
  1553. +    virtual bool TuneMultiplex(uint /*mplexid*/, QString /*inputname*/)
  1554. +        { return false; }
  1555. +    virtual bool Tune(const DTVMultiplex &/*tuning*/, QString /*inputname*/)
  1556. +        { return false; }
  1557. +    virtual bool Retune(void);
  1558. +
  1559. +    // Sets
  1560. +    virtual bool SetChannelByString(const QString &chan);
  1561. +    virtual bool SetChannelByNumber(const QString &channel, int mpeg_prog);
  1562. +    virtual bool SetPowerState(bool on);
  1563. +    void SetSlowTuning(uint how_slow_in_ms)
  1564. +        { tuning_delay = how_slow_in_ms; }
  1565. +
  1566. +    // Gets
  1567. +    virtual bool IsOpen(void) const { return isopen; }
  1568. +    virtual R5000Device::PowerState GetPowerState(void) const;
  1569. +    virtual QString GetDevice(void) const;
  1570. +    virtual R5000Device *GetR5000Device(void) { return device; }
  1571. +
  1572. +  protected:
  1573. +    QString            videodevice;
  1574. +    FireWireDBOptions  fw_opts;
  1575. +    bool               power_on_channel_change;
  1576. +    R5000Device        *device;
  1577. +    QString            current_channel;
  1578. +    uint               current_mpeg_prog;
  1579. +    bool               isopen;
  1580. +    uint               tuning_delay;///< Extra delay to add
  1581. +};
  1582. +
  1583. +#endif // _R5000CHANNEL_H_
  1584. Index: libs/libmythtv/r5000signalmonitor.h
  1585. ===================================================================
  1586. --- libs/libmythtv/r5000signalmonitor.h (revision 0)
  1587. +++ libs/libmythtv/r5000signalmonitor.h (revision 4)
  1588. @@ -0,0 +1,61 @@
  1589. +// -*- Mode: c++ -*-
  1590. +
  1591. +#ifndef _R5000SIGNALMONITOR_H_
  1592. +#define _R5000SIGNALMONITOR_H_
  1593. +
  1594. +#include <qmap.h>
  1595. +#include <qmutex.h>
  1596. +#include <qdatetime.h>
  1597. +
  1598. +#include "dtvsignalmonitor.h"
  1599. +#include "r5000device.h"
  1600. +//#include "util.h"
  1601. +
  1602. +class R5000Channel;
  1603. +
  1604. +class R5000SignalMonitor : public DTVSignalMonitor, public TSDataListener
  1605. +{
  1606. +  public:
  1607. +    R5000SignalMonitor(int db_cardnum, R5000Channel *_channel,
  1608. +                          uint64_t _flags = kFWSigMon_WaitForPower,
  1609. +                          const char *_name = "R5000SignalMonitor");
  1610. +
  1611. +    virtual void HandlePAT(const ProgramAssociationTable*);
  1612. +    virtual void HandlePMT(uint, const ProgramMapTable*);
  1613. +
  1614. +    void Stop(void);
  1615. +
  1616. +  protected:
  1617. +    R5000SignalMonitor(void);
  1618. +    R5000SignalMonitor(const R5000SignalMonitor&);
  1619. +    virtual ~R5000SignalMonitor();
  1620. +
  1621. +    virtual void UpdateValues(void);
  1622. +
  1623. +    static void *TableMonitorThread(void *param);
  1624. +    void RunTableMonitor(void);
  1625. +
  1626. +    bool SupportsTSMonitoring(void);
  1627. +
  1628. +    void AddData(const unsigned char *data, uint dataSize);
  1629. +
  1630. +  public:
  1631. +    static const uint kPowerTimeout;
  1632. +    static const uint kBufferTimeout;
  1633. +
  1634. +  protected:
  1635. +    bool               dtvMonitorRunning;
  1636. +    pthread_t          table_monitor_thread;
  1637. +    bool               stb_needs_retune;
  1638. +    bool               stb_needs_to_wait_for_pat;
  1639. +    bool               stb_needs_to_wait_for_power;
  1640. +    MythTimer          stb_wait_for_pat_timer;
  1641. +    MythTimer          stb_wait_for_power_timer;
  1642. +
  1643. +    vector<unsigned char> buffer;
  1644. +
  1645. +    static QMap<void*,uint> pat_keys;
  1646. +    static QMutex           pat_keys_lock;
  1647. +};
  1648. +
  1649. +#endif // _R5000SIGNALMONITOR_H_
  1650. Index: libs/libmythtv/signalmonitor.cpp
  1651. ===================================================================
  1652. --- libs/libmythtv/signalmonitor.cpp    (revision 1)
  1653. +++ libs/libmythtv/signalmonitor.cpp    (revision 4)
  1654. @@ -54,6 +54,11 @@
  1655.  #   include "cetonchannel.h"
  1656.  #endif
  1657.  
  1658. +#ifdef USING_R5000
  1659. +#   include "r5000signalmonitor.h"
  1660. +#   include "r5000channel.h"
  1661. +#endif
  1662. +
  1663.  #undef DBG_SM
  1664.  #define DBG_SM(FUNC, MSG) LOG(VB_CHANNEL, LOG_DEBUG, \
  1665.      QString("SM(%1)::%2: %3").arg(channel->GetDevice()).arg(FUNC).arg(MSG))
  1666. @@ -154,6 +159,15 @@
  1667.      }
  1668.  #endif
  1669.  
  1670. +#ifdef USING_R5000
  1671. +    if (cardtype.toUpper() == "R5000")
  1672. +    {
  1673. +        R5000Channel *fc = dynamic_cast<R5000Channel*>(channel);
  1674. +        if (fc)
  1675. +            signalMonitor = new R5000SignalMonitor(db_cardnum, fc);
  1676. +    }
  1677. +#endif
  1678. +
  1679.      if (!signalMonitor && channel)
  1680.      {
  1681.          signalMonitor = new ScriptSignalMonitor(db_cardnum, channel);
  1682. Index: libs/libmythtv/videosource.cpp
  1683. ===================================================================
  1684. --- libs/libmythtv/videosource.cpp  (revision 1)
  1685. +++ libs/libmythtv/videosource.cpp  (revision 4)
  1686. @@ -35,6 +35,7 @@
  1687.  #include "frequencies.h"
  1688.  #include "diseqcsettings.h"
  1689.  #include "firewiredevice.h"
  1690. +#include "r5000device.h"
  1691.  #include "compat.h"
  1692.  #include "mythdb.h"
  1693.  #include "mythdirs.h"
  1694. @@ -1530,6 +1531,101 @@
  1695.      _oldValue = v;
  1696.  };
  1697.  
  1698. +class R5000TuningDelay : public SpinBoxSetting, public CaptureCardDBStorage
  1699. +{
  1700. +  public:
  1701. +    R5000TuningDelay(const CaptureCard &parent) :
  1702. +        SpinBoxSetting(this, 0, 2000, 25),
  1703. +        CaptureCardDBStorage(this, parent, "dvb_tuning_delay")
  1704. +    {
  1705. +        setLabel(QObject::tr("R5000 Tuning Delay (msec)"));
  1706. +        setHelpText(
  1707. +            QObject::tr("Some STBS (for example the ViP boxes) require "
  1708. +                        "additional time after setting the channel before starting recording.  "
  1709. +                        "This is especially necessary if different channels use different codecs."));
  1710. +    };
  1711. +};
  1712. +
  1713. +class R5000SendPowerBeforeChannel : public CheckBoxSetting, public CaptureCardDBStorage
  1714. +{
  1715. +  public:
  1716. +    R5000SendPowerBeforeChannel(const CaptureCard &parent) :
  1717. +        CheckBoxSetting(this),
  1718. +        CaptureCardDBStorage(this, parent, "dvb_on_demand")
  1719. +    {
  1720. +        setValue(false);
  1721. +        setLabel(QObject::tr("Turn on before Channel Change"));
  1722. +        setHelpText(QObject::tr(
  1723. +                        "On some STBs klike the ViP211, the power on/off "
  1724. +                        "detection isn't reliable if you let the box go into "
  1725. +                        "standby.  This forces a 'power-on' command before "
  1726. +                        "changing channels.  This will very likely do the "
  1727. +                        "wrong thing for non ViP boxes."));
  1728. +
  1729. +    };
  1730. +};
  1731. +
  1732. +class R5000Serial : public ComboBoxSetting, public CaptureCardDBStorage
  1733. +{
  1734. +  public:
  1735. +    R5000Serial(const CaptureCard &parent) :
  1736. +        ComboBoxSetting(this),
  1737. +        CaptureCardDBStorage(this, parent, "videodevice")
  1738. +    {
  1739. +        setLabel(QObject::tr("Serial #"));
  1740. +#ifdef USING_R5000
  1741. +        QStringList serials = R5000Device::GetSTBList();
  1742. +        for (int i = 0; i < serials.size(); i++)
  1743. +        {
  1744. +            addSelection(serials[i]);
  1745. +        }
  1746. +#endif // USING_R5000
  1747. +    }
  1748. +};
  1749. +
  1750. +class R5000Model : public ComboBoxSetting, public CaptureCardDBStorage
  1751. +{
  1752. +  public:
  1753. +    R5000Model(const CaptureCard  &parent) :
  1754. +      ComboBoxSetting(this),
  1755. +      CaptureCardDBStorage(this, parent, "firewire_model")
  1756. +    {
  1757. +        setLabel(QObject::tr("R5000 STB type"));
  1758. +        addSelection("VIP211");
  1759. +        addSelection("VIP411");
  1760. +        addSelection("VIP622");
  1761. +        addSelection("VIP722");
  1762. +        addSelection("BEV9242");
  1763. +        addSelection("DISH6000");
  1764. +        addSelection("DIRECTV");
  1765. +        addSelection("STARCHOICE/DSR");
  1766. +        addSelection("HDD-200");
  1767. +        QString help = QObject::tr(
  1768. +            "Choose the type of R5000 enabled STB you are using.");
  1769. +        setHelpText(help);
  1770. +    }
  1771. +};
  1772. +
  1773. +class R5000ConfigurationGroup : public VerticalConfigurationGroup
  1774. +{
  1775. +  public:
  1776. +    R5000ConfigurationGroup(CaptureCard& a_parent):
  1777. +       VerticalConfigurationGroup(false, true, false, false),
  1778. +       parent(a_parent)
  1779. +    {
  1780. +        setUseLabel(false);
  1781. +        addChild(new R5000SendPowerBeforeChannel(parent));
  1782. +        addChild(new R5000TuningDelay(parent));
  1783. +        addChild(new R5000Serial(parent));
  1784. +        addChild(new R5000Model(parent));
  1785. +        addChild(new EmptyAudioDevice(parent));
  1786. +        addChild(new EmptyVBIDevice(parent));
  1787. +    };
  1788. +
  1789. +  private:
  1790. +    CaptureCard &parent;
  1791. +};
  1792. +
  1793.  class IPTVHost : public LineEditSetting, public CaptureCardDBStorage
  1794.  {
  1795.    public:
  1796. @@ -2296,6 +2392,10 @@
  1797.      addTarget("CETON",     new CetonConfigurationGroup(parent));
  1798.  #endif // USING_CETON
  1799.  
  1800. +#ifdef USING_R5000
  1801. +    addTarget("R5000",     new R5000ConfigurationGroup(parent));
  1802. +#endif // USING_R5000
  1803. +
  1804.      // for testing without any actual tuner hardware:
  1805.      addTarget("IMPORT",    new ImportConfigurationGroup(parent));
  1806.      addTarget("DEMO",      new DemoConfigurationGroup(parent));
  1807. @@ -2509,6 +2609,10 @@
  1808.          QObject::tr("Ceton Cablecard tuner "), "CETON");
  1809.  #endif // USING_CETON
  1810.  
  1811. +#ifdef USING_R5000
  1812. +    setting->addSelection(QObject::tr("R5000 Capable STB"), "R5000");
  1813. +#endif // USING_R5000
  1814. +
  1815.      setting->addSelection(QObject::tr("Import test recorder"), "IMPORT");
  1816.      setting->addSelection(QObject::tr("Demo test recorder"),   "DEMO");
  1817.  }
  1818. Index: libs/libmythtv/r5000device.h
  1819. ===================================================================
  1820. --- libs/libmythtv/r5000device.h    (revision 0)
  1821. +++ libs/libmythtv/r5000device.h    (revision 4)
  1822. @@ -0,0 +1,110 @@
  1823. +/**
  1824. + *  R5000Device
  1825. + *  Copyright (c) 2005 by Jim Westfall
  1826. + *  Distributed as part of MythTV under GPL v2 and later.
  1827. + */
  1828. +
  1829. +#ifndef _R5000_DEVICE_H_
  1830. +#define _R5000_DEVICE_H_
  1831. +
  1832. +// C++ headers
  1833. +#include <vector>
  1834. +using namespace std;
  1835. +
  1836. +// Qt headers
  1837. +#include <qstring.h>
  1838. +#include <qmutex.h>
  1839. +
  1840. +// MythTV headers
  1841. +#include "streamlisteners.h"
  1842. +
  1843. +extern "C" {
  1844. +#include "r5000/r5000.h"
  1845. +}
  1846. +
  1847. +class TSPacket;
  1848. +class R5kPriv;
  1849. +class R5000Device
  1850. +{
  1851. +  public:
  1852. +
  1853. +    // Public enums
  1854. +    typedef enum
  1855. +    {
  1856. +        kAVCPowerOn,
  1857. +        kAVCPowerOff,
  1858. +        kAVCPowerUnknown,
  1859. +        kAVCPowerQueryFailed,
  1860. +    } PowerState;
  1861. +
  1862. +
  1863. +    // AVC param 0
  1864. +    typedef enum
  1865. +    {
  1866. +        kAVCPowerStateOn           = 0x70,
  1867. +        kAVCPowerStateOff          = 0x60,
  1868. +        kAVCPowerStateQuery        = 0x7f,
  1869. +    } IEEE1394UnitPowerParam0;
  1870. +
  1871. +    R5000Device(int type, QString serial);
  1872. +    ~R5000Device();
  1873. +
  1874. +    bool OpenPort(void);
  1875. +    bool ClosePort(void);
  1876. +    void RunPortHandler(void);
  1877. +
  1878. +    // Commands
  1879. +    virtual bool ResetBus(void) { return false; }
  1880. +
  1881. +    virtual void AddListener(TSDataListener*);
  1882. +    virtual void RemoveListener(TSDataListener*);
  1883. +
  1884. +    // Sets
  1885. +    virtual bool SetPowerState(bool on);
  1886. +    virtual bool SetChannel(const QString &panel_model,
  1887. +                            const QString &channel, uint mpeg_prog);
  1888. +
  1889. +    // Gets
  1890. +    bool IsSTBBufferCleared(void) const { return m_buffer_cleared; }
  1891. +
  1892. +    // non-const Gets
  1893. +    virtual PowerState GetPowerState(void);
  1894. +
  1895. +    // Statics
  1896. +    static bool IsSTBSupported(const QString &model);
  1897. +    static QString GetModelName(uint vendorid, uint modelid);
  1898. +    static QStringList GetSTBList(void);
  1899. +    static int GetDeviceType(const QString &r5ktype);
  1900. +    void BroadcastToListeners(
  1901. +        const unsigned char *data, uint dataSize);
  1902. +
  1903. +  protected:
  1904. +
  1905. +    bool GetSubunitInfo(uint8_t table[32]);
  1906. +
  1907. +    void SetLastChannel(const QString &channel);
  1908. +    void ProcessPATPacket(const TSPacket&);
  1909. +    bool StartStreaming(void);
  1910. +    bool StopStreaming(void);
  1911. +
  1912. +    int                      m_type;
  1913. +    QString                  m_serial;
  1914. +    uint                     m_subunitid;
  1915. +    uint                     m_speed;
  1916. +    QString                  m_last_channel;
  1917. +    uint                     m_last_crc;
  1918. +    bool                     m_buffer_cleared;
  1919. +
  1920. +    uint                     m_open_port_cnt;
  1921. +    vector<TSDataListener*>  m_listeners;
  1922. +    mutable QMutex           m_lock;
  1923. +
  1924. +    /// Vendor ID + Model ID to R5000Device STB model string
  1925. +    static QMap<uint64_t,QString> s_id_to_model;
  1926. +    static QMutex                 s_static_lock;
  1927. +private:
  1928. +    r5kdev_t                 *usbdev;
  1929. +    R5kPriv                  *m_priv;
  1930. +};
  1931. +
  1932. +#endif // _FIREWIRE_DEVICE_H_
  1933. Index: libs/libmythtv/recorderbase.cpp
  1934. ===================================================================
  1935. --- libs/libmythtv/recorderbase.cpp (revision 1)
  1936. +++ libs/libmythtv/recorderbase.cpp (revision 4)
  1937. @@ -9,12 +9,14 @@
  1938.  #include "firewirechannel.h"
  1939.  #include "importrecorder.h"
  1940.  #include "cetonrecorder.h"
  1941. +#include "r5000recorder.h"
  1942.  #include "dummychannel.h"
  1943.  #include "hdhrrecorder.h"
  1944.  #include "iptvrecorder.h"
  1945.  #include "mpegrecorder.h"
  1946.  #include "recorderbase.h"
  1947.  #include "cetonchannel.h"
  1948. +#include "r5000channel.h"
  1949.  #include "asirecorder.h"
  1950.  #include "dvbrecorder.h"
  1951.  #include "hdhrchannel.h"
  1952. @@ -578,6 +580,13 @@
  1953.          recorder = new ImportRecorder(tvrec);
  1954.  #endif
  1955.      }
  1956. +    else if (genOpt.cardtype == "R5000")
  1957. +    {
  1958. +#ifdef USING_R5000
  1959. +        recorder = new R5000Recorder(
  1960. +            tvrec, dynamic_cast<R5000Channel*>(channel));
  1961. +#endif // USING_R5000
  1962. +    }
  1963.      else if (CardUtil::IsV4L(genOpt.cardtype))
  1964.      {
  1965.  #ifdef USING_V4L2
  1966. Index: configure
  1967. ===================================================================
  1968. --- configure   (revision 1)
  1969. +++ configure   (revision 4)
  1970. @@ -119,6 +119,7 @@
  1971.    --disable-ivtv           disable ivtv support (PVR-x50) req. v4l2 support
  1972.    --disable-hdpvr          disable HD-PVR support
  1973.    --disable-dvb            disable DVB support
  1974. +  --disable-r5000          disable support for R5000 USB STBs
  1975.    --dvb-path=HDRLOC        location of directory containing
  1976.                             'linux/dvb/frontend.h', not the
  1977.                             directory with frontend.h [$dvb_path_default]
  1978. @@ -1514,6 +1515,7 @@
  1979.      hdpvr
  1980.      iptv
  1981.      ivtv
  1982. +    r5000
  1983.      asi
  1984.      joystick_menu
  1985.      libcec
  1986. @@ -2033,6 +2035,7 @@
  1987.  audio_oss_deps_any="soundcard_h sys_soundcard_h"
  1988.  dvb_deps="backend"
  1989.  firewire_deps="backend"
  1990. +r5000_deps="backend"
  1991.  iptv_deps="backend"
  1992.  ivtv_deps="backend v4l2"
  1993.  hdpvr_deps="backend v4l2"
  1994. @@ -2239,6 +2242,7 @@
  1995.  enable hdpvr
  1996.  enable iptv
  1997.  enable ivtv
  1998. +enable r5000
  1999.  enable asi
  2000.  enable lamemp3
  2001.  enable libass
  2002. @@ -5016,6 +5020,7 @@
  2003.    echo "HDHomeRun support         ${hdhomerun-no}"
  2004.    echo "Ceton support             ${ceton-no}"
  2005.    echo "IPTV support              ${iptv-no}"
  2006. +  echo "R5000 support             ${r5000-no}"
  2007.    echo "ASI support               ${asi-no}"
  2008.  fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement