Ticket #1648: firewire-sm-v37.patch
| File firewire-sm-v37.patch, 180.4 KB (added by , 20 years ago) |
|---|
-
configure
2450 2450 2451 2451 if test x"$firewire_cable_box" = x"yes" ; then 2452 2452 firewire_cable_box="no" 2453 if has_library libiec61883 -a has_library libavc1394 ; then 2453 libavc_5_3="no" 2454 if has_library libiec61883 -a \ 2455 has_library libavc1394 -a \ 2456 has_library librom1394; then 2454 2457 if test x`which pkg-config 2>/dev/null` != x"" ; then 2455 2458 if `pkg-config --atleast-version 0.5.0 libavc1394` ; then 2456 2459 if `pkg-config --atleast-version 1.0.0 libiec61883` ; then 2457 2460 firewire_cable_box="yes" 2461 if `pkg-config --atleast-version 0.5.3 libavc1394` ; then 2462 libavc_5_3="yes" 2463 fi 2458 2464 fi 2459 2465 fi 2460 2466 fi … … 3434 3440 if test x"$darwin" = x"yes" ; then 3435 3441 echo "CONFIG_MAC_AVC=$mac_avc" >> $MYTH_CONFIG_MAK 3436 3442 else 3437 echo "CONFIG_FIREWIRE_LIBS=-lraw1394 -liec61883 -lavc1394" >> $MYTH_CONFIG_MAK 3443 echo "CONFIG_FIREWIRE_LIBS=-lraw1394 -liec61883 -lavc1394 -lrom1394" >> $MYTH_CONFIG_MAK 3444 if test x"$libavc_5_3" = x"yes" ; then 3445 CCONFIG="$CCONFIG using_libavc_5_3" 3446 fi 3438 3447 fi 3439 3448 fi 3440 3449 -
libs/libmythtv/firewirechannel.cpp
1 1 /** 2 2 * FirewireChannel 3 * Copyright (c) 2005 by Jim Westfall 4 * SA3250HD support Copyright (c) 2005 by Matt Porter 5 * SA4200HD/Alternate 3250 support Copyright (c) 2006 by Chris Ingrassia 3 * Copyright (c) 2005 by Jim Westfall, Dave Abrahams 4 * Copyright (c) 2006 by Daniel Kristjansson 6 5 * Distributed as part of MythTV under GPL v2 and later. 7 6 */ 8 7 9 10 #include <iostream>11 8 #include "mythcontext.h" 9 #include "tv_rec.h" 10 #include "linuxfirewiredevice.h" 11 #include "darwinfirewiredevice.h" 12 12 #include "firewirechannel.h" 13 13 14 class TVRec; 14 #define LOC QString("FireChan(%1): ").arg(GetDevice()) 15 #define LOC_WARN QString("FireChan(%1), Warning: ").arg(GetDevice()) 16 #define LOC_ERR QString("FireChan(%1), Error: ").arg(GetDevice()) 15 17 16 #define LOC QString("FireChan: ") 17 #define LOC_ERR QString("FireChan, Error: ") 18 19 #ifndef AVC1394_PANEL_COMMAND_PASS_THROUGH 20 #define AVC1394_PANEL_COMMAND_PASS_THROUGH 0x000007C00 18 FirewireChannel::FirewireChannel(TVRec *parent, const QString &_videodevice, 19 const FireWireDBOptions &firewire_opts) : 20 DTVChannel(parent), 21 videodevice(_videodevice), 22 fw_opts(firewire_opts), 23 device(NULL), 24 current_channel(0), 25 isopen(false) 26 { 27 uint64_t guid = videodevice.toULongLong(NULL, 16); 28 uint subunitid = 0; // we only support first tuner on STB... 29 #ifdef USING_LINUX_FIREWIRE 30 device = new LinuxFirewireDevice( 31 guid, subunitid, fw_opts.speed, 32 LinuxFirewireDevice::kConnectionP2P == (uint) fw_opts.connection); 33 #elif USING_OSX_FIREWIRE 34 device = new DarwinFirewireDevice(guid, subunitid, fw_opts.speed); 21 35 #endif 22 36 23 #ifndef AVC1394_PANEL_OPERATION_0 24 #define AVC1394_PANEL_OPERATION_0 0x000000020 25 #endif 37 InitializeInputs(); 38 } 26 39 27 #define DCT6200_CMD0 (AVC1394_CTYPE_CONTROL | \ 28 AVC1394_SUBUNIT_TYPE_PANEL | \ 29 AVC1394_SUBUNIT_ID_0 | \30 AVC1394_PANEL_COMMAND_PASS_THROUGH | \31 AVC1394_PANEL_OPERATION_0)40 bool FirewireChannel::SetChannelByString(const QString &channum) 41 { 42 InputMap::const_iterator it = inputs.find(currentInputID); 43 if (it == inputs.end()) 44 return false; 32 45 33 // SA3250HD defines 34 #define AVC1394_SA3250_OPERAND_KEY_PRESS 0xE7 35 #define AVC1394_SA3250_OPERAND_KEY_RELEASE 0x67 46 // Fetch tuning data from the database. 47 QString tvformat, modulation, freqtable, freqid, dtv_si_std; 48 int finetune; 49 uint64_t frequency; 50 int mpeg_prog_num; 51 uint atsc_major, atsc_minor, mplexid, tsid, netid; 36 52 37 #define SA3250_CMD0 (AVC1394_CTYPE_CONTROL | \ 38 AVC1394_SUBUNIT_TYPE_PANEL | \ 39 AVC1394_SUBUNIT_ID_0 | \ 40 AVC1394_PANEL_COMMAND_PASS_THROUGH) 41 #define SA3250_CMD1 (0x04 << 24) 42 #define SA3250_CMD2 0xff000000 53 if (!ChannelUtil::GetChannelData( 54 (*it)->sourceid, channum, 55 tvformat, modulation, freqtable, freqid, 56 finetune, frequency, 57 dtv_si_std, mpeg_prog_num, atsc_major, atsc_minor, tsid, netid, 58 mplexid, commfree)) 59 { 60 return false; 61 } 43 62 44 // power defines 45 #define AVC1394_CMD_OPERAND_POWER_STATE 0x7F 46 #define STB_POWER_STATE (AVC1394_CTYPE_STATUS | \ 47 AVC1394_SUBUNIT_TYPE_UNIT | \ 48 AVC1394_SUBUNIT_ID_IGNORE | \ 49 AVC1394_COMMAND_POWER | \ 50 AVC1394_CMD_OPERAND_POWER_STATE) 63 bool ok = false; 64 if (!(*it)->externalChanger.isEmpty()) 65 ok = ChangeExternalChannel(freqid); 66 else 67 { 68 uint ichan = freqid.toUInt(&ok); 69 ok = ok && isopen && SetChannelByNumber(ichan); 70 } 51 71 52 #define STB_POWER_ON (AVC1394_CTYPE_CONTROL | \ 53 AVC1394_SUBUNIT_TYPE_UNIT | \ 54 AVC1394_SUBUNIT_ID_IGNORE | \ 55 AVC1394_COMMAND_POWER | \ 56 AVC1394_CMD_OPERAND_POWER_ON) 72 if (ok) 73 { 74 // Set the current channum to the new channel's channum 75 curchannelname = QDeepCopy<QString>(channum); 76 (*it)->startChanNum = QDeepCopy<QString>(channum); 77 } 57 78 58 static bool is_supported(const QString &model) 59 { 60 return ((model == "DCT-6200") || 61 (model == "SA3250HD") || 62 (model == "SA4200HD")); 79 return ok; 63 80 } 64 81 65 FirewireChannel::FirewireChannel(FireWireDBOptions firewire_opts, 66 TVRec *parent) 67 : FirewireChannelBase(parent), fw_opts(firewire_opts), fwhandle(NULL) 82 bool FirewireChannel::Open(void) 68 83 { 69 } 84 VERBOSE(VB_CHANNEL, LOC + "Open()"); 70 85 71 FirewireChannel::~FirewireChannel(void) 72 { 73 Close(); 74 } 86 if (inputs.find(currentInputID) == inputs.end()) 87 return false; 75 88 76 bool FirewireChannel::SetChannelByNumber(int channel) 77 { 78 // Change channel using internal changer 89 if (!device) 90 return false; 79 91 80 if (!is_supported(fw_opts.model)) 92 if (isopen) 93 return true; 94 95 InputMap::const_iterator it = inputs.find(currentInputID); 96 if (!FirewireDevice::IsSTBSupported(fw_opts.model) && 97 (*it)->externalChanger.isEmpty()) 81 98 { 82 99 VERBOSE(VB_IMPORTANT, LOC_ERR + 83 QString("Model: '%1' ").arg(fw_opts.model) +84 "is not supported by internal channel changer."); 100 QString("Model: '%1' is not supported.").arg(fw_opts.model)); 101 85 102 return false; 86 103 } 87 104 88 int dig[3]; 89 dig[0] = (channel % 1000) / 100; 90 dig[1] = (channel % 100) / 10; 91 dig[2] = (channel % 10); 105 if (!device->OpenPort()) 106 return false; 92 107 93 if (fw_opts.model == "DCT-6200") 94 { 95 VERBOSE(VB_CHANNEL, LOC + 96 QString("Channel1: %1%2%3 cmds: 0x%4, 0x%5, 0x%6") 97 .arg(dig[0]).arg(dig[1]) 98 .arg(dig[2]).arg(DCT6200_CMD0 | dig[0], 0, 16) 99 .arg(DCT6200_CMD0 | dig[1], 0, 16) 100 .arg(DCT6200_CMD0 | dig[2], 0, 16)); 108 isopen = true; 101 109 102 for (uint i = 0; i < 3 ;i++) 103 { 104 quadlet_t cmd[2] = { DCT6200_CMD0 | dig[i], 0x0, }; 105 if (!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 2, 1)) 106 { 107 VERBOSE(VB_IMPORTANT, "AVC transaction failed."); 108 return false; 109 } 110 usleep(500000); 111 } 112 } 113 else if (fw_opts.model == "SA3250HD") 110 return true; 111 } 112 113 void FirewireChannel::Close(void) 114 { 115 VERBOSE(VB_CHANNEL, LOC + "Close()"); 116 if (isopen) 114 117 { 115 dig[0] |= 0x30; 116 dig[1] |= 0x30; 117 dig[2] |= 0x30; 118 device->ClosePort(); 119 isopen = false; 120 } 121 } 118 122 119 quadlet_t cmd[3] = 120 { 121 SA3250_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS, 122 SA3250_CMD1 | (dig[2] << 16) | (dig[1] << 8) | dig[0], 123 SA3250_CMD2, 124 }; 123 bool FirewireChannel::SwitchToInput(const QString &input, const QString &chan) 124 { 125 int inputNum = GetInputByName(input); 126 if (inputNum < 0) 127 return false; 125 128 126 VERBOSE(VB_CHANNEL, LOC + 127 QString("Channel2: %1%2%3 cmds: 0x%4, 0x%5, 0x%6") 128 .arg(dig[0] & 0xf).arg(dig[1] & 0xf) 129 .arg(dig[2] & 0xf) 130 .arg(cmd[0], 0, 16).arg(cmd[1], 0, 16) 131 .arg(cmd[2], 0, 16)); 129 return SetChannelByString(chan); 130 } 132 131 133 if(!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 3, 1)) 134 { 135 VERBOSE(VB_IMPORTANT, "AVC transaction failed."); 136 return false; 137 } 132 bool FirewireChannel::SwitchToInput(int newInputNum, bool setstarting) 133 { 134 (void) setstarting; 138 135 139 cmd[0] = SA3250_CMD0 | AVC1394_SA3250_OPERAND_KEY_RELEASE;140 cmd[1] = SA3250_CMD1 | (dig[0] << 16) | (dig[1] << 8) | dig[2];141 cmd[2] = SA3250_CMD2;136 InputMap::const_iterator it = inputs.find(newInputNum); 137 if (it == inputs.end() || (*it)->startChanNum.isEmpty()) 138 return false; 142 139 143 VERBOSE(VB_CHANNEL, LOC + 144 QString("Channel3: %1%2%3 cmds: 0x%4, 0x%5, 0x%6") 145 .arg(dig[0] & 0xf).arg(dig[1] & 0xf) 146 .arg(dig[2] & 0xf) 147 .arg(cmd[0], 0, 16).arg(cmd[1], 0, 16) 148 .arg(cmd[2], 0, 16)); 140 return SetChannelByString((*it)->startChanNum); 141 } 149 142 150 if (!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 3, 1)) 151 { 152 VERBOSE(VB_IMPORTANT, "AVC transaction failed."); 153 return false; 154 } 155 } 156 else if (fw_opts.model == "SA4200HD") 143 QString FirewireChannel::GetDevice(void) const 144 { 145 return videodevice; 146 } 147 148 bool FirewireChannel::SetPowerState(bool on) 149 { 150 if (!isopen) 157 151 { 158 quadlet_t cmd[3] = 159 { 160 SA3250_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS, 161 SA3250_CMD1 | (channel << 8), 162 SA3250_CMD2, 163 }; 152 VERBOSE(VB_IMPORTANT, LOC_ERR + 153 "SetPowerState() called on closed FirewireChannel."); 164 154 165 VERBOSE(VB_CHANNEL, LOC + 166 QString("SA4200Channel: %1 cmds: 0x%2 0x%3 0x%4") 167 .arg(channel).arg(cmd[0], 0, 16) 168 .arg(cmd[1], 0, 16) 169 .arg(cmd[2], 0, 16)); 170 171 if (!avc1394_transaction_block(fwhandle, fw_opts.node, cmd, 3, 1)) 172 { 173 VERBOSE(VB_IMPORTANT, "AVC transaction failed."); 174 return false; 175 } 155 return false; 176 156 } 177 157 178 return true;158 return device->SetPowerState(on); 179 159 } 180 160 181 bool FirewireChannel::OpenFirewire(void) 161 FirewireDevice::PowerState FirewireChannel::GetPowerState(void) const 182 162 { 183 if (!is _supported(fw_opts.model))163 if (!isopen) 184 164 { 185 165 VERBOSE(VB_IMPORTANT, LOC_ERR + 186 QString("Model: '%1' ").arg(fw_opts.model) + 187 "is not supported by internal channel changer."); 188 return false; 189 } 166 "GetPowerState() called on closed FirewireChannel."); 190 167 191 // Open channel 192 fwhandle = raw1394_new_handle_on_port(fw_opts.port); 193 if (!fwhandle) 194 { 195 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to get handle " + 196 QString("for port: %1").arg(fw_opts.port)); 197 return false; 168 return FirewireDevice::kAVCPowerQueryFailed; 198 169 } 199 170 200 VERBOSE(VB_CHANNEL, LOC + "Allocated raw1394 handle " +201 QString("for port %1").arg(fw_opts.port)); 171 return device->GetPowerState(); 172 } 202 173 203 // verify node looks like a stb 204 if (!avc1394_check_subunit_type(fwhandle, fw_opts.node, 205 AVC1394_SUBUNIT_TYPE_TUNER)) 206 { 207 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("node %1 is not subunit " 208 "type tuner.").arg(fw_opts.node)); 209 CloseFirewire(); 210 return false; 211 } 174 bool FirewireChannel::Retune(void) 175 { 176 VERBOSE(VB_CHANNEL, LOC + "Retune()"); 212 177 213 if (!avc1394_check_subunit_type(fwhandle, fw_opts.node, 214 AVC1394_SUBUNIT_TYPE_PANEL)) 178 if (FirewireDevice::kAVCPowerOff == GetPowerState()) 215 179 { 216 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("node %1 is not subunit "217 " type panel.").arg(fw_opts.node));218 CloseFirewire(); 180 VERBOSE(VB_IMPORTANT, LOC_ERR + 181 "STB is turned off, must be on to retune."); 182 219 183 return false; 220 184 } 221 185 222 // check power, power on if off 223 if (GetPowerState() == Off) 224 { 225 quadlet_t *rval, response, cmd = STB_POWER_ON; 226 VERBOSE(VB_IMPORTANT, LOC + QString("Powering on (cmd: 0x%1)") 227 .arg(cmd, 0, 16)); 228 rval = avc1394_transaction_block(fwhandle, fw_opts.node, &cmd, 1, 1); 229 if (rval) 230 { 231 response = rval[0]; 186 if (current_channel) 187 return SetChannelByNumber(current_channel); 232 188 233 if (AVC1394_MASK_RESPONSE(response) == AVC1394_RESPONSE_ACCEPTED) 234 { 235 VERBOSE(VB_IMPORTANT, LOC + QString("Power on cmd successful " 236 "(0x%1)") 237 .arg(response, 0, 16)); 238 // allow some time for the stb to power on 239 sleep(3); 240 if (GetPowerState() == Off) 241 { 242 VERBOSE(VB_IMPORTANT, LOC + "STB is still off!?"); 243 return false; 244 } 245 return true; 246 } 247 else 248 { 249 VERBOSE(VB_IMPORTANT, LOC + QString("Power on cmd failed " 250 "(0x%1)") 251 .arg(response, 0, 16)); 252 return false; 253 } 254 } 255 else 256 { 257 VERBOSE(VB_IMPORTANT, LOC + "Power on cmd failed (no response)"); 258 return false; 259 } 260 } 261 return true; 189 return false; 262 190 } 263 191 264 void FirewireChannel::CloseFirewire(void)192 bool FirewireChannel::SetChannelByNumber(int channel) 265 193 { 266 VERBOSE(VB_CHANNEL, LOC + "Releasing raw1394 handle"); 267 raw1394_destroy_handle(fwhandle); 268 } 194 current_channel = channel; 269 195 270 FirewireChannel::PowerState FirewireChannel::GetPowerState(void) 271 { 272 quadlet_t *rval, response, cmd = STB_POWER_STATE; 273 274 VERBOSE(VB_CHANNEL, LOC + QString("Requesting STB Power State (cmd: 0x%1)") 275 .arg(STB_POWER_STATE, 0, 16)); 276 rval = avc1394_transaction_block(fwhandle, fw_opts.node, &cmd, 1, 1); 277 278 if (rval) 196 if (FirewireDevice::kAVCPowerOff == GetPowerState()) 279 197 { 280 response = rval[0]; 198 VERBOSE(VB_IMPORTANT, LOC_WARN + 199 "STB is turned off, must be on to set channel."); 281 200 282 if (AVC1394_MASK_RESPONSE(response) == AVC1394_RESPONSE_IMPLEMENTED) 283 { 284 if ((response & 0xFF) == AVC1394_CMD_OPERAND_POWER_ON) 285 { 286 VERBOSE(VB_CHANNEL, LOC + QString("STB Power State: ON (0x%1)") 287 .arg(response, 0, 16)); 288 return On; 289 } 290 else if ((response & 0xFF) == AVC1394_CMD_OPERAND_POWER_OFF) 291 { 292 VERBOSE(VB_IMPORTANT, LOC + QString("STB Power State: OFF " 293 "(0x%1)") 294 .arg(response, 0, 16)); 295 return Off; 296 } 297 else 298 { 299 VERBOSE(VB_CHANNEL, LOC + QString("STB Power State: " 300 "Unknown Response (0x%1)") 301 .arg(response, 0, 16)); 302 return Failed; 303 } 304 } 305 else 306 { 307 VERBOSE(VB_CHANNEL, LOC + QString("STB Power State: Failed (0x%1)") 308 .arg(response, 0, 16)); 309 return Failed; 310 } 201 SetSIStandard("mpeg"); 202 SetCachedATSCInfo(QString("%1-1").arg(channel)); 203 204 return true; // signal monitor will call retune later... 311 205 } 312 VERBOSE(VB_CHANNEL, LOC + "Failed to get STB Power State"); 313 return Failed; 206 207 if (!device->SetChannel(fw_opts.model, 0, channel)) 208 return false; 209 210 SetSIStandard("mpeg"); 211 SetCachedATSCInfo(QString("%1-1").arg(channel)); 212 213 return true; 314 214 } -
libs/libmythtv/firewirerecorderbase.h
1 /**2 * FirewireRecorderBase3 * Copyright (c) 2005 by Jim Westfall4 * Distributed as part of MythTV under GPL v2 and later.5 */6 7 #ifndef FIREWIRERECORDERBASE_H_8 #define FIREWIRERECORDERBASE_H_9 10 #include "dtvrecorder.h"11 #include "tsstats.h"12 #include "tspacket.h"13 #include "streamlisteners.h"14 15 /** \class FirewireRecorderBase16 * \brief This is a specialization of DTVRecorder used to17 * handle DVB and ATSC streams from a firewire input.18 *19 * \sa DTVRecorder20 */21 class FirewireRecorderBase : public DTVRecorder,22 public MPEGSingleProgramStreamListener23 {24 friend class MPEGStreamData;25 friend class TSPacketProcessor;26 27 public:28 FirewireRecorderBase(TVRec *rec);29 ~FirewireRecorderBase();30 31 // Commands32 void StartRecording(void);33 void ProcessTSPacket(const TSPacket &tspacket);34 bool PauseAndWait(int timeout = 100);35 36 // Sets37 void SetOptionsFromProfile(RecordingProfile *profile,38 const QString &videodev,39 const QString &audiodev,40 const QString &vbidev);41 void SetStreamData(MPEGStreamData*);42 43 // Gets44 MPEGStreamData* StreamData(void) { return _mpeg_stream_data; }45 46 // MPEG Single Program47 void HandleSingleProgramPAT(ProgramAssociationTable*);48 void HandleSingleProgramPMT(ProgramMapTable*);49 50 private:51 virtual void Close() = 0;52 virtual void start() = 0;53 virtual void stop() = 0;54 virtual bool grab_frames() = 0;55 56 MPEGStreamData *_mpeg_stream_data;57 TSStats _ts_stats;58 59 protected:60 static const int kTimeoutInSeconds;61 };62 63 #endif -
libs/libmythtv/firewirechannelbase.h
1 /**2 * FirewireChannelBase3 * Copyright (c) 2005 by Jim Westfall and Dave Abrahams4 * Distributed as part of MythTV under GPL v2 and later.5 */6 7 8 #ifndef LIBMYTHTV_FIREWIRECHANNELBASE_H9 #define LIBMYTHTV_FIREWIRECHANNELBASE_H10 11 #include <qstring.h>12 #include "tv_rec.h"13 #include "channelbase.h"14 15 #include "mythconfig.h"16 17 namespace AVS18 {19 class AVCDeviceController;20 class AVCDevice;21 }22 23 class FirewireChannelBase : public ChannelBase24 {25 public:26 FirewireChannelBase(TVRec *parent)27 : ChannelBase(parent), isopen(false) { }28 ~FirewireChannelBase() { Close(); }29 30 bool Open(void);31 void Close(void);32 33 // Sets34 bool SetChannelByString(const QString &chan);35 virtual bool SetChannelByNumber(int channel) = 0;36 37 // Gets38 bool IsOpen(void) const { return isopen; }39 40 // Commands41 bool SwitchToInput(const QString &inputname, const QString &chan);42 bool SwitchToInput(int newcapchannel, bool setstarting)43 { (void)newcapchannel; (void)setstarting; return false; }44 45 private:46 virtual bool OpenFirewire() = 0;47 virtual void CloseFirewire() = 0;48 49 protected:50 bool isopen;51 };52 53 #endif -
libs/libmythtv/firewiredevice.cpp
1 /** 2 * FirewireDevice 3 * Copyright (c) 2005 by Jim Westfall 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 // Qt headers 8 #include <qdeepcopy.h> 9 10 // MythTV headers 11 #include "linuxfirewiredevice.h" 12 #include "darwinfirewiredevice.h" 13 #include "mythcontext.h" 14 #include "pespacket.h" 15 16 #define LOC QString("FireDev(%1): ").arg(m_guid) 17 #define LOC_WARN QString("FireDev(%1), Warning: ").arg(m_guid) 18 #define LOC_ERR QString("FireDev(%1), Error: ").arg(m_guid) 19 20 21 AVCInfo::AVCInfo() : 22 port(-1), node(-1), 23 guid(0), specid(0), vendorid(0), modelid(0), 24 firmware_revision(0), product_name(QString::null) 25 { 26 } 27 28 AVCInfo::AVCInfo(const AVCInfo &o) : 29 port(o.port), node(o.node), 30 guid(o.guid), specid(o.specid), 31 vendorid(o.vendorid), modelid(o.modelid), 32 firmware_revision(o.firmware_revision), 33 product_name(QDeepCopy<QString>(o.product_name)) 34 { 35 } 36 37 AVCInfo &AVCInfo::operator=(const AVCInfo &o) 38 { 39 port = o.port; 40 node = o.node; 41 guid = o.guid; 42 specid = o.specid; 43 vendorid = o.vendorid; 44 modelid = o.modelid; 45 firmware_revision = o.firmware_revision; 46 product_name = QDeepCopy<QString>(o.product_name); 47 48 return *this; 49 } 50 51 QString AVCInfo::GetGUIDString(void) const 52 { 53 QString g0 = QString("%1").arg((uint32_t) (guid >> 32), 0, 16); 54 QString g1 = QString("%1").arg((uint32_t) guid, 0, 16); 55 56 while (g0.length() < 8) 57 g0 = "0" + g0; 58 while (g1.length() < 8) 59 g1 = "0" + g1; 60 61 return QDeepCopy<QString>(g0.upper() + g1.upper()); 62 } 63 64 static void fw_init(QMap<uint64_t,QString> &id_to_model); 65 66 QMap<uint64_t,QString> FirewireDevice::s_id_to_model; 67 QMutex FirewireDevice::s_static_lock; 68 69 FirewireDevice::FirewireDevice(uint64_t guid, uint subunitid, uint speed) : 70 m_guid(guid), m_subunitid(subunitid), 71 m_speed(speed), 72 m_last_channel(0), m_last_crc(0), 73 m_buffer_cleared(true), m_open_port_cnt(0), 74 m_lock(false) 75 { 76 } 77 78 void FirewireDevice::AddListener(TSDataListener *listener) 79 { 80 QMutexLocker locker(&m_lock); 81 82 if (listener) 83 { 84 vector<TSDataListener*>::iterator it = 85 find(m_listeners.begin(), m_listeners.end(), listener); 86 87 if (it == m_listeners.end()) 88 m_listeners.push_back(listener); 89 } 90 91 VERBOSE(VB_RECORD, LOC + "AddListener() "<<m_listeners.size()); 92 } 93 94 void FirewireDevice::RemoveListener(TSDataListener *listener) 95 { 96 QMutexLocker locker(&m_lock); 97 98 vector<TSDataListener*>::iterator it = m_listeners.end(); 99 100 do 101 { 102 it = find(m_listeners.begin(), m_listeners.end(), listener); 103 if (it != m_listeners.end()) 104 m_listeners.erase(it); 105 } 106 while (it != m_listeners.end()); 107 108 VERBOSE(VB_RECORD, LOC + "RemoveListener() "<<m_listeners.size()); 109 } 110 111 bool FirewireDevice::SetPowerState(bool on) 112 { 113 QMutexLocker locker(&m_lock); 114 115 vector<uint8_t> cmd; 116 vector<uint8_t> ret; 117 118 cmd.push_back(kAVCControlCommand); 119 cmd.push_back(kAVCSubunitTypeUnit | kAVCSubunitIdIgnore); 120 cmd.push_back(kAVCUnitPowerOpcode); 121 cmd.push_back((on) ? kAVCPowerStateOn : kAVCPowerStateOff); 122 123 QString cmdStr = (on) ? "on" : "off"; 124 VERBOSE(VB_RECORD, LOC + QString("Powering %1").arg(cmdStr)); 125 126 if (SendAVCCommand(cmd, ret, -1)) 127 { 128 VERBOSE(VB_IMPORTANT, LOC + "Power on cmd failed (no response)"); 129 return false; 130 } 131 132 if (kAVCAcceptedStatus != ret[0]) 133 { 134 VERBOSE(VB_IMPORTANT, LOC_ERR + 135 QString("Power %1 failed").arg(cmdStr)); 136 137 return false; 138 } 139 140 VERBOSE(VB_RECORD, LOC + 141 QString("Power %1 cmd sent successfully").arg(cmdStr)); 142 143 return true; 144 } 145 146 FirewireDevice::PowerState FirewireDevice::GetPowerState(void) 147 { 148 QMutexLocker locker(&m_lock); 149 150 vector<uint8_t> cmd; 151 vector<uint8_t> ret; 152 153 cmd.push_back(kAVCStatusInquiryCommand); 154 cmd.push_back(kAVCSubunitTypeUnit | kAVCSubunitIdIgnore); 155 cmd.push_back(kAVCUnitPowerOpcode); 156 cmd.push_back(kAVCPowerStateQuery); 157 158 VERBOSE(VB_CHANNEL, LOC + "Requesting STB Power State"); 159 160 if (!SendAVCCommand(cmd, ret, -1)) 161 { 162 VERBOSE(VB_IMPORTANT, LOC_ERR + "Power cmd failed (no response)"); 163 return kAVCPowerQueryFailed; 164 } 165 166 QString loc = LOC + "STB Power State: "; 167 168 if (ret[0] != kAVCResponseImplemented) 169 { 170 VERBOSE(VB_CHANNEL, loc + "Query not implemented"); 171 return kAVCPowerUnknown; 172 } 173 174 // check 1st operand.. 175 if (ret[3] == kAVCPowerStateOn) 176 { 177 VERBOSE(VB_CHANNEL, loc + "On"); 178 return kAVCPowerOn; 179 } 180 181 if (ret[3] == kAVCPowerStateOff) 182 { 183 VERBOSE(VB_CHANNEL, loc + "Off"); 184 return kAVCPowerOff; 185 } 186 187 VERBOSE(VB_IMPORTANT, LOC_ERR + "STB Power State: Unknown Response"); 188 189 return kAVCPowerUnknown; 190 } 191 192 bool FirewireDevice::GetSubunitInfo(uint8_t table[32]) 193 { 194 memset(table, 0xff, 32 * sizeof(uint8_t)); 195 196 for (uint i = 0; i < 8; i++) 197 { 198 vector<uint8_t> cmd; 199 vector<uint8_t> ret; 200 201 cmd.push_back(kAVCStatusInquiryCommand); 202 cmd.push_back(kAVCSubunitTypeUnit | kAVCSubunitIdIgnore); 203 cmd.push_back(kAVCUnitSubunitInfoOpcode); 204 cmd.push_back((i<<4) | 0x07); 205 cmd.push_back(0xFF); 206 cmd.push_back(0xFF); 207 cmd.push_back(0xFF); 208 cmd.push_back(0xFF); 209 210 if (!SendAVCCommand(cmd, ret, -1)) 211 return false; 212 213 if (ret.size() >= 8) 214 { 215 table[(i<<2)+0] = ret[4]; 216 table[(i<<2)+1] = ret[5]; 217 table[(i<<2)+2] = ret[6]; 218 table[(i<<2)+3] = ret[7]; 219 } 220 } 221 222 return true; 223 } 224 225 bool FirewireDevice::SetChannel(const QString &panel_model, 226 uint alt_method, uint channel) 227 { 228 QMutexLocker locker(&m_lock); 229 230 if (!IsSTBSupported(panel_model)) 231 { 232 VERBOSE(VB_IMPORTANT, LOC_ERR + 233 QString("Model: '%1' ").arg(panel_model) + 234 "is not supported by internal channel changer."); 235 return false; 236 } 237 238 int digit[3]; 239 digit[0] = (channel % 1000) / 100; 240 digit[1] = (channel % 100) / 10; 241 digit[2] = (channel % 10); 242 243 if (m_subunitid >= kAVCSubunitIdExtended) 244 return false; 245 246 vector<uint8_t> cmd; 247 vector<uint8_t> ret; 248 249 if ((panel_model.upper() == "GENERIC") || 250 (panel_model.upper() == "SA4200HD")) 251 { 252 cmd.push_back(kAVCControlCommand); 253 cmd.push_back(kAVCSubunitTypePanel | m_subunitid); 254 cmd.push_back(kAVCPanelPassThrough); 255 cmd.push_back(kAVCPanelKeyTuneFunction | kAVCPanelKeyPress); 256 257 cmd.push_back(4); // operand length 258 cmd.push_back((channel>>8) & 0x0f); 259 cmd.push_back(channel & 0xff); 260 cmd.push_back(0x00); 261 cmd.push_back(0x00); 262 263 if (!SendAVCCommand(cmd, ret, -1)) 264 return false; 265 266 bool press_ok = (kAVCAcceptedStatus == ret[0]); 267 268 cmd[3]= kAVCPanelKeyTuneFunction | kAVCPanelKeyRelease; 269 if (!SendAVCCommand(cmd, ret, -1)) 270 return false; 271 272 bool release_ok = (kAVCAcceptedStatus == ret[0]); 273 274 if (!press_ok && !release_ok) 275 { 276 VERBOSE(VB_IMPORTANT, LOC_ERR + "Tuning failed"); 277 return false; 278 } 279 280 SetLastChannel(channel); 281 return true; 282 } 283 284 bool is_mot = ((panel_model.upper() == "DCT-6200") || 285 (panel_model.upper() == "DCT-6212") || 286 (panel_model.upper() == "DCT-6216")); 287 288 if (is_mot && !alt_method) 289 { 290 for (uint i = 0; i < 3 ;i++) 291 { 292 cmd.clear(); 293 cmd.push_back(kAVCControlCommand); 294 cmd.push_back(kAVCSubunitTypePanel | m_subunitid); 295 cmd.push_back(kAVCPanelPassThrough); 296 cmd.push_back(kAVCPanelKey0 + digit[i] | kAVCPanelKeyPress); 297 cmd.push_back(0x00); 298 cmd.push_back(0x00); 299 cmd.push_back(0x00); 300 cmd.push_back(0x00); 301 302 if (!SendAVCCommand(cmd, ret, -1)) 303 return false; 304 305 usleep(500000); 306 } 307 308 SetLastChannel(channel); 309 return true; 310 } 311 312 if (is_mot && alt_method) 313 { 314 cmd.push_back(kAVCControlCommand); 315 cmd.push_back(kAVCSubunitTypePanel | m_subunitid); 316 cmd.push_back(kAVCPanelPassThrough); 317 cmd.push_back(kAVCPanelKeyTuneFunction | kAVCPanelKeyPress); 318 319 cmd.push_back(4); // operand length 320 cmd.push_back((channel>>8) & 0x0f); 321 cmd.push_back(channel & 0xff); 322 cmd.push_back(0x00); 323 cmd.push_back(0xff); 324 325 if (!SendAVCCommand(cmd, ret, -1)) 326 return false; 327 328 SetLastChannel(channel); 329 return true; 330 } 331 332 if (panel_model.upper() == "SA3250HD") 333 { 334 cmd.push_back(kAVCControlCommand); 335 cmd.push_back(kAVCSubunitTypePanel | m_subunitid); 336 cmd.push_back(kAVCPanelPassThrough); 337 cmd.push_back(kAVCPanelKeyTuneFunction | kAVCPanelKeyRelease); 338 339 cmd.push_back(4); // operand length 340 cmd.push_back(0x30 | digit[2]); 341 cmd.push_back(0x30 | digit[1]); 342 cmd.push_back(0x30 | digit[0]); 343 cmd.push_back(0xff); 344 345 if (!SendAVCCommand(cmd, ret, -1)) 346 return false; 347 348 cmd[5] = 0x30 | digit[0]; 349 cmd[6] = 0x30 | digit[1]; 350 cmd[7] = 0x30 | digit[2]; 351 352 if (!SendAVCCommand(cmd, ret, -1)) 353 return false; 354 355 SetLastChannel(channel); 356 return true; 357 } 358 359 return false; 360 } 361 362 void FirewireDevice::BroadcastToListeners( 363 const unsigned char *data, uint dataSize) 364 { 365 if ((dataSize >= TSPacket::SIZE) && (data[0] == SYNC_BYTE) && 366 ((data[1] & 0x1f) == 0) && (data[2] == 0)) 367 { 368 ProcessPATPacket(*((const TSPacket*)data)); 369 } 370 371 vector<TSDataListener*>::iterator it = m_listeners.begin(); 372 for (; it != m_listeners.end(); ++it) 373 (*it)->AddData(data, dataSize); 374 } 375 376 void FirewireDevice::SetLastChannel(const uint channel) 377 { 378 m_buffer_cleared = (channel == m_last_channel); 379 m_last_channel = channel; 380 381 VERBOSE(VB_IMPORTANT, QString("SetLastChannel(%1): cleared: %2") 382 .arg(channel).arg(m_buffer_cleared ? "yes" : "no")); 383 } 384 385 void FirewireDevice::ProcessPATPacket(const TSPacket &tspacket) 386 { 387 if (!tspacket.TransportError() && !tspacket.ScramplingControl() && 388 tspacket.HasPayload() && tspacket.PayloadStart() && !tspacket.PID()) 389 { 390 PESPacket pes = PESPacket::View(tspacket); 391 uint crc = pes.CalcCRC(); 392 m_buffer_cleared |= (crc != m_last_crc); 393 m_last_crc = crc; 394 VERBOSE(VB_RECORD, LOC + 395 QString("ProcessPATPacket: CRC 0x%1 cleared: %2") 396 .arg(crc,0,16).arg(m_buffer_cleared ? "yes" : "no")); 397 } 398 else 399 { 400 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't handle large PAT's"); 401 } 402 } 403 404 QString FirewireDevice::GetModelName(uint vendor_id, uint model_id) 405 { 406 QMutexLocker locker(&s_static_lock); 407 if (s_id_to_model.empty()) 408 fw_init(s_id_to_model); 409 410 QString ret = s_id_to_model[(((uint64_t) vendor_id) << 32) | model_id]; 411 412 if (ret.isEmpty()) 413 return "GENERIC"; 414 415 return QDeepCopy<QString>(ret); 416 } 417 418 vector<AVCInfo> FirewireDevice::GetSTBList(void) 419 { 420 vector<AVCInfo> list; 421 422 #ifdef USING_LINUX_FIREWIRE 423 list = LinuxFirewireDevice::GetSTBList(); 424 #elif USING_OSX_FIREWIRE 425 list = DarwinFirewireDevice::GetSTBList(); 426 #endif 427 428 //#define DEBUG_AVC_INFO 429 #ifdef DEBUG_AVC_INFO 430 AVCInfo info; 431 info.guid = 0x0016928a7b600001ULL; 432 info.specid = 0x0; 433 info.vendorid = 0x000014f8; 434 info.modelid = 0x00001072; 435 info.firmware_revision = 0x0; 436 info.product_name = "Explorer 4200 HD"; 437 list.push_back(info); 438 439 info.guid = 0xff2145a850e39810ULL; 440 info.specid = 0x0; 441 info.vendorid = 0x000014f8; 442 info.modelid = 0x00000be0; 443 info.firmware_revision = 0x0; 444 info.product_name = "Explorer 3250 HD"; 445 list.push_back(info); 446 #endif // DEBUG_AVC_INFO 447 448 return list; 449 } 450 451 bool FirewireDevice::IsSubunitType( 452 const uint8_t unit_table[32], IEEE1394UnitAddress subunit_type) 453 { 454 for (uint i = 0; i < 32; i++) 455 { 456 int subunit = unit_table[i]; 457 if ((subunit != 0xff) && 458 (subunit & kAVCSubunitTypeUnit) == subunit_type) 459 { 460 return true; 461 } 462 } 463 464 return false; 465 } 466 467 QString FirewireDevice::GetSubunitInfoString(const uint8_t table[32]) 468 { 469 QString str = "Subunit Types: "; 470 471 if (IsSubunitType(table, kAVCSubunitTypeVideoMonitor)) 472 str += "Video Monitor, "; 473 if (IsSubunitType(table, kAVCSubunitTypeAudio)) 474 str += "Audio, "; 475 if (IsSubunitType(table, kAVCSubunitTypePrinter)) 476 str += "Printer, "; 477 if (IsSubunitType(table, kAVCSubunitTypeDiscRecorder)) 478 str += "Disk Recorder, "; 479 if (IsSubunitType(table, kAVCSubunitTypeTapeRecorder)) 480 str += "Tape Recorder, "; 481 if (IsSubunitType(table, kAVCSubunitTypeTuner)) 482 str += "Tuner, "; 483 if (IsSubunitType(table, kAVCSubunitTypeCA)) 484 str += "CA, "; 485 if (IsSubunitType(table, kAVCSubunitTypeVideoCamera)) 486 str += "Camera, "; 487 if (IsSubunitType(table, kAVCSubunitTypePanel)) 488 str += "Panel, "; 489 if (IsSubunitType(table, kAVCSubunitTypeBulletinBoard)) 490 str += "Bulletin Board, "; 491 if (IsSubunitType(table, kAVCSubunitTypeCameraStorage)) 492 str += "Camera Storage, "; 493 if (IsSubunitType(table, kAVCSubunitTypeMusic)) 494 str += "Music, "; 495 if (IsSubunitType(table, kAVCSubunitTypeVendorUnique)) 496 str += "Vendor Unique, "; 497 498 return str; 499 } 500 501 static void fw_init(QMap<uint64_t,QString> &id_to_model) 502 { 503 id_to_model[0x11e6ULL << 32 | 0x0be0] = "SA3250HD"; 504 id_to_model[0x14f8ULL << 32 | 0x0be0] = "SA3250HD"; 505 id_to_model[0x1692ULL << 32 | 0x0be0] = "SA3250HD"; 506 507 id_to_model[0x11e6ULL << 32 | 0x1072] = "SA4200HD"; 508 id_to_model[0x14f8ULL << 32 | 0x1072] = "SA4200HD"; 509 id_to_model[0x1692ULL << 32 | 0x1072] = "SA4200HD"; 510 511 const uint64_t motorolla_vendor_ids[] = 512 { /* 6200 */ 513 0x0ce5, 0x0e5c, 0x1225, 0x0f9f, 0x1180, 514 0x12c9, 0x11ae, 0x152f, 0x14e8, 0x16b5, 0x1371, 515 /* 6412 */ 516 0x0f9f, 0x152f, 517 /* 6416 */ 518 0x17ee, 519 }; 520 const uint motorolla_vendor_id_cnt = 521 sizeof(motorolla_vendor_ids) / sizeof(uint32_t); 522 523 const uint32_t motorolla_6200model_ids[] = { 0x620a, 0x6200, }; 524 const uint32_t motorolla_6212model_ids[] = { 0x64ca, 0x64cb, }; 525 const uint32_t motorolla_6216model_ids[] = { 0x646b, }; 526 527 for (uint i = 0; i < motorolla_vendor_id_cnt; i++) 528 for (uint j = 0; j < 2; j++) 529 id_to_model[motorolla_vendor_ids[i] << 32 | 530 motorolla_6200model_ids[j]] = "DCT-6200"; 531 532 for (uint i = 0; i < motorolla_vendor_id_cnt; i++) 533 for (uint j = 0; j < 2; j++) 534 id_to_model[motorolla_vendor_ids[i] << 32 | 535 motorolla_6212model_ids[j]] = "DCT-6212"; 536 537 for (uint i = 0; i < motorolla_vendor_id_cnt; i++) 538 for (uint j = 0; j < 2; j++) 539 id_to_model[motorolla_vendor_ids[i] << 32 | 540 motorolla_6216model_ids[j]] = "DCT-6216"; 541 } -
libs/libmythtv/videosource.h
413 413 DiSEqCDevTree *diseqc_tree; 414 414 }; 415 415 416 class FirewireGUID; 417 class FirewireModel : public ComboBoxSetting, public CaptureCardDBStorage 418 { 419 Q_OBJECT 420 421 public: 422 FirewireModel(const CaptureCard &parent, const FirewireGUID*); 423 424 public slots: 425 void SetGUID(const QString&); 426 427 private: 428 const FirewireGUID *guid; 429 }; 430 431 class FirewireDesc : public TransLabelSetting 432 { 433 Q_OBJECT 434 435 public: 436 FirewireDesc(const FirewireGUID *_guid) : 437 TransLabelSetting(), guid(_guid) { } 438 439 public slots: 440 void SetGUID(const QString&); 441 442 private: 443 const FirewireGUID *guid; 444 }; 445 446 416 447 class CaptureCardGroup : public TriggeredConfigurationGroup 417 448 { 418 449 Q_OBJECT -
libs/libmythtv/libmythtv.pro
377 377 } 378 378 379 379 # Support for cable boxes that provide Firewire out 380 using_firewire { 381 HEADERS += firewirechannelbase.h firewirerecorderbase.h 382 SOURCES += firewirechannelbase.cpp firewirerecorderbase.cpp 380 using_firewire { 381 HEADERS += firewirechannel.h firewirerecorder.h 382 HEADERS += firewiresignalmonitor.h firewiredevice.h 383 SOURCES += firewirechannel.cpp firewirerecorder.cpp 384 SOURCES += firewiresignalmonitor.cpp firewiredevice.cpp 383 385 384 386 macx { 385 HEADERS += darwinfirewirechannel.h darwinfirewirerecorder.h 386 SOURCES += darwinfirewirechannel.cpp darwinfirewirerecorder.cpp 387 HEADERS += selectavcdevice.h 388 SOURCES += selectavcdevice.cpp 387 HEADERS += darwinfirewiredevice.h darwinavcinfo.h 388 SOURCES += darwinfirewiredevice.cpp darwinavcinfo.cpp 389 DEFINES += USING_OSX_FIREWIRE 389 390 } 390 391 391 392 !macx { 392 HEADERS += firewirechannel.h firewirerecorder.h 393 SOURCES += firewirechannel.cpp firewirerecorder.cpp 393 HEADERS += linuxfirewiredevice.h 394 SOURCES += linuxfirewiredevice.cpp 395 DEFINES += USING_LINUX_FIREWIRE 394 396 } 395 397 396 398 DEFINES += USING_FIREWIRE 399 using_libavc_5_3:DEFINES += USING_LIBAVC_5_3 397 400 } 398 401 399 402 # Support for set top boxes (Nokia DBox2 etc.) -
libs/libmythtv/darwinfirewirerecorder.cpp
1 /**2 * DarwinDarwinFirewireRecorder3 * Copyright (c) 2005 by Jim Westfall and Dave Abrahams4 * Distributed as part of MythTV under GPL v2 and later.5 */6 7 // MythTV includes8 #include "darwinfirewirerecorder.h"9 #include "tspacket.h"10 11 #undef always_inline12 #include <AVCVideoServices/AVCVideoServices.h>13 14 DarwinFirewireRecorder::DarwinFirewireRecorder(TVRec *rec, ChannelBase* tuner)15 : FirewireRecorderBase(rec),16 capture_device(17 dynamic_cast<DarwinFirewireChannel*>(tuner)->GetAVCDevice()18 ),19 message_log(NULL),20 video_stream(NULL),21 isopen(false)22 {;}23 24 DarwinFirewireRecorder::~DarwinFirewireRecorder()25 {26 this->Close();27 }28 29 // Various message callbacks.30 IOReturn DarwinFirewireRecorder::MPEGNoData(void *pRefCon)31 {32 33 DarwinFirewireRecorder* self = static_cast<DarwinFirewireRecorder*>(pRefCon);34 self->no_data();35 return 0;36 }37 38 void DarwinFirewireRecorder::no_data()39 {40 VERBOSE(41 VB_IMPORTANT,42 QString("Firewire: No Input in %1 seconds").arg(kTimeoutInSeconds));43 }44 45 namespace46 {47 void avs_log_message(char *pString)48 {49 // I don't know what QString does with plain char*, but surely it50 // treats char const* as an NTBS.51 char const* s = pString;52 53 VERBOSE(VB_GENERAL,QString("Firewire MPEG2Receiver log: %1")54 .arg(s));55 }56 57 void avs_message_received(58 UInt32 msg, UInt32 param1, UInt32 param2, void *pRefCon)59 {60 (void)pRefCon;61 62 VERBOSE(VB_RECORD,QString("Firewire MPEG2Receiver message: %1")63 .arg(msg));64 65 switch (msg)66 {67 case AVS::kMpeg2ReceiverAllocateIsochPort:68 VERBOSE(69 VB_RECORD,70 QString("Firewire MPEG2Receiver allocated channel: %1, speed %2")71 .arg(param2).arg(param1)72 );73 break;74 75 case AVS::kMpeg2ReceiverDCLOverrun:76 VERBOSE(77 VB_IMPORTANT,78 QString("Firewire MPEG2Receiver DCL Overrun")79 );80 break;81 82 case AVS::kMpeg2ReceiverReceivedBadPacket:83 VERBOSE(84 VB_IMPORTANT,85 QString("Firewire MPEG2Receiver Received Bad Packet ")86 );87 break;88 89 default:90 break;91 }92 }93 94 bool find_capture_device(AVS::AVCDevice* d)95 {96 // We'd check isMPEGDevice, but it turns out that for the97 // DCT-6200, Apple doesn't set that flag. So instead we rule98 // out DV devices.99 // A more general OSX AVCRecorder class that also handles DV100 // devices might not check either flag.101 return d->isAttached && !d->isDVDevice102 // && (d->hasTapeSubunit || d->hasMonitorOrTunerSubunit)103 ;104 }105 106 IOReturn device_controller_notification(AVS::AVCDeviceController *, void *, AVS::AVCDevice*)107 {108 return 0;109 }110 }111 112 IOReturn DarwinFirewireRecorder::tspacket_callback(UInt32 tsPacketCount, UInt32 **ppBuf,void *pRefCon)113 {114 DarwinFirewireRecorder* self = static_cast<DarwinFirewireRecorder*>(pRefCon);115 if (!self)116 return kIOReturnBadArgument;117 118 for (UInt32 i = 0; i < tsPacketCount; ++i)119 self->ProcessTSPacket(*(reinterpret_cast<TSPacket*>(ppBuf[i])));120 121 return 0;122 }123 124 125 bool DarwinFirewireRecorder::Open()126 {127 if (isopen)128 return true;129 130 VERBOSE(VB_GENERAL,QString("Firewire: Creating logger object"));131 132 this->message_log = new AVS::StringLogger(avs_log_message);133 if (!this->message_log)134 {135 VERBOSE(VB_IMPORTANT, QString("Firewire: Couldn't create logger") );136 return false;137 }138 139 // If we don't set this immediately, Close() will refuse to clean140 // up after whatever mess we make here141 this->isopen = true;142 143 VERBOSE(VB_GENERAL,QString("Firewire: Creating MPEG-2 device stream"));144 145 // This not only builds an MPEG2Receiver object but also starts dedicated real-time threads.146 this->video_stream = capture_device->CreateMPEGReceiverForDevicePlug(147 0, // Plug number. Why is zero always OK? I148 // don't know, but that's what Apple's149 // examples do.150 tspacket_callback,151 this,152 avs_message_received,153 this,154 this->message_log,155 AVS::kCyclesPerReceiveSegment,156 // Why multiply by 2 instead of using the default,157 // kNumReceiveSegments? Because it's what Apple's only158 // example of the use of this function does.159 AVS::kNumReceiveSegments*2);160 161 if (!this->video_stream)162 {163 VERBOSE(VB_IMPORTANT, QString("Firewire: Couldn't create MPEG-2 device stream") );164 this->Close();165 return false;166 }167 168 // We could set the channel to receive on, but it doesn't seem169 // like we need to, and if the device is already transmitting it170 // could lead to inefficiency because the device stream is smart171 // enough to avoid allocating new bandwidth.172 173 // Register a no-data notification callback174 video_stream->pMPEGReceiver->registerNoDataNotificationCallback(175 MPEGNoData, this, kTimeoutInSeconds * 1000);176 177 return true;178 }179 180 void DarwinFirewireRecorder::Close()181 {182 if (!isopen)183 return;184 185 isopen = false;186 187 if (this->video_stream)188 {189 this->stop();190 VERBOSE(VB_RECORD, "Firewire: Destroying device stream");191 this->capture_device->DestroyAVCDeviceStream(this->video_stream);192 this->video_stream = 0;193 }194 195 delete this->message_log;196 this->message_log = 0;197 }198 199 void DarwinFirewireRecorder::start()200 {201 VERBOSE(VB_RECORD, "Firewire: Starting video stream");202 this->capture_device->StartAVCDeviceStream(this->video_stream);203 }204 205 void DarwinFirewireRecorder::stop()206 {207 VERBOSE(VB_RECORD, "Firewire: Stopping video stream");208 this->capture_device->StopAVCDeviceStream(this->video_stream);209 }210 211 bool DarwinFirewireRecorder::grab_frames()212 {213 usleep(1000000 / 2); // 2 times a second214 return true;215 }216 217 void DarwinFirewireRecorder::SetOption(const QString &name, const QString &value)218 {219 (void)name;220 (void)value;221 }222 223 void DarwinFirewireRecorder::SetOption(const QString &name, int value)224 {225 (void)name;226 (void)value;227 } -
libs/libmythtv/scanwizardhelpers.h
49 49 class AnalogPane; 50 50 class STPane; 51 51 class DVBUtilsImportPane; 52 class QApplication; 52 53 53 54 /// Max range of the ScanProgressPopup progress bar 54 55 #define PROGRESS_MAX 1000 … … 86 87 87 88 class ScannerEvent : public QCustomEvent 88 89 { 90 friend class QApplication; // to suppress Apple gcc warning 91 89 92 public: 90 93 enum TYPE 91 94 { -
libs/libmythtv/dbcheck.cpp
10 10 #include "mythdbcon.h" 11 11 12 12 /// This is the DB schema version expected by the running MythTV instance. 13 const QString currentDatabaseVersion = "117 3";13 const QString currentDatabaseVersion = "1174"; 14 14 15 15 static bool UpdateDBVersionNumber(const QString &newnumber); 16 16 static bool performActualUpdate(const QString updates[], QString version, … … 2782 2782 return false; 2783 2783 } 2784 2784 2785 if (dbver == "1173") 2786 { 2787 const QString updates[] = { 2788 "DELETE FROM capturecard WHERE cardtype = 'FIREWIRE';", 2789 "" 2790 }; 2791 if (!performActualUpdate(updates, "1174", dbver)) 2792 return false; 2793 } 2794 2785 2795 //"ALTER TABLE cardinput DROP COLUMN preference;" in 0.22 2786 2796 //"ALTER TABLE channel DROP COLUMN atscsrcid;" in 0.22 2787 2797 //"ALTER TABLE recordedmarkup DROP COLUMN offset;" in 0.22 … … 2790 2800 //"ALTER TABLE cardinput DROP lnb_lof_switch;" in 0.22 2791 2801 //"ALTER TABLE cardinput DROP lnb_lof_hi;" in 0.22 2792 2802 //"ALTER TABLE cardinput DROP lnb_lof_lo;" in 0.22 2803 //"ALTER TABLE capturecard DROP firewire_port;" in 0.22 2804 //"ALTER TABLE capturecard DROP firewire_node;" in 0.22 2793 2805 2794 2806 return true; 2795 2807 } -
libs/libmythtv/signalmonitor.h
285 285 return (CardUtil::IsDVBCardType(cardtype) || 286 286 (cardtype.upper() == "HDTV") || 287 287 (cardtype.upper() == "HDHOMERUN") || 288 (cardtype.upper() == "FIREWIRE") || 288 289 (cardtype.upper() == "FREEBOX")); 289 290 } 290 291 -
libs/libmythtv/darwinfirewiredevice.cpp
1 /** 2 * DarwinFirewireChannel 3 * Copyright (c) 2005 by Jim Westfall 4 * SA3250HD support Copyright (c) 2005 by Matt Porter 5 * Copyright (c) 2006 by Dave Abrahams 6 * Distributed as part of MythTV under GPL v2 and later. 7 */ 8 9 // POSIX headers 10 #include <pthread.h> 11 12 // OS X headers 13 #undef always_inline 14 #include <IOKit/IOMessage.h> 15 #include <IOKit/IOKitLib.h> 16 #include <IOKit/firewire/IOFireWireLib.h> 17 #include <IOKit/firewire/IOFireWireLibIsoch.h> 18 #include <IOKit/firewire/IOFireWireFamilyCommon.h> 19 #include <IOKit/avc/IOFireWireAVCLib.h> 20 21 // Std C++ headers 22 #include <vector> 23 using namespace std; 24 25 // MythTV headers 26 #include "darwinfirewiredevice.h" 27 #include "darwinavcinfo.h" 28 #include "mythcontext.h" 29 30 // Apple Firewire example headers 31 #include <AVCVideoServices/StringLogger.h> 32 #include <AVCVideoServices/MPEG2Receiver.h> 33 34 // header not used because it also requires MPEG2Transmitter.h 35 //#include <AVCVideoServices/FireWireMPEG.h> 36 namespace AVS 37 { 38 IOReturn CreateMPEG2Receiver( 39 MPEG2Receiver **ppReceiver, 40 DataPushProc dataPushProcHandler, 41 void *pDataPushProcRefCon = nil, 42 MPEG2ReceiverMessageProc messageProcHandler = nil, 43 void *pMessageProcRefCon = nil, 44 StringLogger *stringLogger = nil, 45 IOFireWireLibNubRef nubInterface = nil, 46 unsigned int cyclesPerSegment = 47 kCyclesPerReceiveSegment, 48 unsigned int numSegments = 49 kNumReceiveSegments, 50 bool doIRMAllocations = false); 51 IOReturn DestroyMPEG2Receiver(MPEG2Receiver *pReceiver); 52 } 53 54 #define LOC QString("DFireDev(): ") 55 #define LOC_WARN QString("DFireDev(), Warning: ") 56 #define LOC_ERR QString("DFireDev(), Error: ") 57 58 #define kAnyAvailableIsochChannel 0xFFFFFFFF 59 #define kNoDataTimeout 250 /* msec */ 60 61 static IOReturn dfd_tspacket_handler_thunk( 62 long unsigned int tsPacketCount, UInt32 **ppBuf, void *callback_data); 63 static void dfd_update_device_list(void *dfd, io_iterator_t iterator); 64 static void dfd_streaming_log_message(char *pString); 65 66 class DFDPriv 67 { 68 public: 69 DFDPriv() : 70 controller_thread_cf_ref(NULL), controller_thread_running(false), 71 notify_port(NULL), notify_source(NULL), deviter(NULL), 72 actual_fwchan(-1), is_streaming(false), avstream(NULL), logger(NULL) 73 { 74 logger = new AVS::StringLogger(dfd_streaming_log_message); 75 } 76 77 ~DFDPriv() 78 { 79 avcinfo_list_t::iterator it = devices.begin(); 80 for (; it != devices.end(); ++it) 81 delete (*it); 82 devices.clear(); 83 84 if (logger) 85 { 86 delete logger; 87 logger = NULL; 88 } 89 } 90 91 pthread_t controller_thread; 92 CFRunLoopRef controller_thread_cf_ref; 93 bool controller_thread_running; 94 95 IONotificationPortRef notify_port; 96 CFRunLoopSourceRef notify_source; 97 io_iterator_t deviter; 98 99 int actual_fwchan; 100 bool is_streaming; 101 AVS::MPEG2Receiver *avstream; 102 AVS::StringLogger *logger; 103 104 avcinfo_list_t devices; 105 }; 106 107 DarwinFirewireDevice::DarwinFirewireDevice( 108 uint64_t guid, uint subunitid, uint speed) : 109 FirewireDevice(guid, subunitid, speed), 110 m_node(0), m_priv(new DFDPriv()) 111 { 112 } 113 114 DarwinFirewireDevice::~DarwinFirewireDevice() 115 { 116 if (IsPortOpen()) 117 { 118 VERBOSE(VB_IMPORTANT, LOC_ERR + "ctor called with open port"); 119 while (IsPortOpen()) 120 ClosePort(); 121 } 122 123 if (m_priv) 124 { 125 delete m_priv; 126 m_priv = NULL; 127 } 128 } 129 130 void DarwinFirewireDevice::RunController(void) 131 { 132 m_priv->controller_thread_cf_ref = CFRunLoopGetCurrent(); 133 134 // Set up IEEE-1394 bus change notification 135 mach_port_t master_port; 136 int ret = IOMasterPort(bootstrap_port, &master_port); 137 if (kIOReturnSuccess == ret) 138 { 139 m_priv->notify_port = IONotificationPortCreate(master_port); 140 m_priv->notify_source = IONotificationPortGetRunLoopSource( 141 m_priv->notify_port); 142 143 CFRunLoopAddSource(m_priv->controller_thread_cf_ref, 144 m_priv->notify_source, 145 kCFRunLoopDefaultMode); 146 147 ret = IOServiceAddMatchingNotification( 148 m_priv->notify_port, kIOMatchedNotification, 149 IOServiceMatching("IOFireWireAVCUnit"), 150 dfd_update_device_list, this, &m_priv->deviter); 151 } 152 153 if (kIOReturnSuccess == ret) 154 dfd_update_device_list(this, m_priv->deviter); 155 156 m_priv->controller_thread_running = true; 157 158 if (kIOReturnSuccess == ret) 159 CFRunLoopRun(); 160 161 QMutexLocker locker(&m_lock); // ensure that controller_thread_running seen 162 163 m_priv->controller_thread_running = false; 164 } 165 166 void DarwinFirewireDevice::StartController(void) 167 { 168 m_lock.unlock(); 169 170 pthread_create(&m_priv->controller_thread, NULL, 171 dfd_controller_thunk, this); 172 173 m_lock.lock(); 174 while (!m_priv->controller_thread_running) 175 { 176 m_lock.unlock(); 177 usleep(5000); 178 m_lock.lock(); 179 } 180 } 181 182 void DarwinFirewireDevice::StopController(void) 183 { 184 if (!m_priv->controller_thread_running) 185 return; 186 187 if (m_priv->deviter) 188 { 189 IOObjectRelease(m_priv->deviter); 190 m_priv->deviter = NULL; 191 } 192 193 if (m_priv->notify_source) 194 { 195 CFRunLoopSourceInvalidate(m_priv->notify_source); 196 m_priv->notify_source = NULL; 197 } 198 199 if (m_priv->notify_port) 200 { 201 IONotificationPortDestroy(m_priv->notify_port); 202 m_priv->notify_port = NULL; 203 } 204 205 CFRunLoopStop(m_priv->controller_thread_cf_ref); 206 207 while (m_priv->controller_thread_running) 208 { 209 m_lock.unlock(); 210 usleep(100 * 1000); 211 m_lock.lock(); 212 } 213 } 214 215 bool DarwinFirewireDevice::OpenPort(void) 216 { 217 QMutexLocker locker(&m_lock); 218 219 VERBOSE(VB_RECORD, LOC + "OpenPort()"); 220 221 if (GetInfoPtr() && GetInfoPtr()->IsOpen()) 222 { 223 m_open_port_cnt++; 224 return true; 225 } 226 227 StartController(); 228 229 if (!m_priv->controller_thread_running) 230 { 231 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to start firewire thread."); 232 return false; 233 } 234 235 if (!GetInfoPtr()) 236 { 237 VERBOSE(VB_IMPORTANT, LOC_ERR + "No IEEE-1394 device at " + 238 QString("guid: 0x%1").arg(m_guid,0,16)); 239 240 StopController(); 241 return false; 242 } 243 244 VERBOSE(VB_RECORD, LOC + "Opening AVC Device"); 245 VERBOSE(VB_RECORD, LOC + GetSubunitInfoString(GetInfoPtr()->unit_table)); 246 247 if (!IsSubunitType(GetInfoPtr()->unit_table, kAVCSubunitTypeTuner) || 248 !IsSubunitType(GetInfoPtr()->unit_table, kAVCSubunitTypePanel)) 249 { 250 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("No STB at guid: 0x%1") 251 .arg(m_guid,0,16)); 252 253 StopController(); 254 return false; 255 } 256 257 bool ok = GetInfoPtr()->Open(m_priv->controller_thread_cf_ref); 258 if (!ok) 259 { 260 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to get handle for port"); 261 262 return false; 263 } 264 265 // TODO we should set m_node... 266 267 m_open_port_cnt++; 268 269 return true; 270 } 271 272 bool DarwinFirewireDevice::ClosePort(void) 273 { 274 QMutexLocker locker(&m_lock); 275 276 VERBOSE(VB_RECORD, LOC + "ClosePort()"); 277 278 if (m_open_port_cnt < 1) 279 return false; 280 281 m_open_port_cnt--; 282 283 if (m_open_port_cnt != 0) 284 return true; 285 286 if (GetInfoPtr() && GetInfoPtr()->IsOpen()) 287 { 288 VERBOSE(VB_RECORD, LOC + "Closing AVC Device"); 289 290 GetInfoPtr()->Close(); 291 } 292 293 StopController(); 294 295 return true; 296 } 297 298 bool DarwinFirewireDevice::OpenAVStream(void) 299 { 300 if (IsAVStreamOpen()) 301 return true; 302 303 int max_speed = GetMaxSpeed(); 304 VERBOSE(VB_IMPORTANT, "Max Speed: "<<max_speed<<" Our speed: "<<m_speed); 305 m_speed = min((uint)max_speed, m_speed); 306 307 uint fwchan = 0; 308 bool streaming = IsSTBStreaming(&fwchan); 309 VERBOSE(VB_IMPORTANT, QString("STB is %1already streaming on fwchan: %2") 310 .arg(streaming?"":"not ").arg(fwchan)); 311 312 // TODO we should use the stream if it already exists, 313 // this is especially true if it is a broadcast stream... 314 315 int ret = AVS::CreateMPEG2Receiver( 316 &m_priv->avstream, 317 dfd_tspacket_handler_thunk, this, 318 dfd_stream_msg, this, 319 m_priv->logger /* StringLogger */, 320 GetInfoPtr()->fw_handle, 321 AVS::kCyclesPerReceiveSegment, 322 AVS::kNumReceiveSegments, 323 true /* p2p */); 324 325 if (kIOReturnSuccess != ret) 326 { 327 VERBOSE(VB_IMPORTANT, LOC_ERR + "Couldn't create A/V stream object"); 328 return false; 329 } 330 331 m_priv->avstream->registerNoDataNotificationCallback( 332 dfd_no_data_notification, this, kNoDataTimeout); 333 334 return true; 335 } 336 337 int DarwinFirewireDevice::GetMaxSpeed(void) // oMPR read 338 { 339 IOFireWireLibDeviceRef fw_handle = GetInfoPtr()->fw_handle; 340 io_object_t dev = (*fw_handle)->GetDevice(fw_handle); 341 342 FWAddress addr(0xffff, 0xf0000900, m_node); 343 uint32_t val; 344 int ret = (*fw_handle)->ReadQuadlet( 345 fw_handle, dev, &addr, (UInt32*) &val, false, 0); 346 347 return (int)((ret == kIOReturnSuccess) ? ((val>>30) & 0x3) : 0xffffffff); 348 } 349 350 bool DarwinFirewireDevice::IsSTBStreaming(uint *fw_channel) 351 { 352 IOFireWireLibDeviceRef fw_handle = GetInfoPtr()->fw_handle; 353 io_object_t dev = (*fw_handle)->GetDevice(fw_handle); 354 355 FWAddress addr(0xffff, 0xf0000904, m_node); 356 uint32_t val; 357 int ret = (*fw_handle)->ReadQuadlet( 358 fw_handle, dev, &addr, (UInt32*) &val, false, 0); 359 360 if (ret != kIOReturnSuccess) 361 return false; 362 363 if (val & (kIOFWPCRBroadcast | kIOFWPCRP2PCount)) 364 { 365 if (fw_channel) 366 *fw_channel = (val & kIOFWPCRChannel) >> kIOFWPCRChannelPhase; 367 368 return true; 369 } 370 371 return false; 372 } 373 374 bool DarwinFirewireDevice::CloseAVStream(void) 375 { 376 if (!m_priv->avstream) 377 return true; 378 379 StopStreaming(); 380 381 VERBOSE(VB_RECORD, LOC + "Destroying A/V stream object"); 382 AVS::DestroyMPEG2Receiver(m_priv->avstream); 383 m_priv->avstream = NULL; 384 385 return true; 386 } 387 388 bool DarwinFirewireDevice::IsAVStreamOpen(void) const 389 { 390 return m_priv->avstream; 391 } 392 393 bool DarwinFirewireDevice::StartStreaming(void) 394 { 395 if (m_priv->is_streaming) 396 return m_priv->is_streaming; 397 398 VERBOSE(VB_RECORD, LOC + "Starting A/V streaming"); 399 400 if (!IsAVStreamOpen() && !OpenAVStream()) 401 { 402 VERBOSE(VB_IMPORTANT, LOC + "Starting A/V streaming: FAILED"); 403 return false; 404 } 405 406 m_priv->avstream->setReceiveIsochChannel(kAnyAvailableIsochChannel); 407 m_priv->avstream->setReceiveIsochSpeed((IOFWSpeed) m_speed); 408 int ret = m_priv->avstream->startReceive(); 409 410 m_priv->is_streaming = (kIOReturnSuccess == ret); 411 412 VERBOSE(VB_IMPORTANT, LOC + "Starting A/V streaming: " 413 <<((m_priv->is_streaming)?"success":"failure")); 414 415 return m_priv->is_streaming; 416 } 417 418 bool DarwinFirewireDevice::StopStreaming(void) 419 { 420 if (!m_priv->is_streaming) 421 return true; 422 423 VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming"); 424 425 bool ok = (kIOReturnSuccess == m_priv->avstream->stopReceive()); 426 m_priv->is_streaming = !ok; 427 428 if (!ok) 429 { 430 VERBOSE(VB_RECORD, LOC_ERR + "Failed to stop A/V streaming"); 431 return false; 432 } 433 434 VERBOSE(VB_RECORD, LOC + "Stopped A/V streaming"); 435 return true; 436 } 437 438 bool DarwinFirewireDevice::SendAVCCommand(const vector<uint8_t> &cmd, 439 vector<uint8_t> &result, 440 int retry_cnt) 441 { 442 return GetInfoPtr()->SendAVCCommand(cmd, result, retry_cnt); 443 } 444 445 bool DarwinFirewireDevice::IsPortOpen(void) const 446 { 447 QMutexLocker locker(&m_lock); 448 449 if (!GetInfoPtr()) 450 return false; 451 452 return GetInfoPtr()->IsOpen(); 453 } 454 455 void DarwinFirewireDevice::AddListener(TSDataListener *listener) 456 { 457 FirewireDevice::AddListener(listener); 458 459 QMutexLocker locker(&m_lock); 460 if (!m_listeners.empty()) 461 StartStreaming(); 462 } 463 464 void DarwinFirewireDevice::RemoveListener(TSDataListener *listener) 465 { 466 FirewireDevice::RemoveListener(listener); 467 468 QMutexLocker locker(&m_lock); 469 if (m_priv->is_streaming && m_listeners.empty()) 470 { 471 StopStreaming(); 472 CloseAVStream(); 473 } 474 } 475 476 void DarwinFirewireDevice::BroadcastToListeners( 477 const unsigned char *data, uint dataSize) 478 { 479 QMutexLocker locker(&m_lock); 480 FirewireDevice::BroadcastToListeners(data, dataSize); 481 } 482 483 void DarwinFirewireDevice::PrintNoDataMessage(void) 484 { 485 VERBOSE(VB_IMPORTANT, LOC_WARN + 486 QString("No Input in %1 msecs").arg(kNoDataTimeout)); 487 } 488 489 void DarwinFirewireDevice::ProcessStreamingMessage( 490 uint32_t msg, uint32_t param1, uint32_t param2) 491 { 492 int plug_number = 0; 493 494 if (AVS::kMpeg2ReceiverAllocateIsochPort == msg) 495 { 496 int speed = param1, fw_channel = param2; 497 498 bool ok = UpdatePlugRegister( 499 plug_number, fw_channel, speed, true, false); 500 501 VERBOSE(VB_IMPORTANT, LOC + QString("AllocateIsochPort(%1,%2) %3") 502 .arg(fw_channel).arg(speed).arg(((ok)?"ok":"error"))); 503 } 504 else if (AVS::kMpeg2ReceiverReleaseIsochPort == msg) 505 { 506 int ret = UpdatePlugRegister(plug_number, -1, -1, false, true); 507 508 VERBOSE(VB_IMPORTANT, LOC + "ReleaseIsochPort " 509 <<((kIOReturnSuccess == ret)?"ok":"error")); 510 } 511 else if (AVS::kMpeg2ReceiverDCLOverrun == msg) 512 { 513 VERBOSE(VB_IMPORTANT, LOC_ERR + "DCL Overrun"); 514 } 515 else if (AVS::kMpeg2ReceiverReceivedBadPacket == msg) 516 { 517 VERBOSE(VB_IMPORTANT, LOC_ERR + "Received Bad Packet"); 518 } 519 else 520 { 521 VERBOSE(VB_GENERAL, LOC + 522 QString("Streaming Message: %1").arg(msg)); 523 } 524 } 525 526 vector<AVCInfo> DarwinFirewireDevice::GetSTBList(void) 527 { 528 vector<AVCInfo> list; 529 530 { 531 DarwinFirewireDevice dev(0,0,0); 532 533 dev.m_lock.lock(); 534 dev.StartController(); 535 dev.m_lock.unlock(); 536 537 list = dev.GetSTBListPrivate(); 538 539 dev.m_lock.lock(); 540 dev.StopController(); 541 dev.m_lock.unlock(); 542 } 543 544 return list; 545 } 546 547 vector<AVCInfo> DarwinFirewireDevice::GetSTBListPrivate(void) 548 { 549 VERBOSE(VB_IMPORTANT, "GetSTBListPrivate -- begin"); 550 QMutexLocker locker(&m_lock); 551 VERBOSE(VB_IMPORTANT, "GetSTBListPrivate -- got lock"); 552 553 vector<AVCInfo> list; 554 555 avcinfo_list_t::iterator it = m_priv->devices.begin(); 556 for (; it != m_priv->devices.end(); ++it) 557 { 558 if (IsSubunitType((*it)->unit_table, kAVCSubunitTypeTuner) && 559 IsSubunitType((*it)->unit_table, kAVCSubunitTypePanel)) 560 { 561 list.push_back(*(*it)); 562 } 563 } 564 565 VERBOSE(VB_IMPORTANT, "GetSTBListPrivate -- end"); 566 return list; 567 } 568 569 void DarwinFirewireDevice::UpdateDeviceListItem(uint64_t guid, void *pitem) 570 { 571 QMutexLocker locker(&m_lock); 572 573 avcinfo_list_t::iterator it = m_priv->devices.find(guid); 574 575 if (it == m_priv->devices.end()) 576 { 577 DarwinAVCInfo *ptr = new DarwinAVCInfo(); 578 579 VERBOSE(VB_IMPORTANT, "Adding device list item 0x" 580 <<hex<<guid<<" ptr: "<<ptr<<dec); 581 582 m_priv->devices[guid] = ptr; 583 it = m_priv->devices.find(guid); 584 } 585 586 io_object_t &item = *((io_object_t*) pitem); 587 if (it != m_priv->devices.end()) 588 { 589 (*it)->Update(guid, this, m_priv->notify_port, 590 m_priv->controller_thread_cf_ref, item); 591 } 592 } 593 594 DarwinAVCInfo *DarwinFirewireDevice::GetInfoPtr(void) 595 { 596 avcinfo_list_t::iterator it = m_priv->devices.find(m_guid); 597 return (it == m_priv->devices.end()) ? NULL : *it; 598 } 599 600 const DarwinAVCInfo *DarwinFirewireDevice::GetInfoPtr(void) const 601 { 602 avcinfo_list_t::iterator it = m_priv->devices.find(m_guid); 603 return (it == m_priv->devices.end()) ? NULL : *it; 604 } 605 606 607 bool DarwinFirewireDevice::UpdatePlugRegisterPrivate( 608 uint plug_number, int new_fw_chan, int new_speed, 609 bool add_plug, bool remove_plug) 610 { 611 if (!GetInfoPtr()) 612 return false; 613 614 IOFireWireLibDeviceRef fw_handle = GetInfoPtr()->fw_handle; 615 if (!fw_handle) 616 return false; 617 618 io_object_t dev = (*fw_handle)->GetDevice(fw_handle); 619 620 // Read the register 621 uint low_addr = kPCRBaseAddress + 4 + (plug_number << 2); 622 FWAddress addr(0xffff, low_addr, m_node); 623 uint32_t old_plug_val; 624 if (kIOReturnSuccess != (*fw_handle)->ReadQuadlet( 625 fw_handle, dev, &addr, (UInt32*) &old_plug_val, false, 0)) 626 { 627 return false; 628 } 629 630 int old_plug_cnt = (old_plug_val >> 24) & 0x3f; 631 int old_fw_chan = (old_plug_val >> 16) & 0x3f; 632 int old_speed = (old_plug_val >> 14) & 0x03; 633 634 int new_plug_cnt = (int) old_plug_cnt; 635 new_plug_cnt += ((add_plug) ? 1 : 0) - ((remove_plug) ? 1 : 0); 636 if ((new_plug_cnt > 0x3f) || (new_plug_cnt < 0)) 637 { 638 VERBOSE(VB_IMPORTANT, LOC_ERR + "Invalid Plug Count "<<new_plug_cnt); 639 640 return false; 641 } 642 643 new_fw_chan = (new_fw_chan >= 0) ? new_fw_chan : old_fw_chan; 644 if (old_plug_cnt && (new_fw_chan != old_fw_chan)) 645 { 646 VERBOSE(VB_IMPORTANT, LOC_WARN + 647 "Ignoring FWChan change request, plug already open"); 648 649 new_fw_chan = old_fw_chan; 650 } 651 652 new_speed = (new_speed >= 0) ? new_speed : old_speed; 653 if (old_plug_cnt && (new_speed != old_speed)) 654 { 655 VERBOSE(VB_IMPORTANT, LOC_WARN + 656 "Ignoring speed change request, plug already open"); 657 658 new_speed = old_speed; 659 } 660 661 uint32_t new_plug_val = old_plug_val; 662 663 new_plug_val &= ~(0x3f<<24); 664 new_plug_val &= (remove_plug) ? ~kIOFWPCRBroadcast : ~0x0; 665 new_plug_val |= (new_plug_cnt & 0x3f) << 24; 666 667 new_plug_val &= ~(0x3f<<16); 668 new_plug_val |= (new_fw_chan & 0x3F) << 16; 669 670 new_plug_val &= ~(0x03<<14); 671 new_plug_val |= (new_speed & 0x03) << 14; 672 673 return (kIOReturnSuccess == (*fw_handle)->CompareSwap( 674 fw_handle, dev, &addr, old_plug_val, new_plug_val, false, 0)); 675 } 676 677 void DarwinFirewireDevice::HandleBusReset(void) 678 { 679 int plug_number = 0; 680 if (!GetInfoPtr()) 681 return; 682 683 int fw_channel = m_priv->actual_fwchan; 684 bool ok = UpdatePlugRegister(plug_number, fw_channel, 685 m_speed, true, false); 686 if (!ok) 687 { 688 ok = UpdatePlugRegister(plug_number, kAnyAvailableIsochChannel, 689 m_speed, true, false); 690 } 691 692 if (!ok) 693 VERBOSE(VB_IMPORTANT, LOC + "Reset: Failed to reconnect"); 694 else 695 VERBOSE(VB_RECORD, LOC + "Reset: Reconnected succesfully"); 696 } 697 698 bool DarwinFirewireDevice::UpdatePlugRegister( 699 uint plug_number, int fw_chan, int speed, 700 bool add_plug, bool remove_plug, uint retry_cnt) 701 { 702 if (!GetInfoPtr() || !GetInfoPtr()->fw_handle) 703 return false; 704 705 bool ok = false; 706 707 for (uint i = 0; (i < retry_cnt) && !ok; i++) 708 { 709 ok = UpdatePlugRegisterPrivate( 710 plug_number, fw_chan, speed, add_plug, remove_plug); 711 } 712 713 m_priv->actual_fwchan = (ok) ? fw_chan : kAnyAvailableIsochChannel; 714 715 return ok; 716 } 717 718 void DarwinFirewireDevice::HandleDeviceChange(uint messageType) 719 { 720 QString loc = LOC + "HandleDeviceChange: "; 721 722 if (kIOMessageServiceIsTerminated == messageType) 723 { 724 VERBOSE(VB_RECORD, loc + "Disconnect"); 725 // stop printing no data messages.. don't try to open 726 return; 727 } 728 729 if (kIOMessageServiceIsAttemptingOpen == messageType) 730 { 731 VERBOSE(VB_RECORD, loc + "Attempting open"); 732 return; 733 } 734 735 if (kIOMessageServiceWasClosed == messageType) 736 { 737 VERBOSE(VB_RECORD, loc + "Device Closed"); 738 // fill unit_table 739 return; 740 } 741 742 if (kIOMessageServiceIsSuspended == messageType) 743 { 744 VERBOSE(VB_RECORD, loc + "kIOMessageServiceIsSuspended"); 745 // start of reset 746 return; 747 } 748 749 if (kIOMessageServiceIsResumed == messageType) 750 { 751 // end of reset 752 HandleBusReset(); 753 } 754 755 if (kIOMessageServiceIsTerminated == messageType) 756 VERBOSE(VB_RECORD, loc + "kIOMessageServiceIsTerminated"); 757 else if (kIOMessageServiceIsRequestingClose == messageType) 758 VERBOSE(VB_RECORD, loc + "kIOMessageServiceIsRequestingClose"); 759 else if (kIOMessageServiceIsAttemptingOpen == messageType) 760 VERBOSE(VB_RECORD, loc + "kIOMessageServiceIsAttemptingOpen"); 761 else if (kIOMessageServiceWasClosed == messageType) 762 VERBOSE(VB_RECORD, loc + "kIOMessageServiceWasClosed"); 763 else if (kIOMessageServiceBusyStateChange == messageType) 764 VERBOSE(VB_RECORD, loc + "kIOMessageServiceBusyStateChange"); 765 else if (kIOMessageCanDevicePowerOff == messageType) 766 VERBOSE(VB_RECORD, loc + "kIOMessageCanDevicePowerOff"); 767 else if (kIOMessageDeviceWillPowerOff == messageType) 768 VERBOSE(VB_RECORD, loc + "kIOMessageDeviceWillPowerOff"); 769 else if (kIOMessageDeviceWillNotPowerOff == messageType) 770 VERBOSE(VB_RECORD, loc + "kIOMessageDeviceWillNotPowerOff"); 771 else if (kIOMessageDeviceHasPoweredOn == messageType) 772 VERBOSE(VB_RECORD, loc + "kIOMessageDeviceHasPoweredOn"); 773 else if (kIOMessageCanSystemPowerOff == messageType) 774 VERBOSE(VB_RECORD, loc + "kIOMessageCanSystemPowerOff"); 775 else if (kIOMessageSystemWillPowerOff == messageType) 776 VERBOSE(VB_RECORD, loc + "kIOMessageSystemWillPowerOff"); 777 else if (kIOMessageSystemWillNotPowerOff == messageType) 778 VERBOSE(VB_RECORD, loc + "kIOMessageSystemWillNotPowerOff"); 779 else if (kIOMessageCanSystemSleep == messageType) 780 VERBOSE(VB_RECORD, loc + "kIOMessageCanSystemSleep"); 781 else if (kIOMessageSystemWillSleep == messageType) 782 VERBOSE(VB_RECORD, loc + "kIOMessageSystemWillSleep"); 783 else if (kIOMessageSystemWillNotSleep == messageType) 784 VERBOSE(VB_RECORD, loc + "kIOMessageSystemWillNotSleep"); 785 else if (kIOMessageSystemHasPoweredOn == messageType) 786 VERBOSE(VB_RECORD, loc + "kIOMessageSystemHasPoweredOn"); 787 else if (kIOMessageSystemWillRestart == messageType) 788 VERBOSE(VB_RECORD, loc + "kIOMessageSystemWillRestart"); 789 else 790 { 791 VERBOSE(VB_RECORD, loc + "unknown message 0x" 792 <<hex<<messageType<<dec); 793 } 794 } 795 796 // Various message callbacks. 797 798 void *dfd_controller_thunk(void *param) 799 { 800 ((DarwinFirewireDevice*)param)->RunController(); 801 return NULL; 802 } 803 804 void dfd_update_device_list_item( 805 DarwinFirewireDevice *dev, uint64_t guid, void *item) 806 { 807 dev->UpdateDeviceListItem(guid, item); 808 } 809 810 int dfd_no_data_notification(void *callback_data) 811 { 812 ((DarwinFirewireDevice*)callback_data)->PrintNoDataMessage(); 813 814 return kIOReturnSuccess; 815 } 816 817 void dfd_stream_msg(long unsigned int msg, long unsigned int param1, 818 long unsigned int param2, void *callback_data) 819 { 820 ((DarwinFirewireDevice*)callback_data)-> 821 ProcessStreamingMessage(msg, param1, param2); 822 } 823 824 int dfd_tspacket_handler(uint tsPacketCount, uint32_t **ppBuf, 825 void *callback_data) 826 { 827 DarwinFirewireDevice *fw = (DarwinFirewireDevice*) callback_data; 828 if (!fw) 829 return kIOReturnBadArgument; 830 831 for (uint32_t i = 0; i < tsPacketCount; ++i) 832 fw->BroadcastToListeners((const unsigned char*) ppBuf[i], 188); 833 834 return kIOReturnSuccess; 835 } 836 837 static IOReturn dfd_tspacket_handler_thunk( 838 long unsigned int tsPacketCount, UInt32 **ppBuf, void *callback_data) 839 { 840 return dfd_tspacket_handler( 841 tsPacketCount, (uint32_t**)ppBuf, callback_data); 842 } 843 844 static void dfd_update_device_list(void *dfd, io_iterator_t deviter) 845 { 846 DarwinFirewireDevice *dev = (DarwinFirewireDevice*) dfd; 847 848 io_object_t it = NULL; 849 while ((it = IOIteratorNext(deviter))) 850 { 851 uint64_t guid = 0; 852 853 CFMutableDictionaryRef props; 854 int ret = IORegistryEntryCreateCFProperties( 855 it, &props, kCFAllocatorDefault, kNilOptions); 856 857 if (kIOReturnSuccess == ret) 858 { 859 CFNumberRef GUIDDesc = (CFNumberRef) 860 CFDictionaryGetValue(props, CFSTR("GUID")); 861 CFNumberGetValue(GUIDDesc, kCFNumberSInt64Type, &guid); 862 CFRelease(props); 863 dfd_update_device_list_item(dev, guid, &it); 864 } 865 } 866 } 867 868 static void dfd_streaming_log_message(char *msg) 869 { 870 VERBOSE(VB_RECORD, QString("MPEG2Receiver: %1").arg(msg)); 871 } -
libs/libmythtv/firewirerecorderbase.cpp
1 /**2 * FirewireRecorder3 * Copyright (c) 2005 by Jim Westfall and Dave Abrahams4 * Distributed as part of MythTV under GPL v2 and later.5 */6 7 // MythTV includes8 #include "firewirerecorderbase.h"9 #include "mythcontext.h"10 #include "mpegtables.h"11 #include "mpegstreamdata.h"12 #include "tv_rec.h"13 14 #define LOC QString("FireRecBase: ")15 #define LOC_ERR QString("FireRecBase, Error: ")16 17 const int FirewireRecorderBase::kTimeoutInSeconds = 15;18 19 FirewireRecorderBase::FirewireRecorderBase(TVRec *rec)20 : DTVRecorder(rec), _mpeg_stream_data(NULL)21 {22 SetStreamData(new MPEGStreamData(1, true));23 }24 25 FirewireRecorderBase::~FirewireRecorderBase()26 {27 SetStreamData(NULL);28 }29 30 void FirewireRecorderBase::StartRecording(void) {31 32 VERBOSE(VB_RECORD, LOC + "StartRecording");33 34 if (!Open()) {35 _error = true;36 return;37 }38 39 _request_recording = true;40 _recording = true;41 42 start();43 44 while(_request_recording) {45 if (PauseAndWait())46 continue;47 48 if (!grab_frames())49 {50 _error = true;51 return;52 }53 }54 55 stop();56 FinishRecording();57 58 _recording = false;59 }60 61 void FirewireRecorderBase::ProcessTSPacket(const TSPacket &tspacket)62 {63 if (tspacket.TransportError())64 return;65 66 if (tspacket.ScramplingControl())67 return;68 69 if (tspacket.HasAdaptationField())70 StreamData()->HandleAdaptationFieldControl(&tspacket);71 72 if (tspacket.HasPayload())73 {74 const unsigned int lpid = tspacket.PID();75 76 // Pass or reject packets based on PID, and parse info from them77 if (lpid == StreamData()->VideoPIDSingleProgram())78 {79 _buffer_packets = !FindMPEG2Keyframes(&tspacket);80 BufferedWrite(tspacket);81 }82 else if (StreamData()->IsAudioPID(lpid))83 BufferedWrite(tspacket);84 else if (StreamData()->IsListeningPID(lpid))85 StreamData()->HandleTSTables(&tspacket);86 else if (StreamData()->IsWritingPID(lpid))87 BufferedWrite(tspacket);88 }89 90 _ts_stats.IncrTSPacketCount();91 if (0 == _ts_stats.TSPacketCount()%1000000)92 VERBOSE(VB_RECORD, _ts_stats.toString());93 }94 95 void FirewireRecorderBase::SetOptionsFromProfile(RecordingProfile *profile,96 const QString &videodev,97 const QString &audiodev,98 const QString &vbidev)99 {100 (void)videodev;101 (void)audiodev;102 (void)vbidev;103 (void)profile;104 }105 106 // documented in recorderbase.cpp107 bool FirewireRecorderBase::PauseAndWait(int timeout)108 {109 if (request_pause)110 {111 if (!paused)112 {113 stop();114 paused = true;115 pauseWait.wakeAll();116 if (tvrec)117 tvrec->RecorderPaused();118 }119 unpauseWait.wait(timeout);120 }121 if (!request_pause && paused)122 {123 start();124 paused = false;125 }126 return paused;127 }128 129 void FirewireRecorderBase::SetStreamData(MPEGStreamData *data)130 {131 if (data == _mpeg_stream_data)132 return;133 134 MPEGStreamData *old_data = _mpeg_stream_data;135 _mpeg_stream_data = data;136 137 if (data)138 data->AddMPEGSPListener(this);139 140 if (old_data)141 delete old_data;142 }143 144 void FirewireRecorderBase::HandleSingleProgramPAT(145 ProgramAssociationTable *pat)146 {147 if (!pat)148 return;149 150 int next = (pat->tsheader()->ContinuityCounter()+1)&0xf;151 pat->tsheader()->SetContinuityCounter(next);152 BufferedWrite(*(reinterpret_cast<const TSPacket*>(pat->tsheader())));153 }154 155 void FirewireRecorderBase::HandleSingleProgramPMT(ProgramMapTable *pmt)156 {157 if (!pmt)158 return;159 160 int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf;161 pmt->tsheader()->SetContinuityCounter(next);162 BufferedWrite(*(reinterpret_cast<const TSPacket*>(pmt->tsheader())));163 } -
libs/libmythtv/firewirerecorder.cpp
1 1 /** 2 2 * FirewireRecorder 3 * Copyright (c) 2005 by Jim Westfall 3 * Copyright (c) 2005 by Jim Westfall and Dave Abrahams 4 4 * Distributed as part of MythTV under GPL v2 and later. 5 5 */ 6 6 7 // C includes8 #include <pthread.h>9 #include <sys/select.h>10 11 // C++ includes12 #include <iostream>13 using namespace std;14 15 7 // MythTV includes 16 8 #include "firewirerecorder.h" 9 #include "firewirechannel.h" 17 10 #include "mythcontext.h" 18 11 #include "mpegtables.h" 19 12 #include "mpegstreamdata.h" 20 13 #include "tv_rec.h" 21 14 22 #define LOC QString("FireRec : ")23 #define LOC_ERR QString("FireRec , Error: ")15 #define LOC QString("FireRecBase(%1): ").arg(channel->GetDevice()) 16 #define LOC_ERR QString("FireRecBase(%1), Error: ").arg(channel->GetDevice()) 24 17 25 const int FirewireRecorder::kBroadcastChannel = 63; 26 const int FirewireRecorder::kConnectionP2P = 0; 27 const int FirewireRecorder::kConnectionBroadcast = 1; 28 const uint FirewireRecorder::kMaxBufferedPackets = 2000; 29 30 // callback function for libiec61883 31 int fw_tspacket_handler(unsigned char *tspacket, int /*len*/, 32 uint dropped, void *callback_data) 18 FirewireRecorder::FirewireRecorder(TVRec *rec, FirewireChannel *chan) : 19 DTVRecorder(rec), _mpeg_stream_data(NULL), 20 channel(chan), isopen(false) 33 21 { 34 if (dropped)35 {36 VERBOSE(VB_RECORD, LOC_ERR +37 QString("Dropped %1 packet(s).").arg(dropped));38 }39 40 if (SYNC_BYTE != tspacket[0])41 {42 VERBOSE(VB_IMPORTANT, LOC_ERR + "TS packet out of sync.");43 return 1;44 }45 46 FirewireRecorder *fw = (FirewireRecorder*) callback_data;47 if (fw)48 fw->ProcessTSPacket(*(reinterpret_cast<TSPacket*>(tspacket)));49 50 return (fw) ? 1 : 0;51 22 } 52 23 53 static QString speed_to_string(uint speed)24 FirewireRecorder::~FirewireRecorder() 54 25 { 55 if (speed > RAW1394_ISO_SPEED_400) 56 return QString("Invalid Speed (%1)").arg(speed); 57 58 static const uint speeds[] = { 100, 200, 400, }; 59 return QString("%1Mbps").arg(speeds[speed]); 26 SetStreamData(NULL); 27 Close(); 60 28 } 61 29 62 30 bool FirewireRecorder::Open(void) 63 31 { 64 if (isopen)65 return true;32 if (!isopen) 33 isopen = channel->GetFirewireDevice()->OpenPort(); 66 34 67 VERBOSE(VB_RECORD, LOC + 68 QString("Initializing Port: %1, Node: %2, Speed: %3") 69 .arg(fwport).arg(fwnode).arg(speed_to_string(fwspeed))); 35 return isopen; 36 } 70 37 71 fwhandle = raw1394_new_handle_on_port(fwport); 72 if (!fwhandle) 73 { 74 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to get handle for " + 75 QString("port: %1, bailing").arg(fwport) + ENO); 76 return false; 77 } 38 void FirewireRecorder::Close(void) 39 { 40 if (isopen) 41 { 42 channel->GetFirewireDevice()->ClosePort(); 43 isopen = false; 44 } 45 } 78 46 79 if (kConnectionP2P == fwconnection) 80 { 81 VERBOSE(VB_RECORD, LOC + "Creating P2P Connection " + 82 QString("with Node: %1").arg(fwnode)); 83 fwchannel = iec61883_cmp_connect(fwhandle, 84 fwnode | 0xffc0, &fwoplug, 85 raw1394_get_local_id(fwhandle), 86 &fwiplug, &fwbandwidth); 87 if (fwchannel > -1) 88 { 89 VERBOSE(VB_RECORD, LOC + 90 QString("Created Channel: %1, " 91 "Bandwidth Allocation: %2") 92 .arg(fwchannel).arg(fwbandwidth)); 93 } 94 } 95 else 96 { 97 fwchannel = kBroadcastChannel - fwnode; 47 void FirewireRecorder::StartStreaming(void) 48 { 49 channel->GetFirewireDevice()->AddListener(this); 50 } 98 51 99 VERBOSE(VB_RECORD, LOC + "Creating Broadcast Connection " + 100 QString("with Node: %1, Channel: %2").arg(fwnode) 101 .arg(fwchannel)); 102 if (iec61883_cmp_create_bcast_output(fwhandle, 103 fwnode | 0xffc0, 0, 104 fwchannel, 105 fwspeed) != 0) 106 { 107 VERBOSE(VB_IMPORTANT, LOC + "Failed to create connection"); 108 // release raw1394 object; 109 raw1394_destroy_handle(fwhandle); 110 return false; 111 } 112 fwbandwidth = 0; 113 } 52 void FirewireRecorder::StopStreaming(void) 53 { 54 channel->GetFirewireDevice()->RemoveListener(this); 55 } 114 56 115 fwmpeg = iec61883_mpeg2_recv_init(fwhandle, fw_tspacket_handler, this); 116 if (!fwmpeg) 117 { 118 VERBOSE(VB_IMPORTANT, LOC + 119 "Unable to init iec61883_mpeg2 object, bailing" + ENO); 57 void FirewireRecorder::StartRecording(void) 58 { 59 VERBOSE(VB_RECORD, LOC + "StartRecording"); 120 60 121 // release raw1394 object; 122 raw1394_destroy_handle(fwhandle); 123 return false; 124 } 61 if (!Open()) 62 { 63 _error = true; 64 return; 65 } 125 66 126 // Set buffered packets size 127 size_t buffer_size = gContext->GetNumSetting("HDRingbufferSize", 128 50 * TSPacket::SIZE); 129 size_t buffered_packets = min(buffer_size / 4, 130 (size_t) kMaxBufferedPackets); 131 iec61883_mpeg2_set_buffers(fwmpeg, buffered_packets); 132 VERBOSE(VB_IMPORTANT, LOC + 133 QString("Buffered packets %1 (%2 KB)") 134 .arg(buffered_packets).arg(buffered_packets * 4)); 67 _request_recording = true; 68 _recording = true; 135 69 136 // Set speed if needed. 137 // Probably shouldn't even allow user to set, 138 // 100Mbps should be more the enough. 139 int curspeed = iec61883_mpeg2_get_speed(fwmpeg); 140 if (curspeed != fwspeed) 141 { 142 VERBOSE(VB_RECORD, LOC + 143 QString("Changing Speed %1 -> %2") 144 .arg(speed_to_string(curspeed)) 145 .arg(speed_to_string(fwspeed))); 70 StartStreaming(); 146 71 147 iec61883_mpeg2_set_speed(fwmpeg, fwspeed); 148 if (fwspeed != iec61883_mpeg2_get_speed(fwmpeg)) 149 { 150 VERBOSE(VB_IMPORTANT, LOC + 151 "Unable to set firewire speed, continuing"); 152 } 153 } 72 while (_request_recording) 73 { 74 if (!PauseAndWait()) 75 usleep(50 * 1000); 76 } 154 77 155 fwfd = raw1394_get_fd(fwhandle); 78 StopStreaming(); 79 FinishRecording(); 156 80 157 return isopen = true;81 _recording = false; 158 82 } 159 83 160 void FirewireRecorder:: Close(void)84 void FirewireRecorder::AddData(const unsigned char *data, uint len) 161 85 { 162 if (!isopen) 86 uint bufsz = buffer.size(); 87 if ((SYNC_BYTE == data[0]) && (TSPacket::SIZE == len) && 88 (TSPacket::SIZE > bufsz)) 89 { 90 if (bufsz) 91 buffer.clear(); 92 93 ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(data))); 163 94 return; 95 } 164 96 165 isopen = false; 97 buffer.insert(buffer.end(), data, data + len); 98 bufsz += len; 166 99 167 VERBOSE(VB_RECORD, LOC + "Releasing iec61883_mpeg2 object"); 168 iec61883_mpeg2_close(fwmpeg); 100 int sync_at = -1; 101 for (uint i = 0; (i < bufsz) && (sync_at < 0); i++) 102 { 103 if (buffer[i] == SYNC_BYTE) 104 sync_at = i; 105 } 169 106 170 if (fwconnection == kConnectionP2P && fwchannel > -1) 107 if (sync_at < 0) 108 return; 109 110 if (bufsz < 30 * TSPacket::SIZE) 111 return; // build up a little buffer 112 113 while (sync_at + TSPacket::SIZE < bufsz) 171 114 { 172 VERBOSE(VB_RECORD, LOC +173 QString("Disconnecting channel %1").arg(fwchannel));115 ProcessTSPacket(*(reinterpret_cast<const TSPacket*>( 116 &buffer[0] + sync_at))); 174 117 175 iec61883_cmp_disconnect(fwhandle, fwnode | 0xffc0, fwoplug, 176 raw1394_get_local_id (fwhandle), 177 fwiplug, fwchannel, fwbandwidth); 118 sync_at += TSPacket::SIZE; 178 119 } 179 120 180 VERBOSE(VB_RECORD, LOC + "Releasing raw1394 handle"); 181 raw1394_destroy_handle(fwhandle); 121 buffer.erase(buffer.begin(), buffer.begin() + sync_at); 122 123 return; 182 124 } 183 125 184 bool FirewireRecorder::grab_frames()126 void FirewireRecorder::ProcessTSPacket(const TSPacket &tspacket) 185 127 { 186 struct timeval tv;187 fd_set rfds;128 if (tspacket.TransportError()) 129 return; 188 130 189 FD_ZERO(&rfds); 190 FD_SET(fwfd, &rfds); 191 tv.tv_sec = kTimeoutInSeconds; 192 tv.tv_usec = 0; 131 if (tspacket.ScramplingControl()) 132 return; 193 133 194 if (select(fwfd + 1, &rfds, NULL, NULL, &tv) <= 0) 195 { 196 VERBOSE(VB_IMPORTANT, LOC + 197 QString("No Input in %1 seconds [P:%2 N:%3] (select)") 198 .arg(kTimeoutInSeconds).arg(fwport).arg(fwnode)); 199 return false; 200 } 134 if (tspacket.HasAdaptationField()) 135 GetStreamData()->HandleAdaptationFieldControl(&tspacket); 201 136 202 int ret = raw1394_loop_iterate(fwhandle); 203 if (ret) 137 if (tspacket.HasPayload()) 204 138 { 205 VERBOSE(VB_IMPORTANT, LOC_ERR + "libraw1394_loop_iterate() " + 206 QString("returned %1").arg(ret)); 207 return false; 208 } 139 const unsigned int lpid = tspacket.PID(); 209 140 210 return true; 141 // Pass or reject packets based on PID, and parse info from them 142 if (lpid == GetStreamData()->VideoPIDSingleProgram()) 143 { 144 _buffer_packets = !FindMPEG2Keyframes(&tspacket); 145 BufferedWrite(tspacket); 146 } 147 else if (GetStreamData()->IsAudioPID(lpid)) 148 BufferedWrite(tspacket); 149 else if (GetStreamData()->IsListeningPID(lpid)) 150 GetStreamData()->HandleTSTables(&tspacket); 151 else if (GetStreamData()->IsWritingPID(lpid)) 152 BufferedWrite(tspacket); 153 } 211 154 } 212 155 213 void FirewireRecorder::SetOption(const QString &name, const QString &value) 156 void FirewireRecorder::SetOptionsFromProfile(RecordingProfile *profile, 157 const QString &videodev, 158 const QString &audiodev, 159 const QString &vbidev) 214 160 { 215 if (name == "model") 216 fwmodel = value; 161 (void)videodev; 162 (void)audiodev; 163 (void)vbidev; 164 (void)profile; 217 165 } 218 166 219 void FirewireRecorder::SetOption(const QString &name, int value) 167 // documented in recorderbase.cpp 168 bool FirewireRecorder::PauseAndWait(int timeout) 220 169 { 221 if (name == "port") 222 fwport = value; 223 else if (name == "node") 224 fwnode = value; 225 else if (name == "speed") 170 if (request_pause) 226 171 { 227 if (RAW1394_ISO_SPEED_100 != value && 228 RAW1394_ISO_SPEED_200 != value && 229 RAW1394_ISO_SPEED_400 != value) 172 VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- pause"); 173 if (!paused) 230 174 { 231 VERBOSE(VB_IMPORTANT, LOC_ERR +232 QString("Unknown speed '%1', will use 100Mbps")233 .arg(value));234 235 value = RAW1394_ISO_SPEED_100;175 StopStreaming(); 176 paused = true; 177 pauseWait.wakeAll(); 178 if (tvrec) 179 tvrec->RecorderPaused(); 236 180 } 237 fwspeed = value;181 unpauseWait.wait(timeout); 238 182 } 239 else if (name == "connection")183 if (!request_pause && paused) 240 184 { 241 if (kConnectionP2P != value && 242 kConnectionBroadcast != value)243 {244 VERBOSE(VB_IMPORTANT, LOC_ERR + 245 QString("Unknown connection type '%1', will use P2P")246 .arg(fwconnection)); 185 VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- unpause"); 186 StartStreaming(); 187 paused = false; 188 } 189 return paused; 190 } 247 191 248 fwconnection = kConnectionP2P; 249 } 250 fwconnection = value; 192 void FirewireRecorder::SetStreamData(MPEGStreamData *data) 193 { 194 if (data == _mpeg_stream_data) 195 return; 196 197 MPEGStreamData *old_data = _mpeg_stream_data; 198 _mpeg_stream_data = data; 199 if (old_data) 200 delete old_data; 201 202 if (data) 203 { 204 data->AddMPEGSPListener(this); 205 206 if (data->DesiredProgram() >= 0) 207 data->SetDesiredProgram(data->DesiredProgram()); 251 208 } 252 209 } 210 211 void FirewireRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat) 212 { 213 if (!pat) 214 return; 215 216 int next = (pat->tsheader()->ContinuityCounter()+1)&0xf; 217 pat->tsheader()->SetContinuityCounter(next); 218 BufferedWrite(*(reinterpret_cast<const TSPacket*>(pat->tsheader()))); 219 } 220 221 void FirewireRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 222 { 223 if (!pmt) 224 return; 225 226 int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf; 227 pmt->tsheader()->SetContinuityCounter(next); 228 BufferedWrite(*(reinterpret_cast<const TSPacket*>(pmt->tsheader()))); 229 } -
libs/libmythtv/firewirerecorder.h
4 4 * Distributed as part of MythTV under GPL v2 and later. 5 5 */ 6 6 7 #ifndef FIREWIRERECORDER_H_8 #define FIREWIRERECORDER_H_7 #ifndef _FIREWIRERECORDER_H_ 8 #define _FIREWIRERECORDER_H_ 9 9 10 #include "firewirerecorderbase.h" 11 #include " tsstats.h"12 #include <libraw1394/raw1394.h>13 #include <libiec61883/iec61883.h>10 // MythTV headers 11 #include "dtvrecorder.h" 12 #include "tspacket.h" 13 #include "streamlisteners.h" 14 14 15 class TVRec; 16 class FirewireChannel; 17 15 18 /** \class FirewireRecorder 16 * \brief Linux FirewireRFecorder 19 * \brief This is a specialization of DTVRecorder used to 20 * handle DVB and ATSC streams from a firewire input. 17 21 * 18 * \sa FirewireRecorderBase22 * \sa DTVRecorder 19 23 */ 20 class FirewireRecorder : public FirewireRecorderBase 24 class FirewireRecorder : public DTVRecorder, 25 public MPEGSingleProgramStreamListener, 26 public TSDataListener 21 27 { 22 friend int fw_tspacket_handler(unsigned char*,int,uint,void*); 28 friend class MPEGStreamData; 29 friend class TSPacketProcessor; 23 30 24 31 public: 25 FirewireRecorder(TVRec *rec) 26 : FirewireRecorderBase(rec), 27 fwport(-1), fwchannel(-1), fwspeed(-1), fwbandwidth(-1), 28 fwfd(-1), fwconnection(kConnectionP2P), 29 fwoplug(-1), fwiplug(-1), fwmodel(""), fwnode(0), 30 fwhandle(NULL), fwmpeg(NULL), isopen(false) { } 31 ~FirewireRecorder() { Close(); } 32 FirewireRecorder(TVRec *rec, FirewireChannel *chan); 33 virtual ~FirewireRecorder(); 32 34 33 35 // Commands 34 bool Open(void); 36 bool Open(void); 37 void Close(void); 35 38 39 void StartStreaming(void); 40 void StopStreaming(void); 41 42 void StartRecording(void); 43 bool PauseAndWait(int timeout = 100); 44 45 void AddData(const unsigned char *data, uint dataSize); 46 void ProcessTSPacket(const TSPacket &tspacket); 47 36 48 // Sets 37 void SetOption(const QString &name, const QString &value); 38 void SetOption(const QString &name, int value); 49 void SetOptionsFromProfile(RecordingProfile *profile, 50 const QString &videodev, 51 const QString &audiodev, 52 const QString &vbidev); 53 void SetStreamData(MPEGStreamData*); 39 54 40 private: 41 void Close(void); 42 void start() { iec61883_mpeg2_recv_start(fwmpeg, fwchannel); } 43 void stop() { iec61883_mpeg2_recv_stop(fwmpeg); } 44 bool grab_frames(); 55 // Gets 56 MPEGStreamData *GetStreamData(void) { return _mpeg_stream_data; } 45 57 58 // MPEG Single Program 59 void HandleSingleProgramPAT(ProgramAssociationTable*); 60 void HandleSingleProgramPMT(ProgramMapTable*); 61 62 protected: 63 FirewireRecorder(TVRec *rec); 64 46 65 private: 47 int fwport; 48 int fwchannel; 49 int fwspeed; 50 int fwbandwidth; 51 int fwfd; 52 int fwconnection; 53 int fwoplug; 54 int fwiplug; 55 QString fwmodel; 56 nodeid_t fwnode; 57 raw1394handle_t fwhandle; 58 iec61883_mpeg2_t fwmpeg; 59 bool isopen; 60 61 static const int kBroadcastChannel; 62 static const int kConnectionP2P; 63 static const int kConnectionBroadcast; 64 static const uint kMaxBufferedPackets; 66 MPEGStreamData *_mpeg_stream_data; 67 FirewireChannel *channel; 68 bool isopen; 69 vector<unsigned char> buffer; 65 70 }; 66 71 67 #endif 72 #endif // _FIREWIRERECORDER_H_ -
libs/libmythtv/darwinavcinfo.cpp
1 /** 2 * DarwinFirewireChannel 3 * Copyright (c) 2006 by Daniel Kristjansson 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 // Std C++ headers 8 #include <vector> 9 using namespace std; 10 11 // MythTV headers 12 #include "darwinfirewiredevice.h" 13 #include "darwinavcinfo.h" 14 #include "mythcontext.h" 15 16 #ifndef kIOFireWireAVCLibUnitInterfaceID2 17 #define kIOFireWireAVCLibUnitInterfaceID2 \ 18 CFUUIDGetConstantUUIDWithBytes( \ 19 NULL, \ 20 0x85, 0xB5, 0xE9, 0x54, 0x0A, 0xEF, 0x11, 0xD8, \ 21 0x8D, 0x19, 0x00, 0x03, 0x93, 0x91, 0x4A, 0xBA) 22 #endif 23 24 static void dfd_device_change_msg( 25 void*, io_service_t, natural_t messageType, void*); 26 27 void DarwinAVCInfo::Update(uint64_t _guid, DarwinFirewireDevice *dev, 28 IONotificationPortRef notify_port, 29 CFRunLoopRef &thread_cf_ref, io_object_t obj) 30 { 31 IOObjectRelease(fw_device_notifier_ref); 32 IOObjectRelease(fw_node_ref); 33 IOObjectRelease(fw_device_ref); 34 IOObjectRelease(fw_service_ref); 35 IOObjectRelease(avc_service_ref); 36 37 avc_service_ref = obj; 38 39 IORegistryEntryGetParentEntry( 40 avc_service_ref, kIOServicePlane, &fw_service_ref); 41 IORegistryEntryGetParentEntry( 42 fw_service_ref, kIOServicePlane, &fw_device_ref); 43 IORegistryEntryGetParentEntry( 44 fw_device_ref, kIOServicePlane, &fw_node_ref); 45 46 if (notify_port) 47 { 48 IOServiceAddInterestNotification( 49 notify_port, obj, kIOGeneralInterest, 50 dfd_device_change_msg, dev, 51 &fw_device_notifier_ref); 52 } 53 54 if (guid == _guid) 55 return; // we're done 56 57 guid = _guid; 58 59 ////////////////////////// 60 // get basic info 61 62 CFMutableDictionaryRef props; 63 int ret = IORegistryEntryCreateCFProperties( 64 obj, &props, kCFAllocatorDefault, kNilOptions); 65 if (kIOReturnSuccess != ret) 66 return; // this is bad 67 68 CFNumberRef specDesc = (CFNumberRef) 69 CFDictionaryGetValue(props, CFSTR("Unit_Spec_ID")); 70 CFNumberGetValue(specDesc, kCFNumberSInt32Type, &specid); 71 72 CFNumberRef typeDesc = (CFNumberRef) 73 CFDictionaryGetValue(props, CFSTR("Unit_Type")); 74 CFNumberGetValue(typeDesc, kCFNumberSInt32Type, &modelid); 75 76 CFNumberRef vendorDesc = (CFNumberRef) 77 CFDictionaryGetValue(props, CFSTR("Vendor_ID")); 78 CFNumberGetValue(vendorDesc, kCFNumberSInt32Type, &vendorid); 79 80 CFNumberRef versionDesc = (CFNumberRef) 81 CFDictionaryGetValue(props, CFSTR("Unit_SW_Version")); 82 CFNumberGetValue(versionDesc, kCFNumberSInt32Type, &firmware_revision); 83 84 CFStringRef tmp0 = (CFStringRef) 85 CFDictionaryGetValue(props, CFSTR("FireWire Product Name")); 86 if (tmp0) 87 { 88 char tmp1[1024]; 89 bzero(tmp1, sizeof(tmp1)); 90 CFStringGetCString(tmp0, tmp1, sizeof(tmp1) - sizeof(char), 91 kCFStringEncodingMacRoman); 92 product_name = QString("%1").arg(tmp1); 93 } 94 95 CFRelease(props); 96 97 ////////////////////////// 98 // get subunit info 99 100 VERBOSE(VB_RECORD, "Scanning guid: 0x"<<hex<<guid<<dec); 101 102 bool wasOpen = IsAVCInterfaceOpen(); 103 if (OpenAVCInterface(thread_cf_ref)) 104 { 105 memset(unit_table, 0xff, 32 * sizeof(uint8_t)); 106 107 for (uint i = 0; i < 8; i++) 108 { 109 vector<uint8_t> cmd; 110 vector<uint8_t> ret; 111 112 cmd.push_back(FirewireDevice::kAVCStatusInquiryCommand); 113 cmd.push_back(FirewireDevice::kAVCSubunitTypeUnit | 114 FirewireDevice::kAVCSubunitIdIgnore); 115 cmd.push_back(FirewireDevice::kAVCUnitSubunitInfoOpcode); 116 cmd.push_back((i<<4) | 0x07); 117 cmd.push_back(0xFF); 118 cmd.push_back(0xFF); 119 cmd.push_back(0xFF); 120 cmd.push_back(0xFF); 121 122 if (!SendAVCCommand(cmd, ret, -1)) 123 { 124 VERBOSE(VB_IMPORTANT, "SendAVCCommand failed"); 125 continue; 126 } 127 128 if (ret.size() >= 8) 129 { 130 unit_table[(i<<2)+0] = ret[4]; 131 unit_table[(i<<2)+1] = ret[5]; 132 unit_table[(i<<2)+2] = ret[6]; 133 unit_table[(i<<2)+3] = ret[7]; 134 135 VERBOSE(VB_RECORD, "Added subunits:"<<hex 136 <<" 0x"<<((int)ret[4])<<" 0x"<<((int)ret[5]) 137 <<" 0x"<<((int)ret[6])<<" 0x"<<((int)ret[7]) 138 <<" filt:" 139 <<" 0x"<<(ret[4] & FirewireDevice::kAVCSubunitTypeUnit) 140 <<" 0x"<<(ret[5] & FirewireDevice::kAVCSubunitTypeUnit) 141 <<" 0x"<<(ret[6] & FirewireDevice::kAVCSubunitTypeUnit) 142 <<" 0x"<<(ret[7] & FirewireDevice::kAVCSubunitTypeUnit) 143 <<dec); 144 } 145 } 146 147 if (!wasOpen) 148 CloseAVCInterface(); 149 } 150 } 151 152 bool DarwinAVCInfo::SendAVCCommand( 153 const vector<uint8_t> &cmd, 154 vector<uint8_t> &result, 155 int /*retry_cnt*/) 156 { 157 result.clear(); 158 159 uint32_t result_length = 4096; 160 uint8_t response[4096]; 161 162 if (!avc_handle) 163 return false; 164 165 int ret = (*avc_handle)-> 166 AVCCommand(avc_handle, (const UInt8*) &cmd[0], cmd.size(), 167 response, (UInt32*) &result_length); 168 169 if (ret != kIOReturnSuccess) 170 return false; 171 172 if (result_length) 173 result.insert(result.end(), response, response + result_length); 174 175 return true; 176 } 177 178 bool DarwinAVCInfo::Open(CFRunLoopRef &thread_cf_ref) 179 { 180 if (IsOpen()) 181 return true; 182 183 if (!OpenAVCInterface(thread_cf_ref)) 184 return false; 185 186 if (!OpenDeviceInterface(thread_cf_ref)) 187 { 188 CloseAVCInterface(); 189 return false; 190 } 191 192 return true; 193 } 194 195 void DarwinAVCInfo::Close(void) 196 { 197 CloseDeviceInterface(); 198 CloseAVCInterface(); 199 } 200 201 bool DarwinAVCInfo::OpenAVCInterface(CFRunLoopRef &thread_cf_ref) 202 { 203 if (IsAVCInterfaceOpen()) 204 return true; 205 206 if (!avc_service_ref) 207 return false; 208 209 IOCFPlugInInterface **input_plug; 210 int32_t dummy; 211 int ret = IOCreatePlugInInterfaceForService( 212 avc_service_ref, kIOFireWireAVCLibUnitTypeID, kIOCFPlugInInterfaceID, 213 &input_plug, (SInt32*) &dummy); 214 215 if (kIOReturnSuccess != ret) 216 return false; 217 218 // Try to get post-Jaguar interface 219 HRESULT err = (*input_plug)->QueryInterface( 220 input_plug, CFUUIDGetUUIDBytes(kIOFireWireAVCLibUnitInterfaceID2), 221 (void**) &avc_handle); 222 223 // On failure, try Jaguar interface 224 if (S_OK != err) 225 { 226 err = (*input_plug)->QueryInterface( 227 input_plug, CFUUIDGetUUIDBytes(kIOFireWireAVCLibUnitInterfaceID), 228 (void**) &avc_handle); 229 } 230 231 if (S_OK != err) 232 { 233 (*input_plug)->Release(input_plug); 234 return false; 235 } 236 237 // Add avc_handle to the event loop 238 ret = (*avc_handle)->addCallbackDispatcherToRunLoop( 239 avc_handle, thread_cf_ref); 240 241 (*input_plug)->Release(input_plug); 242 243 if (kIOReturnSuccess != ret) 244 { 245 (*avc_handle)->Release(avc_handle); 246 avc_handle = NULL; 247 return false; 248 } 249 250 ret = (*avc_handle)->open(avc_handle); 251 if (kIOReturnSuccess != ret) 252 { 253 (*avc_handle)->Release(avc_handle); 254 avc_handle = NULL; 255 return false; 256 } 257 258 return true; 259 } 260 261 void DarwinAVCInfo::CloseAVCInterface(void) 262 { 263 if (!avc_handle) 264 return; 265 266 (*avc_handle)->removeCallbackDispatcherFromRunLoop(avc_handle); 267 (*avc_handle)->close(avc_handle); 268 (*avc_handle)->Release(avc_handle); 269 270 avc_handle = NULL; 271 } 272 273 bool DarwinAVCInfo::OpenDeviceInterface(CFRunLoopRef &thread_cf_ref) 274 { 275 if (fw_handle) 276 return true; 277 278 if (!avc_handle) 279 return false; 280 281 IOCFPlugInInterface **input_plug; 282 int32_t dummy; 283 int ret = IOCreatePlugInInterfaceForService( 284 fw_device_ref, kIOFireWireLibTypeID, kIOCFPlugInInterfaceID, 285 &input_plug, (SInt32*) &dummy); 286 287 if (kIOReturnSuccess != ret) 288 return false; 289 290 HRESULT err = (*input_plug)->QueryInterface( 291 input_plug, CFUUIDGetUUIDBytes(kIOFireWireNubInterfaceID), 292 (void**) &fw_handle); 293 294 if (S_OK != err) 295 { 296 (*input_plug)->Release(input_plug); 297 return false; 298 } 299 300 // Add fw_handle to the event loop 301 ret = (*fw_handle)->AddCallbackDispatcherToRunLoop( 302 fw_handle, thread_cf_ref); 303 304 (*input_plug)->Release(input_plug); 305 306 if (kIOReturnSuccess == ret) 307 { 308 // open the interface 309 ret = (*fw_handle)->OpenWithSessionRef( 310 fw_handle, (*avc_handle)->getSessionRef(avc_handle)); 311 } 312 313 if (kIOReturnSuccess != ret) 314 { 315 (*fw_handle)->Release(fw_handle); 316 fw_handle = NULL; 317 return false; 318 } 319 320 return true; 321 } 322 323 void DarwinAVCInfo::CloseDeviceInterface(void) 324 { 325 if (!fw_handle) 326 return; 327 328 (*fw_handle)->RemoveCallbackDispatcherFromRunLoop(fw_handle); 329 (*fw_handle)->Close(fw_handle); 330 (*fw_handle)->Release(fw_handle); 331 332 fw_handle = NULL; 333 } 334 335 static void dfd_device_change_msg( 336 void *dfd, io_service_t, natural_t messageType, void*) 337 { 338 DarwinFirewireDevice *dev = (DarwinFirewireDevice*) dfd; 339 dev->HandleDeviceChange(messageType); 340 } -
libs/libmythtv/darwinfirewiredevice.h
1 #ifndef _DARWIN_FIREWIRE_DEVICE_H_ 2 #define _DARWIN_FIREWIRE_DEVICE_H_ 3 4 #include "firewiredevice.h" 5 6 class DFDPriv; 7 class DarwinAVCInfo; 8 9 class DarwinFirewireDevice : public FirewireDevice 10 { 11 friend void *dfd_controller_thunk(void *param); 12 friend void dfd_update_device_list_item(DarwinFirewireDevice *dev, 13 uint64_t guid, void *item); 14 friend int dfd_no_data_notification(void *cb_data); 15 friend void dfd_stream_msg( 16 long unsigned int msg, long unsigned int param1, 17 long unsigned int param2, void *callback_data); 18 friend int dfd_tspacket_handler( 19 uint tsPacketCount, uint32_t **ppBuf, void *callback_data); 20 21 22 public: 23 DarwinFirewireDevice(uint64_t guid, uint subunitid, uint speed); 24 ~DarwinFirewireDevice(); 25 26 virtual bool OpenPort(void); 27 virtual bool ClosePort(void); 28 void HandleDeviceChange(uint messageType); 29 30 virtual void AddListener(TSDataListener*); 31 virtual void RemoveListener(TSDataListener*); 32 33 // Gets 34 virtual bool IsPortOpen(void) const; 35 36 // Statics 37 static vector<AVCInfo> GetSTBList(void); 38 39 private: 40 void StartController(void); 41 void StopController(void); 42 43 bool OpenAVStream(void); 44 bool CloseAVStream(void); 45 bool IsAVStreamOpen(void) const; 46 47 bool StartStreaming(void); 48 bool StopStreaming(void); 49 50 virtual bool SendAVCCommand( 51 const vector<uint8_t> &cmd, 52 vector<uint8_t> &result, 53 int /*retry_cnt*/); 54 55 void HandleBusReset(void); 56 bool UpdatePlugRegisterPrivate( 57 uint plug_number, int fw_chan, int new_speed, 58 bool add_plug, bool remove_plug); 59 bool UpdatePlugRegister( 60 uint plug_number, int fw_chan, int speed, 61 bool add_plug, bool remove_plug, uint retry_cnt = 4); 62 63 void RunController(void); 64 void BroadcastToListeners(const unsigned char *data, uint dataSize); 65 void UpdateDeviceListItem(uint64_t guid, void *item); 66 void PrintNoDataMessage(void); 67 void ProcessStreamingMessage( 68 uint32_t msg, uint32_t param1, uint32_t param2); 69 70 DarwinAVCInfo *GetInfoPtr(void); 71 const DarwinAVCInfo *GetInfoPtr(void) const; 72 73 int GetMaxSpeed(void); 74 bool IsSTBStreaming(uint *fw_channel = NULL); 75 76 vector<AVCInfo> GetSTBListPrivate(void); 77 78 private: 79 uint m_node; 80 DFDPriv *m_priv; 81 }; 82 83 #endif // _DARWIN_FIREWIRE_DEVICE_H_ -
libs/libmythtv/darwinfirewirechannel.cpp
1 /**2 * DarwinFirewireChannel3 * Copyright (c) 2005 by Jim Westfall4 * SA3250HD support Copyright (c) 2005 by Matt Porter5 * Distributed as part of MythTV under GPL v2 and later.6 */7 8 9 #include <iostream>10 #include "mythcontext.h"11 #include "darwinfirewirechannel.h"12 13 #include "selectavcdevice.h"14 15 #undef always_inline16 #include <AVCVideoServices/AVCVideoServices.h>17 18 19 namespace20 {21 bool find_device(AVS::AVCDevice* d)22 {23 return d->isAttached && d->hasMonitorOrTunerSubunit24 // For the time being, the DarwinFireWireRecorder doesn't25 // handle DVB devices, so there's no point in finding one we26 // can tune to, here. That saves us from having to search27 // twice for an eligible device.28 && !d->isDVDevice29 ;30 }31 }32 33 DarwinFirewireChannel::DarwinFirewireChannel(FireWireDBOptions const& firewire_opts,TVRec *parent)34 : FirewireChannelBase(parent)35 , device_controller(0)36 , device(0)37 {38 (void)firewire_opts;39 }40 41 bool DarwinFirewireChannel::OpenFirewire()42 {43 IOReturn err = AVS::CreateAVCDeviceController(&this->device_controller);44 if (err)45 {46 VERBOSE(47 VB_IMPORTANT,48 QString("unable to open device controller: %1").arg(err,0,16));49 return false;50 }51 52 if ((this->device = SelectAVCDevice(device_controller, find_device)))53 {54 VERBOSE(VB_RECORD, QString("DarwinFirewireChannel: opening device") );55 err = this->device->openDevice();56 if (!err)57 return true;58 59 VERBOSE(60 VB_IMPORTANT,61 QString("FireWireChannel: couldn't open tuner device: %1").arg(err,0,16));62 }63 else64 {65 VERBOSE(66 VB_IMPORTANT,67 QString(68 "DarwinFireWireChannel: unable to find an attached"69 " MPEG2 device that supports channel changes"));70 }71 AVS::DestroyAVCDeviceController(this->device_controller);72 return false;73 }74 75 void DarwinFirewireChannel::CloseFirewire()76 {77 this->device->closeDevice();78 AVS::DestroyAVCDeviceController(this->device_controller);79 // Leave the device controller for the destructor80 }81 82 AVS::AVCDevice* DarwinFirewireChannel::GetAVCDevice() const83 {84 return this->device;85 }86 87 bool DarwinFirewireChannel::SetChannelByNumber(int channel)88 {89 // If the tuner is off, try to turn it on.90 UInt8 power_state;91 IOReturn err = this->device->GetPowerState(&power_state);92 if (err == kIOReturnSuccess && power_state == kAVCPowerStateOff)93 {94 this->device->SetPowerState(kAVCPowerStateOn);95 96 // Give it time to power up.97 usleep(2000000); // Sleep for two seconds98 }99 100 AVS::PanelSubunitController panel(this->device);101 err = panel.Tune(channel);102 if (err != kIOReturnSuccess)103 {104 VERBOSE(VB_GENERAL, QString("DarwinFirewireChannel: Tuning failed: %1").arg(err,0,16));105 VERBOSE(VB_GENERAL, QString("Ignoring error per apple example"));106 }107 // Give it time to transition.108 usleep(1000000); // Sleep for one second109 return true;110 } -
libs/libmythtv/firewiresignalmonitor.cpp
1 // -*- Mode: c++ -*- 2 // Copyright (c) 2006, Daniel Thor Kristjansson 3 4 #include <pthread.h> 5 #include <fcntl.h> 6 #include <unistd.h> 7 #include <sys/select.h> 8 9 #include "mythcontext.h" 10 #include "mythdbcon.h" 11 #include "atscstreamdata.h" 12 #include "mpegtables.h" 13 #include "atsctables.h" 14 #include "firewirechannel.h" 15 #include "firewiresignalmonitor.h" 16 17 #define LOC QString("FireSM(%1): ").arg(channel->GetDevice()) 18 #define LOC_WARN QString("FireSM(%1), Warning: ").arg(channel->GetDevice()) 19 #define LOC_ERR QString("FireSM(%1), Error: ").arg(channel->GetDevice()) 20 21 const uint FirewireSignalMonitor::kPowerTimeout = 3000; /* ms */ 22 const uint FirewireSignalMonitor::kBufferTimeout = 5000; /* ms */ 23 24 QMap<void*,uint> FirewireSignalMonitor::pat_keys; 25 QMutex FirewireSignalMonitor::pat_keys_lock; 26 27 /** \fn FirewireSignalMonitor::FirewireSignalMonitor(int,FirewireChannel*,uint,const char*) 28 * \brief Initializes signal lock and signal values. 29 * 30 * Start() must be called to actually begin continuous 31 * signal monitoring. The timeout is set to 3 seconds, 32 * and the signal threshold is initialized to 0%. 33 * 34 * \param db_cardnum Recorder number to monitor, 35 * if this is less than 0, SIGNAL events will not be 36 * sent to the frontend even if SetNotifyFrontend(true) 37 * is called. 38 * \param _channel FirewireChannel for card 39 * \param _flags Flags to start with 40 * \param _name Name for Qt signal debugging 41 */ 42 FirewireSignalMonitor::FirewireSignalMonitor( 43 int db_cardnum, 44 FirewireChannel *_channel, 45 uint _flags, const char *_name) : 46 DTVSignalMonitor(db_cardnum, _channel, _flags, _name), 47 dtvMonitorRunning(false), 48 stb_needs_retune(true), 49 stb_needs_to_wait_for_pat(false), 50 stb_needs_to_wait_for_power(false) 51 { 52 VERBOSE(VB_CHANNEL, LOC + "ctor"); 53 54 signalStrength.SetThreshold(65); 55 56 AddFlags(kDTVSigMon_WaitForSig); 57 58 stb_needs_retune = 59 (FirewireDevice::kAVCPowerOff == _channel->GetPowerState()); 60 } 61 62 /** \fn FirewireSignalMonitor::~FirewireSignalMonitor() 63 * \brief Stops signal monitoring and table monitoring threads. 64 */ 65 FirewireSignalMonitor::~FirewireSignalMonitor() 66 { 67 VERBOSE(VB_CHANNEL, LOC + "dtor"); 68 Stop(); 69 } 70 71 void FirewireSignalMonitor::deleteLater(void) 72 { 73 disconnect(); // disconnect signals we may be sending... 74 Stop(); 75 DTVSignalMonitor::deleteLater(); 76 } 77 78 /** \fn FirewireSignalMonitor::Stop(void) 79 * \brief Stop signal monitoring and table monitoring threads. 80 */ 81 void FirewireSignalMonitor::Stop(void) 82 { 83 VERBOSE(VB_CHANNEL, LOC + "Stop() -- begin"); 84 SignalMonitor::Stop(); 85 if (dtvMonitorRunning) 86 { 87 dtvMonitorRunning = false; 88 pthread_join(table_monitor_thread, NULL); 89 } 90 VERBOSE(VB_CHANNEL, LOC + "Stop() -- end"); 91 } 92 93 void FirewireSignalMonitor::HandlePAT(const ProgramAssociationTable *pat) 94 { 95 AddFlags(kDTVSigMon_PATSeen); 96 97 FirewireChannel *fwchan = dynamic_cast<FirewireChannel*>(channel); 98 bool crc_bogus = !fwchan->GetFirewireDevice()->IsSTBBufferCleared(); 99 if (crc_bogus && stb_needs_to_wait_for_pat && 100 (stb_wait_for_pat_timer.elapsed() < (int)kBufferTimeout)) 101 { 102 VERBOSE(VB_CHANNEL, LOC + "HandlePAT() ignoring PAT"); 103 uint tsid = pat->TransportStreamID(); 104 GetStreamData()->SetVersionPAT(tsid, -1,0); 105 return; 106 } 107 108 if (crc_bogus && stb_needs_to_wait_for_pat) 109 { 110 VERBOSE(VB_IMPORTANT, LOC_WARN + "Wait for valid PAT timed out"); 111 stb_needs_to_wait_for_pat = false; 112 } 113 114 DTVSignalMonitor::HandlePAT(pat); 115 } 116 117 void FirewireSignalMonitor::HandlePMT(uint pnum, const ProgramMapTable *pmt) 118 { 119 VERBOSE(VB_CHANNEL, LOC + "HandlePMT()"); 120 121 AddFlags(kDTVSigMon_PMTSeen); 122 123 if (!HasFlags(kDTVSigMon_PATMatch)) 124 { 125 GetStreamData()->SetVersionPMT(pnum, -1,0); 126 VERBOSE(VB_CHANNEL, LOC + "HandlePMT() ignoring PMT"); 127 return; 128 } 129 130 DTVSignalMonitor::HandlePMT(pnum, pmt); 131 } 132 133 void *FirewireSignalMonitor::TableMonitorThread(void *param) 134 { 135 FirewireSignalMonitor *mon = (FirewireSignalMonitor*) param; 136 mon->RunTableMonitor(); 137 return NULL; 138 } 139 140 void FirewireSignalMonitor::RunTableMonitor(void) 141 { 142 stb_needs_to_wait_for_pat = true; 143 stb_wait_for_pat_timer.start(); 144 dtvMonitorRunning = true; 145 146 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- begin"); 147 148 FirewireChannel *lchan = dynamic_cast<FirewireChannel*>(channel); 149 if (!lchan) 150 { 151 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- err end"); 152 dtvMonitorRunning = false; 153 return; 154 } 155 156 FirewireDevice *dev = lchan->GetFirewireDevice(); 157 158 dev->OpenPort(); 159 dev->AddListener(this); 160 161 while (dtvMonitorRunning && GetStreamData()) 162 usleep(100000); 163 164 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- shutdown "); 165 166 dev->RemoveListener(this); 167 dev->ClosePort(); 168 169 dtvMonitorRunning = false; 170 171 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- end"); 172 } 173 174 void FirewireSignalMonitor::AddData(const unsigned char *data, uint len) 175 { 176 if (!dtvMonitorRunning) 177 return; 178 179 if (GetStreamData()) 180 GetStreamData()->ProcessData((unsigned char *)data, len); 181 } 182 183 /** \fn FirewireSignalMonitor::UpdateValues(void) 184 * \brief Fills in frontend stats and emits status Qt signals. 185 * 186 * This function uses five ioctl's FE_READ_SNR, FE_READ_SIGNAL_STRENGTH 187 * FE_READ_BER, FE_READ_UNCORRECTED_BLOCKS, and FE_READ_STATUS to obtain 188 * statistics from the frontend. 189 * 190 * This is automatically called by MonitorLoop(), after Start() 191 * has been used to start the signal monitoring thread. 192 */ 193 void FirewireSignalMonitor::UpdateValues(void) 194 { 195 if (!running || exit) 196 return; 197 198 if (dtvMonitorRunning) 199 { 200 EmitFirewireSignals(); 201 if (IsAllGood()) 202 emit AllGood(); 203 // TODO dtv signals... 204 205 update_done = true; 206 return; 207 } 208 209 if (stb_needs_to_wait_for_power && 210 (stb_wait_for_power_timer.elapsed() < (int)kPowerTimeout)) 211 { 212 return; 213 } 214 stb_needs_to_wait_for_power = false; 215 216 FirewireChannel *fwchan = dynamic_cast<FirewireChannel*>(channel); 217 218 if (HasFlags(kFWSigMon_WaitForPower) && !HasFlags(kFWSigMon_PowerMatch)) 219 { 220 FirewireDevice::PowerState power = fwchan->GetPowerState(); 221 if (FirewireDevice::kAVCPowerOn == power) 222 { 223 AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch); 224 } 225 else if (FirewireDevice::kAVCPowerOff == power) 226 { 227 AddFlags(kFWSigMon_PowerSeen); 228 fwchan->SetPowerState(true); 229 stb_wait_for_power_timer.start(); 230 stb_needs_to_wait_for_power = true; 231 } 232 } 233 234 bool isLocked = !HasFlags(kFWSigMon_WaitForPower) || 235 HasFlags(kFWSigMon_WaitForPower | kFWSigMon_PowerMatch); 236 237 if (isLocked && stb_needs_retune) 238 { 239 fwchan->Retune(); 240 isLocked = stb_needs_retune = false; 241 } 242 243 // Set SignalMonitorValues from info from card. 244 { 245 QMutexLocker locker(&statusLock); 246 signalStrength.SetValue(isLocked ? 100 : 0); 247 signalLock.SetValue(isLocked ? 1 : 0); 248 } 249 250 EmitFirewireSignals(); 251 if (IsAllGood()) 252 emit AllGood(); 253 254 // Start table monitoring if we are waiting on any table 255 // and we have a lock. 256 if (isLocked && GetStreamData() && 257 HasAnyFlag(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT | 258 kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT | 259 kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT)) 260 { 261 pthread_create(&table_monitor_thread, NULL, 262 TableMonitorThread, this); 263 264 VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 265 "Waiting for table monitor to start"); 266 267 while (!dtvMonitorRunning) 268 usleep(50); 269 270 VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 271 "Table monitor started"); 272 } 273 274 update_done = true; 275 } 276 277 #define EMIT(SIGNAL_FUNC, SIGNAL_VAL) \ 278 do { statusLock.lock(); \ 279 SignalMonitorValue val = SIGNAL_VAL; \ 280 statusLock.unlock(); \ 281 emit SIGNAL_FUNC(val); } while (false) 282 283 /** \fn FirewireSignalMonitor::EmitFirewireSignals(void) 284 * \brief Emits signals for lock, signal strength, etc. 285 */ 286 void FirewireSignalMonitor::EmitFirewireSignals(void) 287 { 288 // Emit signals.. 289 EMIT(StatusSignalLock, signalLock); 290 if (HasFlags(kDTVSigMon_WaitForSig)) 291 EMIT(StatusSignalStrength, signalStrength); 292 } 293 294 #undef EMIT -
libs/libmythtv/darwinavcinfo.h
1 #ifndef _DARWIN_AVC_INFO_H_ 2 #define _DARWIN_AVC_INFO_H_ 3 4 #ifdef USING_OSX_FIREWIRE 5 6 // OS X headers 7 #undef always_inline 8 #include <IOKit/IOKitLib.h> 9 #include <IOKit/firewire/IOFireWireLib.h> 10 #include <IOKit/firewire/IOFireWireLibIsoch.h> 11 #include <IOKit/firewire/IOFireWireFamilyCommon.h> 12 #include <IOKit/avc/IOFireWireAVCLib.h> 13 14 // Qt headers 15 #include <qmap.h> 16 17 // MythTV headers 18 #include "firewiredevice.h" 19 20 class DarwinFirewireDevice; 21 22 class DarwinAVCInfo : public AVCInfo 23 { 24 public: 25 DarwinAVCInfo() : 26 fw_node_ref(NULL), fw_device_ref(NULL), 27 fw_service_ref(NULL), avc_service_ref(NULL), 28 fw_device_notifier_ref(NULL), 29 avc_handle(NULL), fw_handle(NULL) 30 { 31 memset(unit_table, 0xff, sizeof(unit_table)); 32 } 33 34 void Update(uint64_t _guid, DarwinFirewireDevice *dev, 35 IONotificationPortRef notify_port, 36 CFRunLoopRef &thread_cf_ref, io_object_t obj); 37 38 bool Open(CFRunLoopRef &thread_cf_ref); 39 void Close(void); 40 41 bool OpenAVCInterface(CFRunLoopRef &thread_cf_ref); 42 void CloseAVCInterface(void); 43 44 bool OpenDeviceInterface(CFRunLoopRef &thread_cf_ref); 45 void CloseDeviceInterface(void); 46 47 bool SendAVCCommand( 48 const vector<uint8_t> &cmd, 49 vector<uint8_t> &result, 50 int retry_cnt); 51 52 bool IsAVCInterfaceOpen(void) const 53 { return avc_handle; } 54 55 bool IsOpen(void) const 56 { return fw_handle; } 57 58 public: 59 uint8_t unit_table[32]; 60 61 io_service_t fw_node_ref; // parent of fw_device_ref 62 io_service_t fw_device_ref; // parent of fw_service_ref 63 io_service_t fw_service_ref; // parent of avc_service_ref 64 io_service_t avc_service_ref; 65 66 io_object_t fw_device_notifier_ref; 67 68 IOFireWireAVCLibUnitInterface **avc_handle; 69 IOFireWireLibDeviceRef fw_handle; 70 }; 71 typedef QMap<uint64_t,DarwinAVCInfo*> avcinfo_list_t; 72 73 #endif // USING_OSX_FIREWIRE 74 75 #endif // _DARWIN_AVC_INFO_H_ -
libs/libmythtv/mpeg/streamlisteners.h
33 33 class ServiceDescriptionTable; 34 34 class DVBEventInformationTable; 35 35 36 class TSDataListener 37 { 38 public: 39 /// Callback function to add MPEG2 TS data 40 virtual void AddData(const unsigned char *data, uint dataSize) = 0; 41 42 protected: 43 virtual ~TSDataListener() { } 44 }; 45 36 46 class MPEGStreamListener 37 47 { 38 48 protected: -
libs/libmythtv/darwinfirewirechannel.h
1 /**2 * DarwinFirewireChannel3 * Copyright (c) 2005 by Dave Abrahams4 * Distributed as part of MythTV under GPL v2 and later.5 */6 7 8 #ifndef LIBMYTHTV_DARWINFIREWIRECHANNEL_H9 #define LIBMYTHTV_DARWINFIREWIRECHANNEL_H10 11 #include <qstring.h>12 #include "tv_rec.h"13 #include "firewirechannelbase.h"14 15 16 namespace AVS17 {18 class AVCDeviceController;19 class AVCDevice;20 }21 22 class DarwinFirewireChannel : public FirewireChannelBase23 {24 public:25 DarwinFirewireChannel(FireWireDBOptions const&, TVRec *parent);26 27 // Gets28 AVS::AVCDevice* GetAVCDevice() const;29 30 // Sets31 bool SetChannelByNumber(int channel);32 33 private:34 bool OpenFirewire();35 void CloseFirewire();36 37 private:38 AVS::AVCDeviceController* device_controller;39 AVS::AVCDevice* device;40 };41 42 #endif -
libs/libmythtv/signalmonitor.cpp
34 34 # include "iptvchannel.h" 35 35 #endif 36 36 37 #ifdef USING_FIREWIRE 38 # include "firewiresignalmonitor.h" 39 # include "firewirechannel.h" 40 #endif 41 37 42 #undef DBG_SM 38 43 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \ 39 44 "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG); … … 117 122 } 118 123 #endif 119 124 125 #ifdef USING_FIREWIRE 126 if (cardtype.upper() == "FIREWIRE") 127 { 128 FirewireChannel *fc = dynamic_cast<FirewireChannel*>(channel); 129 if (fc) 130 signalMonitor = new FirewireSignalMonitor(db_cardnum, fc); 131 } 132 #endif 133 120 134 if (!signalMonitor) 121 135 { 122 136 VERBOSE(VB_IMPORTANT, -
libs/libmythtv/firewiresignalmonitor.h
1 // -*- Mode: c++ -*- 2 3 #ifndef _FIREWIRESIGNALMONITOR_H_ 4 #define _FIREWIRESIGNALMONITOR_H_ 5 6 #include <qmap.h> 7 #include <qmutex.h> 8 #include <qdatetime.h> 9 10 #include "dtvsignalmonitor.h" 11 #include "firewiredevice.h" 12 #include "util.h" 13 14 class FirewireChannel; 15 16 class FirewireSignalMonitor : public DTVSignalMonitor, public TSDataListener 17 { 18 Q_OBJECT 19 20 public: 21 FirewireSignalMonitor(int db_cardnum, FirewireChannel *_channel, 22 uint _flags = kFWSigMon_WaitForPower, 23 const char *_name = "FirewireSignalMonitor"); 24 25 virtual void HandlePAT(const ProgramAssociationTable*); 26 virtual void HandlePMT(uint, const ProgramMapTable*); 27 28 void Stop(void); 29 30 public slots: 31 void deleteLater(void); 32 33 protected: 34 FirewireSignalMonitor(void); 35 FirewireSignalMonitor(const FirewireSignalMonitor&); 36 virtual ~FirewireSignalMonitor(); 37 38 virtual void UpdateValues(void); 39 void EmitFirewireSignals(void); 40 41 static void *TableMonitorThread(void *param); 42 void RunTableMonitor(void); 43 44 bool SupportsTSMonitoring(void); 45 46 void AddData(const unsigned char *data, uint dataSize); 47 48 public: 49 static const uint kPowerTimeout; 50 static const uint kBufferTimeout; 51 52 protected: 53 bool dtvMonitorRunning; 54 pthread_t table_monitor_thread; 55 bool stb_needs_retune; 56 bool stb_needs_to_wait_for_pat; 57 bool stb_needs_to_wait_for_power; 58 MythTimer stb_wait_for_pat_timer; 59 MythTimer stb_wait_for_power_timer; 60 61 vector<unsigned char> buffer; 62 63 static QMap<void*,uint> pat_keys; 64 static QMutex pat_keys_lock; 65 }; 66 67 #endif // _FIREWIRESIGNALMONITOR_H_ -
libs/libmythtv/darwinfirewirerecorder.h
1 /**2 * FirewireRecorder3 * Copyright (c) 2005 by Jim Westfall and Dave Abrahams4 * Distributed as part of MythTV under GPL v2 and later.5 */6 7 #ifndef LIBMYTHTV_DARWINFIREWIRERECORDER_H_8 #define LIBMYTHTV_DARWINFIREWIRERECORDER_H_9 10 #include "firewirerecorderbase.h"11 #include "darwinfirewirechannel.h"12 13 //#include <IOKit/IOReturn.h>14 //#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>15 16 typedef unsigned long UInt32;17 typedef int IOReturn;18 19 namespace AVS20 {21 class AVCDeviceController;22 class AVCDevice;23 class StringLogger;24 class AVCDeviceStream;25 }26 27 /** \class DarwinFirewireRecorder28 * \brief This is a specialization of DTVRecorder used to29 * handle DVB and ATSC streams from a firewire input.30 *31 * \sa DTVRecorder32 */33 class DarwinFirewireRecorder : public FirewireRecorderBase34 {35 public:36 DarwinFirewireRecorder(TVRec *rec, ChannelBase* tuner);37 ~DarwinFirewireRecorder();38 39 bool Open(void);40 41 void SetOption(const QString &name, const QString &value);42 void SetOption(const QString &name, int value);43 44 private:45 void Close();46 47 void start();48 void stop();49 void no_data();50 bool grab_frames();51 52 static IOReturn MPEGNoData(void* pRefCon);53 static IOReturn tspacket_callback(UInt32 tsPacketCount, UInt32 **ppBuf, void *pRefCon);54 55 AVS::AVCDevice* capture_device;56 AVS::StringLogger* message_log;57 AVS::AVCDeviceStream* video_stream;58 59 bool isopen;60 };61 62 #endif -
libs/libmythtv/cardutil.cpp
680 680 { 681 681 QString label = QString::null; 682 682 683 if (cardtype == " FIREWIRE")683 if (cardtype == "DBOX2") 684 684 { 685 685 MSqlQuery query(MSqlQuery::InitCon()); 686 686 query.prepare( 687 "SELECT firewire_port, firewire_node "688 "FROM capturecard "689 "WHERE cardid = :CARDID");690 query.bindValue(":CARDID", cardid);691 692 if (!query.exec() || !query.isActive() || !query.next())693 label = "[ DB ERROR ]";694 else695 label = QString("[ FIREWIRE : Port %2 Node %3 ]")696 .arg(query.value(0).toString())697 .arg(query.value(1).toString());698 699 }700 else if (cardtype == "DBOX2")701 {702 MSqlQuery query(MSqlQuery::InitCon());703 query.prepare(704 687 "SELECT dbox2_host, dbox2_port, dbox2_httpport " 705 688 "FROM capturecard " 706 689 "WHERE cardid = :CARDID"); -
libs/libmythtv/firewirechannel.h
1 1 /** 2 2 * FirewireChannel 3 * Copyright (c) 2005 by Jim Westfall 4 * SA3250HD support Copyright (c) 2005 by Matt Porter 3 * Copyright (c) 2005 by Jim Westfall and Dave Abrahams 5 4 * Distributed as part of MythTV under GPL v2 and later. 6 5 */ 7 6 7 #ifndef _FIREWIRECHANNEL_H_ 8 #define _FIREWIRECHANNEL_H_ 8 9 9 #ifndef FIREWIRECHANNEL_H10 #define FIREWIRECHANNEL_H11 12 #include <qstring.h>13 10 #include "tv_rec.h" 14 #include " firewirechannelbase.h"15 #include <libavc1394/avc1394.h>11 #include "dtvchannel.h" 12 #include "firewiredevice.h" 16 13 17 using namespace std; 18 19 class FirewireChannel : public FirewireChannelBase 14 class FirewireChannel : public DTVChannel 20 15 { 21 16 public: 22 enum PowerState { 23 On, 24 Off, 25 Failed 26 }; 17 FirewireChannel(TVRec *parent, const QString &videodevice, 18 const FireWireDBOptions &firewire_opts); 19 ~FirewireChannel() { Close(); } 27 20 28 FirewireChannel(FireWireDBOptions firewire_opts, TVRec *parent); 29 ~FirewireChannel(void); 21 // Commands 22 virtual bool Open(void); 23 virtual void Close(void); 24 virtual bool SwitchToInput(const QString &inputname, const QString &chan); 25 virtual bool SwitchToInput(int newcapchannel, bool setstarting); 30 26 31 bool OpenFirewire(void); 32 void CloseFirewire(void); 27 virtual bool TuneMultiplex(uint /*mplexid*/, QString /*inputname*/) 28 { return false; } 29 virtual bool Tune(const DTVMultiplex &/*tuning*/, QString /*inputname*/) 30 { return false; } 31 virtual bool Retune(void); 33 32 34 33 // Sets 35 void SetExternalChanger(void); 36 bool SetChannelByNumber(int channel); 34 virtual bool SetChannelByString(const QString &chan); 35 virtual bool SetChannelByNumber(int channel); 36 virtual bool SetPowerState(bool on); 37 37 38 38 // Gets 39 bool IsOpen(void) const { return isopen; }40 QString GetDevice(void) const41 { return QString("%1:%2").arg(fw_opts.port).arg(fw_opts.node); }42 PowerState GetPowerState(void);39 virtual bool IsOpen(void) const { return isopen; } 40 virtual FirewireDevice::PowerState GetPowerState(void) const; 41 virtual QString GetDevice(void) const; 42 virtual FirewireDevice *GetFirewireDevice(void) { return device; } 43 43 44 private: 44 protected: 45 QString videodevice; 45 46 FireWireDBOptions fw_opts; 46 nodeid_t fwnode; 47 raw1394handle_t fwhandle; 47 FirewireDevice *device; 48 uint current_channel; 49 bool isopen; 48 50 }; 49 51 50 #endif 52 #endif // _FIREWIRECHANNEL_H_ -
libs/libmythtv/videosource.cpp
8 8 #include <sys/stat.h> 9 9 10 10 // C++ headers 11 #include <iostream> 11 #include <algorithm> 12 using namespace std; 12 13 13 14 // Qt headers 14 15 #include <qapplication.h> … … 33 34 #include "channelutil.h" 34 35 #include "frequencies.h" 35 36 #include "diseqcsettings.h" 37 #include "firewiredevice.h" 36 38 37 39 #ifdef USING_DVB 38 40 #include "dvbtypes.h" … … 929 931 }; 930 932 }; 931 933 932 class Firewire Model: public ComboBoxSetting, public CaptureCardDBStorage934 class FirewireGUID : public ComboBoxSetting, public CaptureCardDBStorage 933 935 { 934 936 public: 935 Firewire Model(const CaptureCard &parent) :937 FirewireGUID(const CaptureCard &parent) : 936 938 ComboBoxSetting(this), 937 CaptureCardDBStorage(this, parent, " firewire_model")939 CaptureCardDBStorage(this, parent, "videodevice") 938 940 { 939 setLabel(QObject::tr(" Cable box model"));940 addSelection(QObject::tr("Other")); 941 addSelection("DCT-6200");942 addSelection("SA3250HD");943 addSelection("SA4200HD"); 944 QString help = QObject::tr(945 "Choose the model that most closely resembles your set top box. "946 "Depending on firmware revision SA4200HD may work better for a "947 "SA3250HD box.");948 setHelpText(help); 941 setLabel(QObject::tr("GUID")); 942 #ifdef USING_FIREWIRE 943 vector<AVCInfo> list = FirewireDevice::GetSTBList(); 944 for (uint i = 0; i < list.size(); i++) 945 { 946 QString guid = list[i].GetGUIDString(); 947 guid_to_avcinfo[guid] = list[i]; 948 addSelection(guid); 949 } 950 #endif // USING_FIREWIRE 949 951 } 952 953 AVCInfo GetAVCInfo(const QString &guid) const 954 { return guid_to_avcinfo[guid]; } 955 956 private: 957 QMap<QString,AVCInfo> guid_to_avcinfo; 950 958 }; 951 959 960 FirewireModel::FirewireModel(const CaptureCard &parent, 961 const FirewireGUID *_guid) : 962 ComboBoxSetting(this), 963 CaptureCardDBStorage(this, parent, "firewire_model"), 964 guid(_guid) 965 { 966 setLabel(QObject::tr("Cable box model")); 967 addSelection(QObject::tr("Generic"), "GENERIC"); 968 addSelection("DCT-6200"); 969 addSelection("DCT-6212"); 970 addSelection("DCT-6216"); 971 addSelection("SA3250HD"); 972 addSelection("SA4200HD"); 973 QString help = QObject::tr( 974 "Choose the model that most closely resembles your set top box. " 975 "Depending on firmware revision SA4200HD may work better for a " 976 "SA3250HD box."); 977 setHelpText(help); 978 } 979 980 void FirewireModel::SetGUID(const QString &_guid) 981 { 982 #ifdef USING_FIREWIRE 983 AVCInfo info = guid->GetAVCInfo(_guid); 984 QString model = FirewireDevice::GetModelName(info.vendorid, info.modelid); 985 setValue(max(getValueIndex(model), 0)); 986 #endif // USING_FIREWIRE 987 } 988 989 void FirewireDesc::SetGUID(const QString &_guid) 990 { 991 setLabel(tr("Description")); 992 993 #ifdef USING_FIREWIRE 994 QString name = guid->GetAVCInfo(_guid).product_name; 995 name.replace("Scientific-Atlanta", "SA"); 996 name.replace(", Inc.", ""); 997 name.replace("Explorer(R)", ""); 998 name = name.simplifyWhiteSpace(); 999 setValue((name.isEmpty()) ? "" : name); 1000 #endif // USING_FIREWIRE 1001 } 1002 952 1003 class FirewireConnection : public ComboBoxSetting, public CaptureCardDBStorage 953 1004 { 954 1005 public: … … 962 1013 } 963 1014 }; 964 1015 965 class FirewirePort : public SpinBoxSetting, public CaptureCardDBStorage966 {967 public:968 FirewirePort(const CaptureCard &parent) :969 SpinBoxSetting(this, 0, 63, 1),970 CaptureCardDBStorage(this, parent, "firewire_port")971 {972 setValue(0);973 setLabel(QObject::tr("IEEE-1394 Port"));974 setHelpText(QObject::tr("Firewire port on your firewire card."));975 }976 };977 978 class FirewireNode : public SpinBoxSetting, public CaptureCardDBStorage979 {980 public:981 FirewireNode(const CaptureCard &parent) :982 SpinBoxSetting(this, 0, 63, 1),983 CaptureCardDBStorage(this, parent, "firewire_node")984 {985 setValue(2);986 setLabel(QObject::tr("Node"));987 setHelpText(QObject::tr("Firewire node is the remote device."));988 }989 };990 991 1016 class FirewireSpeed : public ComboBoxSetting, public CaptureCardDBStorage 992 1017 { 993 1018 public: … … 999 1024 addSelection(QObject::tr("100Mbps"),"0"); 1000 1025 addSelection(QObject::tr("200Mbps"),"1"); 1001 1026 addSelection(QObject::tr("400Mbps"),"2"); 1027 addSelection(QObject::tr("800Mbps"),"3"); 1002 1028 } 1003 1029 }; 1004 1030 … … 1007 1033 public: 1008 1034 FirewireConfigurationGroup(CaptureCard& a_parent) : 1009 1035 VerticalConfigurationGroup(false, true, false, false), 1010 parent(a_parent) 1036 parent(a_parent), 1037 dev(new FirewireGUID(parent)), 1038 desc(new FirewireDesc(dev)), 1039 model(new FirewireModel(parent, dev)) 1011 1040 { 1012 HorizontalConfigurationGroup *hg0 =1013 new HorizontalConfigurationGroup(false, false, true, true);1014 hg0->addChild(new FirewireModel(parent));1015 hg0->addChild(new FirewireConnection(parent)); 1016 addChild(hg0); 1017 HorizontalConfigurationGroup *hg1 =1018 new HorizontalConfigurationGroup(false, false, true, true);1019 hg1->addChild(new FirewirePort(parent)); 1020 hg1->addChild(new FirewireNode(parent)); 1021 hg1->addChild(new FirewireSpeed(parent));1022 addChild( hg1);1041 addChild(dev); 1042 addChild(desc); 1043 addChild(model); 1044 1045 #ifdef USING_LINUX_FIREWIRE 1046 addChild(new FirewireConnection(parent)); 1047 addChild(new FirewireSpeed(parent)); 1048 #endif // USING_LINUX_FIREWIRE 1049 1050 addChild(new SignalTimeout(parent, 2000, 1000)); 1051 addChild(new ChannelTimeout(parent, 9000, 1750)); 1023 1052 addChild(new SingleCardInput(parent)); 1053 1054 connect(dev, SIGNAL(valueChanged(const QString&)), 1055 model, SLOT( SetGUID( const QString&))); 1056 connect(dev, SIGNAL(valueChanged(const QString&)), 1057 desc, SLOT( SetGUID( const QString&))); 1024 1058 }; 1059 1025 1060 private: 1026 CaptureCard &parent; 1061 CaptureCard &parent; 1062 FirewireGUID *dev; 1063 FirewireDesc *desc; 1064 FirewireModel *model; 1027 1065 }; 1028 1066 1029 1067 class DBOX2Port : public LineEditSetting, public CaptureCardDBStorage -
libs/libmythtv/selectavcdevice.cpp
1 /**2 * SelectAVCDevice3 * Copyright (c) 2006 by Dave Abrahams4 * Distributed as part of MythTV under GPL v2 and later.5 */6 7 #include "mythconfig.h"8 9 #ifdef CONFIG_DARWIN10 # include "mythcontext.h"11 # include "selectavcdevice.h"12 # undef always_inline13 # include <AVCVideoServices/AVCVideoServices.h>14 15 AVS::AVCDevice* SelectAVCDevice(16 AVS::AVCDeviceController* controller,17 bool (*filter)(AVS::AVCDevice*)18 )19 {20 VERBOSE(VB_GENERAL, QString("SelectAVCDevice:"));21 22 for (unsigned n = CFArrayGetCount(controller->avcDeviceArray),23 i = 0; i < n; ++i)24 {25 AVS::AVCDevice& d = *(AVS::AVCDevice*)CFArrayGetValueAtIndex(controller->avcDeviceArray, i);26 27 VERBOSE(28 VB_GENERAL,29 QString("SelectAVCDevice: %1, format: %2, attached: %3, type: %4")30 .arg(d.deviceName)31 .arg(d.isDVDevice ? "DV" : d.isMPEGDevice ? "MPEG2-TS" : "unknown")32 .arg(d.isAttached ? "yes" : "no")33 .arg(d.hasTapeSubunit ? "tape" : d.hasMonitorOrTunerSubunit ? "tuner" : "unknown")34 );35 36 if (filter(&d))37 {38 VERBOSE(VB_GENERAL, QString("SelectAVCDevice: FOUND"));39 return &d;40 }41 }42 VERBOSE(VB_GENERAL, QString("SelectAVCDevice: NOT FOUND"));43 return 0;44 }45 46 #endif // CONFIG_DARWIN47 -
libs/libmythtv/firewirechannelbase.cpp
1 /**2 * FirewireChannelBase3 * Copyright (c) 2005 by Jim Westfall Dave Abrahams4 * Distributed as part of MythTV under GPL v2 and later.5 */6 7 8 #include <iostream>9 #include "mythcontext.h"10 #include "firewirechannelbase.h"11 12 bool FirewireChannelBase::SetChannelByString(const QString &chan)13 {14 inputs[currentInputID]->startChanNum = chan;15 curchannelname = chan;16 17 InputMap::const_iterator it = inputs.find(currentInputID);18 19 if (!(*it)->externalChanger.isEmpty())20 return ChangeExternalChannel(chan);21 22 return isopen && SetChannelByNumber(chan.toInt());23 }24 25 bool FirewireChannelBase::Open()26 {27 if (!InitializeInputs())28 return false;29 30 InputMap::const_iterator it = inputs.find(currentInputID);31 if (!(*it)->externalChanger.isEmpty())32 return true;33 34 if (!isopen)35 {36 isopen = OpenFirewire();37 return isopen;38 }39 return true;40 }41 42 void FirewireChannelBase::Close()43 {44 if (isopen)45 CloseFirewire();46 isopen = false;47 }48 49 bool FirewireChannelBase::SwitchToInput(const QString &input,50 const QString &chan)51 {52 int inputNum = GetInputByName(input);53 if (inputNum < 0)54 return false;55 56 return SetChannelByString(chan);57 } -
libs/libmythtv/linuxfirewiredevice.h
1 /** 2 * LinuxFirewireDevice 3 * Copyright (c) 2005 by Jim Westfall 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #ifndef _LINUX_FIREWIRE_DEVICE_H_ 8 #define _LINUX_FIREWIRE_DEVICE_H_ 9 10 #include "firewiredevice.h" 11 12 class LFDPriv; 13 14 class LinuxFirewireDevice : public FirewireDevice 15 { 16 friend void *linux_firewire_device_streaming_thunk(void *param); 17 friend int linux_firewire_device_tspacket_handler( 18 unsigned char *tspacket, int len, uint dropped, void *callback_data); 19 20 public: 21 LinuxFirewireDevice(uint64_t guid, uint subunitid, 22 uint speed, bool use_p2p, 23 uint av_buffer_size_in_bytes = 0); 24 ~LinuxFirewireDevice(); 25 26 // Commands 27 virtual bool OpenPort(void); 28 virtual bool ClosePort(void); 29 void HandleBusReset(uint); 30 31 virtual void AddListener(TSDataListener*); 32 virtual void RemoveListener(TSDataListener*); 33 34 // Gets 35 virtual bool IsPortOpen(void) const; 36 37 // Statics 38 static vector<AVCInfo> GetSTBList(void); 39 40 // Constants 41 static const uint kBroadcastChannel; 42 static const uint kConnectionP2P; 43 static const uint kConnectionBroadcast; 44 static const uint kMaxBufferedPackets; 45 46 private: 47 bool GetPortAndNode(void); 48 49 bool OpenNode(void); 50 bool CloseNode(void); 51 52 bool OpenAVStream(void); 53 bool CloseAVStream(void); 54 55 bool OpenP2PNode(void); 56 bool CloseP2PNode(void); 57 58 bool OpenBroadcastNode(void); 59 bool CloseBroadcastNode(void); 60 61 bool StartStreaming(void); 62 bool StopStreaming(void); 63 bool StopStreamingLater(void); 64 65 bool ResetBus(void); 66 67 void RunStreaming(void); 68 bool LoopIteration(uint timeout_in_msec); 69 void PrintDropped(uint dropped_packets); 70 71 bool SetAVStreamBufferSize(uint size_in_bytes); 72 bool SetAVStreamSpeed(uint speed); 73 74 bool IsNodeOpen(void) const; 75 bool IsAVStreamOpen(void) const; 76 77 virtual bool SendAVCCommand(const vector<uint8_t> &cmd, 78 vector<uint8_t> &result, 79 int retry_cnt); 80 81 private: 82 int m_port; 83 int m_node; 84 uint m_bufsz; 85 bool m_use_p2p; 86 bool m_resetting; 87 LFDPriv *m_priv; 88 }; 89 90 #endif // _LINUX_FIREWIRE_DEVICE_H_ -
libs/libmythtv/tv_rec.cpp
48 48 #include "dbox2channel.h" 49 49 #include "hdhrchannel.h" 50 50 #include "iptvchannel.h" 51 #include "firewirechannel.h" 51 52 52 53 #include "recorderbase.h" 53 54 #include "NuppelVideoRecorder.h" … … 57 58 #include "dbox2recorder.h" 58 59 #include "hdhrrecorder.h" 59 60 #include "iptvrecorder.h" 61 #include "firewirerecorder.h" 60 62 61 63 #ifdef USING_V4L 62 64 #include "channel.h" 63 65 #endif 64 66 65 #ifdef USING_FIREWIRE66 #ifdef CONFIG_DARWIN67 #include "darwinfirewirerecorder.h"68 #include "darwinfirewirechannel.h"69 #else70 #include "firewirerecorder.h"71 #include "firewirechannel.h"72 #endif73 #endif74 75 67 #define DEBUG_CHANNEL_PREFIX 0 /**< set to 1 to channel prefixing */ 76 68 77 69 #define LOC QString("TVRec(%1): ").arg(cardid) … … 158 150 else if (genOpt.cardtype == "FIREWIRE") 159 151 { 160 152 #ifdef USING_FIREWIRE 161 # ifdef CONFIG_DARWIN 162 channel = new DarwinFirewireChannel(fwOpt, this); 163 # else 164 channel = new FirewireChannel(fwOpt, this); 165 # endif 153 channel = new FirewireChannel(this, genOpt.videodev, fwOpt); 166 154 if (!channel->Open()) 167 155 return false; 168 156 InitChannel(genOpt.defaultinput, startchannel); … … 831 819 else if (genOpt.cardtype == "FIREWIRE") 832 820 { 833 821 #ifdef USING_FIREWIRE 834 # ifdef CONFIG_DARWIN 835 recorder = new DarwinFirewireRecorder(this, this->channel); 836 # else 837 recorder = new FirewireRecorder(this); 838 recorder->SetOption("port", fwOpt.port); 839 recorder->SetOption("node", fwOpt.node); 840 recorder->SetOption("speed", fwOpt.speed); 841 recorder->SetOption("model", fwOpt.model); 842 recorder->SetOption("connection", fwOpt.connection); 843 # endif // !CONFIG_DARWIN 822 recorder = new FirewireRecorder(this, GetFirewireChannel()); 844 823 #endif // USING_FIREWIRE 845 824 } 846 825 else if (genOpt.cardtype == "DBOX2") … … 1114 1093 #endif // USING_DVB 1115 1094 } 1116 1095 1096 FirewireChannel *TVRec::GetFirewireChannel(void) 1097 { 1098 #ifdef USING_FIREWIRE 1099 return dynamic_cast<FirewireChannel*>(channel); 1100 #else 1101 return NULL; 1102 #endif // USING_FIREWIRE 1103 } 1104 1117 1105 Channel *TVRec::GetV4LChannel(void) 1118 1106 { 1119 1107 #ifdef USING_V4L … … 1418 1406 "" 1419 1407 " dvb_on_demand, dvb_tuning_delay, " 1420 1408 "" 1421 " firewire_port, firewire_node, firewire_speed, " 1422 " firewire_model, firewire_connection, " 1409 " firewire_speed, firewire_model, firewire_connection, " 1423 1410 "" 1424 1411 " dbox2_port, dbox2_host, dbox2_httpport " 1425 1412 "" … … 1479 1466 1480 1467 // Firewire options 1481 1468 uint fireoff = dvboff + 2; 1482 firewire_opts.port = query.value(fireoff + 0).toUInt(); 1483 firewire_opts.node = query.value(fireoff + 1).toUInt(); 1484 firewire_opts.speed = query.value(fireoff + 2).toUInt(); 1469 firewire_opts.speed = query.value(fireoff + 0).toUInt(); 1485 1470 1486 test = query.value(fireoff + 3).toString();1471 test = query.value(fireoff + 1).toString(); 1487 1472 if (test != QString::null) 1488 1473 firewire_opts.model = QString::fromUtf8(test); 1489 1474 1490 firewire_opts.connection = query.value(fireoff + 4).toUInt();1475 firewire_opts.connection = query.value(fireoff + 2).toUInt(); 1491 1476 1492 1477 // DBOX2/HDHomeRun options 1493 uint dbox2off = fireoff + 5;1478 uint dbox2off = fireoff + 3; 1494 1479 dbox2_opts.port = query.value(dbox2off + 0).toUInt(); 1495 1480 1496 1481 test = query.value(dbox2off + 1).toString(); -
libs/libmythtv/tv_rec.h
35 35 class DBox2Channel; 36 36 class DTVChannel; 37 37 class DVBChannel; 38 class FirewireChannel; 38 39 class Channel; 39 40 class HDHRChannel; 40 41 … … 85 86 class FireWireDBOptions 86 87 { 87 88 public: 88 FireWireDBOptions() : 89 port(-1), node(-1), speed(-1), connection(-1), model("") {;} 90 91 int port; 92 int node; 89 FireWireDBOptions() : speed(-1), connection(-1), model("") {;} 90 93 91 int speed; 94 92 int connection; 95 93 QString model; … … 261 259 DTVChannel *GetDTVChannel(void); 262 260 HDHRChannel *GetHDHRChannel(void); 263 261 DVBChannel *GetDVBChannel(void); 262 FirewireChannel *GetFirewireChannel(void); 264 263 Channel *GetV4LChannel(void); 265 264 266 265 bool SetupSignalMonitor(bool enable_table_monitoring, bool notify); -
libs/libmythtv/selectavcdevice.h
1 /**2 * SelectAVCDevice3 * Copyright (c) 2006 by Dave Abrahams4 * Distributed as part of MythTV under GPL v2 and later.5 */6 7 #ifndef LIBMYTHTV_SELECTAVCDEVICE_H_8 # define LIBMYTHTV_SELECTAVCDEVICE_H_9 10 # include "mythconfig.h"11 12 # ifdef CONFIG_DARWIN13 # undef always_inline14 # include <AVCVideoServices/AVCVideoServices.h>15 16 AVS::AVCDevice* SelectAVCDevice(17 AVS::AVCDeviceController*,18 bool (*)(AVS::AVCDevice*)19 );20 21 # endif // CONFIG_DARWIN22 23 #endif LIBMYTHTV_SELECTAVCDEVICE_H_24 -
libs/libmythtv/firewiredevice.h
1 /** 2 * FirewireDevice 3 * Copyright (c) 2005 by Jim Westfall 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #ifndef _FIREWIRE_DEVICE_H_ 8 #define _FIREWIRE_DEVICE_H_ 9 10 // C++ headers 11 #include <vector> 12 using namespace std; 13 14 // Qt headers 15 #include <qstring.h> 16 #include <qmutex.h> 17 18 // MythTV headers 19 #include "streamlisteners.h" 20 21 class TSPacket; 22 23 class AVCInfo 24 { 25 public: 26 int port; 27 int node; 28 uint64_t guid; 29 uint specid; 30 uint vendorid; 31 uint modelid; 32 uint firmware_revision; 33 QString product_name; 34 35 AVCInfo(); 36 AVCInfo(const AVCInfo &o); 37 AVCInfo &operator=(const AVCInfo &o); 38 39 QString GetGUIDString(void) const; 40 }; 41 42 class FirewireDevice 43 { 44 public: 45 46 // Public enums 47 typedef enum 48 { 49 kAVCPowerOn, 50 kAVCPowerOff, 51 kAVCPowerUnknown, 52 kAVCPowerQueryFailed, 53 } PowerState; 54 55 // AVC commands 56 typedef enum 57 { 58 kAVCControlCommand = 0x00, 59 kAVCStatusInquiryCommand = 0x01, 60 kAVCSpecificInquiryCommand = 0x02, 61 kAVCNotifyCommand = 0x03, 62 kAVCGeneralInquiryCommand = 0x04, 63 64 kAVCNotImplementedStatus = 0x08, 65 kAVCAcceptedStatus = 0x09, 66 kAVCRejectedStatus = 0x0a, 67 kAVCInTransitionStatus = 0x0b, 68 kAVCImplementedStatus = 0x0c, 69 kAVCChangedStatus = 0x0d, 70 71 kAVCInterimStatus = 0x0f, 72 kAVCResponseImplemented = 0x0c, 73 } IEEE1394Command; 74 75 // AVC unit addresses 76 typedef enum 77 { 78 kAVCSubunitId0 = 0x00, 79 kAVCSubunitId1 = 0x01, 80 kAVCSubunitId2 = 0x02, 81 kAVCSubunitId3 = 0x03, 82 kAVCSubunitId4 = 0x04, 83 kAVCSubunitIdExtended = 0x05, 84 kAVCSubunitIdIgnore = 0x07, 85 86 kAVCSubunitTypeVideoMonitor = (0x00 << 3), 87 kAVCSubunitTypeAudio = (0x01 << 3), 88 kAVCSubunitTypePrinter = (0x02 << 3), 89 kAVCSubunitTypeDiscRecorder = (0x03 << 3), 90 kAVCSubunitTypeTapeRecorder = (0x04 << 3), 91 kAVCSubunitTypeTuner = (0x05 << 3), 92 kAVCSubunitTypeCA = (0x06 << 3), 93 kAVCSubunitTypeVideoCamera = (0x07 << 3), 94 kAVCSubunitTypePanel = (0x09 << 3), 95 kAVCSubunitTypeBulletinBoard = (0x0a << 3), 96 kAVCSubunitTypeCameraStorage = (0x0b << 3), 97 kAVCSubunitTypeMusic = (0x0c << 3), 98 kAVCSubunitTypeVendorUnique = (0x1c << 3), 99 kAVCSubunitTypeExtended = (0x1e << 3), 100 kAVCSubunitTypeUnit = (0x1f << 3), 101 } IEEE1394UnitAddress; 102 103 // AVC opcode 104 typedef enum 105 { 106 // Unit 107 kAVCUnitPlugInfoOpcode = 0x02, 108 kAVCUnitDigitalOutputOpcode = 0x10, 109 kAVCUnitDigitalInputOpcode = 0x11, 110 kAVCUnitChannelUsageOpcode = 0x12, 111 kAVCUnitOutputPlugSignalFormatOpcode = 0x18, 112 kAVCUnitInputPlugSignalFormatOpcode = 0x19, 113 kAVCUnitConnectAVOpcode = 0x20, 114 kAVCUnitDisconnectAVOpcode = 0x21, 115 kAVCUnitConnectionsOpcode = 0x22, 116 kAVCUnitConnectOpcode = 0x24, 117 kAVCUnitDisconnectOpcode = 0x25, 118 kAVCUnitUnitInfoOpcode = 0x30, 119 kAVCUnitSubunitInfoOpcode = 0x31, 120 kAVCUnitSignalSourceOpcode = 0x1a, 121 kAVCUnitPowerOpcode = 0xb2, 122 123 // Common Unit + Subunit 124 kAVCCommonOpenDescriptorOpcode = 0x08, 125 kAVCCommonReadDescriptorOpcode = 0x09, 126 kAVCCommonWriteDescriptorOpcode = 0x0A, 127 kAVCCommonSearchDescriptorOpcode = 0x0B, 128 kAVCCommonObjectNumberSelectOpcode = 0x0D, 129 kAVCCommonPowerOpcode = 0xB2, 130 kAVCCommonReserveOpcode = 0x01, 131 kAVCCommonPlugInfoOpcode = 0x02, 132 kAVCCommonVendorDependentOpcode = 0x00, 133 134 // Panel 135 kAVCPanelPassThrough = 0x7c, 136 } IEEE1394Opcode; 137 138 // AVC param 0 139 typedef enum 140 { 141 kAVCPowerStateOn = 0x70, 142 kAVCPowerStateOff = 0x60, 143 kAVCPowerStateQuery = 0x7f, 144 } IEEE1394UnitPowerParam0; 145 146 typedef enum 147 { 148 kAVCPanelKeySelect = 0x00, 149 kAVCPanelKeyUp = 0x01, 150 kAVCPanelKeyDown = 0x02, 151 kAVCPanelKeyLeft = 0x03, 152 kAVCPanelKeyRight = 0x04, 153 kAVCPanelKeyRightUp = 0x05, 154 kAVCPanelKeyRightDown = 0x06, 155 kAVCPanelKeyLeftUp = 0x07, 156 kAVCPanelKeyLeftDown = 0x08, 157 kAVCPanelKeyRootMenu = 0x09, 158 kAVCPanelKeySetupMenu = 0x0A, 159 kAVCPanelKeyContentsMenu = 0x0B, 160 kAVCPanelKeyFavoriteMenu = 0x0C, 161 kAVCPanelKeyExit = 0x0D, 162 163 kAVCPanelKey0 = 0x20, 164 kAVCPanelKey1 = 0x21, 165 kAVCPanelKey2 = 0x22, 166 kAVCPanelKey3 = 0x23, 167 kAVCPanelKey4 = 0x24, 168 kAVCPanelKey5 = 0x25, 169 kAVCPanelKey6 = 0x26, 170 kAVCPanelKey7 = 0x27, 171 kAVCPanelKey8 = 0x28, 172 kAVCPanelKey9 = 0x29, 173 kAVCPanelKeyDot = 0x2A, 174 kAVCPanelKeyEnter = 0x2B, 175 kAVCPanelKeyClear = 0x2C, 176 177 kAVCPanelKeyChannelUp = 0x30, 178 kAVCPanelKeyChannelDown = 0x31, 179 kAVCPanelKeyPreviousChannel = 0x32, 180 kAVCPanelKeySoundSelect = 0x33, 181 kAVCPanelKeyInputSelect = 0x34, 182 kAVCPanelKeyDisplayInfo = 0x35, 183 kAVCPanelKeyHelp = 0x36, 184 kAVCPanelKeyPageUp = 0x37, 185 kAVCPanelKeyPageDown = 0x38, 186 187 kAVCPanelKeyPower = 0x40, 188 kAVCPanelKeyVolumeUp = 0x41, 189 kAVCPanelKeyVolumeDown = 0x42, 190 kAVCPanelKeyMute = 0x43, 191 kAVCPanelKeyPlay = 0x44, 192 kAVCPanelKeyStop = 0x45, 193 kAVCPanelKeyPause = 0x46, 194 kAVCPanelKeyRecord = 0x47, 195 kAVCPanelKeyRewind = 0x48, 196 kAVCPanelKeyFastForward = 0x49, 197 kAVCPanelKeyEject = 0x4a, 198 kAVCPanelKeyForward = 0x4b, 199 kAVCPanelKeyBackward = 0x4c, 200 201 kAVCPanelKeyAngle = 0x50, 202 kAVCPanelKeySubPicture = 0x51, 203 204 kAVCPanelKeyTuneFunction = 0x67, 205 206 kAVCPanelKeyPress = 0x00, 207 kAVCPanelKeyRelease = 0x80, 208 209 } IEEE1394PanelPassThroughParam0; 210 211 virtual ~FirewireDevice() { } 212 213 // Commands 214 virtual bool OpenPort(void) = 0; 215 virtual bool ClosePort(void) = 0; 216 217 virtual void AddListener(TSDataListener*); 218 virtual void RemoveListener(TSDataListener*); 219 220 // Sets 221 virtual bool SetPowerState(bool on); 222 virtual bool SetChannel(const QString &panel_model, 223 uint alt_method, uint channel); 224 225 // Gets 226 virtual bool IsPortOpen(void) const = 0; 227 bool IsSTBBufferCleared(void) const { return m_buffer_cleared; } 228 229 // non-const Gets 230 virtual PowerState GetPowerState(void); 231 232 // Statics 233 static inline bool IsSTBSupported(const QString &model); 234 static QString GetModelName(uint vendorid, uint modelid); 235 static vector<AVCInfo> GetSTBList(void); 236 static bool IsSubunitType( 237 const uint8_t unit_table[32], IEEE1394UnitAddress subunit_type); 238 static QString GetSubunitInfoString(const uint8_t table[32]); 239 240 protected: 241 FirewireDevice(uint64_t guid, uint subunitid, uint speed); 242 243 virtual bool SendAVCCommand(const vector<uint8_t> &cmd, 244 vector<uint8_t> &result, 245 int retry_cnt) = 0; 246 bool GetSubunitInfo(uint8_t table[32]); 247 248 void SetLastChannel(uint channel); 249 void ProcessPATPacket(const TSPacket&); 250 virtual void BroadcastToListeners( 251 const unsigned char *data, uint dataSize); 252 253 uint64_t m_guid; 254 uint m_subunitid; 255 uint m_speed; 256 uint m_last_channel; 257 uint m_last_crc; 258 bool m_buffer_cleared; 259 260 uint m_open_port_cnt; 261 vector<TSDataListener*> m_listeners; 262 mutable QMutex m_lock; 263 264 /// Vendor ID + Model ID to FirewireDevice STB model string 265 static QMap<uint64_t,QString> s_id_to_model; 266 static QMutex s_static_lock; 267 }; 268 269 inline bool FirewireDevice::IsSTBSupported(const QString &panel_model) 270 { 271 QString model = panel_model.upper(); 272 return ((model == "DCT-6200") || 273 (model == "DCT-6212") || 274 (model == "DCT-6216") || 275 (model == "SA3250HD") || 276 (model == "SA4200HD") || 277 (model == "GENERIC")); 278 } 279 280 #endif // _FIREWIRE_DEVICE_H_ -
libs/libmythtv/linuxfirewiredevice.cpp
1 /** 2 * LinuxFirewireDevice 3 * Copyright (c) 2005 by Jim Westfall 4 * Copyright (c) 2006 by Daniel Kristjansson 5 * SA3250HD support Copyright (c) 2005 by Matt Porter 6 * SA4200HD/Alternate 3250 support Copyright (c) 2006 by Chris Ingrassia 7 * Distributed as part of MythTV under GPL v2 and later. 8 */ 9 10 // POSIX headers 11 #include <pthread.h> 12 #include <sys/select.h> 13 14 #include <cassert> 15 16 // Linux headers 17 #include <libraw1394/raw1394.h> 18 #include <libraw1394/csr.h> 19 #include <libiec61883/iec61883.h> 20 #include <libavc1394/avc1394.h> 21 #include <libavc1394/rom1394.h> 22 23 //#include <unistd.h> 24 //#include <string.h> 25 //#include <stdio.h> 26 //#include <stdlib.h> 27 #include <netinet/in.h> 28 29 // C++ headers 30 #include <algorithm> 31 using namespace std; 32 33 // Qt headers 34 #include <qdatetime.h> 35 36 // MythTV headers 37 #include "linuxfirewiredevice.h" 38 #include "firewirerecorder.h" 39 #include "mythcontext.h" 40 41 #define LOC QString("LFireDev(%1:%2): ").arg(m_port).arg(m_node) 42 #define LOC_WARN QString("LFireDev(%1:%2), Warning: ").arg(m_port).arg(m_node) 43 #define LOC_ERR QString("LFireDev(%1:%2), Error: ").arg(m_port).arg(m_node) 44 45 #define kNoDataTimeout 50 /* msec */ 46 47 typedef QMap<raw1394handle_t,LinuxFirewireDevice*> handle_to_lfd_t; 48 49 class LFDPriv 50 { 51 public: 52 LFDPriv() : 53 handle(NULL), generation(0), reset_start(true), 54 avstream(NULL), channel(-1), 55 is_p2p_node_open(false), is_bcast_node_open(false), 56 is_streaming(false), is_streaming_running(false) 57 { 58 memset(unit_table, 0xff, sizeof(unit_table)); 59 } 60 61 raw1394handle_t handle; 62 uint generation; 63 bool reset_start; 64 uint8_t unit_table[32]; 65 66 iec61883_mpeg2_t avstream; 67 int channel; 68 69 bool is_p2p_node_open; 70 bool is_bcast_node_open; 71 bool is_streaming; 72 bool is_streaming_running; 73 74 QDateTime stop_streaming_timer; 75 pthread_t streaming_thread; 76 QMutex start_stop_streaming_lock; 77 78 static QMutex s_lock; 79 static handle_to_lfd_t s_handle_info; 80 }; 81 QMutex LFDPriv::s_lock; 82 handle_to_lfd_t LFDPriv::s_handle_info; 83 84 const uint LinuxFirewireDevice::kBroadcastChannel = 63; 85 const uint LinuxFirewireDevice::kConnectionP2P = 0; 86 const uint LinuxFirewireDevice::kConnectionBroadcast = 1; 87 const uint LinuxFirewireDevice::kMaxBufferedPackets = 2000; 88 89 // callback function for libiec61883 90 int linux_firewire_device_tspacket_handler( 91 unsigned char *tspacket, int len, uint dropped, void *callback_data); 92 static QString speed_to_string(uint speed); 93 static int linux_firewire_device_bus_reset_handler( 94 raw1394handle_t handle, uint generation); 95 static uint64_t get_guid(raw1394handle_t handle, nodeid_t node); 96 97 LinuxFirewireDevice::LinuxFirewireDevice( 98 uint64_t guid, uint subunitid, 99 uint speed, bool use_p2p, uint av_buffer_size_in_bytes) : 100 FirewireDevice(guid, subunitid, speed), 101 m_port(-1), m_node(-1), 102 m_bufsz(av_buffer_size_in_bytes), 103 m_use_p2p(use_p2p), m_resetting(false), 104 m_priv(new LFDPriv()) 105 { 106 if (!m_bufsz) 107 m_bufsz = gContext->GetNumSetting("HDRingbufferSize"); 108 } 109 110 LinuxFirewireDevice::~LinuxFirewireDevice() 111 { 112 if (IsPortOpen()) 113 { 114 VERBOSE(VB_IMPORTANT, LOC_ERR + "ctor called with open port"); 115 while (IsPortOpen()) 116 ClosePort(); 117 } 118 119 if (m_priv) 120 { 121 delete m_priv; 122 m_priv = NULL; 123 } 124 } 125 126 void LinuxFirewireDevice::HandleBusReset(uint generation) 127 { 128 QString loc = LOC + QString("HandleBusReset(%1->%2)") 129 .arg(m_priv->generation).arg(generation); 130 131 m_priv->generation = generation; 132 133 if (m_priv->reset_start) 134 { 135 m_priv->reset_start = false; 136 if (m_priv->is_streaming) 137 { 138 VERBOSE(VB_IMPORTANT, loc + ": Stopping Streaming"); 139 iec61883_mpeg2_recv_stop(m_priv->avstream); 140 VERBOSE(VB_IMPORTANT, loc + ": Stopped Streaming"); 141 } 142 return; 143 } 144 m_priv->reset_start = true; 145 146 raw1394_update_generation(m_priv->handle, generation); 147 148 if (m_priv->channel >= 0) 149 { 150 int bandwidth = 1; 151 int oplug = -1, iplug = -1; 152 int fwchan = iec61883_cmp_reconnect( 153 m_priv->handle, m_node | 0xffc0, &oplug, 154 raw1394_get_local_id(m_priv->handle), &iplug, 155 &bandwidth, m_priv->channel); 156 157 if (fwchan < 0) 158 { 159 VERBOSE(VB_IMPORTANT, LOC_ERR + "Bus Reset: Failed to reconnect"); 160 } 161 else if (fwchan != m_priv->channel) 162 { 163 VERBOSE(VB_IMPORTANT, LOC_WARN + QString("FWChan changed %1->%2") 164 .arg(m_priv->channel).arg(fwchan)); 165 } 166 m_priv->channel = fwchan; 167 168 VERBOSE(VB_IMPORTANT, loc + ": Reconnected fwchan: "<<fwchan); 169 170 if (m_priv->is_streaming) 171 { 172 VERBOSE(VB_IMPORTANT, loc + ": Starting Streaming"); 173 iec61883_mpeg2_recv_start(m_priv->avstream, m_priv->channel); 174 VERBOSE(VB_IMPORTANT, loc + ": Started Streaming"); 175 } 176 } 177 } 178 179 bool LinuxFirewireDevice::OpenPort(void) 180 { 181 QMutexLocker mlocker(&m_lock); 182 QMutexLocker slocker(&LFDPriv::s_lock); 183 184 VERBOSE(VB_RECORD, LOC + "OpenPort()"); 185 186 if (m_priv->handle) 187 { 188 m_open_port_cnt++; 189 return true; 190 } 191 192 if (!GetPortAndNode()) 193 return false; 194 195 VERBOSE(VB_RECORD, LOC + "Getting raw1394 handle "<<(m_open_port_cnt-1)); 196 m_priv->handle = raw1394_new_handle_on_port(m_port); 197 198 if (!m_priv->handle) 199 { 200 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to get handle for " + 201 QString("port: %1").arg(m_port) + ENO); 202 203 return false; 204 } 205 206 LFDPriv::s_handle_info[m_priv->handle] = this; 207 208 m_priv->generation = raw1394_get_generation(m_priv->handle); 209 raw1394_set_bus_reset_handler( 210 m_priv->handle, linux_firewire_device_bus_reset_handler); 211 212 GetSubunitInfo(m_priv->unit_table); 213 VERBOSE(VB_RECORD, LOC + GetSubunitInfoString(m_priv->unit_table)); 214 215 if (!IsSubunitType(m_priv->unit_table, kAVCSubunitTypeTuner) || 216 !IsSubunitType(m_priv->unit_table, kAVCSubunitTypePanel)) 217 { 218 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("No STB at guid: 0x%1") 219 .arg(m_guid,0,16)); 220 221 ClosePort(); 222 return false; 223 } 224 225 m_open_port_cnt++; 226 227 return true; 228 } 229 230 bool LinuxFirewireDevice::ClosePort(void) 231 { 232 QMutexLocker mlocker(&m_lock); 233 QMutexLocker slocker(&LFDPriv::s_lock); 234 235 VERBOSE(VB_RECORD, LOC + "ClosePort()"); 236 237 if (m_open_port_cnt < 1) 238 return false; 239 240 m_open_port_cnt--; 241 242 if (m_open_port_cnt != 0) 243 return true; 244 245 if (m_priv->handle) 246 { 247 if (IsNodeOpen()) 248 CloseNode(); 249 250 VERBOSE(VB_RECORD, LOC + "Releasing raw1394 handle "<<m_open_port_cnt); 251 raw1394_destroy_handle(m_priv->handle); 252 LFDPriv::s_handle_info.erase(m_priv->handle); 253 m_priv->handle = NULL; 254 } 255 256 return true; 257 } 258 259 void LinuxFirewireDevice::AddListener(TSDataListener *listener) 260 { 261 FirewireDevice::AddListener(listener); 262 263 QMutexLocker locker(&m_lock); 264 if (!m_listeners.empty()) 265 { 266 OpenNode(); 267 OpenAVStream(); 268 StartStreaming(); 269 } 270 } 271 272 void LinuxFirewireDevice::RemoveListener(TSDataListener *listener) 273 { 274 FirewireDevice::RemoveListener(listener); 275 276 QMutexLocker locker(&m_lock); 277 if (m_listeners.empty()) 278 { 279 StopStreaming(); 280 CloseAVStream(); 281 CloseNode(); 282 } 283 } 284 285 bool LinuxFirewireDevice::SendAVCCommand( 286 const vector<uint8_t> &_cmd, 287 vector<uint8_t> &result, 288 int retry_cnt) 289 { 290 retry_cnt = (retry_cnt < 0) ? 2 : retry_cnt; 291 292 result.clear(); 293 294 if (!m_priv->handle || (m_node < 0)) 295 return false; 296 297 vector<uint8_t> cmd = _cmd; 298 while (cmd.size() & 0x3) 299 cmd.push_back(0x00); 300 301 if (cmd.size() > 4096) 302 return false; 303 304 uint32_t cmdbuf[1024]; 305 for (uint i = 0; i < cmd.size(); i+=4) 306 cmdbuf[i>>2] = cmd[i]<<24 | cmd[i+1]<<16 | cmd[i+2]<<8 | cmd[i+3]; 307 308 uint result_length = 0; 309 310 #ifdef USING_LIBAVC_5_3 311 uint32_t *ret = avc1394_transaction_block2( 312 m_priv->handle, m_node, cmdbuf, cmd.size() >> 2, 313 &result_length, retry_cnt); 314 #else // if !USING_LIBAVC_5_3 315 uint32_t *ret = avc1394_transaction_block( 316 m_priv->handle, m_node, cmdbuf, cmd.size() >> 2, retry_cnt); 317 result_length = cmd.size() >> 2; 318 #endif // !USING_LIBAVC_5_3 319 320 if (!ret) 321 return false; 322 323 for (uint i = 0; i < result_length; i++) 324 { 325 result.push_back((ret[i]>>24) & 0xff); 326 result.push_back((ret[i]>>16) & 0xff); 327 result.push_back((ret[i]>>8) & 0xff); 328 result.push_back((ret[i]) & 0xff); 329 } 330 331 #ifdef USING_LIBAVC_5_3 332 avc1394_transaction_block_close(m_priv->handle); 333 #endif // USING_LIBAVC_5_3 334 335 return true; 336 } 337 338 bool LinuxFirewireDevice::IsPortOpen(void) const 339 { 340 QMutexLocker locker(&m_lock); 341 342 return m_priv->handle; 343 } 344 345 /////////////////////////////////////////////////////////////////////////////// 346 // Private methods 347 348 bool LinuxFirewireDevice::GetPortAndNode(void) 349 { 350 m_port = m_node = -1; 351 352 vector<AVCInfo> list = GetSTBList(); 353 for (uint i = 0; i < list.size(); i++) 354 { 355 if (list[i].guid == m_guid) 356 { 357 m_port = list[i].port; 358 m_node = list[i].node; 359 break; 360 } 361 } 362 363 bool ok = (m_port >= 0) && (m_node >= 0); 364 365 if (!ok) 366 { 367 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to find port and node " + 368 QString("for guid: 0x%1").arg(m_guid,0,16)); 369 } 370 else 371 { 372 VERBOSE(VB_RECORD, LOC + QString("port: %1, node: %2") 373 .arg(m_port).arg(m_node)); 374 } 375 376 return ok; 377 } 378 379 bool LinuxFirewireDevice::OpenNode(void) 380 { 381 if (m_use_p2p) 382 return OpenP2PNode(); 383 else 384 return OpenBroadcastNode(); 385 } 386 387 bool LinuxFirewireDevice::CloseNode(void) 388 { 389 if (m_priv->is_p2p_node_open) 390 return CloseP2PNode(); 391 392 if (m_priv->is_bcast_node_open) 393 return CloseBroadcastNode(); 394 395 return true; 396 } 397 398 bool LinuxFirewireDevice::OpenP2PNode(void) 399 { 400 if (m_priv->is_bcast_node_open) 401 return false; 402 403 if (m_priv->is_p2p_node_open) 404 return true; 405 406 VERBOSE(VB_RECORD, LOC + "Opening P2P connection"); 407 408 m_priv->channel = m_node; 409 if (iec61883_cmp_create_p2p_output(m_priv->handle, m_node | 0xffc0, 0, 410 m_priv->channel, m_speed) != 0) 411 { 412 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create P2P connection"); 413 414 m_priv->channel = -1; 415 return false; 416 } 417 418 m_priv->is_p2p_node_open = true; 419 420 return true; 421 } 422 423 bool LinuxFirewireDevice::CloseP2PNode(void) 424 { 425 if (m_priv->is_p2p_node_open && (m_priv->channel >= 0)) 426 { 427 VERBOSE(VB_RECORD, LOC + "Closing P2P connection"); 428 429 if (m_priv->avstream) 430 CloseAVStream(); 431 432 iec61883_cmp_disconnect(m_priv->handle, m_node | 0xffc0, 0, 433 raw1394_get_local_id(m_priv->handle), 434 -1, m_priv->channel, 0); 435 436 m_priv->channel = -1; 437 m_priv->is_p2p_node_open = false; 438 } 439 440 return true; 441 } 442 443 bool LinuxFirewireDevice::OpenBroadcastNode(void) 444 { 445 if (m_priv->is_p2p_node_open) 446 return false; 447 448 if (m_priv->is_bcast_node_open) 449 return true; 450 451 m_priv->channel = kBroadcastChannel - m_node; 452 453 VERBOSE(VB_RECORD, LOC + "Opening broadcast connection on " + 454 QString("node %1, channel %2") 455 .arg(m_node).arg(m_priv->channel)); 456 457 if (m_priv->avstream) 458 CloseAVStream(); 459 460 int err = iec61883_cmp_create_bcast_output( 461 m_priv->handle, m_node | 0xffc0, 0, m_priv->channel, m_speed); 462 463 if (err != 0) 464 { 465 VERBOSE(VB_IMPORTANT, LOC_ERR + 466 "Failed to create Broadcast connection"); 467 468 m_priv->channel = -1; 469 return false; 470 } 471 472 m_priv->is_bcast_node_open = true; 473 474 return true; 475 } 476 477 bool LinuxFirewireDevice::CloseBroadcastNode(void) 478 { 479 if (m_priv->is_bcast_node_open) 480 { 481 VERBOSE(VB_RECORD, LOC + "Closing broadcast connection"); 482 483 m_priv->channel = -1; 484 m_priv->is_bcast_node_open = false; 485 } 486 return true; 487 } 488 489 bool LinuxFirewireDevice::OpenAVStream(void) 490 { 491 VERBOSE(VB_RECORD, LOC + "OpenAVStream"); 492 493 if (!IsNodeOpen() && !OpenNode()) 494 return false; 495 496 if (m_priv->avstream) 497 return true; 498 499 VERBOSE(VB_RECORD, LOC + "Opening A/V stream object"); 500 501 if (!m_priv->handle) 502 { 503 VERBOSE(VB_IMPORTANT, LOC + 504 "Can not open AVStream without IEEE 1394 Port"); 505 506 return false; 507 } 508 509 m_priv->avstream = iec61883_mpeg2_recv_init( 510 m_priv->handle, linux_firewire_device_tspacket_handler, this); 511 512 if (!m_priv->avstream) 513 { 514 VERBOSE(VB_IMPORTANT, LOC + "Unable to open AVStream" + ENO); 515 516 return false; 517 } 518 519 iec61883_mpeg2_set_synch(m_priv->avstream, 1 /* sync on close */); 520 521 if (m_bufsz) 522 SetAVStreamBufferSize(m_bufsz); 523 524 return true; 525 } 526 527 bool LinuxFirewireDevice::CloseAVStream(void) 528 { 529 if (!m_priv->avstream) 530 return true; 531 532 VERBOSE(VB_RECORD, LOC + "Closing A/V stream object"); 533 534 while (!m_resetting && m_listeners.size()) 535 RemoveListener(m_listeners[m_listeners.size() - 1]); 536 537 if (m_priv->is_streaming) 538 StopStreaming(); 539 540 iec61883_mpeg2_close(m_priv->avstream); 541 m_priv->avstream = NULL; 542 543 return true; 544 } 545 546 void *linux_firewire_device_streaming_thunk(void *param) 547 { 548 LinuxFirewireDevice *mon = (LinuxFirewireDevice*) param; 549 mon->RunStreaming(); 550 return NULL; 551 } 552 553 void LinuxFirewireDevice::RunStreaming(void) 554 { 555 VERBOSE(VB_RECORD, LOC + "RunStreaming -- start"); 556 m_lock.lock(); 557 m_priv->is_streaming_running = true; 558 559 uint no_data_cnt = 0; 560 while (m_priv->is_streaming) 561 { 562 no_data_cnt = (LoopIteration(kNoDataTimeout)) ? 0 : no_data_cnt + 1; 563 564 if (m_priv->is_streaming && (no_data_cnt > 30)) 565 { 566 no_data_cnt = 0; 567 ResetBus(); 568 } 569 } 570 571 m_priv->is_streaming_running = false; 572 m_lock.unlock(); 573 VERBOSE(VB_RECORD, LOC + "RunStreaming -- end"); 574 } 575 576 bool LinuxFirewireDevice::StartStreaming(void) 577 { 578 VERBOSE(VB_RECORD, LOC + "Starting A/V streaming"); 579 QMutexLocker locker(&m_priv->start_stop_streaming_lock); 580 VERBOSE(VB_RECORD, LOC + "Starting A/V streaming -- locked"); 581 582 if (m_priv->is_streaming) 583 return m_priv->is_streaming; 584 585 assert(!m_priv->is_streaming_running); 586 587 if (!IsAVStreamOpen() && !OpenAVStream()) 588 return false; 589 590 if (m_priv->channel < 0) 591 { 592 VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming, no channel"); 593 return false; 594 } 595 596 VERBOSE(VB_RECORD, LOC + "Starting A/V streaming -- really"); 597 598 if (iec61883_mpeg2_recv_start(m_priv->avstream, m_priv->channel) == 0) 599 { 600 m_priv->is_streaming = true; 601 602 pthread_create(&m_priv->streaming_thread, NULL, 603 linux_firewire_device_streaming_thunk, this); 604 605 m_lock.unlock(); 606 while (!m_priv->is_streaming_running) 607 usleep(5000); 608 m_lock.lock(); 609 } 610 else 611 { 612 VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming " + ENO); 613 } 614 615 return m_priv->is_streaming; 616 } 617 618 bool LinuxFirewireDevice::StopStreaming(void) 619 { 620 VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming"); 621 QMutexLocker locker(&m_priv->start_stop_streaming_lock); 622 VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming -- locked"); 623 624 if (m_priv->is_streaming) 625 { 626 VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming -- really"); 627 628 m_priv->is_streaming = false; 629 630 VERBOSE(VB_RECORD, LOC + "Waiting for A/V streaming to stop"); 631 while (m_priv->is_streaming_running) 632 { 633 m_lock.unlock(); 634 usleep(5000); 635 m_lock.lock(); 636 } 637 638 VERBOSE(VB_RECORD, LOC + "Joining A/V streaming thread"); 639 pthread_join(m_priv->streaming_thread, NULL); 640 641 iec61883_mpeg2_recv_stop(m_priv->avstream); 642 643 raw1394_iso_recv_flush(m_priv->handle); 644 } 645 646 VERBOSE(VB_RECORD, LOC + "Stopped A/V streaming"); 647 648 return true; 649 } 650 651 bool LinuxFirewireDevice::StopStreamingLater(void) 652 { 653 // TODO 654 return true; 655 } 656 657 bool LinuxFirewireDevice::SetAVStreamBufferSize(uint size_in_bytes) 658 { 659 if (!m_priv->avstream) 660 return false; 661 662 // Set buffered packets size 663 uint buffer_size = max(size_in_bytes, 50 * TSPacket::SIZE); 664 size_t buffered_packets = min(buffer_size / 4, kMaxBufferedPackets); 665 666 iec61883_mpeg2_set_buffers(m_priv->avstream, buffered_packets); 667 668 VERBOSE(VB_IMPORTANT, LOC + 669 QString("Buffered packets %1 (%2 KB)") 670 .arg(buffered_packets).arg(buffered_packets * 4)); 671 672 return true; 673 } 674 675 bool LinuxFirewireDevice::SetAVStreamSpeed(uint speed) 676 { 677 if (!m_priv->avstream) 678 return false; 679 680 uint curspeed = iec61883_mpeg2_get_speed(m_priv->avstream); 681 682 if (curspeed == speed) 683 { 684 m_speed = speed; 685 return true; 686 } 687 688 VERBOSE(VB_RECORD, LOC + 689 QString("Changing Speed %1 -> %2") 690 .arg(speed_to_string(curspeed)) 691 .arg(speed_to_string(m_speed))); 692 693 iec61883_mpeg2_set_speed(m_priv->avstream, speed); 694 695 if (speed == (uint)iec61883_mpeg2_get_speed(m_priv->avstream)) 696 { 697 m_speed = speed; 698 return true; 699 } 700 701 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set firewire speed."); 702 703 return false; 704 } 705 706 bool LinuxFirewireDevice::IsNodeOpen(void) const 707 { 708 return m_priv->is_p2p_node_open || m_priv->is_bcast_node_open; 709 } 710 711 bool LinuxFirewireDevice::IsAVStreamOpen(void) const 712 { 713 return m_priv->avstream; 714 } 715 716 bool LinuxFirewireDevice::ResetBus(void) 717 { 718 VERBOSE(VB_IMPORTANT, LOC + "ResetBus() -- begin"); 719 720 bool ok = (raw1394_reset_bus_new(m_priv->handle, RAW1394_LONG_RESET) == 0); 721 if (!ok) 722 VERBOSE(VB_IMPORTANT, LOC_ERR + "Bus Reset failed" + ENO); 723 724 VERBOSE(VB_IMPORTANT, LOC + "ResetBus() -- end"); 725 726 return ok; 727 } 728 729 bool LinuxFirewireDevice::LoopIteration(uint timeout_in_msec) 730 { 731 if (m_resetting) 732 return true; 733 734 int fwfd = raw1394_get_fd(m_priv->handle); 735 if (fwfd < 0) 736 return false; 737 738 struct timeval tv; 739 fd_set rfds; 740 741 FD_ZERO(&rfds); 742 FD_SET(fwfd, &rfds); 743 744 tv.tv_sec = timeout_in_msec / 1000; 745 tv.tv_usec = (timeout_in_msec % 1000) * 1000; 746 747 m_lock.unlock(); 748 if (select(fwfd + 1, &rfds, NULL, NULL, &tv) <= 0) 749 { 750 m_lock.lock(); 751 VERBOSE(VB_IMPORTANT, LOC + QString("No Input in %1 msec...") 752 .arg(timeout_in_msec)); 753 754 return false; 755 } 756 m_lock.lock(); 757 758 int ret = raw1394_loop_iterate(m_priv->handle); 759 if (ret) 760 { 761 VERBOSE(VB_IMPORTANT, LOC_ERR + "libraw1394_loop_iterate() " + 762 QString("returned %1").arg(ret)); 763 764 return false; 765 } 766 767 return true; 768 } 769 770 void LinuxFirewireDevice::PrintDropped(uint dropped_packets) 771 { 772 if (dropped_packets == 1) 773 { 774 VERBOSE(VB_RECORD, LOC_ERR + "Dropped a TS packet"); 775 } 776 else if (dropped_packets > 1) 777 { 778 VERBOSE(VB_RECORD, LOC_ERR + 779 QString("Dropped %1 TS packets").arg(dropped_packets)); 780 } 781 } 782 783 vector<AVCInfo> LinuxFirewireDevice::GetSTBList(void) 784 { 785 vector<AVCInfo> list; 786 787 raw1394handle_t handle = raw1394_new_handle(); 788 if (!handle) 789 { 790 VERBOSE(VB_IMPORTANT, "Couldn't get handle" + ENO); 791 return list; 792 } 793 794 struct raw1394_portinfo port_info[16]; 795 int numcards = raw1394_get_port_info(handle, port_info, 16); 796 if (numcards < 1) 797 { 798 raw1394_destroy_handle(handle); 799 return list; 800 } 801 802 for (int port = 0; port < numcards; port++) 803 { 804 if (raw1394_set_port(handle, port) < 0) 805 { 806 VERBOSE(VB_IMPORTANT, "Couldn't set port to " << port); 807 continue; 808 } 809 810 for (int node = 0; node < raw1394_get_nodecount(handle); node++) 811 { 812 AVCInfo info; 813 814 info.guid = get_guid(handle, 0xffc0 | node); 815 816 rom1394_directory dir; 817 if (rom1394_get_directory(handle, node, &dir) < 0) 818 { 819 continue; 820 } 821 info.port = port; 822 info.node = node; 823 info.vendorid = dir.vendor_id; 824 info.modelid = dir.model_id; 825 info.specid = dir.unit_spec_id; 826 info.firmware_revision = dir.unit_sw_version; 827 info.product_name = QString("%1").arg(dir.label); 828 829 uint8_t unit_table[32]; 830 831 if (avc1394_subunit_info(handle, node, (uint32_t*)unit_table) < 0) 832 memset(unit_table, 0xff, sizeof(unit_table)); 833 834 if (IsSubunitType(unit_table, kAVCSubunitTypeTuner) && 835 IsSubunitType(unit_table, kAVCSubunitTypePanel)) 836 { 837 list.push_back(info); 838 } 839 } 840 841 raw1394_destroy_handle(handle); 842 843 handle = raw1394_new_handle(); 844 if (!handle) 845 { 846 VERBOSE(VB_IMPORTANT, "Couldn't get handle " 847 "(after setting port "<<port<<")" + ENO); 848 handle = NULL; 849 break; 850 } 851 852 numcards = raw1394_get_port_info(handle, port_info, 16); 853 } 854 855 if (handle) 856 raw1394_destroy_handle(handle); 857 858 return list; 859 } 860 861 int linux_firewire_device_tspacket_handler( 862 unsigned char *tspacket, int len, uint dropped, void *callback_data) 863 { 864 LinuxFirewireDevice *fw = (LinuxFirewireDevice*) callback_data; 865 if (!fw) 866 return 0; 867 868 if (dropped) 869 fw->PrintDropped(dropped); 870 871 if (len > 0) 872 fw->BroadcastToListeners(tspacket, len); 873 874 return 1; 875 } 876 877 static QString speed_to_string(uint speed) 878 { 879 if (speed > 3) 880 return QString("Invalid Speed (%1)").arg(speed); 881 882 static const uint speeds[] = { 100, 200, 400, 800 }; 883 return QString("%1Mbps").arg(speeds[speed]); 884 } 885 886 static int linux_firewire_device_bus_reset_handler( 887 raw1394handle_t handle, unsigned int generation) 888 { 889 QMutexLocker locker(&LFDPriv::s_lock); 890 891 handle_to_lfd_t::iterator it = LFDPriv::s_handle_info.find(handle); 892 893 if (it != LFDPriv::s_handle_info.end()) 894 (*it)->HandleBusReset(generation); 895 896 return 0; 897 } 898 899 // get_guid copied from plugreport, Copyright 2002-2004 Dan Dennedy GPL v2+ 900 #define PLUGREPORT_GUID_HI 0x0C 901 #define PLUGREPORT_GUID_LO 0x10 902 static uint64_t get_guid(raw1394handle_t handle, nodeid_t node) 903 { 904 uint32_t quadlet; 905 uint64_t offset; 906 uint64_t guid = 0; 907 908 offset = CSR_REGISTER_BASE + CSR_CONFIG_ROM + PLUGREPORT_GUID_HI; 909 raw1394_read(handle, node, offset, sizeof(uint32_t), &quadlet); 910 quadlet = htonl(quadlet); 911 guid = quadlet; 912 guid <<= 32; 913 offset = CSR_REGISTER_BASE + CSR_CONFIG_ROM + PLUGREPORT_GUID_LO; 914 raw1394_read(handle, node, offset, sizeof(uint32_t), &quadlet); 915 quadlet = htonl(quadlet); 916 guid += quadlet; 917 918 return guid; 919 } -
programs/mythbackend/backendutil.cpp
2 2 #ifdef CONFIG_DARWIN 3 3 #include <sys/param.h> 4 4 #include <sys/mount.h> 5 unsigned long long int abs(long long int v) 6 { return (unsigned long long int) ((v < 0) ? -v : v); } 5 7 #elif __linux__ 6 8 #include <sys/vfs.h> 7 9 #endif
