00001
00006 #include <algorithm>
00007
00008 #include "iptvfeederudp.h"
00009
00010
00011 #include <qurl.h>
00012
00013
00014 #include <BasicUsageEnvironment.hh>
00015 #include <Groupsock.hh>
00016 #include <GroupsockHelper.hh>
00017 #include <BasicUDPSource.hh>
00018 #include <TunnelEncaps.hh>
00019
00020
00021 #include "iptvmediasink.h"
00022 #include "mythcontext.h"
00023 #include "tspacket.h"
00024
00025 #define LOC QString("IPTVFeedUDP: ")
00026 #define LOC_ERR QString("IPTVFeedUDP, Error: ")
00027
00028 IPTVFeederUDP::IPTVFeederUDP() :
00029 _source(NULL),
00030 _sink(NULL)
00031 {
00032 VERBOSE(VB_RECORD, LOC + "ctor -- success");
00033 }
00034
00035 IPTVFeederUDP::~IPTVFeederUDP()
00036 {
00037 VERBOSE(VB_RECORD, LOC + "dtor -- begin");
00038 Close();
00039 VERBOSE(VB_RECORD, LOC + "dtor -- end");
00040 }
00041
00042 bool IPTVFeederUDP::IsUDP(const QString &url)
00043 {
00044 return url.startsWith("udp://", false);
00045 }
00046
00047 bool IPTVFeederUDP::Open(const QString &url)
00048 {
00049 VERBOSE(VB_RECORD, LOC + QString("Open(%1) -- begin").arg(url));
00050
00051 QMutexLocker locker(&_lock);
00052
00053 if (_source)
00054 {
00055 VERBOSE(VB_RECORD, LOC + "Open() -- end 1");
00056 return true;
00057 }
00058
00059 QUrl parse(url);
00060 if (!parse.isValid() || !parse.hasHost() || !parse.hasPort())
00061 {
00062 VERBOSE(VB_RECORD, LOC + "Open() -- end 2");
00063 return false;
00064 }
00065
00066 struct in_addr addr;
00067 addr.s_addr = our_inet_addr(parse.host().latin1());
00068
00069
00070 if (!InitEnv())
00071 return false;
00072
00073 ReceivingSocketAddr = our_inet_addr(parse.host().latin1());
00074
00075 Groupsock *socket = new Groupsock(*_live_env, addr, parse.port(), 0);
00076 if (!socket)
00077 {
00078 VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live UDP Socket.");
00079 FreeEnv();
00080 return false;
00081 }
00082 _source = BasicUDPSource::createNew(*_live_env, socket);
00083 if (!_source)
00084 {
00085 VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live UDP Source.");
00086
00087 if (socket)
00088 delete socket;
00089
00090 FreeEnv();
00091 return false;
00092 }
00093
00094 _sink = IPTVMediaSink::CreateNew(*_live_env, TSPacket::SIZE * 128*1024);
00095 if (!_sink)
00096 {
00097 VERBOSE(VB_IMPORTANT,
00098 QString("IPTV # Failed to create sink: %1")
00099 .arg(_live_env->getResultMsg()));
00100
00101 Medium::close(_source);
00102 _source = NULL;
00103 if (socket)
00104 delete socket;
00105 FreeEnv();
00106
00107 return false;
00108 }
00109
00110 _sink->startPlaying(*_source, NULL, NULL);
00111 vector<TSDataListener*>::iterator it = _listeners.begin();
00112 for (; it != _listeners.end(); ++it)
00113 _sink->AddListener(*it);
00114
00115 VERBOSE(VB_RECORD, LOC + "Open() -- end");
00116
00117 return true;
00118 }
00119
00120 void IPTVFeederUDP::Close(void)
00121 {
00122 VERBOSE(VB_RECORD, LOC + "Close() -- begin");
00123 Stop();
00124
00125 QMutexLocker locker(&_lock);
00126
00127 if (_sink)
00128 {
00129 Medium::close(_sink);
00130 _sink = NULL;
00131 }
00132
00133 if (_source)
00134 {
00135 Groupsock *socket = _source->gs();
00136 Medium::close(_source);
00137 _source = NULL;
00138 if (socket)
00139 delete socket;
00140 }
00141
00142 FreeEnv();
00143
00144 VERBOSE(VB_RECORD, LOC + "Close() -- end");
00145 }
00146
00147 void IPTVFeederUDP::AddListener(TSDataListener *item)
00148 {
00149 VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin");
00150 if (!item)
00151 {
00152 VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end");
00153 return;
00154 }
00155
00156
00157 RemoveListener(item);
00158
00159
00160 QMutexLocker locker(&_lock);
00161 _listeners.push_back(item);
00162
00163 if (_sink)
00164 _sink->AddListener(item);
00165
00166 VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end");
00167 }
00168
00169 void IPTVFeederUDP::RemoveListener(TSDataListener *item)
00170 {
00171 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin");
00172 QMutexLocker locker(&_lock);
00173 vector<TSDataListener*>::iterator it =
00174 find(_listeners.begin(), _listeners.end(), item);
00175
00176 if (it == _listeners.end())
00177 {
00178 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 1");
00179 return;
00180 }
00181
00182
00183 *it = *_listeners.rbegin();
00184 _listeners.resize(_listeners.size() - 1);
00185
00186 if (_sink)
00187 _sink->RemoveListener(item);
00188
00189 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 2");
00190 }