def __init__(self, standalone=False): """ init the upsoon plugin """ _debug_('upsoon.PluginInterface.__init__()', 2) plugin.DaemonPlugin.__init__(self) plugin.register(self, 'upsoon') self.standalone = standalone self.lock = thread.allocate_lock() self.running = True self.timer = Timer(self.timer_handler).start(15) self.event = EventHandler(self.event_handler) #self.event.register(('VIDEO_START', 'VIDEO_END')) self.event.register() self.recordclient = RecordClient() self.fc = FreevoChannels() self.rdev = config.RADIO_DEVICE self.next_program = None self.seconds_before_announce = 120 self.seconds_before_start = 60 self.pending_lockfile = config.FREEVO_CACHEDIR + '/record.soon' self.tv_lockfile = None # lockfile of recordserver self.stopped = None # flag that tells upsoon what stopped
def __init__(self, app, remote): self.tuner_chidx = 0 # Current channel, index into config.TV_CHANNELS self.app_mode = 'tv' self.fc = FreevoChannels() self.current_vg = None self.xawtv_prog = app self.remote_prog = remote
def __init__(self, standalone=False): """ init the upsoon plugin """ logger.log( 9, 'upsoon.PluginInterface.__init__()') plugin.DaemonPlugin.__init__(self) plugin.register(self, 'upsoon') self.standalone = standalone self.lock = thread.allocate_lock() self.running = True self.timer = Timer(self.timer_handler).start(15) self.event = EventHandler(self.event_handler) #self.event.register(('VIDEO_START', 'VIDEO_END')) self.event.register() self.recordclient = RecordClient() self.fc = FreevoChannels() self.rdev = config.RADIO_DEVICE self.next_program = None self.announced = False self.seconds_before_announce = config.TV_UPSOON_ANNOUNCE self.seconds_before_start = config.TV_UPSOON_BEFORE_START self.pending_lockfile = config.FREEVO_CACHEDIR + '/record.soon' self.tv_lockfile = None # lockfile of recordserver self.stopped = None # flag that tells upsoon what stopped if os.path.exists(self.pending_lockfile): os.remove(self.pending_lockfile) logger.debug('%r lockfile removed', self.pending_lockfile)
def __init__(self): self.ivtv_init = False self.fc = FreevoChannels() self.curr_channel = None self.embed = None self.stack = []
def __init__(self, xine): """ TunerControl constructor """ self.xine = xine self.ivtv_init = False self.fc = FreevoChannels() self.curr_channel = None self.embed = None self.stack = []
class Recorder: def __init__(self): logger.debug('Recorder.__init__()') # Disable this plugin if not loaded by record_server. if string.find(sys.argv[0], 'recordserver') == -1: return logger.info('ACTIVATING GENERIC RECORD PLUGIN') self.fc = FreevoChannels() self.thread = Record_Thread() self.thread.setDaemon(1) self.thread.mode = 'idle' self.thread.start() def Record(self, rec_prog): logger.debug('Record(rec_prog=%r)', rec_prog) vg = self.fc.getVideoGroup(rec_prog.tunerid, False) frequency = self.fc.chanSet(str(rec_prog.tunerid), False, 'record plugin') rec_prog.filename = tv_util.getProgFilename(rec_prog) cl_options = { 'channel' : rec_prog.tunerid, 'frequency' : frequency, 'frequencyMHz' : float(frequency) / 1000, 'filename' : rec_prog.filename, 'base_filename' : os.path.basename(rec_prog.filename), 'title' : rec_prog.title, 'sub-title' : rec_prog.sub_title, 'seconds' : rec_prog.rec_duration, 'start' : rec_prog.start, 'pdc-start' : rec_prog.pdc_start, 'group-type' : vg.group_type } if isinstance(config.VCR_CMD, str) or isinstance(config.VCR_CMD, unicode): self.rec_command = config.VCR_CMD % cl_options elif isinstance(config.VCR_CMD, list) or isinstance(config.VCR_CMD, tuple): self.rec_command = [] for arg in config.VCR_CMD: self.rec_command.append(arg % cl_options) self.thread.mode = 'record' self.thread.prog = rec_prog self.thread.command = self.rec_command self.thread.autokill = float(rec_prog.rec_duration + 10) self.thread.mode_flag.set() logger.debug('Recorder::Record: %s', self.rec_command) def Stop(self): logger.debug('Stop()') self.thread.mode = 'stop' self.thread.mode_flag.set()
class Recorder: def __init__(self): logger.debug("Recorder.__init__()") # Disable this plugin if not loaded by record_server. if string.find(sys.argv[0], "recordserver") == -1: return logger.info("ACTIVATING GENERIC RECORD PLUGIN") self.fc = FreevoChannels() self.thread = Record_Thread() self.thread.setDaemon(1) self.thread.mode = "idle" self.thread.start() def Record(self, rec_prog): logger.debug("Record(rec_prog=%r)", rec_prog) vg = self.fc.getVideoGroup(rec_prog.tunerid, False) frequency = self.fc.chanSet(str(rec_prog.tunerid), False, "record plugin") rec_prog.filename = tv_util.getProgFilename(rec_prog) cl_options = { "channel": rec_prog.tunerid, "frequency": frequency, "frequencyMHz": float(frequency) / 1000, "filename": rec_prog.filename, "base_filename": os.path.basename(rec_prog.filename), "title": rec_prog.title, "sub-title": rec_prog.sub_title, "seconds": rec_prog.rec_duration, "start": rec_prog.start, "pdc-start": rec_prog.pdc_start, "group-type": vg.group_type, } if isinstance(config.VCR_CMD, str) or isinstance(config.VCR_CMD, unicode): self.rec_command = config.VCR_CMD % cl_options elif isinstance(config.VCR_CMD, list) or isinstance(config.VCR_CMD, tuple): self.rec_command = [] for arg in config.VCR_CMD: self.rec_command.append(arg % cl_options) self.thread.mode = "record" self.thread.prog = rec_prog self.thread.command = self.rec_command self.thread.autokill = float(rec_prog.rec_duration + 10) self.thread.mode_flag.set() logger.debug("Recorder::Record: %s", self.rec_command) def Stop(self): logger.debug("Stop()") self.thread.mode = "stop" self.thread.mode_flag.set()
def __init__(self): # Disable this plugin if not loaded by record_server. if string.find(sys.argv[0], 'recordserver') == -1: return if DEBUG: print 'ACTIVATING GENERIC RECORD PLUGIN' self.fc = FreevoChannels() self.thread = Record_Thread() self.thread.setDaemon(1) self.thread.mode = 'idle' self.thread.start()
def __init__(self, manager): """ Initialise the recording thread passing in the DVBStreamerControl object to use to control instances of dvbstreamer. """ threading.Thread.__init__(self) self.fc = FreevoChannels() self.manager = manager self.mode = 'idle' self.mode_flag = threading.Event() self.prog = None self.app = None
def __init__(self, manager, path, size): self.name = 'vlc' self.app_mode = 'tv' self.app = None self.adapter_in_use = -1 self.fc = FreevoChannels() self.path = path self.size = size self.buffer = ring_buffer.RingBuffer(size, path) self.last_channel = None self.subtitles = False self.paused = False self.stop_time = 0 self.state = STATE_IDLE self.manager = manager self.udp_receiver = UDPReceiver(self.buffer, WAIT_FOR_DATA_TIMEOUT) self.slave_server = SlaveServer(self.buffer, self) self.fill = 0 self.cur_audio = None self.cur_sub = None self.cur_audiodev = None self.lastchan = None self.timer = kaa.Timer(self.__update_data_from_vlc) self.timer_start = kaa.OneShotTimer( self.__update_data_from_vlc) self.timer_disablebuffering = kaa.OneShotTimer( self.disable_buffering) if hasattr(config, 'LIVE_PAUSE_BUFFER_TIMEOUT'): self. buffering_timeout=config.LIVE_PAUSE_BUFFER_TIMEOUT else: # Disable after 5min if not LIVE_PAUSE_BUFFERING_TIMEOUT self.buffering_timeout= 5 * 60 # Create the command used to start vlc. # NOTE: We add the slave server MRL twice so that we can toggle between # them, this allows use to effectively reset vlc rendering pipeline and # make it possible to seek quickly. self.command = [ '--prio=%s' % config.MPLAYER_NICE ] + \ config.VLC_COMMAND.split(' ') + \ [ '--intf', 'rc' ] + \ ['--no-interact','--rc-fake-tty'] + \ [ '--sub-filter' ,'marq' ] + \ [ '--marq-marquee' ,'Playing' ] + \ [ '--marq-position','4'] + \ [ '--fullscreen', self.slave_server.get_vlc_mrl(), self.slave_server.get_vlc_mrl()] if not rc.PYLIRC and '--no-lirc' in self.command: self.command.remove('--no-lirc') self.udp_receiver.start() self.slave_server.start()
def __init__(self, type): self.name = 'xine' self.app_mode = 'tv' self.xine_type = type self.app = None self.fc = FreevoChannels() self.command = [ '--prio=%s' % config.MPLAYER_NICE ] + \ config.XINE_COMMAND.split(' ') + \ [ '--stdctl', '-V', config.XINE_VO_DEV, '-A', config.XINE_AO_DEV ] + \ config.XINE_ARGS_DEF.split(' ')
def __init__(self): # Disable this plugin if not loaded by record_server. if string.find(sys.argv[0], 'recordserver') == -1: return if DEBUG: print 'ACTIVATING VBI2SRT RECORD PLUGIN' self.vg = None self.fc = FreevoChannels() self.tuner_chidx = 0 # Current channel, index into config.TV_CHANNELS self.thread = Record_Thread() self.thread.setDaemon(1) self.thread.mode = 'idle' self.thread.start()
def run(self): logger.log( 9, 'Record_Thread.run()') while 1: logger.debug('mode=%s', self.mode) if self.mode == 'idle': self.mode_flag.wait() self.mode_flag.clear() elif self.mode == 'record': rc.post_event(Event('RECORD_START', arg=self.prog)) fc = FreevoChannels() logger.debug('channel %s', fc.getChannel()) self.vg = fc.getVideoGroup(self.prog.tunerid, False) v = tv.ivtv.IVTV(self.vg.vdev) v.init_settings() logger.debug('Using video device=%r', self.vg.vdev) logger.debug('Setting Channel to %r', self.prog.tunerid) fc.chanSet(str(self.prog.tunerid), False) logger.debug('command %r', self.command) self.app = RecordApp(self.command) logger.debug('command pid: %s', self.app.child.pid) while self.mode == 'record' and self.app.isAlive(): self.autokill -= 0.5 time.sleep(0.5) if self.autokill <= 0: logger.debug('autokill timeout, stopping recording') self.mode = 'stop' if self.app.isAlive(): # might not want to do this is PDC is valid, programme may be delayed logger.debug('past wait!!') self.app.kill() rc.post_event(Event('RECORD_STOP', arg=self.prog)) logger.debug('finished recording') self.mode = 'idle' else: self.mode = 'idle' time.sleep(0.5)
def __init__(self): """ init the upsoon plugin """ _debug_('__init__(self)', 2) plugin.DaemonPlugin.__init__(self) self.lock = thread.allocate_lock() self.poll_interval = 1500 #15 secs self.poll_menu_only = 0 self.event_listener = 1 plugin.register(self, 'upsoon') server_string = 'http://%s:%s/' % (config.RECORDSERVER_IP, config.RECORDSERVER_PORT) _debug_('%s' % server_string) self.server = xmlrpclib.Server(server_string, allow_none=1) _debug_('%s' % self.server) self.serverup = None self.next_program = self.findNextProgram() _debug_('%s' % (self.next_program)) self.fc = FreevoChannels() self.seconds_before_announce = 120 self.seconds_before_start = 60 self.pending_lockfile = config.FREEVO_CACHEDIR + '/record.soon' self.tv_lockfile = None # lockfile of recordserver self.stopped = False # flag that tells upsoon stopped the tv, not the user
def __init__(self, app, remote): self.tuner_chidx = 0 # Current channel, index into config.TV_CHANNELS self.event_context = 'tv' self.fc = FreevoChannels() self.current_vg = None self.xawtv_prog = app self.remote_prog = remote
def __init__(self, xine): """ TunerControl constructor """ self.xine = xine self.ivtv_init = False self.fc = FreevoChannels() self.curr_channel = None self.embed = None self.stack = [ ]
def play(self, arg=None, menuw=None): """ Start watching TV """ logger.log(9, 'play(arg=%r, menuw=%r)', arg, menuw) # watching TV should only be possible from the guide if not self.context == 'guide': rc.post_event(MENU_SELECT) return now = time.time() if menuw: menuw.delete_submenu() # Check if the selected program is >7 min in the future if self.prog.start > now + (7 * 60): if menuw: menuw.show() # this program is in the future if self.scheduled: msgtext = _( 'Do you want to remove the Program from the record schedule?' ) confirmbtn = _('Remove') else: msgtext = _( 'This Program is in the future. Do you want to record it?') confirmbtn = _('Record') dialog.show_confirmation(msgtext, lambda: self.toggle_rec(menuw=menuw), proceed_text=confirmbtn) return else: # check if the device is free fc = FreevoChannels() # for that we need the name of the lock file suffix = fc.getVideoGroup(self.prog.channel_id, True, CHANNEL_ID).vdev suffix = suffix.split('/')[-1] tvlockfile = config.FREEVO_CACHEDIR + '/record.' + suffix if os.path.exists(tvlockfile): if menuw: menuw.show() # XXX: In the future add the options to watch what we are # recording or cancel it and watch TV. msgtext = _('Sorry, you cannot watch TV while recording. ') msgtext += _('If this is not true then remove ') msgtext += tvlockfile + '.' dialog.show_alert(msgtext) else: # everything is ok, we can start watching! self.parent.hide() self.parent.player('tv', self.prog.channel_id)
class Record_Thread(threading.Thread): """ Thread class that actually does the recording. """ def __init__(self, manager): """ Initialise the recording thread passing in the DVBStreamerControl object to use to control instances of dvbstreamer. """ threading.Thread.__init__(self) self.fc = FreevoChannels() self.manager = manager self.mode = 'idle' self.mode_flag = threading.Event() self.prog = None self.app = None def run(self): """ Thread loop. """ while 1: if DEBUG: print('Record_Thread::run: mode=%s' % self.mode) if self.mode == 'idle': self.mode_flag.wait() self.mode_flag.clear() elif self.mode == 'record': rc.post_event(Event('RECORD_START', arg=self.prog)) if DEBUG: print('Record_Thread::run: started recording') prog = self.prog filename = tv_util.getProgFilename(prog) vg = self.fc.getVideoGroup(prog.tunerid, False) adapter = vg.vdev seconds = prog.rec_duration # Select the channel and start streaming to the file. self.manager.select(adapter, prog.tunerid) self.manager.enable_file_output(adapter,filename) while (self.mode == 'record') and (seconds > 0): seconds -= 0.5 time.sleep(0.5) # Close the file self.manager.disable_output(adapter) rc.post_event(Event('RECORD_STOP', arg=self.prog)) if DEBUG: print('Record_Thread::run: finished recording') self.mode = 'idle' else: self.mode = 'idle' time.sleep(0.5)
class Record_Thread(threading.Thread): """ Thread class that actually does the recording. """ def __init__(self, manager): """ Initialise the recording thread passing in the DVBStreamerControl object to use to control instances of dvbstreamer. """ threading.Thread.__init__(self) self.fc = FreevoChannels() self.manager = manager self.mode = 'idle' self.mode_flag = threading.Event() self.prog = None self.app = None def run(self): """ Thread loop. """ while 1: if DEBUG: print('Record_Thread::run: mode=%s' % self.mode) if self.mode == 'idle': self.mode_flag.wait() self.mode_flag.clear() elif self.mode == 'record': rc.post_event(Event('RECORD_START', arg=self.prog)) if DEBUG: print('Record_Thread::run: started recording') prog = self.prog filename = tv_util.getProgFilename(prog) vg = self.fc.getVideoGroup(prog.channel_id, False) adapter = int(vg.vdev) seconds = prog.rec_duration # Select the channel and start streaming to the file. self.manager.select(adapter, prog.tunerid) self.manager.enable_file_output(adapter, filename) while (self.mode == 'record') and (seconds > 0): seconds -= 0.5 time.sleep(0.5) # Close the file self.manager.disable_output(adapter) rc.post_event(Event('RECORD_STOP', arg=self.prog)) if DEBUG: print('Record_Thread::run: finished recording') self.mode = 'idle' else: self.mode = 'idle' time.sleep(0.5)
def writeTvtimeXML(self): tvtimexml = os.path.join(os.environ['HOME'], '.tvtime', 'tvtime.xml') configcmd = os.path.join(os.path.dirname(config.TVTIME_CMD), "tvtime-configure") #cf_norm, cf_input, cf_clist, cf_device = config.TV_SETTINGS.split() fc = FreevoChannels() vg = fc.getVideoGroup(config.TV_CHANNELS[0][2], True) cf_norm = vg.tuner_norm cf_input = vg.input_num cf_device = vg.vdev s_norm = cf_norm.upper() daoptions = '' if os.path.isfile(tvtimexml): daoptions = ' -F ' + tvtimexml if self.xmltv_supported: daoptions += ' -d %s -n %s -t %s' % (cf_device, s_norm, config.XMLTV_FILE) else: daoptions += ' -d %s -n %s' % (cf_device, s_norm) if hasattr(config, "TV_TVTIME_SETUP_OPTS") and config.TV_TVTIME_SETUP_OPTS: daoptions += ' %s' % config.TV_TVTIME_SETUP_OPTS os.system(configcmd+daoptions)
def __init__(self): super(LocalBackend, self).__init__() self.fc = FreevoChannels() self.livepause_app = None self.controller = None self.device_in_use = None self.last_channel = None self.mode = 'raw' self.events_enabled = False
def play(self, arg=None, menuw=None): """ Start watching TV """ logger.log( 9, 'play(arg=%r, menuw=%r)', arg, menuw) # watching TV should only be possible from the guide if not self.context == 'guide': rc.post_event(MENU_SELECT) return now = time.time() if menuw: menuw.delete_submenu() # Check if the selected program is >7 min in the future if self.prog.start > now + (7*60): if menuw: menuw.show() # this program is in the future if self.scheduled: msgtext= _('Do you want to remove the Program from the record schedule?') confirmbtn = _('Remove') else: msgtext = _('This Program is in the future. Do you want to record it?') confirmbtn = _('Record') dialog.show_confirmation(msgtext, lambda: self.toggle_rec(menuw=menuw), proceed_text=confirmbtn) return else: # check if the device is free fc = FreevoChannels() # for that we need the name of the lock file suffix = fc.getVideoGroup(self.prog.channel_id, True, CHANNEL_ID).vdev suffix = suffix.split('/')[-1] tvlockfile = config.FREEVO_CACHEDIR + '/record.'+suffix if os.path.exists(tvlockfile): if menuw: menuw.show() # XXX: In the future add the options to watch what we are # recording or cancel it and watch TV. msgtext = _('Sorry, you cannot watch TV while recording. ') msgtext += _('If this is not true then remove ') msgtext += tvlockfile + '.' dialog.show_alert(msgtext) else: # everything is ok, we can start watching! self.parent.hide() self.parent.player('tv', self.prog.channel_id)
def __init__(self): logger.debug('Recorder.__init__()') # Disable this plugin if not loaded by record_server. if string.find(sys.argv[0], 'recordserver') == -1: return logger.info('ACTIVATING GENERIC RECORD PLUGIN') self.fc = FreevoChannels() self.thread = Record_Thread() self.thread.setDaemon(1) self.thread.mode = 'idle' self.thread.start()
def __init__(self, type, version, manager, path, size): self.name = 'xine' self.app_mode = 'tv' self.xine_type = type self.version = version self.app = None self.adapter_in_use = -1 self.fc = FreevoChannels() self.path = path self.size = size self.buffer = ring_buffer.RingBuffer(size, path) self.last_channel = None self.subtitles = False self.paused = False self.stop_time = 0 self.state = STATE_IDLE self.manager = manager self.udp_receiver = UDPReceiver(self.buffer, WAIT_FOR_DATA_TIMEOUT) self.slave_server = SlaveServer(self.buffer, self) # Create the command used to start xine. # NOTE: We add the slave server MRL twice so that we can toggle between # them, this allows use to effectively reset Xine rendering pipeline and # make it possible to seek quickly. self.command = [ '--prio=%s' % config.MPLAYER_NICE ] + \ config.XINE_COMMAND.split(' ') + \ [ '--stdctl', '-V', config.XINE_VO_DEV, '-A', config.XINE_AO_DEV ] + \ config.XINE_ARGS_DEF.split(' ') + \ [self.slave_server.get_xine_mrl(), self.slave_server.get_xine_mrl()] if not rc.PYLIRC and '--no-lirc' in self.command: self.command.remove('--no-lirc') self.udp_receiver.start() self.slave_server.start()
def __init__(self, start_time, player, menuw): Item.__init__(self) self.n_items, hours_per_page = skin.items_per_page(('tv', self)) stop_time = start_time + hours_per_page * 60 * 60 msgtext = _('Preparing the program guide') guide = epg_xmltv.get_guide(PopupBox(text=msgtext)) channels = guide.GetPrograms(start=start_time + 1, stop=stop_time - 1) if not channels: AlertBox(text=_('TV Guide is corrupt!')).show() return selected = None for chan in channels: if chan.programs: selected = chan.programs[0] break self.col_time = 30 # each col represents 30 minutes self.n_cols = (stop_time - start_time) / 60 / self.col_time self.player = player self.type = 'tv' self.menuw = menuw self.visible = True self.select_time = start_time self.last_update = 0 self.lastinput_value = None self.lastinput_time = None self.update_schedules(force=True) self.fc = FreevoChannels() self.rebuild(start_time, stop_time, guide.chan_list[0].id, selected) self.event_context = 'tvmenu' menuw.pushmenu(self)
def __init__(self, manager): """ Initialise the recorder passing in the DVBStreamerControl object to use to control instances of dvbstreamer. """ # Disable this plugin if not loaded by record_server. if sys.argv[0].find('recordserver') == -1: return self.fc = FreevoChannels() self.thread = Record_Thread(manager) self.thread.setDaemon(1) self.thread.mode = 'idle' self.thread.start()
def __init__(self, type): self.name = 'xine' self.event_context = 'tv' self.xine_type = type self.app = None self.fc = FreevoChannels() self.command = [ '--prio=%s' % config.MPLAYER_NICE ] + \ config.XINE_COMMAND.split(' ') + \ [ '--stdctl', '-V', config.XINE_VO_DEV, '-A', config.XINE_AO_DEV ] + \ config.XINE_ARGS_DEF.split(' ')
def run(self): while 1: if DEBUG: print('Record_Thread::run: mode=%s' % self.mode) if self.mode == 'idle': self.mode_flag.wait() self.mode_flag.clear() elif self.mode == 'record': rc.post_event(Event('RECORD_START', arg=self.prog)) if DEBUG: print 'Record_Thread::run: started recording' fc = FreevoChannels() if DEBUG: print 'CHAN: %s' % fc.getChannel() (v_norm, v_input, v_clist, v_dev) = config.TV_SETTINGS.split() v = tv.ivtv.IVTV(v_dev) v.init_settings() vg = fc.getVideoGroup(self.prog.tunerid, False) if DEBUG: print 'Setting Input to %s' % vg.input_num v.setinput(vg.input_num) if DEBUG: print 'Setting Channel to %s' % self.prog.tunerid fc.chanSet(str(self.prog.tunerid), False) if DEBUG: v.print_settings() now = time.time() stop = now + self.prog.rec_duration time.sleep(2) v_in = open(v_dev, 'r') v_out = open(self.prog.filename, 'w') while time.time() < stop: buf = v_in.read(CHUNKSIZE) v_out.write(buf) if self.mode == 'stop': break v_in.close() v_out.close() v.close() v = None self.mode = 'idle' rc.post_event(Event('RECORD_STOP', arg=self.prog)) if DEBUG: print('Record_Thread::run: finished recording') else: self.mode = 'idle' time.sleep(0.5)
def __init__(self): logger.log( 9, 'Recorder.__init__()') # Disable this plugin if not loaded by record_server. if string.find(sys.argv[0], 'recordserver') == -1: return logger.info('ACTIVATING VBI2SRT RECORD PLUGIN') self.vg = None self.fc = FreevoChannels() self.tuner_chidx = 0 # Current channel, index into config.TV_CHANNELS self.thread = Record_Thread() self.thread.setDaemon(1) self.thread.mode = 'idle' self.thread.start()
def run(self): while 1: if DEBUG: print('Record_Thread::run: mode=%s' % self.mode) if self.mode == 'idle': self.mode_flag.wait() self.mode_flag.clear() elif self.mode == 'record': rc.post_event(Event('RECORD_START', arg=self.prog)) if DEBUG: print('Record_Thread::run: cmd=%s' % self.command) fc = FreevoChannels() if DEBUG: print 'CHAN: %s' % fc.getChannel() (v_norm, v_input, v_clist, v_dev) = config.TV_SETTINGS.split() v = tv.ivtv.IVTV(v_dev) v.init_settings() self.vg = fc.getVideoGroup(self.prog.tunerid, False) if DEBUG: print 'Using video device %s' % self.vg.vdev if DEBUG: print 'Setting Input to %s' % self.vg.input_num v.setinput(self.vg.input_num) if DEBUG: print 'Setting Channel to %s' % self.prog.tunerid fc.chanSet(str(self.prog.tunerid), False) if DEBUG: v.print_settings() self.app = RecordApp(self.command) while self.mode == 'record' and self.app.isAlive(): self.autokill -= 0.5 time.sleep(0.5) if self.autokill <= 0: if DEBUG: print 'autokill timeout, stopping recording' self.mode = 'stop' if self.app.isAlive(): # might not want to do this is PDC is valid, programme may be delayed if DEBUG: print('Record_Thread::run: past wait!!') rc.post_event( Event(OS_EVENT_KILL, (self.app.child.pid, 15))) self.app.kill() rc.post_event(Event('RECORD_STOP', arg=self.prog)) if DEBUG: print('Record_Thread::run: finished recording') self.mode = 'idle' else: self.mode = 'idle' time.sleep(0.5)
class Recorder: def __init__(self): # Disable this plugin if not loaded by record_server. if string.find(sys.argv[0], 'recordserver') == -1: return if DEBUG: print 'ACTIVATING GENERIC RECORD PLUGIN' self.fc = FreevoChannels() self.thread = Record_Thread() self.thread.setDaemon(1) self.thread.mode = 'idle' self.thread.start() def Record(self, rec_prog): frequency = self.fc.chanSet(str(rec_prog.tunerid), False, 'record plugin') rec_prog.filename = tv_util.getProgFilename(rec_prog) cl_options = { 'channel': rec_prog.tunerid, 'frequency': frequency, 'frequencyMHz': float(frequency) / 1000, 'filename': rec_prog.filename, 'base_filename': os.path.basename(rec_prog.filename), 'title': rec_prog.title, 'sub-title': rec_prog.sub_title, 'seconds': rec_prog.rec_duration } self.rec_command = config.VCR_CMD % cl_options self.thread.mode = 'record' self.thread.prog = rec_prog self.thread.command = self.rec_command self.thread.autokill = float(rec_prog.rec_duration + 10) self.thread.mode_flag.set() if DEBUG: print('Recorder::Record: %s' % self.rec_command) def Stop(self): self.thread.mode = 'stop' self.thread.mode_flag.set()
def run(self): _debug_('Record_Thread.run()', 2) while 1: _debug_('mode=%s' % self.mode) if self.mode == 'idle': self.mode_flag.wait() self.mode_flag.clear() elif self.mode == 'record': rc.post_event(Event('RECORD_START', arg=self.prog)) fc = FreevoChannels() _debug_('channel %s' % fc.getChannel()) self.vg = fc.getVideoGroup(self.prog.tunerid, False) v = tv.ivtv.IVTV(self.vg.vdev) v.init_settings() _debug_('Using video device=%r' % self.vg.vdev) _debug_('Setting Channel to %r' % self.prog.tunerid) fc.chanSet(str(self.prog.tunerid), False) _debug_('command %r' % self.command) self.app = RecordApp(self.command) _debug_('app child pid: %s' % self.app.child.pid) while self.mode == 'record' and self.app.isAlive(): self.autokill -= 0.5 time.sleep(0.5) if self.autokill <= 0: _debug_('autokill timeout, stopping recording') self.mode = 'stop' if self.app.isAlive(): # might not want to do this is PDC is valid, programme may be delayed _debug_('past wait!!') rc.post_event( Event(OS_EVENT_KILL, (self.app.child.pid, 15))) self.app.kill() rc.post_event(Event('RECORD_STOP', arg=self.prog)) _debug_('finished recording') self.mode = 'idle' else: self.mode = 'idle' time.sleep(0.5)
class Xawtv: __muted = 0 __igainvol = 0 def __init__(self, app, remote): self.tuner_chidx = 0 # Current channel, index into config.TV_CHANNELS self.event_context = 'tv' self.fc = FreevoChannels() self.current_vg = None self.xawtv_prog = app self.remote_prog = remote def TunerSetChannel(self, tuner_channel): for pos in range(len(config.TV_CHANNELS)): channel = config.TV_CHANNELS[pos] if channel[2] == tuner_channel: self.tuner_chidx = pos return print 'ERROR: Cannot find tuner channel "%s" in the TV channel listing' % tuner_channel self.tuner_chidx = 0 def TunerGetChannelInfo(self): '''Get program info for the current channel''' tuner_id = config.TV_CHANNELS[self.tuner_chidx][2] chan_name = config.TV_CHANNELS[self.tuner_chidx][1] chan_id = config.TV_CHANNELS[self.tuner_chidx][0] channels = epg.get_guide().get_programs(time.time(), time.time(), chan_id) if channels and channels[0] and channels[0].programs: start_s = time.strftime(config.TV_TIME_FORMAT, time.localtime(channels[0].programs[0].start)) stop_s = time.strftime(config.TV_TIME_FORMAT, time.localtime(channels[0].programs[0].stop)) ts = '(%s-%s)' % (start_s, stop_s) prog_info = '%s %s' % (ts, channels[0].programs[0].title) else: prog_info = 'No info' return tuner_id, chan_name, prog_info def TunerGetChannel(self): return config.TV_CHANNELS[self.tuner_chidx][2] def TunerNextChannel(self): self.tuner_chidx = (self.tuner_chidx+1) % len(config.TV_CHANNELS) def TunerPrevChannel(self): self.tuner_chidx = (self.tuner_chidx-1) % len(config.TV_CHANNELS) def Play(self, mode, tuner_channel=None, channel_change=0): if tuner_channel != None: try: self.TunerSetChannel(tuner_channel) except ValueError: pass if not tuner_channel: tuner_channel = self.fc.getChannel() vg = self.current_vg = self.fc.getVideoGroup(tuner_channel, True) if not vg.group_type == 'normal': print 'Xawtv only supports normal. "%s" is not implemented' % vg.group_type return if mode == 'tv' or mode == 'vcr': w, h = config.TV_VIEW_SIZE cf_norm = vg.tuner_norm cf_input = vg.input_num cf_device = vg.vdev s_norm = cf_norm.upper() if mode == 'vcr': cf_input = '1' if hasattr(config, "TV_VCR_INPUT_NUM") and config.TV_VCR_INPUT_NUM: cf_input = config.TV_VCR_INPUT_NUM if hasattr(config, "TV_XAWTV_OPTS") and config.TV_XAWTV_OPTS: daoptions = config.TV_XAWTV_OPTS else: daoptions = '-xv -f' command = '%s %s -device %s ' % (self.xawtv_prog, daoptions, cf_device) else: print 'Mode "%s" is not implemented' % mode # BUG ui.message() return self.mode = mode mixer = plugin.getbyname('MIXER') # BUG Mixer manipulation code. # TV is on line in # VCR is mic in # btaudio (different dsp device) will be added later if mixer and config.MIXER_MAJOR_CTRL == 'VOL': mixer_vol = mixer.getMainVolume() mixer.setMainVolume(0) elif mixer and config.MIXER_MAJOR_CTRL == 'PCM': mixer_vol = mixer.getPcmVolume() mixer.setPcmVolume(0) # Start up the TV task self.app=XawtvApp(command, self.remote_prog) if tuner_channel: time.sleep(0.5) self.app.sendcmd('setstation %s' % tuner_channel) #XXX use remote to change the input we want rc.add_app(self) # Suppress annoying audio clicks time.sleep(0.4) # BUG Hm.. This is hardcoded and very unflexible. if mixer and mode == 'vcr': mixer.setMicVolume(config.MIXER_VOLUME_VCR_IN) elif mixer: mixer.setLineinVolume(config.MIXER_VOLUME_TV_IN) mixer.setIgainVolume(config.MIXER_VOLUME_TV_IN) if mixer and config.MIXER_MAJOR_CTRL == 'VOL': mixer.setMainVolume(mixer_vol) elif mixer and config.MIXER_MAJOR_CTRL == 'PCM': mixer.setPcmVolume(mixer_vol) logger.debug('%s: started %s app', time.time(), self.mode) def Stop(self, channel_change=0): mixer = plugin.getbyname('MIXER') if mixer and not channel_change: mixer.setLineinVolume(0) mixer.setMicVolume(0) mixer.setIgainVolume(0) # Input on emu10k cards. self.app.stop() rc.remove_app(self) def eventhandler(self, event, menuw=None): logger.debug('%s: %s app got %s event', time.time(), self.mode, event) if event == em.STOP or event == em.PLAY_END: self.app.sendcmd('quit') time.sleep(1) self.Stop() rc.post_event(em.PLAY_END) return True elif event == em.TV_CHANNEL_UP or event == em.TV_CHANNEL_DOWN: if self.mode == 'vcr': return if event == em.TV_CHANNEL_UP: self.TunerPrevChannel() self.app.sendcmd('setstation next') else: self.TunerNextChannel() self.app.sendcmd('setstation prev') return True elif event == em.TOGGLE_OSD: #try to send channel name self.app.sendcmd('msg \'%s\'' % self.TunerGetChannel()) return True elif event == em.OSD_MESSAGE: self.app.sendcmd('msg \'%s\'' % event.arg) return True elif event in em.INPUT_ALL_NUMBERS: self.app.sendcmd('keypad %s' % event.arg) elif event == em.BUTTON: if event.arg == 'PREV_CH': self.app.sendcmd('setstation back') return True return False
def run(self): logger.log( 9, 'Record_Thread.run()') while 1: logger.debug('Record_Thread::run: mode=%s', self.mode) if self.mode == 'idle': self.mode_flag.wait() self.mode_flag.clear() elif self.mode == 'record': try: logger.info('Record_Thread::run: started recording') fc = FreevoChannels() logger.debug('Channel: %s', fc.getChannel()) vg = fc.getVideoGroup(self.prog.tunerid, False) logger.debug('Opening device %r', vg.vdev) v = tv.ivtv.IVTV(vg.vdev) v.init_settings() logger.debug('Setting input to %r', vg.input_type) v.setinputbyname(vg.input_type) cur_std = v.getstd() try: new_std = V4L2.NORMS.get(vg.tuner_norm) if cur_std != new_std: logger.debug('Setting standard to %s', new_std) v.setstd(new_std) except: logger.error("Videogroup norm value '%s' not from NORMS: %s", vg.tuner_norm, V4L2.NORMS.keys()) logger.debug('Setting channel to %r', self.prog.tunerid) fc.chanSet(str(self.prog.tunerid), False) # Setting the input sound level on the PVR card channel = self.prog.tunerid try: # lookup the channel name in TV_CHANNELS for pos in range(len(config.TV_CHANNELS)): entry = config.TV_CHANNELS[pos] if str(channel) == str(entry[2]): channel_index = pos break except ValueError: pass logger.debug('SetAudioByChannel: Channel: %r TV_CHANNEL pos(%d)', channel, channel_index) try: ivtv_avol = vg.avol except AttributeError: ivtv_avol = 0 if ivtv_avol <= 0: logger.debug('SetAudioByChannel: The tv_video group for %r doesn\'t set the volume', channel) else: # Is there a specific volume level in TV_CHANNELS_VOLUME avol_percent = 100 try: # lookup the channel name in TV_CHANNELS for pos in range(len(config.TV_CHANNELS_VOLUME)): if config.TV_CHANNELS_VOLUME[pos][0] == config.TV_CHANNELS[channel_index][0]: avol_percent = config.TV_CHANNELS_VOLUME[pos][1] break except: pass try: avol_percent = int(avol_percent) except ValueError: avol_percent = 100 avol = int(ivtv_avol * avol_percent / 100) if avol > 65535: avol = 65535 if avol < 0: avol = 0 logger.debug('SetAudioByChannel: Current PVR Sound level is : %s', v.getctrl(0x00980905)) logger.debug('SetAudioByChannel: Set the PVR Sound Level to : %s (%s * %s)', avol, ivtv_avol, avol_percent) v.setctrl(0x00980905, avol) logger.debug('SetAudioByChannel: New PVR Sound level is : %s', v.getctrl(0x00980905)) if vg.cmd != None: logger.debug("Running command %r", vg.cmd) retcode = os.system(vg.cmd) logger.debug("exit code: %g", retcode) now = time.time() stop = now + self.prog.rec_duration rc.post_event(Event('RECORD_START', arg=self.prog)) time.sleep(2) v_in = open(vg.vdev, 'r') v_out = open(self.prog.filename, 'w') logger.debug('Recording from %r to %r in %s byte chunks', vg.vdev, self.prog.filename, CHUNKSIZE) while time.time() < stop: buf = v_in.read(CHUNKSIZE) v_out.write(buf) if self.mode == 'stop': logger.info('Recording stopped') break v_in.close() v_out.close() v.close() v = None self.mode = 'idle' rc.post_event(Event('RECORD_STOP', arg=self.prog)) logger.info('Record_Thread::run: finished recording') except Exception, why: logger.critical('%s', why) return else: self.mode = 'idle' time.sleep(0.5)
def __init__(self, player): self.name = 'livepause' self.event_context = 'tv' self.fc = FreevoChannels() self.backend = backend.get_backend() self.backend.set_mode(player.mode) self.last_channel = None self.stop_time = 0 self.data_started_timer = kaa.OneShotTimer(self.__buffering_data_timedout) self.disable_buffering_timer = kaa.OneShotTimer(self.__disable_buffering_timeout) self.state = State.IDLE self.player = player self.changing_channel = False self.subtitles = None self.subtitle_index = -1 self.audio_langs = None self.audio_lang_index = -1 self.recording = False self.state_dialog = None # Setup Event Maps self.event_maps = {} self.event_maps[State.IDLE] = { 'READER_OVERTAKEN' : self.__idle_reader_overtaken, } self.event_maps[State.TUNING] = { 'DATA_STARTED' : self.__tuning_data_started, 'DATA_TIMEDOUT': self.__tuning_data_timedout, 'PLAY_END' : self.__handle_stop, 'USER_END' : self.__handle_stop, 'STOP' : self.__handle_stop } self.event_maps[State.BUFFERING] = { 'DATA_ACQUIRED': self.__buffering_data_acquired, 'DATA_TIMEDOUT': self.__buffering_data_timedout, 'PLAY_END' : self.__handle_stop, 'USER_END' : self.__handle_stop, 'STOP' : self.__handle_stop } self.event_maps[State.PLAYING] = { 'PLAY' : self.__playing_play_pause, 'PAUSE' : self.__playing_play_pause, 'PLAY_END' : self.__handle_stop, 'USER_END' : self.__handle_stop, 'STOP' : self.__handle_stop, 'TV_CHANNEL_UP' : self.__playing_tv_channel_up, 'TV_CHANNEL_DOWN' : self.__playing_tv_channel_down, 'TV_CHANNEL_NUMBER' : self.__playing_tv_channel_number, 'TV_START_RECORDING' : self.__playing_tv_record, 'SAVE_STARTED' : self.__playing_tv_record_start, 'SAVE_FINISHED' : self.__playing_tv_record_stop, 'BUTTON' : self.__playing_button_pressed, 'TOGGLE_OSD' : self.__playing_display_info, 'SEEK' : self.__playing_seek, 'SECONDS_LEFT' : self.__playing_seconds_left, 'READER_OVERTAKEN' : self.__playing_reader_overtaken, 'DATA_ACQUIRED' : None, 'DATA_TIMEDOUT' : None, 'VIDEO_NEXT_FILLMODE' : None, 'VIDEO_NEXT_AUDIOMODE': None, 'VIDEO_NEXT_AUDIOLANG': None, #self.__playing_toggle_audo_lang, 'VIDEO_NEXT_SUBTITLE' : self.__playing_toggle_subtitles, } self.current_event_map = self.event_maps[self.state]
class TVTime: __muted = 0 __igainvol = 0 def __init__(self): self.event_context = 'tv' self.fc = FreevoChannels() self.current_vg = None self.optionD_supported = False self.xmltv_supported = False def TunerSetChannel(self, tuner_channel): for pos in range(len(config.TV_CHANNELS)): channel = config.TV_CHANNELS[pos] if channel[2] == tuner_channel: return pos print 'ERROR: Cannot find tuner channel "%s" in the TV channel listing' % tuner_channel return 0 def TunerGetChannelInfo(self): return self.fc.getChannelInfo() def TunerGetChannel(self): return self.fc.getChannel() def Play(self, mode, tuner_channel=None, channel_change=0): if not tuner_channel: tuner_channel = self.fc.getChannel() vg = self.current_vg = self.fc.getVideoGroup(tuner_channel, True) if not vg.group_type == 'normal': print 'Tvtime only supports normal. "%s" is not implemented' % vg.group_type return if mode == 'tv' or mode == 'vcr': w, h = config.TV_VIEW_SIZE cf_norm = vg.tuner_norm cf_input = vg.input_num cf_device = vg.vdev s_norm = cf_norm.upper() outputplugin = '' if plugin.getbyname(plugin.TV).optionD_supported: if config.CONF.display == 'x11': outputplugin = 'Xv' elif config.CONF.display == 'mga': outputplugin = 'mga' elif config.CONF.display in ('directfb', 'dfbmga'): outputplugin = 'directfb' else: outputplugin = config.CONF.display outputplugin = '-D %s' % outputplugin if mode == 'vcr': cf_input = '1' if hasattr(config, "TV_VCR_INPUT_NUM") and config.TV_VCR_INPUT_NUM: cf_input = config.TV_VCR_INPUT_NUM self.fc.chan_index = self.TunerSetChannel(tuner_channel) if hasattr(config, 'TV_PAD_CHAN_NUMBERS') and config.TV_PAD_CHAN_NUMBERS: mychan = tuner_channel else: mychan = self.fc.chan_index logger.debug('starting channel is %s', mychan) command = '%s %s -k -I %s -n %s -d %s -f %s -c %s -i %s' % \ (config.TVTIME_CMD, outputplugin, w, s_norm, cf_device, 'freevo', mychan, cf_input) if osd.get_fullscreen() == 1: command += ' -m' else: command += ' -M' else: print 'Mode "%s" is not implemented' % mode # BUG ui.message() return self.mode = mode mixer = plugin.getbyname('MIXER') # BUG Mixer manipulation code. # TV is on line in # VCR is mic in # btaudio (different dsp device) will be added later if mixer and config.MIXER_MAJOR_CTRL == 'VOL': mixer_vol = mixer.getMainVolume() mixer.setMainVolume(0) elif mixer and config.MIXER_MAJOR_CTRL == 'PCM': mixer_vol = mixer.getPcmVolume() mixer.setPcmVolume(0) # Start up the TV task self.app = TVTimeApp(command) rc.add_app(self) # Suppress annoying audio clicks time.sleep(0.4) # BUG Hm.. This is hardcoded and very unflexible. if mixer and mode == 'vcr': mixer.setMicVolume(config.MIXER_VOLUME_VCR_IN) elif mixer: mixer.setLineinVolume(config.MIXER_VOLUME_TV_IN) mixer.setIgainVolume(config.MIXER_VOLUME_TV_IN) if mixer and config.MIXER_MAJOR_CTRL == 'VOL': mixer.setMainVolume(mixer_vol) elif mixer and config.MIXER_MAJOR_CTRL == 'PCM': mixer.setPcmVolume(mixer_vol) logger.debug('%s: started %s app', time.time(), self.mode) def Stop(self, channel_change=0): mixer = plugin.getbyname('MIXER') if mixer and not channel_change: mixer.setLineinVolume(0) mixer.setMicVolume(0) mixer.setIgainVolume(0) # Input on emu10k cards. self.app.stop('quit\n') rc.remove_app(self) def eventhandler(self, event, menuw=None): logger.debug('%s: %s app got %s event', time.time(), self.mode, event) if event == em.STOP or event == em.PLAY_END: self.Stop() rc.post_event(em.PLAY_END) return True elif event == em.TV_CHANNEL_UP or event == em.TV_CHANNEL_DOWN: if self.mode == 'vcr': return if event == em.TV_CHANNEL_UP: nextchan = self.fc.getNextChannel() elif event == em.TV_CHANNEL_DOWN: nextchan = self.fc.getPrevChannel() nextvg = self.fc.getVideoGroup(nextchan, True) logger.debug("nextchan is %s", nextchan) # XXX hazardous to your health. don't use tvtime with anything # other than one normal video_group. # we lose track of the channel index at some points and # chaos ensues #if self.current_vg != nextvg: # self.Stop(channel_change=1) # self.Play('tv', nextchan) # return TRUE self.fc.chanSet(nextchan, True, app=self.app) #self.current_vg = self.fc.getVideoGroup(self.fc.getChannel(), True) # Go to the prev/next channel in the list if event == em.TV_CHANNEL_UP: self.app.write('CHANNEL_UP\n') else: self.app.write('CHANNEL_DOWN\n') return True elif event == em.TOGGLE_OSD: self.app.write('DISPLAY_INFO\n') return True elif event == em.OSD_MESSAGE: # XXX this doesn't work #self.app.write('display_message %s\n' % event.arg) #this does os.system('tvtime-command display_message \'%s\'' % event.arg) return True elif event == em.TV_SEND_TVTIME_CMD: os.system('tvtime-command %s' % event.arg) return True elif event in em.INPUT_ALL_NUMBERS: self.app.write('CHANNEL_%s\n' % event.arg) elif event == em.BUTTON: if event.arg == 'PREV_CH': self.app.write('CHANNEL_PREV\n') return True return False
class TunerControl: """ Class that controls the tuner device """ def __init__(self, xine): """ TunerControl constructor """ self.xine = xine self.ivtv_init = False self.fc = FreevoChannels() self.curr_channel = None self.embed = None self.stack = [] self.timer = OneShotTimer(self.timer_handler) def _kill_(self): """ TunerControl destructor """ if self.embed: ivtv_dev.setvbiembed(self.embed) def program_timer(self): """ program the timer to start of next show on the current channel """ _debug_('TunerControl: Program timer') # set timer to mark the next program start_t, stop_t, prog_s = self.GetInfo() if stop_t > 0: stop_t = stop_t - time.time() self.timer.start(stop_t) _debug_( 'TunerControl: Timer set to mark next program in: %s seconds' % stop_t) else: _debug_('TunerControl: Timer not set, stop_t not available') self.ShowInfo() def timer_handler(self): """ handle timer event """ _debug_('TunerControl: Timer event, mark new show') self.xine.SetMark() self.program_timer() def Stop(self): """ stop """ self.ivtv_init = False def GetName(self): """ get channel name """ tuner_id, chan_name, prog_info = self.fc.getChannelInfo(showtime=True) return prog_info def GetInfo(self): """ get channel info """ tuner_id, chan_id, chan_name, start_t, stop_t, prog_s = self.fc.getChannelInfoRaw( ) return (start_t, stop_t, prog_s) def ShowInfo(self): """ show channel info """ if self.curr_channel != None: # show channel info #vg = self.fc.getVideoGroup(self.curr_channel, True) tuner_id, chan_name, prog_info = self.fc.getChannelInfo( showtime=False) self.xine.ShowMessage(msg='%s: %s' % (chan_name, prog_info)) def PushChannel(self): """ push the current channel on the channel stack """ if self.curr_channel != None: self.stack.append(self.curr_channel) _debug_('TunerControl: Pushed channel %s' % self.curr_channel) _debug_('TunerControl: Channel stack = %s' % self.stack) def UnpushChannel(self): """ remove the top channel fromthe channel stack """ if len(self.stack) == 0: _debug_('TunerControl: Channel stack is empty') else: channel = self.stack.pop() _debug_('TunerControl: Unpushed channel %s' % channel) _debug_('TunerControl: Channel stack = %s' % self.stack) def PopChannel(self): """ pop the top channel from the channel stack and switch channel """ if len(self.stack) == 0: _debug_('TunerControl: Channel stack is empty') else: channel = self.stack.pop() _debug_('TunerControl: Popped channel %s' % channel) self.SetVideoGroup(channel) _debug_('TunerControl: Channel stack = %s' % self.stack) def SetChannelByName(self, channel=None, clearstack=False): """ tune to a new channel by name """ last_channel = self.curr_channel next_channel = None channel_index = -1 if clearstack == True: self.stack = [] self.curr_channel = None if channel == None: # get a channel next_channel = self.fc.getChannel() try: # lookup the channel name in TV_CHANNELS for pos in range(len(config.TV_CHANNELS)): entry = config.TV_CHANNELS[pos] if str(channel) == str(entry[2]): channel_index = pos next_channel = channel break except ValueError: pass if (next_channel == None): _debug_( 'TunerControl: Cannot find tuner channel %r in the TV channel listing' % channel, DWARNING) else: self.SetChannelByIndex(channel_index + 1) def SetChannelByIndex(self, channel): """ tune to a channel by index from the TV_CHANNELS list """ # tune channel by index next_channel = self.fc.getManChannel(channel) _debug_('TunerControl: Explicit channel selection by index = %r' % next_channel) self.PushChannel() self.SetVideoGroup(next_channel) def SetChannelByNumber(self, channel): """ tune to a channel by actual channel number """ # tune channel by number _debug_('TunerControl: Explicit channel selection by number = %r' % channel) self.PushChannel() self.SetVideoGroup(channel) def NextChannel(self): """ jump to the next channel in the TV_CHANNELS list """ next_channel = self.fc.getNextChannel() _debug_('TunerControl: Next channel selection = %r' % next_channel) self.PushChannel() self.SetVideoGroup(next_channel) def PrevChannel(self): """ jump to the previous channel in the TV_CHANNELS list """ prev_channel = self.fc.getPrevChannel() _debug_('TunerControl: Previous channel selection = %r' % prev_channel) self.PushChannel() self.SetVideoGroup(prev_channel) def SetVideoGroup(self, channel): """ select a channel's video group and tune to that channel """ _debug_('TunerControl: Channel: %r' % channel) new_vg = self.fc.getVideoGroup(channel, True) _debug_('TunerControl: Group: type=%r, desc=%r' % (new_vg.group_type, new_vg.desc)) _debug_('TunerControl: Input: type=%r, num=%r' % (new_vg.input_type, new_vg.input_num)) if (new_vg.group_type != 'ivtv'): _debug_( 'TunerControl: Video group %r is not supported' % new_vg.group_type, DERROR) pop = AlertBox( text=_('This plugin only supports the ivtv video group!')) pop.show() return # check if videogroup switch is needed switch_vg = (self.ivtv_init == False) or \ (self.curr_channel == None) or \ (new_vg != self.fc.getVideoGroup(self.curr_channel, True)) if switch_vg == True: # switch to a different video group _debug_('TunerControl: Set video group: %s' % new_vg.vdev, DINFO) ivtv_dev = ivtv.IVTV(new_vg.vdev) ivtv_dev.init_settings() self.xine.SetInput(new_vg.input_num) # disable embedded vbi data self.embed = ivtv_dev.getvbiembed() ivtv_dev.setvbiembed(0) if self.ivtv_init == False: # set channel directly on v4l device self.ivtv_init = True self.fc.chanSet(channel, True) self.curr_channel = channel if config.XINE_TV_LIVE_RECORD: # video stream is marked implicitly # start timer to mark next show self.program_timer() else: self.ShowInfo() else: # set channel through xine process # get channel frequency freq = self.fc.chanSet(channel, True, 'ivtv_xine_tv', None) if freq != 0: # channel has frequency _debug_('TunerControl: Set frequency: %s' % freq) self.xine.SetFrequency(freq) else: # channel has no frequency _debug_('TunerControl: Channel has no frequency') self.curr_channel = channel if config.XINE_TV_LIVE_RECORD: # explicitly mark video stream self.xine.SetMark() # start timer to mark next show self.program_timer() else: self.xine.SeekEnd() self.ShowInfo()
class TunerControl: """ Class that controls the tuner device """ def __init__(self, xine): """ TunerControl constructor """ self.xine = xine self.ivtv_init = False self.fc = FreevoChannels() self.curr_channel = None self.embed = None self.stack = [ ] def _kill_(self): """ TunerControl destructor """ if self.embed: ivtv_dev.setvbiembed(self.embed) def Stop(self): """ stop """ self.ivtv_init = False def GetChannelName(self): """ get channel info """ tuner_id, chan_name, prog_info = self.fc.getChannelInfo(showtime=False) return (chan_name) def GetProgramName(self): """ get channel name """ tuner_id, chan_name, prog_info = self.fc.getChannelInfo(showtime=True) return prog_info def GetInfo(self): """ get channel info """ tuner_id, chan_id, chan_name, start_t, stop_t, prog_s = self.fc.getChannelInfoRaw() return (start_t, stop_t, prog_s) def ShowInfo(self): """ show channel info """ if self.curr_channel is not None: tuner_id, chan_name, prog_info = self.fc.getChannelInfo(showtime=False) self.xine.ShowMessage(msg = '%s: %s' % (chan_name, prog_info)) def PushChannel(self): """ push the current channel on the channel stack """ if self.curr_channel is not None: self.stack.append(self.curr_channel) logger.debug('TunerControl: Pushed channel %s', self.curr_channel) logger.debug('TunerControl: Channel stack = %s', self.stack) def UnpushChannel(self): """ remove the top channel from the channel stack """ if len(self.stack) == 0: logger.debug('TunerControl: Channel stack is empty') else: channel = self.stack.pop() logger.debug('TunerControl: Unpushed channel %s', channel) logger.debug('TunerControl: Channel stack = %s', self.stack) def PopChannel(self): """ pop the top channel from the channel stack and switch channel """ if len(self.stack) == 0: logger.debug('TunerControl: Channel stack is empty') else: channel = self.stack.pop() logger.debug('TunerControl: Popped channel %s', channel) self.SetVideoGroup(channel) logger.debug('TunerControl: Channel stack = %s', self.stack) def SwapChannel(self): """swap the current display channel and the top of the stack channel """ if self.curr_channel is not None: toswap = self.curr_channel if len(self.stack) == 0: logger.debug('TunerControl: Channel stack is empty') else: channel = self.stack.pop() logger.debug('TunerControl: Popped channel %s', channel) self.SetVideoGroup(channel) self.stack.append(toswap) logger.debug('TunerControl: Pushed channel %s', toswap) logger.debug('TunerControl: Channel stack = %s', self.stack) def SetChannelByName(self, channel=None, clearstack=False): """ tune to a new channel by name """ last_channel = self.curr_channel next_channel = None channel_index = -1 if clearstack: self.stack = [ ] self.curr_channel = None if channel is None: # get a channel next_channel = self.fc.getChannel() try: # lookup the channel name in TV_CHANNELS for pos in range(len(config.TV_CHANNELS)): entry = config.TV_CHANNELS[pos] if str(channel) == str(entry[2]): channel_index = pos next_channel = channel break except ValueError: pass if next_channel is None: logger.warning('TunerControl: Cannot find tuner channel %r in the TV channel listing', channel) else: self.SetChannelByIndex(channel_index + 1) def SetChannelByIndex(self, channel, tvlike=0): """ tune to a channel by index from the TV_CHANNELS list """ next_channel = self.fc.getManChannel(channel, tvlike) logger.debug('TunerControl: Explicit channel selection by index = %r', next_channel) self.PushChannel() self.SetVideoGroup(next_channel) def SetChannelByNumber(self, channel): """ tune to a channel by actual channel number """ logger.debug('TunerControl: Explicit channel selection by number = %r', channel) self.PushChannel() self.SetVideoGroup(channel) def NextChannel(self): """ jump to the next channel in the TV_CHANNELS list """ next_channel = self.fc.getNextChannel() logger.debug('TunerControl: Next channel selection = %r', next_channel) self.PushChannel() self.SetVideoGroup(next_channel) def PrevChannel(self): """ jump to the previous channel in the TV_CHANNELS list """ prev_channel = self.fc.getPrevChannel() logger.debug('TunerControl: Previous channel selection = %r', prev_channel) self.PushChannel() self.SetVideoGroup(prev_channel) def SetVideoGroup(self, channel): """ select a channel's video group and tune to that channel """ try: channel_num = int(channel) except ValueError: channel_num = 0 logger.debug('TunerControl: Channel: %r', channel) new_vg = self.fc.getVideoGroup(channel, True) logger.debug('TunerControl: Group: type=%r, desc=%r', new_vg.group_type, new_vg.desc) logger.debug('TunerControl: Input: type=%r, num=%r', new_vg.input_type, new_vg.input_num) if new_vg.group_type != 'ivtv': logger.error('TunerControl: VideoGroup %s is not supported', new_vg) pop = AlertBox(text=_('This plugin only supports the ivtv video group!')) pop.show() return # check if videogroup switch is needed switch_vg = not self.ivtv_init or self.curr_channel is None or \ new_vg != self.fc.getVideoGroup(self.curr_channel, True) if switch_vg: # switch to a different video group logger.info('TunerControl: Set VideoGroup: %s', new_vg) ivtv_dev = ivtv.IVTV(new_vg.vdev) ivtv_dev.init_settings() self.xine.SetInput(new_vg.input_num) # disable embedded vbi data self.embed = ivtv_dev.getvbiembed() ivtv_dev.setvbiembed(0) if not self.ivtv_init: # set channel directly on v4l device, if channel is not negative if channel_num >= 0: self.fc.chanSet(channel, True) self.curr_channel = channel self.ivtv_init = True else: # set channel through xine process freq = self.fc.chanSet(channel, True, 'ivtv_xine_tv', None) if freq != 0: # channel has frequency logger.debug('TunerControl: Set frequency: %s', freq) self.xine.SetFrequency(freq) else: # channel has no frequency logger.debug('TunerControl: Channel has no frequency') self.curr_channel = channel self.xine.SeekEnd() self.ShowInfo() self.SetAudioByChannel(channel) def SetAudioByChannel(self, channel=-1): """ Set the PVR sound level This is a mix : The base volume is set by the avol option in each TV_VIDEO_GROUP. The value is hardware dependant. seems bo be between 0 and 65535. If this value is missing in the tv_video_group, that sub does nothing If the value is present, the actual audio value is this value time the 6th field in TV_CHANNELS (expressed in % ) """ try: # lookup the channel name in TV_CHANNELS for pos in range(len(config.TV_CHANNELS)): entry = config.TV_CHANNELS[pos] if str(channel) == str(entry[2]): channel_index = pos break except ValueError: pass logger.debug('SetAudioByChannel: Channel: %r TV_CHANNEL pos(%d)', channel, channel_index) vg = self.fc.getVideoGroup(channel, True) try: ivtv_avol = vg.avol except AttributeError: ivtv_avol = 0 if ivtv_avol <= 0: logger.debug('SetAudioByChannel: The tv_video group for %r doesn\'t set the volume', channel) else: # Is there a specific volume level in TV_CHANNELS_VOLUME ivtv_dev = ivtv.IVTV(vg.vdev) avol_percent = 100 try: # lookup the channel name in TV_CHANNELS for pos in range(len(config.TV_CHANNELS_VOLUME)): if config.TV_CHANNELS_VOLUME[pos][0] == config.TV_CHANNELS[channel_index][0]: avol_percent = config.TV_CHANNELS_VOLUME[pos][1] break except: pass try: avol_percent = int(avol_percent) except ValueError: avol_percent = 100 avol = int(ivtv_avol * avol_percent / 100) if avol > 65535: avol = 65535 if avol < 0: avol = 0 logger.debug('SetAudioByChannel: Current PVR Sound level is : %s', ivtv_dev.getctrl(0x00980905)) logger.debug('SetAudioByChannel: Set the PVR Sound Level to : %s (%s * %s)', avol, ivtv_avol, avol_percent) ivtv_dev.setctrl(0x00980905, avol) logger.debug('SetAudioByChannel: New PVR Sound level is : %s', ivtv_dev.getctrl(0x00980905))
def __init__(self): self.event_context = 'tv' self.fc = FreevoChannels() self.current_vg = None self.optionD_supported = False self.xmltv_supported = False
class LocalBackend(Backend): """ Class used to control tuning and the ringbuffer locally. """ def __init__(self): super(LocalBackend, self).__init__() self.fc = FreevoChannels() self.livepause_app = None self.controller = None self.device_in_use = None self.last_channel = None self.mode = 'raw' self.events_enabled = False def get_server_address(self): return 'localhost' def set_mode(self, mode): if self.livepause_app: self.livepause_app.set_mode(mode) self.mode = mode def get_buffer_info(self): if self.livepause_app: return self.livepause_app.info() return (0.0,0,0,0) def set_events_enabled(self, enable): if self.livepause_app: self.livepause_app.events_enabled = enable self.events_enabled = enable def seekto(self, to_time): if self.livepause_app: self.livepause_app.seekto(to_time) def seek(self, time_delta, now=False): if self.livepause_app: self.livepause_app.seek(time_delta, now) def disable_buffering(self): if self.device_in_use: self.last_channel = None self.controller.stop_filling() self.controller = None self.device_in_use = None self.livepause_app.quit() self.livepause_app = None logger.debug('Buffering disabled.') def change_channel(self, channel): if self.last_channel == channel: # Already tune to this channel so nothing to do! return if self.device_in_use: self.controller.stop_filling() self.controller = None self.device_in_use = None if self.livepause_app is None: self.livepause_app = LivePauseApp(config.CONF.livepause, config.LIVE_PAUSE2_BUFFER_PATH, config.LIVE_PAUSE2_BUFFER_SIZE, config.LIVE_PAUSE2_PORT, self.send_event) self.livepause_app.set_mode(self.mode) self.livepause_app.events_enabled = self.events_enabled # Find the controller for this VideoGroup type vg = self.fc.getVideoGroup(channel, True) self.controller = controllers.get_controller(vg.group_type) if not self.controller: logger.debug('Failed to find controller for device') return self.fc.chanSet(channel, True) self.livepause_app.reset() self.livepause_app.events_enabled = True self.controller.start_filling(self.livepause_app, vg, channel, WAIT_FOR_DATA_TIMEOUT) self.device_in_use = vg self.last_channel = channel def save(self, filename, time_start, time_end): if self.livepause_app: self.livepause_app.save(filename, time_start, time_end) def cancelsave(self): if self.livepause_app: self.livepause_app.cancel_save() def send_event(self, to_send): to_send.post()
# test code, run with freevo execute /path/to/upsoon.py config.DEBUG = 2 function = None if len(sys.argv) > 1: function = sys.argv[1].lower() server = RecordClient() if function == 'run': #import rc as rctrl #rc = rctrl.get_singleton(False) pi = PluginInterface() kaa.main.run() elif function == 'findnextprogram': def handler(result): print 'findnextprogram=%r' % (result,) print result.__dict__ raise SystemExit server.findNextProgram(handler) kaa.main.run() else: fc = FreevoChannels() vg=fc.getVideoGroup('K10', False) print 'vg=%s' % vg print 'dir(%s)' % dir(vg) for it in dir(vg): print ' %s:%s' % (it, eval('vg.'+it)) vdev=vg.vdev print 'vdev=%s' % vdev
def __init__(self): self.tuner_chidx = 0 # Current channel, index into config.TV_CHANNELS self.event_context = 'tv' self.fc = FreevoChannels() self.current_vg = None
class MPlayer: __muted = 0 __igainvol = 0 def __init__(self): self.tuner_chidx = 0 # Current channel, index into config.TV_CHANNELS self.event_context = 'tv' self.fc = FreevoChannels() self.current_vg = None def Play(self, mode, tuner_channel=None): """ """ logger.log( 9, 'MPlayer.Play(mode=%r, tuner_channel=%r)', mode, tuner_channel) # Try to see if the channel is not tunable try: channel = int(tuner_channel) except ValueError: channel = 0 vg = self.current_vg = self.fc.getVideoGroup(tuner_channel, True) if not tuner_channel: tuner_channel = self.fc.getChannel() # Convert to MPlayer TV setting strings device = 'device=%s' % vg.vdev input = 'input=%s' % vg.input_num norm = 'norm=%s' % vg.tuner_norm w, h = config.TV_VIEW_SIZE outfmt = 'outfmt=%s' % config.TV_VIEW_OUTFMT # Build the MPlayer command line args = { 'nice': config.MPLAYER_NICE, 'cmd': config.MPLAYER_CMD, 'vo': '-vo %s' % config.MPLAYER_VO_DEV, 'vo_opts': config.MPLAYER_VO_DEV_OPTS, 'vc': '', 'ao': '-ao %s' % config.MPLAYER_AO_DEV, 'ao_opts': config.MPLAYER_AO_DEV_OPTS, 'default_args': config.MPLAYER_ARGS_DEF.split(), 'mode_args': config.MPLAYER_ARGS.has_key(mode) and config.MPLAYER_ARGS[mode].split() or [], 'geometry': (config.CONF.x or config.CONF.y) and '-geometry %d:%d' % (config.CONF.x, config.CONF.y) or '', 'verbose': '', 'dvd-device': '', 'cdrom-device': '', 'alang': '', 'aid': '', 'slang': '', 'sid': '', 'playlist': '', 'field-dominance': '', 'edl': '', 'mc': '', 'delay': '', 'sub': '', 'audiofile': '', 'af': [], 'vf': [], 'tv': '', 'url': '', 'disable_osd': False, } if dialog.overlay_display_supports_dialogs: # Disable the mplayer OSD if we have a better option. args['disable_osd'] = True if mode == 'tv': if vg.group_type == 'ivtv': ivtv_dev = ivtv.IVTV(vg.vdev) ivtv_dev.init_settings() ivtv_dev.setinputbyname(vg.input_type) cur_std = ivtv_dev.getstd() import tv.v4l2 try: new_std = tv.v4l2.NORMS.get(vg.tuner_norm) if cur_std != new_std: ivtv_dev.setstd(new_std) except: logger.error('Error! Videogroup norm value "%s" not from NORMS: %s', vg.tuner_norm, tv.v4l2.NORMS.keys()) ivtv_dev.close() # Do not set the channel if negative if channel >= 0: self.fc.chanSet(tuner_channel, True) args['url'] = vg.vdev if config.MPLAYER_ARGS.has_key('ivtv'): args['mode_args'] = config.MPLAYER_ARGS['ivtv'].split() elif vg.group_type == 'webcam': self.fc.chanSet(tuner_channel, True, app='mplayer') args['url'] = '' if config.MPLAYER_ARGS.has_key('webcam'): args['mode_args'] = config.MPLAYER_ARGS['webcam'].split() elif vg.group_type == 'dvb': self.fc.chanSet(tuner_channel, True, app='mplayer') args['url'] = ('dvb://%s' % (tuner_channel,)) args['mode_args'] = config.MPLAYER_ARGS['dvb'].split() elif vg.group_type == 'tvalsa': freq_khz = self.fc.chanSet(tuner_channel, True, app='mplayer') tuner_freq = '%1.3f' % (freq_khz / 1000.0) args['tv'] = '-tv driver=%s:%s:freq=%s:%s:%s:%s:width=%s:height=%s:%s %s' % \ (config.TV_DRIVER, vg.adev, tuner_freq, device, input, norm, w, h, outfmt, config.TV_OPTS) args['url'] = 'tv://' if config.MPLAYER_ARGS.has_key('tv'): args['mode_args'] = config.MPLAYER_ARGS['tv'].split() else: # group_type == 'normal' freq_khz = self.fc.chanSet(tuner_channel, True, app='mplayer') tuner_freq = '%1.3f' % (freq_khz / 1000.0) args['tv'] = '-tv driver=%s:freq=%s:%s:%s:%s:width=%s:height=%s:%s %s' % \ (config.TV_DRIVER, tuner_freq, device, input, norm, w, h, outfmt, config.TV_OPTS) args['url'] = 'tv://' if config.MPLAYER_ARGS.has_key('tv'): args['mode_args'] = config.MPLAYER_ARGS['tv'].split() elif mode == 'vcr': args['tv'] = '-tv driver=%s:%s:%s:%s:width=%s:height=%s:%s %s' % \ (config.TV_DRIVER, device, input, norm, w, h, outfmt, config.TV_OPTS) args['url'] = 'tv://' if config.MPLAYER_ARGS.has_key('tv'): args['mode_args'] = config.MPLAYER_ARGS['tv'].split() else: logger.error('Mode "%s" is not implemented', mode) return logger.debug('mplayer args = %r', args) vo = ['%(vo)s' % args, '%(vo_opts)s' % args] vo = filter(len, vo) vo = ':'.join(vo) ao = ['%(ao)s' % args, '%(ao_opts)s' % args] ao = filter(len, ao) ao = ':'.join(ao) command = ['--prio=%(nice)s' % args] command += ['%(cmd)s' % args] command += ['-slave'] command += str('%(verbose)s' % args).split() command += str('%(geometry)s' % args).split() command += vo.split() command += str('%(vc)s' % args).split() command += ao.split() command += args['default_args'] command += args['mode_args'] command += str('%(dvd-device)s' % args).split() command += str('%(cdrom-device)s' % args).split() command += str('%(alang)s' % args).split() command += str('%(aid)s' % args).split() command += str('%(audiofile)s' % args).split() command += str('%(slang)s' % args).split() command += str('%(sid)s' % args).split() command += str('%(sub)s' % args).split() command += str('%(field-dominance)s' % args).split() command += str('%(edl)s' % args).split() command += str('%(mc)s' % args).split() command += str('%(delay)s' % args).split() if args['af']: command += ['-af', '%s' % ','.join(args['af'])] if args['vf']: command += ['-vf', '%s' % ','.join(args['vf'])] command += str('%(tv)s' % args).split() command += args['disable_osd'] and ['-osdlevel', '0'] or [] if config.OSD_SINGLE_WINDOW: command += ['-wid', str(osd.video_window.id)] osd.video_window.show() # use software scaler? if '-nosws' in command: command.remove('-nosws') elif '-framedrop' not in command: command += config.MPLAYER_SOFTWARE_SCALER.split() #if options: # command += options command = filter(len, command) #command = self.sort_filter(command) url = '%(url)s' % args command += [url] logger.debug('%r', command) self.mode = mode # XXX Mixer manipulation code. # TV is on line in # VCR is mic in # btaudio (different dsp device) will be added later mixer = plugin.getbyname('MIXER') if mixer and config.MIXER_MAJOR_CTRL == 'VOL': mixer_vol = mixer.getMainVolume() mixer.setMainVolume(0) elif mixer and config.MIXER_MAJOR_CTRL == 'PCM': mixer_vol = mixer.getPcmVolume() mixer.setPcmVolume(0) # Start up the TV task self.app = childapp.ChildApp2(command) rc.add_app(self) # Suppress annoying audio clicks time.sleep(0.4) # XXX Hm.. This is hardcoded and very unflexible. if mixer and mode == 'vcr': mixer.setMicVolume(config.MIXER_VOLUME_VCR_IN) elif mixer: mixer.setLineinVolume(config.MIXER_VOLUME_TV_IN) mixer.setIgainVolume(config.MIXER_VOLUME_TV_IN) if mixer and config.MIXER_MAJOR_CTRL == 'VOL': mixer.setMainVolume(mixer_vol) elif mixer and config.MIXER_MAJOR_CTRL == 'PCM': mixer.setPcmVolume(mixer_vol) dialog.enable_overlay_display(AppTextDisplay(self.show_message)) logger.debug('%s: started %s app', time.time(), self.mode) def Stop(self, channel_change=0): mixer = plugin.getbyname('MIXER') if mixer and not channel_change: mixer.setLineinVolume(0) mixer.setMicVolume(0) mixer.setIgainVolume(0) # Input on emu10k cards. if config.OSD_SINGLE_WINDOW: osd.video_window.hide() self.app.stop('quit\n') rc.remove_app(self) if os.path.exists('/tmp/freevo.wid'): os.unlink('/tmp/freevo.wid') if config.MPLAYER_OLDTVCHANNELCHANGE: lastchanfile = os.path.join(config.FREEVO_CACHEDIR, 'lastchan') lcfp = open(lastchanfile, "w") lastchan = self.fc.getChannel() lastchannum = self.fc.getChannelNum() lcfp.write(str(lastchan)) lcfp.write('\n') lcfp.write(str(lastchannum)) lcfp.write('\n') lcfp.close() dialog.disable_overlay_display() def eventhandler(self, event, menuw=None): s_event = '%s' % event if event == em.STOP or event == em.PLAY_END: self.Stop() rc.post_event(em.PLAY_END) return True elif event == em.PAUSE or event == em.PLAY: self.app.write('pause\n') logger.debug('%s: sending pause to mplayer', time.time()) return True elif event in [ em.TV_CHANNEL_UP, em.TV_CHANNEL_DOWN, em.TV_CHANNEL_LAST ] or s_event.startswith('INPUT_'): chan = None if event == em.TV_CHANNEL_UP: nextchan = self.fc.getNextChannel() nextchannum = self.fc.getNextChannelNum() elif event == em.TV_CHANNEL_DOWN: nextchan = self.fc.getPrevChannel() nextchannum = self.fc.getPrevChannelNum() elif event == em.TV_CHANNEL_LAST: if config.MPLAYER_OLDTVCHANNELCHANGE: if os.path.isfile(os.path.join(config.FREEVO_CACHEDIR, 'lastchan')): lastchanfile = os.path.join(config.FREEVO_CACHEDIR, 'lastchan') lcfp = open(lastchanfile, "r") nextchan = lcfp.readline() nextchan = nextchan.strip() nextchannum = lcfp.readline() nextchannum = nextchannum.strip() nextchannum = int(nextchannum) lcfp.close() else: nextchan = self.fc.getChannel() nextchannum = self.fc.getChannelNum() else: return True else: chan = int(s_event[6]) nextchan = self.fc.getManChannel(chan) nextchannum = self.fc.getManChannelNum(chan) nextvg = self.fc.getVideoGroup(nextchan, True) logger.debug('chan=%s, nextchannum=%s, nextchan=%s nextvg=%s', chan, nextchannum, nextchan, nextvg) if self.current_vg != nextvg: self.Stop(channel_change=1) self.Play('tv', nextchan) return True if self.mode == 'vcr': return elif self.current_vg.group_type == 'dvb': if not config.MPLAYER_OLDTVCHANNELCHANGE: card = 0 # May be this should come from video groups or TV_CHANNELS if em.TV_CHANNEL_UP: self.app.write('dvb_set_channel %s %s\n' % (nextchannum, card)) self.fc.chanSet(nextchan, True) elif em.TV_CHANNEL_DOWN: self.app.write('dvb_set_channel %s %s\n' % (nextchannum, card)) self.fc.chanSet(nextchan, True) else: self.Stop(channel_change=1) self.Play('tv', nextchan) return True elif self.current_vg.group_type == 'ivtv': self.fc.chanSet(nextchan, True) self.app.write('seek 999999 0\n') else: freq_khz = self.fc.chanSet(nextchan, True, app=self.app) new_freq = '%1.3f' % (freq_khz / 1000.0) self.app.write('tv_set_freq %s\n' % new_freq) self.current_vg = self.fc.getVideoGroup(self.fc.getChannel(), True) # Display a channel changed message tuner_id, chan_name, prog_info = self.fc.getChannelInfo() now = time.strftime(config.TV_TIME_FORMAT) msg = '%s %s (%s): %s' % (now, chan_name, tuner_id, prog_info) cmd = 'osd_show_text "%s"\n' % msg self.app.write(cmd) return True elif event == em.TOGGLE_OSD: if dialog.is_dialog_supported(): dialog.show_play_state(dialog.PLAY_STATE_INFO, self.fc) else: # Display the channel info message tuner_id, chan_name, prog_info = self.fc.getChannelInfo() now = time.strftime(config.TV_TIME_FORMAT) msg = '%s %s (%s): %s' % (now, chan_name, tuner_id, prog_info) cmd = 'osd_show_text "%s"\n' % msg self.app.write(cmd) return False elif event == em.OSD_MESSAGE: self.app.write('osd_show_text "%s"\n' % event.arg); return True elif event == em.TV_SEND_MPLAYER_CMD: self.app.write('%s\n' % event.arg); return True return False def show_message(self, message): self.app.write('osd_show_text "%s"\n' % message)
class PluginInterface(plugin.DaemonPlugin): """ plugin to monitor if a recording is about to start and shut down the player if the video device is in use To activate this plugin, just put the following line at the end of your local_conf.py file: | plugin.activate('tv.upsoon') """ __author__ = 'Duncan Webb' __author_email__ = '*****@*****.**' __maintainer__ = __author__ __maintainer_email__ = __author_email__ __version__ = '$Revision$' def __init__(self, standalone=False): """ init the upsoon plugin """ logger.log( 9, 'upsoon.PluginInterface.__init__()') plugin.DaemonPlugin.__init__(self) plugin.register(self, 'upsoon') self.standalone = standalone self.lock = thread.allocate_lock() self.running = True self.timer = Timer(self.timer_handler).start(15) self.event = EventHandler(self.event_handler) #self.event.register(('VIDEO_START', 'VIDEO_END')) self.event.register() self.recordclient = RecordClient() self.fc = FreevoChannels() self.rdev = config.RADIO_DEVICE self.next_program = None self.announced = False self.seconds_before_announce = config.TV_UPSOON_ANNOUNCE self.seconds_before_start = config.TV_UPSOON_BEFORE_START self.pending_lockfile = config.FREEVO_CACHEDIR + '/record.soon' self.tv_lockfile = None # lockfile of recordserver self.stopped = None # flag that tells upsoon what stopped if os.path.exists(self.pending_lockfile): os.remove(self.pending_lockfile) logger.debug('%r lockfile removed', self.pending_lockfile) def config(self): return [ ('TV_UPSOON_BEFORE_START', 1*60, 'Number of seconds before start of recording to stop player'), ('TV_UPSOON_ANNOUNCE', 1*60+60, 'Number of seconds before start of recording to announce starting'), ] def getVideoForChannel(self, channel_id): """ get the video device given a channel id """ logger.log( 9, 'getVideoForChannel(channel_id=%r)', channel_id) return self.fc.getVideoGroup(channel_id, False, CHANNEL_ID).vdev def stopVideoInUse(self, vdev): """ stop the video device if being used """ logger.log( 9, 'stopVideoInUse(vdev=%r)', vdev) if vdev: try: dev_fh = os.open(vdev, os.O_TRUNC) try: os.read(dev_fh, 1) except: if (self.seconds_to_next > self.seconds_before_start): # just announce rc.post_event(Event(OSD_MESSAGE, arg=_('A recording will start in a few minutes'))) else: # stop the tv rc.post_event(STOP) self.stopped = _('TV') os.close(dev_fh) except Exception, why: logger.warning('cannot check video device %r: %s', vdev, why)
class MPlayer: __muted = 0 __igainvol = 0 def __init__(self): self.tuner_chidx = 0 # Current channel, index into config.TV_CHANNELS self.app_mode = 'tv' self.fc = FreevoChannels() self.current_vg = None def Play(self, mode, tuner_channel=None): if not tuner_channel: tuner_channel = self.fc.getChannel() vg = self.current_vg = self.fc.getVideoGroup(tuner_channel, True) # Convert to MPlayer TV setting strings norm = 'norm=%s' % vg.tuner_norm input = 'input=%s' % vg.input_num device = 'device=%s' % vg.vdev w, h = config.TV_VIEW_SIZE outfmt = 'outfmt=%s' % config.TV_VIEW_OUTFMT # Build the MPlayer command args = (config.MPLAYER_NICE, config.MPLAYER_CMD, config.MPLAYER_VO_DEV, config.MPLAYER_VO_DEV_OPTS, config.MPLAYER_AO_DEV, config.MPLAYER_ARGS_DEF) if mode == 'tv': if vg.group_type == 'ivtv': ivtv_dev = ivtv.IVTV(vg.vdev) ivtv_dev.init_settings() ivtv_dev.setinput(vg.input_num) #ivtv_dev.print_settings() ivtv_dev.close() self.fc.chanSet(tuner_channel, True) tvcmd = vg.vdev if config.MPLAYER_ARGS.has_key('ivtv'): args += (config.MPLAYER_ARGS['ivtv'], ) elif vg.group_type == 'webcam': self.fc.chanSet(tuner_channel, True, app='mplayer') tvcmd = '' if config.MPLAYER_ARGS.has_key('webcam'): args += (config.MPLAYER_ARGS['webcam'], ) elif vg.group_type == 'dvb': self.fc.chanSet(tuner_channel, True, app='mplayer') tvcmd = '' args += ('"dvb://%s" %s' % (tuner_channel, config.MPLAYER_ARGS['dvb']), ) elif vg.group_type == 'tvalsa': freq_khz = self.fc.chanSet(tuner_channel, True, app='mplayer') tuner_freq = '%1.3f' % (freq_khz / 1000.0) tvcmd = ('tv:// -tv driver=%s:%s:freq=%s:%s:%s:' '%s:width=%s:height=%s:%s %s' % (config.TV_DRIVER, vg.adev, tuner_freq, device, input, norm, w, h, outfmt, config.TV_OPTS)) if config.MPLAYER_ARGS.has_key('tv'): args += (config.MPLAYER_ARGS['tv'], ) else: # group_type == 'normal' freq_khz = self.fc.chanSet(tuner_channel, True, app='mplayer') tuner_freq = '%1.3f' % (freq_khz / 1000.0) tvcmd = ('tv:// -tv driver=%s:freq=%s:%s:%s:' '%s:width=%s:height=%s:%s %s' % (config.TV_DRIVER, tuner_freq, device, input, norm, w, h, outfmt, config.TV_OPTS)) if config.MPLAYER_ARGS.has_key('tv'): args += (config.MPLAYER_ARGS['tv'], ) elif mode == 'vcr': tvcmd = ('tv:// -tv driver=%s:%s:%s:' '%s:width=%s:height=%s:%s %s' % (config.TV_DRIVER, device, input, norm, w, h, outfmt, config.TV_OPTS)) if config.MPLAYER_ARGS.has_key('tv'): args += (config.MPLAYER_ARGS['tv'], ) else: print 'Mode "%s" is not implemented' % mode # XXX ui.message() return args += (tvcmd, ) mpl = '--prio=%s %s -vo %s %s -ao %s %s -slave %s %s' % args command = mpl _debug_('command=\"%s\"', (command)) self.mode = mode # XXX Mixer manipulation code. # TV is on line in # VCR is mic in # btaudio (different dsp device) will be added later mixer = plugin.getbyname('MIXER') if mixer and config.MAJOR_AUDIO_CTRL == 'VOL': mixer_vol = mixer.getMainVolume() mixer.setMainVolume(0) elif mixer and config.MAJOR_AUDIO_CTRL == 'PCM': mixer_vol = mixer.getPcmVolume() mixer.setPcmVolume(0) # Start up the TV task self.app = childapp.ChildApp2(command) self.prev_app = rc.app() rc.app(self) if osd.focused_app(): osd.focused_app().hide() # Suppress annoying audio clicks time.sleep(0.4) # XXX Hm.. This is hardcoded and very unflexible. if mixer and mode == 'vcr': mixer.setMicVolume(config.VCR_IN_VOLUME) elif mixer: mixer.setLineinVolume(config.TV_IN_VOLUME) mixer.setIgainVolume(config.TV_IN_VOLUME) if mixer and config.MAJOR_AUDIO_CTRL == 'VOL': mixer.setMainVolume(mixer_vol) elif mixer and config.MAJOR_AUDIO_CTRL == 'PCM': mixer.setPcmVolume(mixer_vol) if DEBUG: print '%s: started %s app' % (time.time(), self.mode) def Stop(self, channel_change=0): mixer = plugin.getbyname('MIXER') if mixer and not channel_change: mixer.setLineinVolume(0) mixer.setMicVolume(0) mixer.setIgainVolume(0) # Input on emu10k cards. self.app.stop('quit\n') rc.app(self.prev_app) if osd.focused_app() and not channel_change: osd.focused_app().show() if os.path.exists('/tmp/freevo.wid'): os.unlink('/tmp/freevo.wid') def eventhandler(self, event, menuw=None): s_event = '%s' % event if event == em.STOP or event == em.PLAY_END: self.Stop() rc.post_event(em.PLAY_END) return TRUE elif event == em.PAUSE or event == em.PLAY: self.app.write('pause\n') if DEBUG: print '%s: sending pause to mplayer' % (time.time()) return TRUE elif event in [em.TV_CHANNEL_UP, em.TV_CHANNEL_DOWN ] or s_event.startswith('INPUT_'): chan = None if event == em.TV_CHANNEL_UP: nextchan = self.fc.getNextChannel() nextchannum = self.fc.getNextChannelNum() elif event == em.TV_CHANNEL_DOWN: nextchan = self.fc.getPrevChannel() nextchannum = self.fc.getPrevChannelNum() else: chan = int(s_event[6]) nextchan = self.fc.getManChannel(chan) nextchannum = self.fc.getManChannelNum(chan) nextvg = self.fc.getVideoGroup(nextchan, True) _debug_('chan=%s, nextchannum=%s, nextchan=%s nextvg=%s' % (chan, nextchannum, nextchan, nextvg)) if self.current_vg != nextvg: self.Stop(channel_change=1) self.Play('tv', nextchan) return TRUE if self.mode == 'vcr': return elif self.current_vg.group_type == 'dvb': card = 0 # May be this should come from video groups or TV_CHANNELS if em.TV_CHANNEL_UP: self.app.write('dvb_set_channel %s %s\n' % (nextchannum, card)) elif em.TV_CHANNEL_DOWN: self.app.write('dvb_set_channel %s %s\n' % (nextchannum, card)) return TRUE elif self.current_vg.group_type == 'ivtv': self.fc.chanSet(nextchan, True) self.app.write('seek 999999 0\n') else: freq_khz = self.fc.chanSet(nextchan, True, app=self.app) new_freq = '%1.3f' % (freq_khz / 1000.0) self.app.write('tv_set_freq %s\n' % new_freq) self.current_vg = self.fc.getVideoGroup(self.fc.getChannel(), True) # Display a channel changed message tuner_id, chan_name, prog_info = self.fc.getChannelInfo() now = time.strftime('%H:%M') msg = '%s %s (%s): %s' % (now, chan_name, tuner_id, prog_info) cmd = 'osd_show_text "%s"\n' % msg self.app.write(cmd) return TRUE elif event == em.TOGGLE_OSD: # Display the channel info message tuner_id, chan_name, prog_info = self.fc.getChannelInfo() now = time.strftime('%H:%M') msg = '%s %s (%s): %s' % (now, chan_name, tuner_id, prog_info) cmd = 'osd_show_text "%s"\n' % msg self.app.write(cmd) return FALSE return FALSE
class TVTime: __muted = 0 __igainvol = 0 def __init__(self): self.event_context = 'tv' self.fc = FreevoChannels() self.current_vg = None self.optionD_supported = False self.xmltv_supported = False def TunerSetChannel(self, tuner_channel): for pos in range(len(config.TV_CHANNELS)): channel = config.TV_CHANNELS[pos] if channel[2] == tuner_channel: return pos print 'ERROR: Cannot find tuner channel "%s" in the TV channel listing' % tuner_channel return 0 def TunerGetChannelInfo(self): return self.fc.getChannelInfo() def TunerGetChannel(self): return self.fc.getChannel() def Play(self, mode, tuner_channel=None, channel_change=0): if not tuner_channel: tuner_channel = self.fc.getChannel() vg = self.current_vg = self.fc.getVideoGroup(tuner_channel, True) if not vg.group_type == 'normal': print 'Tvtime only supports normal. "%s" is not implemented' % vg.group_type return if mode == 'tv' or mode == 'vcr': w, h = config.TV_VIEW_SIZE cf_norm = vg.tuner_norm cf_input = vg.input_num cf_device = vg.vdev s_norm = cf_norm.upper() outputplugin = '' if plugin.getbyname(plugin.TV).optionD_supported: if config.CONF.display == 'x11': outputplugin = 'Xv' elif config.CONF.display == 'mga': outputplugin = 'mga' elif config.CONF.display in ( 'directfb', 'dfbmga' ): outputplugin = 'directfb' else: outputplugin = config.CONF.display outputplugin = '-D %s' % outputplugin if mode == 'vcr': cf_input = '1' if hasattr(config, "TV_VCR_INPUT_NUM") and config.TV_VCR_INPUT_NUM: cf_input = config.TV_VCR_INPUT_NUM self.fc.chan_index = self.TunerSetChannel(tuner_channel) if hasattr(config, 'TV_PAD_CHAN_NUMBERS') and config.TV_PAD_CHAN_NUMBERS: mychan = tuner_channel else: mychan = self.fc.chan_index logger.debug('starting channel is %s', mychan) command = '%s %s -k -I %s -n %s -d %s -f %s -c %s -i %s' % \ (config.TVTIME_CMD, outputplugin, w, s_norm, cf_device, 'freevo', mychan, cf_input) if osd.get_fullscreen() == 1: command += ' -m' else: command += ' -M' else: print 'Mode "%s" is not implemented' % mode # BUG ui.message() return self.mode = mode mixer = plugin.getbyname('MIXER') # BUG Mixer manipulation code. # TV is on line in # VCR is mic in # btaudio (different dsp device) will be added later if mixer and config.MIXER_MAJOR_CTRL == 'VOL': mixer_vol = mixer.getMainVolume() mixer.setMainVolume(0) elif mixer and config.MIXER_MAJOR_CTRL == 'PCM': mixer_vol = mixer.getPcmVolume() mixer.setPcmVolume(0) # Start up the TV task self.app=TVTimeApp(command) rc.add_app(self) # Suppress annoying audio clicks time.sleep(0.4) # BUG Hm.. This is hardcoded and very unflexible. if mixer and mode == 'vcr': mixer.setMicVolume(config.MIXER_VOLUME_VCR_IN) elif mixer: mixer.setLineinVolume(config.MIXER_VOLUME_TV_IN) mixer.setIgainVolume(config.MIXER_VOLUME_TV_IN) if mixer and config.MIXER_MAJOR_CTRL == 'VOL': mixer.setMainVolume(mixer_vol) elif mixer and config.MIXER_MAJOR_CTRL == 'PCM': mixer.setPcmVolume(mixer_vol) logger.debug('%s: started %s app', time.time(), self.mode) def Stop(self, channel_change=0): mixer = plugin.getbyname('MIXER') if mixer and not channel_change: mixer.setLineinVolume(0) mixer.setMicVolume(0) mixer.setIgainVolume(0) # Input on emu10k cards. self.app.stop('quit\n') rc.remove_app(self) def eventhandler(self, event, menuw=None): logger.debug('%s: %s app got %s event', time.time(), self.mode, event) if event == em.STOP or event == em.PLAY_END: self.Stop() rc.post_event(em.PLAY_END) return True elif event == em.TV_CHANNEL_UP or event == em.TV_CHANNEL_DOWN: if self.mode == 'vcr': return if event == em.TV_CHANNEL_UP: nextchan = self.fc.getNextChannel() elif event == em.TV_CHANNEL_DOWN: nextchan = self.fc.getPrevChannel() nextvg = self.fc.getVideoGroup(nextchan, True) logger.debug("nextchan is %s", nextchan) # XXX hazardous to your health. don't use tvtime with anything # other than one normal video_group. # we lose track of the channel index at some points and # chaos ensues #if self.current_vg != nextvg: # self.Stop(channel_change=1) # self.Play('tv', nextchan) # return TRUE self.fc.chanSet(nextchan, True, app=self.app) #self.current_vg = self.fc.getVideoGroup(self.fc.getChannel(), True) # Go to the prev/next channel in the list if event == em.TV_CHANNEL_UP: self.app.write('CHANNEL_UP\n') else: self.app.write('CHANNEL_DOWN\n') return True elif event == em.TOGGLE_OSD: self.app.write('DISPLAY_INFO\n') return True elif event == em.OSD_MESSAGE: # XXX this doesn't work #self.app.write('display_message %s\n' % event.arg) #this does os.system('tvtime-command display_message \'%s\'' % event.arg) return True elif event == em.TV_SEND_TVTIME_CMD: os.system('tvtime-command %s' % event.arg) return True elif event in em.INPUT_ALL_NUMBERS: self.app.write('CHANNEL_%s\n' % event.arg) elif event == em.BUTTON: if event.arg == 'PREV_CH': self.app.write('CHANNEL_PREV\n') return True return False
def __init__(self): self.tuner_chidx = 0 # Current channel, index into config.TV_CHANNELS self.app_mode = 'tv' self.fc = FreevoChannels() self.current_vg = None
class Xine: """ the main class to control xine """ def __init__(self, type): self.name = 'xine' self.event_context = 'tv' self.xine_type = type self.app = None self.fc = FreevoChannels() self.command = [ '--prio=%s' % config.MPLAYER_NICE ] + \ config.XINE_COMMAND.split(' ') + \ [ '--stdctl', '-V', config.XINE_VO_DEV, '-A', config.XINE_AO_DEV ] + \ config.XINE_ARGS_DEF.split(' ') def ShowMessage(self, msg): """ Show a message on the OSD """ logger.debug("XINE: Show OSD Message: '%s'", msg) self.app.write("OSDWriteText$ %s\n" % msg) def Play(self, mode, tuner_channel=None): """ play with xine """ if not tuner_channel: tuner_channel = self.fc.getChannel() if plugin.getbyname('MIXER'): plugin.getbyname('MIXER').reset() command = copy.copy(self.command) if config.XINE_HAS_NO_LIRC: command.append('--no-lirc') if config.OSD_SINGLE_WINDOW: command += ['-W', str(osd.video_window.id), '--no-mouse'] osd.video_window.show() command.append('dvb://' + tuner_channel) logger.debug('Starting cmd=%s', command) rc.add_app(self) self.app = childapp.ChildApp2(command) dialog.enable_overlay_display(AppTextDisplay(self.ShowMessage)) return None def stop(self, channel_change=0): """ Stop xine """ if self.app: if config.OSD_SINGLE_WINDOW: osd.video_window.hide() self.app.stop('quit\n') rc.remove_app(self) dialog.disable_overlay_display() if not channel_change: pass def eventhandler(self, event, menuw=None): """ eventhandler for xine control. If an event is not bound in this function it will be passed over to the items eventhandler """ if event in ( PLAY_END, USER_END, STOP ): self.stop() rc.post_event(PLAY_END) return True if event == PAUSE or event == PLAY: self.app.write('pause\n') return True elif event in [ TV_CHANNEL_UP, TV_CHANNEL_DOWN] or str(event).startswith('INPUT_'): if event == TV_CHANNEL_UP: nextchan = self.fc.getNextChannel() elif event == TV_CHANNEL_DOWN: nextchan = self.fc.getPrevChannel() else: nextchan = self.fc.getManChannel(int(event.arg)) self.stop(channel_change=1) self.fc.chanSet(nextchan, True) self.Play('tv', nextchan) return True if event == TOGGLE_OSD: self.app.write('PartMenu\n') return True if event == VIDEO_TOGGLE_INTERLACE: self.app.write('ToggleInterleave\n') return True if event == OSD_MESSAGE: self.ShowMessage(event.arg) return True # nothing found return False
class LivePauseController: """ The main class to control play back. """ def __init__(self, player): self.name = 'livepause' self.event_context = 'tv' self.fc = FreevoChannels() self.backend = backend.get_backend() self.backend.set_mode(player.mode) self.last_channel = None self.stop_time = 0 self.data_started_timer = kaa.OneShotTimer(self.__buffering_data_timedout) self.disable_buffering_timer = kaa.OneShotTimer(self.__disable_buffering_timeout) self.state = State.IDLE self.player = player self.changing_channel = False self.subtitles = None self.subtitle_index = -1 self.audio_langs = None self.audio_lang_index = -1 self.recording = False self.state_dialog = None # Setup Event Maps self.event_maps = {} self.event_maps[State.IDLE] = { 'READER_OVERTAKEN' : self.__idle_reader_overtaken, } self.event_maps[State.TUNING] = { 'DATA_STARTED' : self.__tuning_data_started, 'DATA_TIMEDOUT': self.__tuning_data_timedout, 'PLAY_END' : self.__handle_stop, 'USER_END' : self.__handle_stop, 'STOP' : self.__handle_stop } self.event_maps[State.BUFFERING] = { 'DATA_ACQUIRED': self.__buffering_data_acquired, 'DATA_TIMEDOUT': self.__buffering_data_timedout, 'PLAY_END' : self.__handle_stop, 'USER_END' : self.__handle_stop, 'STOP' : self.__handle_stop } self.event_maps[State.PLAYING] = { 'PLAY' : self.__playing_play_pause, 'PAUSE' : self.__playing_play_pause, 'PLAY_END' : self.__handle_stop, 'USER_END' : self.__handle_stop, 'STOP' : self.__handle_stop, 'TV_CHANNEL_UP' : self.__playing_tv_channel_up, 'TV_CHANNEL_DOWN' : self.__playing_tv_channel_down, 'TV_CHANNEL_NUMBER' : self.__playing_tv_channel_number, 'TV_START_RECORDING' : self.__playing_tv_record, 'SAVE_STARTED' : self.__playing_tv_record_start, 'SAVE_FINISHED' : self.__playing_tv_record_stop, 'BUTTON' : self.__playing_button_pressed, 'TOGGLE_OSD' : self.__playing_display_info, 'SEEK' : self.__playing_seek, 'SECONDS_LEFT' : self.__playing_seconds_left, 'READER_OVERTAKEN' : self.__playing_reader_overtaken, 'DATA_ACQUIRED' : None, 'DATA_TIMEDOUT' : None, 'VIDEO_NEXT_FILLMODE' : None, 'VIDEO_NEXT_AUDIOMODE': None, 'VIDEO_NEXT_AUDIOLANG': None, #self.__playing_toggle_audo_lang, 'VIDEO_NEXT_SUBTITLE' : self.__playing_toggle_subtitles, } self.current_event_map = self.event_maps[self.state] def Play(self, mode, tuner_channel=None): """ Start play back. """ if not tuner_channel: tuner_channel = self.fc.getChannel() if plugin.getbyname('MIXER'): plugin.getbyname('MIXER').reset() self.disable_buffering_timer.stop() rc.add_app(self) # If it's the same channel as last time and we have come back to it after # more than 2 minutes start at the end of the buffer, otherwise jump # straight back in where we left off. if self.last_channel == tuner_channel: now = time.time() seconds_since_played = now - self.stop_time logger.debug('Same channel, seconds since last playing this channel %d', seconds_since_played) self.backend.set_events_enabled(True) if seconds_since_played > 120.0: # Start at the end of the buffer buffer_info = self.backend.get_buffer_info() self.backend.seekto(buffer_info[2] - 3) self.__change_state(State.PLAYING) else: logger.debug('New channel, tuning to %s', tuner_channel) self.backend.set_events_enabled(True) self.change_channel(tuner_channel) return None def stop(self): """ Stop playback and go into idle. """ logger.debug('Stopping play back.') display.get_osd().hide() dialog.disable_overlay_display() self.player.stop() self.stop_time = time.time() self.backend.set_events_enabled(False) self.__change_state(State.IDLE) self.disable_buffering_timer.start(config.LIVE_PAUSE2_BUFFER_TIMEOUT) return True def disable_buffering(self): """ Stop buffering the current channel. """ self.stop_time = 0 self.last_channel = None self.disable_buffering_timer.stop() self.backend.disable_buffering() logger.debug('Buffering disabled.') def shutdown(self): """ Stop buffering and the slave server. """ self.disable_buffering() def change_channel(self, channel): """ Select the correct dvbstreamer instance, change the channel and set the primary mrl. """ if self.last_channel == channel: # Already tune to this channel so nothing to do! return self.fc.chanSet(channel, True) self.last_channel = channel self.backend.change_channel(channel) self.__change_state(State.TUNING) ########################################################################### # Event Handlers ########################################################################### def eventhandler(self, event, menuw=None): """ Eventhandler for livepause control. If an event is not bound in this function it will be passed over to the items eventhandler """ logger.log( 9, 'Event %s', event) event_consumed = False if self.state == State.PLAYING: event_consumed = tv.dialogs.handle_channel_number_input(event) if not event_consumed and event.name in self.current_event_map: handler = self.current_event_map[event.name] if handler: event_consumed = handler(event, menuw) else: # Event was in map but no handler so just consume the event. event_consumed = True if not event_consumed: logger.debug('Unused event %s in state %s', event.name, self.state) return event_consumed def __handle_stop(self, event, menuw): if self.changing_channel: self.changing_channel = False else: self.stop() return True def __idle_reader_overtaken(self, event, menuw): # Seek ten seconds forward from the end of the buffer. self.backend.seek(10, now=True) return True def __tuning_data_started(self, event, menuw): self.__change_state(State.BUFFERING) return True def __tuning_data_timedout(self, event, menuw): # Timeout while waiting for data! # We could display a searching for signal graphic or something here self.__change_state(State.IDLE) return True def __buffering_data_acquired(self, event, menuw): self.wait_for_data_count -= 1 self.__draw_state_screen() if self.wait_for_data_count <= 0: self.__change_state(State.PLAYING) return True def __buffering_data_timedout(self, event, menuw): # Timeout while waiting for data! # We could display a searching for signal graphic or something here self.__change_state(State.IDLE) return True def __playing_play_pause(self, event, menuw): if self.player.paused: self.player.resume() else: self.player.pause() self.osd.display_buffer_pos(self.__get_display_info) return True def __playing_tv_channel_up(self, event, menuw): next_channel = self.fc.getNextChannel() self.changing_channel = True self.player.stop() self.change_channel(next_channel) return True def __playing_tv_channel_down(self, event, menuw): next_channel = self.fc.getPrevChannel() self.changing_channel = True self.player.stop() self.change_channel(next_channel) return True def __playing_tv_channel_number(self, event, menuw): next_channel = self.fc.getManChannel(event.arg) if self.last_channel != next_channel: self.changing_channel = True self.player.stop() self.change_channel(next_channel) return True def __playing_tv_record(self, event, menuw): if self.recording: self.backend.cancelsave() self.recording = False else: self.recording = True record.start_recording(self.backend, self.last_channel) def __playing_tv_record_start(self, event, menuw): dialog.show_message(_('Recording started')) def __playing_tv_record_stop(self, event, menuw): if self.state == State.PLAYING: dialog.show_message(_('Recording stopped')) self.recording = False def __playing_seconds_left(self, event, menuw): if self.player.paused: self.player.resume() dialog.show_message(_('Out of buffer space, playback resumed')) else: logger.debug('while playing ~%d seconds left in buffer before overwrite', event.arg) return True def __playing_reader_overtaken(self, event, menuw): if self.player.paused: self.player.resume() dialog.show_message(_('Out of buffer space, playback resumed')) else: dialog.show_message(_('Out of buffer space')) logger.debug('Out of buffer space while playing!') return True def __playing_button_pressed(self, event, menuw): consumed = False logger.debug('Button %s', event.arg) if event.arg == 'SUBTITLE': self.__playing_toggle_subtitles(event, menuw) consumed = True return consumed def __playing_toggle_subtitles(self, event, menuw): # Enable/Disable subtitles if self.subtitles: self.subtitle_index += 1 else: self.subtitles = self.player.get_subtitles() self.subtitle_index = 0 if self.subtitles: if self.subtitle_index >= len(self.subtitles): self.subtitle_index = -1 self.player.set_subtitles(self.subtitle_index) if self.subtitle_index == -1: subtitle_text = _('Disabled') else: subtitle_text = self.subtitles[self.subtitle_index] dialog.show_message(_('Subtitles: %s') % subtitle_text) else: dialog.show_message(_('Subtitles not supported')) return True def __playing_toggle_audio_lang(self, event, menuw): if self.audio_langs: self.audio_lang_index += 1 else: self.audio_langs = self.player.get_audio_langs() self.audio_lang_index = 0 if self.audio_langs: if self.audio_lang_index >= len(self.audio_langs): self.audio_lang_index = -1 self.player.set_audio_lang(self.audio_lang_index) if self.audio_lang_index == -1: audio_lang_text = _('Default') else: audio_lang_text = self.subtitles[self.subtitle_index] dialog.show_message(_('Audio language: %s') % audio_lang_text) else: dialog.show_message(_('Audio language selection not supported')) return True def __playing_display_info(self, event, menuw): self.osd.display_info(self.__get_display_info) return True def __get_display_info(self): info_dict = {} info_dict['channel'] = self.__get_display_channel() buffer_info = self.backend.get_buffer_info() info_dict['current_time'] = buffer_info[3] info_dict['start_time'] = buffer_info[1] info_dict['end_time'] = buffer_info[2] info_dict['percent_through_buffer'] = float(buffer_info[3] - buffer_info[1]) / float(buffer_info[2] - buffer_info[1]) info_dict['percent_buffer_full'] = buffer_info[0] info_dict['paused'] = self.player.paused info_dict['recording'] = self.recording return info_dict def __playing_seek(self, event, menuw): steps = int(event.arg) buffer_info = self.backend.get_buffer_info() if steps > 0: can_seek = buffer_info[2] != buffer_info[3] steps = min(buffer_info[2] - buffer_info[3], steps) else: steps = max(buffer_info[1] - buffer_info[3], steps) can_seek = buffer_info[1] != buffer_info[3] if can_seek: self.backend.seek(steps) self.player.restart() time.sleep(0.2) self.osd.display_buffer_pos(self.__get_display_info) return True ########################################################################### # State Management ########################################################################### def __change_state(self, new_state): """ Internal function to move to a new state. If new_state is different to the current state, set self.state to new_state and perform any state initialisation for the new state. """ if self.state == new_state: # No change in state nothing todo! return logger.debug('Changing state from %s to %s', self.state, new_state) old_state = self.state self.state = new_state self.current_event_map = self.event_maps[new_state] # State Initialisation code if self.state == State.IDLE: self.state_dialog.hide() rc.remove_app(self) rc.post_event(PLAY_END) self.backend.set_events_enabled(False) elif self.state == State.TUNING: # Display the current state on the OSD self.__draw_state_screen() elif self.state == State.BUFFERING: self.wait_for_data_count = WAIT_FOR_DATA_COUNT # Display the current state on the OSD self.__draw_state_screen() elif self.state == State.PLAYING: # Display the current state on the OSD self.__draw_state_screen() self.player.start((self.backend.get_server_address(), config.LIVE_PAUSE2_PORT)) dialog.enable_overlay_display(self.player.get_display()) self.osd = display.get_osd() def __draw_state_screen(self): if self.state_dialog is None: self.state_dialog = StateDialog() percent = 0.0 if self.state == State.BUFFERING: percent = float(WAIT_FOR_DATA_COUNT - self.wait_for_data_count) / float(WAIT_FOR_DATA_COUNT) elif self.state == State.PLAYING: percent = 1.0 channel = self.__get_display_channel() self.state_dialog.set_state(self.state, percent, channel) self.state_dialog.show() def __get_display_channel(self): channel = self.last_channel for entry in config.TV_CHANNELS: if self.last_channel == entry[2]: channel = entry[1] return channel def __fire_channel_number(self): rc.post_event(TV_CHANNEL_NUMBER) self.channel_number_timer = None def __disable_buffering_timeout(self): self.disable_buffering()
def run(self): logger.log(9, 'Record_Thread.run()') while 1: logger.debug('Record_Thread::run: mode=%s', self.mode) if self.mode == 'idle': self.mode_flag.wait() self.mode_flag.clear() elif self.mode == 'record': try: logger.info('Record_Thread::run: started recording') fc = FreevoChannels() logger.debug('Channel: %s', fc.getChannel()) vg = fc.getVideoGroup(self.prog.tunerid, False) logger.debug('Opening device %r', vg.vdev) v = tv.ivtv.IVTV(vg.vdev) v.init_settings() logger.debug('Setting input to %r', vg.input_type) v.setinputbyname(vg.input_type) cur_std = v.getstd() try: new_std = V4L2.NORMS.get(vg.tuner_norm) if cur_std != new_std: logger.debug('Setting standard to %s', new_std) v.setstd(new_std) except: logger.error( "Videogroup norm value '%s' not from NORMS: %s", vg.tuner_norm, V4L2.NORMS.keys()) logger.debug('Setting channel to %r', self.prog.tunerid) fc.chanSet(str(self.prog.tunerid), False) # Setting the input sound level on the PVR card channel = self.prog.tunerid try: # lookup the channel name in TV_CHANNELS for pos in range(len(config.TV_CHANNELS)): entry = config.TV_CHANNELS[pos] if str(channel) == str(entry[2]): channel_index = pos break except ValueError: pass logger.debug( 'SetAudioByChannel: Channel: %r TV_CHANNEL pos(%d)', channel, channel_index) try: ivtv_avol = vg.avol except AttributeError: ivtv_avol = 0 if ivtv_avol <= 0: logger.debug( 'SetAudioByChannel: The tv_video group for %r doesn\'t set the volume', channel) else: # Is there a specific volume level in TV_CHANNELS_VOLUME avol_percent = 100 try: # lookup the channel name in TV_CHANNELS for pos in range(len(config.TV_CHANNELS_VOLUME)): if config.TV_CHANNELS_VOLUME[pos][ 0] == config.TV_CHANNELS[ channel_index][0]: avol_percent = config.TV_CHANNELS_VOLUME[ pos][1] break except: pass try: avol_percent = int(avol_percent) except ValueError: avol_percent = 100 avol = int(ivtv_avol * avol_percent / 100) if avol > 65535: avol = 65535 if avol < 0: avol = 0 logger.debug( 'SetAudioByChannel: Current PVR Sound level is : %s', v.getctrl(0x00980905)) logger.debug( 'SetAudioByChannel: Set the PVR Sound Level to : %s (%s * %s)', avol, ivtv_avol, avol_percent) v.setctrl(0x00980905, avol) logger.debug( 'SetAudioByChannel: New PVR Sound level is : %s', v.getctrl(0x00980905)) if vg.cmd != None: logger.debug("Running command %r", vg.cmd) retcode = os.system(vg.cmd) logger.debug("exit code: %g", retcode) now = time.time() stop = now + self.prog.rec_duration rc.post_event(Event('RECORD_START', arg=self.prog)) time.sleep(2) v_in = open(vg.vdev, 'r') v_out = open(self.prog.filename, 'w') logger.debug('Recording from %r to %r in %s byte chunks', vg.vdev, self.prog.filename, CHUNKSIZE) while time.time() < stop: buf = v_in.read(CHUNKSIZE) v_out.write(buf) if self.mode == 'stop': logger.info('Recording stopped') break v_in.close() v_out.close() v.close() v = None self.mode = 'idle' rc.post_event(Event('RECORD_STOP', arg=self.prog)) logger.info('Record_Thread::run: finished recording') except Exception, why: logger.critical('%s', why) return else: self.mode = 'idle' time.sleep(0.5)
class Recorder: """ """ def __init__(self): logger.log( 9, 'Recorder.__init__()') # Disable this plugin if not loaded by record_server. if string.find(sys.argv[0], 'recordserver') == -1: return logger.info('ACTIVATING VBI2SRT RECORD PLUGIN') self.vg = None self.fc = FreevoChannels() self.tuner_chidx = 0 # Current channel, index into config.TV_CHANNELS self.thread = Record_Thread() self.thread.setDaemon(1) self.thread.mode = 'idle' self.thread.start() def Record(self, rec_prog): logger.log( 9, 'Record(rec_prog=%r)', rec_prog) frequency = self.fc.chanSet(str(rec_prog.tunerid), False, 'record plugin') rec_prog.filename = tv_util.getProgFilename(rec_prog) rec_prog.filename = os.path.splitext(tv_util.getProgFilename(rec_prog))[0] + '.mpeg' logger.debug('filename=%r', rec_prog.filename) self.vg = self.fc.getVideoGroup(rec_prog.tunerid, False) cl_options = { 'channel' : rec_prog.tunerid, 'frequency' : frequency, 'frequencyMHz' : float(frequency) / 1000, 'filename' : rec_prog.filename, 'base_filename' : os.path.basename(rec_prog.filename), 'title' : rec_prog.title, 'sub-title' : rec_prog.sub_title, 'seconds' : rec_prog.rec_duration, 'start' : rec_prog.start, 'pdc-start' : rec_prog.pdc_start, } logger.debug('cl_options=%r', cl_options) logger.debug('chan_index=%r', self.fc.chan_index) logger.debug('vg.vdev=%r', self.vg.vdev) logger.debug('vg.vvbi=%r', self.vg.vvbi) pagenum = None; try: pagenum = int(config.TV_CHANNELS[self.fc.chan_index][5]) except: pagenum = None; logger.debug('pagenum=%r', pagenum) if pagenum: # there is a bug in vbi2srt that causes out of sync subtitles when VPS is used self.rec_command = \ 'vbi2srt --verbose --video-in=%s --video-out=%s --vbi-device=%s --seconds=%s --vps=%s --page=%s' % \ (self.vg.vdev, rec_prog.filename, self.vg.vvbi, rec_prog.rec_duration, rec_prog.pdc_start, pagenum) else: self.rec_command = \ 'vbi2srt --verbose --video-in=%s --video-out=%s --vbi-device=%s --seconds=%s --vps=%s' % \ (self.vg.vdev, rec_prog.filename, self.vg.vvbi, rec_prog.rec_duration, rec_prog.pdc_start) logger.debug('rec_command=%r', self.rec_command) self.thread.mode = 'record' self.thread.prog = rec_prog self.thread.command = self.rec_command self.thread.autokill = float(rec_prog.rec_duration + 10) self.thread.mode_flag.set() def Stop(self): logger.log( 9, 'Stop()') self.thread.mode = 'stop' self.thread.mode_flag.set()