def __init__(self, appname, installdir): self.appname = appname self.installdir = installdir self.wrapper = None self.config = None self.s = None self.statedir = None self.source = None self.child_processes = [] self.stats = {} self.download = None self.player_id = None self.tsservice = TSService(self)
class StreamApp(): def __init__(self, appname, installdir): self.appname = appname self.installdir = installdir self.wrapper = None self.config = None self.s = None self.statedir = None self.source = None self.child_processes = [] self.stats = {} self.download = None self.player_id = None self.tsservice = TSService(self) def set_wrapper(self, wrapper): self.wrapper = wrapper def state_callback(self, ds): d = ds.get_download() if DEBUG: print >> sys.stderr, `(d.get_def().get_name())`, dlstatus_strings[ds.get_status()], '%3.1f %%' % ds.get_progress(), ds.get_error(), 'up %.1f down %.1f' % (ds.get_current_speed(UPLOAD), ds.get_current_speed(DOWNLOAD)) self.stats['speed_source'] = self.source.ratemeasure.get_rate_noupdate() self.stats['peers'] = ds.get_num_peers() self.stats['speed_up'] = ds.get_current_speed(UPLOAD) if self.wrapper is not None: status_string = 'Source: %.1f\nPeers: %d\nUP: %.1f' % (self.stats['speed_source'] / 1024.0, self.stats['peers'], self.stats['speed_up']) self.wrapper.set_icon_tooltip(status_string) return (1.0, False) def get_piece_size(self, bitrate): mid = bitrate / 2 piece_size = 32768 while piece_size < mid: piece_size *= 2 return piece_size def get_vlc_path(self): vlc_path = os.path.join(self.installdir, '..', 'player', 'tsplayer.exe') if not os.path.isfile(vlc_path): raise Exception, 'Cannot find vlc:', vlc_path return vlc_path def init_source(self, source_id, tdef, dcfg): if source_id == '-': source = sys.stdin elif source_id.startswith('http:'): source = InfiniteHTTPStream(source_id) elif source_id.startswith('pipe:'): cmd = source_id[len('pipe:'):] child_out, source = os.popen2(cmd, 'b') elif source_id.startswith('vlcfile:'): source_id = source_id[len('vlcfile:'):] a = source_id.split('#') if len(a) != 2: raise ValueError, 'Bad source format' path = a[0] transcode_options = a[1] if DEBUG: print >> sys.stderr, 'init_source: vlcfile: path', path, 'transcode_options', transcode_options vlc_path = self.get_vlc_path() vlc_args = [vlc_path, '-I', 'none', '--sout', '#transcode{' + transcode_options + '}:http{mux=ts,dst=:9090}', '--sout-keep', path] print >> sys.stderr, 'init_source: start vlc: vlc_args', vlc_args vlc_process = subprocess.Popen(vlc_args, close_fds=True) self.child_processes.append(vlc_process) source = InfiniteHTTPStream('http://localhost:9090') elif source_id.startswith('vlcdshow:'): source_id = source_id[len('vlcdshow:'):] a = source_id.split('#') if len(a) != 4: raise ValueError, 'Bad source format' video_device_name = a[0] audio_device_name = a[1] video_size = a[2] transcode_options = a[3] if DEBUG: print >> sys.stderr, 'init_source: vlcdshow: video_device_name', video_device_name, 'audio_device_name', audio_device_name, 'video_size', video_size, 'transcode_options', transcode_options vlc_path = self.get_vlc_path() vlc_args = [vlc_path, '-I', 'none', 'dshow://', 'vdev="' + video_device_name + '"', 'adev="' + audio_device_name + '"', 'size="' + video_size + '"', '--sout', '#transcode{' + transcode_options + '}:http{mux=ts,dst=:9090}', '--sout-keep'] print >> sys.stderr, 'init_source: start vlc: vlc_args', vlc_args vlc_process = subprocess.Popen(vlc_args, close_fds=True) self.child_processes.append(vlc_process) source = InfiniteHTTPStream('http://localhost:9090') else: try: stream = open(source_id, 'rb') except IOError: print >> sys.stderr, 'Cannot open file', source_id raise KeyboardInterrupt except: raise source = stream dcfg.set_video_ratelimit(tdef.get_bitrate()) return source def send_torrent_to_server(self, tdef, developer_id = 0, affiliate_id = 0, zone_id = 0): t = Thread(target=self._send_torrent_to_server, args=[tdef, developer_id, affiliate_id, zone_id]) t.setDaemon(True) t.start() def _send_torrent_to_server(self, tdef, developer_id = 0, affiliate_id = 0, zone_id = 0): if DEBUG: log('stream::send_torrent_to_server: infohash', binascii.hexlify(tdef.get_infohash()), 'd', developer_id, 'a', affiliate_id, 'z', zone_id) torrent_data = tdef.save() protected = tdef.get_protected() if protected: infohash = tdef.get_infohash() else: infohash = None self.player_id = self.tsservice.send_torrent(torrent_data, developer_id, affiliate_id, zone_id, protected, infohash) if DEBUG: log('stream::send_torrent_to_server: torrent saved: infohash', binascii.hexlify(tdef.get_infohash()), 'd', developer_id, 'a', affiliate_id, 'z', zone_id, 'player_id', self.player_id) def start_stream(self, config): t = Thread(target=self._start_stream, args=[config]) t.setDaemon(True) t.start() def _start_stream(self, config): if len(config['destdir']) == 0: state_dir = Session.get_default_state_dir() config['destdir'] = os.path.join(state_dir, 'streams') try: config['destdir'] = config['destdir'].decode('utf-8') except: print_exc() if not os.path.isdir(config['destdir']): try: os.makedirs(config['destdir']) except: print_exc() return try: path = os.path.join(config['destdir'], config['name']) if os.path.isfile(path): os.remove(path) except: print_exc() globalConfig.set_mode('stream') sscfg = SessionStartupConfig() statedir = tempfile.mkdtemp() sscfg.set_state_dir(statedir) sscfg.set_listen_port(config['port']) sscfg.set_megacache(False) sscfg.set_overlay(False) sscfg.set_dialback(True) if config['host']: url = 'http://' + str(config['host']) + ':' + str(sscfg.get_listen_port()) + '/announce' sscfg.set_internal_tracker_url(url) s = Session(sscfg) authfilename = os.path.join(config['destdir'], config['name'] + '.sauth') try: authcfg = RSALiveSourceAuthConfig.load(authfilename) except: authcfg = RSALiveSourceAuthConfig() authcfg.save(authfilename) config['protected'] = True provider_key = config['provider-key'] if len(config['provider-key']) else None bitrate = int(config['bitrate']) bitrate *= 125 tdef = TorrentDef() tdef.create_live(config['name'], bitrate, config['duration'], authcfg, config['protected'], provider_key) tdef.set_tracker(s.get_internal_tracker_url()) if config['piecesize'] == 'auto': piece_size = self.get_piece_size(bitrate) else: piece_size = int(config['piecesize']) tdef.set_piece_length(piece_size) print >> sys.stderr, 'bitrate:', config['bitrate'] print >> sys.stderr, 'piece size:', piece_size print >> sys.stderr, 'dest dir:', config['destdir'] print >> sys.stderr, 'tracker url:', s.get_internal_tracker_url() if config['trackers']: trackers = [[s.get_internal_tracker_url()]] for t in config['trackers'].split(','): print >> sys.stderr, 'tracker:', t trackers.append([t]) tdef.set_tracker_hierarchy(trackers) tdef.finalize() print >> sys.stderr, '-------------------' ext = 'acelive' torrentbasename = config['name'] + '.' + ext torrentfilename = os.path.join(config['destdir'], torrentbasename) config['torrentfilename'] = torrentfilename tdef.save(torrentfilename) self.send_torrent_to_server(tdef) dscfg = DownloadStartupConfig() dscfg.set_dest_dir(config['destdir']) source = self.init_source(config['source'], tdef, dscfg) self.source = HaltOnEOFStream(source) restartstatefilename = os.path.join(config['destdir'], config['name'] + '.restart') dscfg.set_video_source(self.source, authcfg, restartstatefilename=restartstatefilename) dscfg.set_max_uploads(config['maxclients']) self.s = s self.statedir = statedir self.config = config self.download = s.start_download(tdef, dscfg) self.download.set_state_callback(self.state_callback, getpeerlist=False) def get_stream_info(self): if self.download is None: return return {'name': self.config['name'], 'bitrate': self.config['bitrate'], 'tracker_url': self.s.get_internal_tracker_url(), 'speed_source': self.stats.get('speed_source', 0), 'peers': self.stats.get('peers', 0), 'speed_up': self.stats.get('speed_up', 0), 'infohash': binascii.hexlify(self.download.get_def().get_infohash())} def get_torrent_path(self, infohash): return self.config['torrentfilename'] def OnExit(self): print >> sys.stderr, 'stopping...' for p in self.child_processes: print >> sys.stderr, 'stop child process:', p try: p.kill() except: if DEBUG: print_exc() if self.s is not None: self.s.shutdown() time.sleep(3) if self.statedir is not None: try: shutil.rmtree(self.statedir) except: pass
class StreamApp(): def __init__(self, appname, installdir): self.appname = appname self.installdir = installdir self.wrapper = None self.config = None self.s = None self.statedir = None self.source = None self.child_processes = [] self.stats = {} self.download = None self.player_id = None self.tsservice = TSService(self) def set_wrapper(self, wrapper): self.wrapper = wrapper def state_callback(self, ds): d = ds.get_download() if DEBUG: print >> sys.stderr, ` ( d.get_def().get_name()) `, dlstatus_strings[ds.get_status( )], '%3.1f %%' % ds.get_progress(), ds.get_error( ), 'up %.1f down %.1f' % (ds.get_current_speed(UPLOAD), ds.get_current_speed(DOWNLOAD)) self.stats['speed_source'] = self.source.ratemeasure.get_rate_noupdate( ) self.stats['peers'] = ds.get_num_peers() self.stats['speed_up'] = ds.get_current_speed(UPLOAD) if self.wrapper is not None: status_string = 'Source: %.1f\nPeers: %d\nUP: %.1f' % ( self.stats['speed_source'] / 1024.0, self.stats['peers'], self.stats['speed_up']) self.wrapper.set_icon_tooltip(status_string) return (1.0, False) def get_piece_size(self, bitrate): mid = bitrate / 2 piece_size = 32768 while piece_size < mid: piece_size *= 2 return piece_size def get_vlc_path(self): vlc_path = os.path.join(self.installdir, '..', 'player', 'tsplayer.exe') if not os.path.isfile(vlc_path): raise Exception, 'Cannot find vlc:', vlc_path return vlc_path def init_source(self, source_id, tdef, dcfg): if source_id == '-': source = sys.stdin elif source_id.startswith('http:'): source = InfiniteHTTPStream(source_id) elif source_id.startswith('pipe:'): cmd = source_id[len('pipe:'):] child_out, source = os.popen2(cmd, 'b') elif source_id.startswith('vlcfile:'): source_id = source_id[len('vlcfile:'):] a = source_id.split('#') if len(a) != 2: raise ValueError, 'Bad source format' path = a[0] transcode_options = a[1] if DEBUG: print >> sys.stderr, 'init_source: vlcfile: path', path, 'transcode_options', transcode_options vlc_path = self.get_vlc_path() vlc_args = [ vlc_path, '-I', 'none', '--sout', '#transcode{' + transcode_options + '}:http{mux=ts,dst=:9090}', '--sout-keep', path ] print >> sys.stderr, 'init_source: start vlc: vlc_args', vlc_args vlc_process = subprocess.Popen(vlc_args, close_fds=True) self.child_processes.append(vlc_process) source = InfiniteHTTPStream('http://localhost:9090') elif source_id.startswith('vlcdshow:'): source_id = source_id[len('vlcdshow:'):] a = source_id.split('#') if len(a) != 4: raise ValueError, 'Bad source format' video_device_name = a[0] audio_device_name = a[1] video_size = a[2] transcode_options = a[3] if DEBUG: print >> sys.stderr, 'init_source: vlcdshow: video_device_name', video_device_name, 'audio_device_name', audio_device_name, 'video_size', video_size, 'transcode_options', transcode_options vlc_path = self.get_vlc_path() vlc_args = [ vlc_path, '-I', 'none', 'dshow://', 'vdev="' + video_device_name + '"', 'adev="' + audio_device_name + '"', 'size="' + video_size + '"', '--sout', '#transcode{' + transcode_options + '}:http{mux=ts,dst=:9090}', '--sout-keep' ] print >> sys.stderr, 'init_source: start vlc: vlc_args', vlc_args vlc_process = subprocess.Popen(vlc_args, close_fds=True) self.child_processes.append(vlc_process) source = InfiniteHTTPStream('http://localhost:9090') else: try: stream = open(source_id, 'rb') except IOError: print >> sys.stderr, 'Cannot open file', source_id raise KeyboardInterrupt except: raise source = stream dcfg.set_video_ratelimit(tdef.get_bitrate()) return source def send_torrent_to_server(self, tdef, developer_id=0, affiliate_id=0, zone_id=0): t = Thread(target=self._send_torrent_to_server, args=[tdef, developer_id, affiliate_id, zone_id]) t.setDaemon(True) t.start() def _send_torrent_to_server(self, tdef, developer_id=0, affiliate_id=0, zone_id=0): if DEBUG: log('stream::send_torrent_to_server: infohash', binascii.hexlify(tdef.get_infohash()), 'd', developer_id, 'a', affiliate_id, 'z', zone_id) torrent_data = tdef.save() protected = tdef.get_protected() if protected: infohash = tdef.get_infohash() else: infohash = None self.player_id = self.tsservice.send_torrent(torrent_data, developer_id, affiliate_id, zone_id, protected, infohash) if DEBUG: log('stream::send_torrent_to_server: torrent saved: infohash', binascii.hexlify(tdef.get_infohash()), 'd', developer_id, 'a', affiliate_id, 'z', zone_id, 'player_id', self.player_id) def start_stream(self, config): t = Thread(target=self._start_stream, args=[config]) t.setDaemon(True) t.start() def _start_stream(self, config): if len(config['destdir']) == 0: state_dir = Session.get_default_state_dir() config['destdir'] = os.path.join(state_dir, 'streams') try: config['destdir'] = config['destdir'].decode('utf-8') except: print_exc() if not os.path.isdir(config['destdir']): try: os.makedirs(config['destdir']) except: print_exc() return try: path = os.path.join(config['destdir'], config['name']) if os.path.isfile(path): os.remove(path) except: print_exc() globalConfig.set_mode('stream') sscfg = SessionStartupConfig() statedir = tempfile.mkdtemp() sscfg.set_state_dir(statedir) sscfg.set_listen_port(config['port']) sscfg.set_megacache(False) sscfg.set_overlay(False) sscfg.set_dialback(True) if config['host']: url = 'http://' + str(config['host']) + ':' + str( sscfg.get_listen_port()) + '/announce' sscfg.set_internal_tracker_url(url) s = Session(sscfg) authfilename = os.path.join(config['destdir'], config['name'] + '.sauth') try: authcfg = RSALiveSourceAuthConfig.load(authfilename) except: authcfg = RSALiveSourceAuthConfig() authcfg.save(authfilename) config['protected'] = True provider_key = config['provider-key'] if len( config['provider-key']) else None bitrate = int(config['bitrate']) bitrate *= 125 tdef = TorrentDef() tdef.create_live(config['name'], bitrate, config['duration'], authcfg, config['protected'], provider_key) tdef.set_tracker(s.get_internal_tracker_url()) if config['piecesize'] == 'auto': piece_size = self.get_piece_size(bitrate) else: piece_size = int(config['piecesize']) tdef.set_piece_length(piece_size) print >> sys.stderr, 'bitrate:', config['bitrate'] print >> sys.stderr, 'piece size:', piece_size print >> sys.stderr, 'dest dir:', config['destdir'] print >> sys.stderr, 'tracker url:', s.get_internal_tracker_url() if config['trackers']: trackers = [[s.get_internal_tracker_url()]] for t in config['trackers'].split(','): print >> sys.stderr, 'tracker:', t trackers.append([t]) tdef.set_tracker_hierarchy(trackers) tdef.finalize() print >> sys.stderr, '-------------------' ext = 'acelive' torrentbasename = config['name'] + '.' + ext torrentfilename = os.path.join(config['destdir'], torrentbasename) config['torrentfilename'] = torrentfilename tdef.save(torrentfilename) self.send_torrent_to_server(tdef) dscfg = DownloadStartupConfig() dscfg.set_dest_dir(config['destdir']) source = self.init_source(config['source'], tdef, dscfg) self.source = HaltOnEOFStream(source) restartstatefilename = os.path.join(config['destdir'], config['name'] + '.restart') dscfg.set_video_source(self.source, authcfg, restartstatefilename=restartstatefilename) dscfg.set_max_uploads(config['maxclients']) self.s = s self.statedir = statedir self.config = config self.download = s.start_download(tdef, dscfg) self.download.set_state_callback(self.state_callback, getpeerlist=False) def get_stream_info(self): if self.download is None: return return { 'name': self.config['name'], 'bitrate': self.config['bitrate'], 'tracker_url': self.s.get_internal_tracker_url(), 'speed_source': self.stats.get('speed_source', 0), 'peers': self.stats.get('peers', 0), 'speed_up': self.stats.get('speed_up', 0), 'infohash': binascii.hexlify(self.download.get_def().get_infohash()) } def get_torrent_path(self, infohash): return self.config['torrentfilename'] def OnExit(self): print >> sys.stderr, 'stopping...' for p in self.child_processes: print >> sys.stderr, 'stop child process:', p try: p.kill() except: if DEBUG: print_exc() if self.s is not None: self.s.shutdown() time.sleep(3) if self.statedir is not None: try: shutil.rmtree(self.statedir) except: pass