예제 #1
0
 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)
예제 #2
0
 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)
예제 #3
0
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
예제 #4
0
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