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 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
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))
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 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))
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 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)