Esempio n. 1
0
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()
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 4
0
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))
Esempio n. 5
0
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)
Esempio n. 6
0
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))
Esempio n. 7
0
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
Esempio n. 8
0
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)