Exemplo n.º 1
0
class Player(object):
    def __init__(self, media_dir):
        self.media_dir = media_dir
        self.player = None
        self.subtitles = True

    def play(self, filename):
        if self.player:
            self.player.quit()
            self.player = None
        video_path = Path(self.media_dir + filename)
        self.player = OMXPlayer(video_path, args=['--no-osd'])

    def quit(self):
        self.player.quit()
        self.player = None

    def pause(self):
        self.player.play_pause()

    def seek(self, val):
        self.player.set_position(val)

    def set_volume(self, val):
        self.player.set_volume(val)

    def toggle_subtitles(self):
        if self.subtitles:
            self.player.hide_subtitles()
        else:
            self.player.show_subtitles()
        self.subtitles = not self.subtitles

    def set_subtitle_track(self, val):
        self.player.select_subtitle(val)

    @property
    def status(self):
        if self.player != None:
            return {
                'time': int(self.player.position()),
                'length': int(self.player.duration()),
                'volume': int(self.player.volume()),
                'subtitle_tracks': self.player.list_subtitles()
            }
        return {'time': 0, 'length': 0, 'volume': 0, 'subtitle_tracks': []}
Exemplo n.º 2
0
class VideoPlayerScreen(Screen):
    slider = ObjectProperty()
    minimized = BooleanProperty(True)
    video_path = StringProperty()  # 20200308tagesthemen.mp4

    def is_playing(self):
        if hasattr(self, 'player'):
            try:
                return self.player.is_playing()
            except OMXPlayerDeadError:
                self.leave_player()
                return False
        else:
            return False

    def set_play_pause_bttn(self, *args):
        print(self.ids)
        if self.is_playing():
            self.ids.play_pause_image.source = 'atlas://data/images/defaulttheme/media-playback-pause'
        else:
            self.ids.play_pause_image.source = 'atlas://data/images/defaulttheme/media-playback-start'

    def play(self):
        VIDEO_PATH = Path("videos/" + self.video_path)
        print(VIDEO_PATH)
        self.player = OMXPlayer(VIDEO_PATH,
                                args=['-o', 'alsa', '--layer', '100000'])
        self.player.set_video_pos(0, 0, 800, 480)
        self.set_slider()
        self.change_size()
        Clock.schedule_interval(self.set_slider, 3)
        Clock.schedule_interval(self.set_play_pause_bttn, 1)

    def player_stop(self):
        Clock.unschedule(self.set_play_pause_bttn)
        Clock.unschedule(self.set_slider)
        if self.is_playing():
            self.player.stop()

    @staticmethod
    def leave_player():
        App.get_running_app().root.current = 'base'

    def play_pause(self):
        self.player.play_pause()

    def quit(self, gg, **kwargs):
        self.player.quit()
        App.get_running_app().stop()

    def set_slider(self, *args):
        try:
            pos = self.player.position()  # in seconds as int
            duration = self.player.duration()  # in seconds as float
            self.slider.value_normalized = pos / duration
        except OMXPlayerDeadError:
            self.leave_player()

    def set_videopos(self, *args):
        pos = self.player.position()  # in seconds as int
        duration = self.player.duration()  # in seconds as float
        if abs(pos / duration - self.slider.value_normalized) > 0.05:
            self.player.set_position(self.slider.value_normalized * duration)

    def change_size(self):

        if self.minimized:
            self.player.set_alpha(255)
        else:
            self.player.set_alpha(100)
        self.minimized = not self.minimized
Exemplo n.º 3
0
class VideoPlayer:
    def __init__(self, root, message_handler, data, name):
        self.root = root
        self.message_handler = message_handler
        self.data = data
        self.omx_player = None
        self.name = name
        self.omx_running = False
        self.status = 'EMPTY'
        self.total_length = 0.0
        self.bankslot_number = '*-*'
        self.start = -1.0
        self.end = -1.0
        self.rate = 1
        self.crop_length = 0.0
        self.location = ''
        self.load_attempts = 0
        self.alpha = 0

    def try_load(self, layer):
        load_attempts = 0
        while (load_attempts < 2):
            load_attempts = load_attempts + 1
            if self.load(layer):
                print('load success')
                return True
            else:
                print('load failed')
        self.message_handler.set_message('ERROR', 'failed to load')
        self.status = 'ERROR'
        return False

    def load(self, layer):
        #try:
        self.get_context_for_player()
        is_dev_mode, first_screen_arg, second_screen_arg = self.set_screen_size_for_dev_mode(
        )
        arguments = [
            '--no-osd', '--layer',
            str(layer), '--adev', 'local', '--alpha', '0', first_screen_arg,
            second_screen_arg
        ]
        if not is_dev_mode:
            arguments.append('--blank=0x{}'.format(
                self.data.get_background_colour()))
        self.status = 'LOADING'
        print('the location is {}'.format(self.location))
        if self.location == '':
            self.status = 'EMPTY'
            return True
        self.omx_player = OMXPlayer(self.location,
                                    args=arguments,
                                    dbus_name=self.name)
        self.omx_running = True
        self.total_length = self.omx_player.duration(
        )  # <-- uneeded once self.duration stores float
        if (self.end is -1):
            self.end = self.total_length
        if (self.start is -1):
            self.start = 0
        self.crop_length = self.end - self.start
        print('{}: the duration is {}'.format(self.name, self.total_length))
        if self.start > 0.9:
            self.set_position(self.start - 0.9)
        if 'show' in self.data.settings['sampler']['ON_LOAD']['value']:
            self.set_alpha_value(255)
        else:
            self.set_alpha_value(0)
        self.pause_at_start()
        return True
        #except (ValueError, SystemError) as e:
        #  print(e)
        #self.message_handler.set_message('ERROR', 'load attempt fail')
        #return False

    def pause_at_start(self):
        position = self.get_position()
        start_threshold = round(self.start - 0.02, 2)
        if position > start_threshold:
            if self.status == 'LOADING':
                self.status = 'LOADED'
                self.omx_player.pause()
        elif self.omx_running:
            self.root.after(5, self.pause_at_start)

    def start_video(self):
        if 'show' in self.data.settings['sampler']['ON_START']['value']:
            self.set_alpha_value(255)
        else:
            self.set_alpha_value(0)
        if 'play' in self.data.settings['sampler']['ON_START']['value']:
            self.status = 'PLAYING'
            self.omx_player.play()
        else:
            self.status = 'START'
        self.pause_at_end()

    def pause_at_end(self):
        position = self.get_position()
        end_threshold = self.end - 0.2
        if (position > end_threshold):
            self.status = 'FINISHED'
            self.omx_player.pause()

            print('its paused at end!')
        elif (self.omx_running):
            self.root.after(5, self.pause_at_end)

    def reload(self, layer):
        self.exit()
        self.omx_running = False
        self.try_load(layer)

    def is_loaded(self):
        return self.status is 'LOADED'

    def is_finished(self):
        return self.status is 'FINISHED'

    def get_position(self):
        try:
            return self.omx_player.position()
        except:
            print('{}: error get_position'.format(self.name))
            return -1

    def get_context_for_player(self):
        next_context = self.data.get_next_context()
        self.location = next_context['location']
        #self.total_length = next_context['length']
        self.start = next_context['start']
        self.end = next_context['end']
        self.bankslot_number = next_context['bankslot_number']
        self.rate = next_context['rate']

    def toggle_pause(self):
        self.omx_player.play_pause()
        self.status = self.omx_player.playback_status().upper()

    def toggle_show(self):
        if self.alpha > 127:
            self.show_toggle_on = False
            self.set_alpha_value(0)
        else:
            self.show_toggle_on = True
            self.set_alpha_value(255)

    def set_alpha_value(self, amount):
        self.omx_player.set_alpha(amount)
        self.alpha = amount

    def seek(self, amount):
        position = self.get_position()
        after_seek_position = position + amount
        if after_seek_position > self.start and after_seek_position < self.end:
            self.set_position(after_seek_position)
            #self.player.seek(amount)
        else:
            self.message_handler.set_message('INFO',
                                             'can not seek outside range')

    def change_rate(self, amount):
        new_rate = self.rate + amount
        if (new_rate > self.omx_player.minimum_rate()
                and new_rate < self.omx_player.maximum_rate()):
            updated_speed = self.omx_player.set_rate(new_rate)
            self.rate = new_rate
            print('max rate {} , min rate {} '.format(
                self.omx_player.maximum_rate(),
                self.omx_player.minimum_rate()))
            return new_rate
        else:
            self.message_handler.set_message(
                'INFO', 'can not set speed outside of range')
            return self.rate

    def set_position(self, position):
        self.omx_player.set_position(position)

    def exit(self):
        try:
            self.omx_player.quit()
            self.status = 'EMPTY'
            self.omx_running = False
        except:
            pass

    def set_screen_size_for_dev_mode(self):
        ## only dev mode is needed now that auto handles all modes... can be removed probably ...
        if self.data.settings['other']['DEV_MODE_RESET']['value'] == 'on':
            return True, '--win', '50,350,550,750'
        else:
            aspect_mode = self.data.settings['video']['SCREEN_MODE']['value']
            return False, '--aspect-mode', aspect_mode
Exemplo n.º 4
0
class VideoPlayerScreen(Screen):
    slider = ObjectProperty()
    minimized = BooleanProperty(False)

    @staticmethod
    def clearbckgrnd():
        Window.clearcolor = (0, 0, 0, 0)

    @staticmethod
    def addbckgrnd():
        Window.clearcolor = (0, 0, 0, 1)

    def play(self):
        VIDEO_PATH = Path("../videos/20200308tagesthemen.mp4")

        self.player = OMXPlayer(VIDEO_PATH,
                                args=['-o', 'alsa', '--layer', '10000'])
        #self.player = OMXPlayer('/home/pi/Documents/Radio/videos/20200223tagesthemen.mp4')
        self.player.set_video_pos(0, 0, 800, 480)
        #self.player.hide_video()
        #self.player.show_video()
        self.player.set_alpha(100)
        self.set_slider()
        #Clock.schedule_once(self.quit, 20)
        Clock.schedule_interval(self.set_slider, 3)

    def playpause(self):
        self.player.play_pause()

    def quit(self, gg, **kwargs):
        self.player.quit()
        App.get_running_app().stop()

    def set_slider(self, *args):
        pos = self.player.position()  # in seconds as int
        duration = self.player.duration()  # in seconds as float
        #return pos/duration
        self.slider.value_normalized = pos / duration
        #return 0.5

    def set_videopos(self, *args):
        pos = self.player.position()  # in seconds as int
        duration = self.player.duration()  # in seconds as float
        if abs(pos / duration - self.slider.value_normalized) > 0.05:
            self.player.set_position(self.slider.value_normalized * duration)

    def change_size(self):
        # pass
        #width 800
        #height 480

        # check if crop as alternative

        if self.minimized:
            # self.player.set_video_pos(2,2,798,478)
            self.player.set_alpha(255)
        else:
            # self.player.set_video_pos(2,2,798,418)
            self.player.set_alpha(100)

        self.minimized = not self.minimized
Exemplo n.º 5
0
class VideoPlayer(object):
    def __init__(self):
        self.player = None
        self.logger = LogObject('Video Player')
        self.args = ['-b']

        self.STATUS_MAP = {
            'volume': self._videoVolume,
            'length': self._videoLength,
            'playback': self._playbackStatus,
            'position': self._videoPosition
        }

        self.CONTROL_MAP = {
            'playpause': self._playPause,
            'stop': self._stop,
            'mute': self._mute,
            'unmute': self._unmute,
            'play': self._play,
            'pause': self._pause
        }

        self.SEEK_MAP = {'relative': self._seek, 'absolute': self._setPosition}

    def playUrl(self, url):

        if not self.player:
            self.player = OMXPlayer(url, args=self.args)
        else:
            self.player.load(url)

    def setVolume(self, volume):
        self._checkPlayerExist()
        try:
            self.player.set_volume(volume)
            return self.logger.writeAndReturnLog('VOL0003', {'volume': volume})
        except (AttributeError, OMXPlayerDeadError):
            self._raisePlayerError('VOL0004')

    def sendCommand(self, command):
        self._checkPlayerExist()
        try:
            return self.CONTROL_MAP[command]()
        except (AttributeError, OMXPlayerDeadError):
            self._raisePlayerError('CTRL0003')

    def _stop(self):
        self.player.quit()
        return self.logger.writeAndReturnLog('CTRL0004')

    def _mute(self):
        self.player.mute()
        return self.logger.writeAndReturnLog('CTRL0006')

    def _unmute(self):
        self.player.unmute()
        return self.logger.writeAndReturnLog('CTRL0007')

    def _playPause(self):
        self.player.play_pause()
        return self.logger.writeAndReturnLog('CTRL0005')

    def _play(self):
        self.player.play()
        return self.logger.writeAndReturnLog('CTRL0008')

    def _pause(self):
        self.player.pause()
        return self.logger.writeAndReturnLog('CTRL0009')

    def seek(self, option, time):
        self._checkPlayerExist()
        try:
            return self.SEEK_MAP[option](time)
        except (AttributeError, OMXPlayerDeadError):
            self._raisePlayerError('SEEK0007')

    def _seek(self, seekTime):
        self.player.seek(seekTime)
        return self.logger.writeAndReturnLog('SEEK0005',
                                             {'position': seekTime})

    def _setPosition(self, position):
        if position > self._videoLength() or position < 0:
            self._raisePlayerError('SEEK0004', {'position': position})
        self.player.set_position(position)
        return self.logger.writeAndReturnLog('SEEK0006',
                                             {'position': position})

    def _checkPlayerExist(self):
        if not self.player:
            self._raisePlayerError('CTRL0003')

    def videoStatus(self, status):
        if not self.player:
            self._raisePlayerError('STAT0003')
        try:
            return self.STATUS_MAP[status]()
        except (AttributeError, OMXPlayerDeadError):
            self._raisePlayerError('STAT0003')

    def _videoPosition(self):
        return self.player.position()

    def _videoLength(self):
        return self.player.duration()

    def _videoVolume(self):
        return self.player.volume()

    def _playbackStatus(self):
        return self.player.playback_status()

    def _raisePlayerError(self, logReference, variablesDict={}):
        returnMsg = self.logger.writeAndReturnLog(logReference, variablesDict)
        raise PlayerError(returnMsg)
Exemplo n.º 6
0
class Omx:
    def __init__(self, media_folder):
        self.player = None
        self.media_folder = media_folder
        self.expects_loading_exit = False
        self.looping = False

    def play(self, filename, loop=False):
        if self.player:
            self.expects_loading_exit = True
            self.player.load(filename)
        else:
            args = ['-b', '--no-osd', '-o', 'both']

            if loop:
                args += ['--loop']
                self.looping = True
            else:
                self.looping = False

            try:
                self.player = OMXPlayer(filename, args=args)
            except SystemError as e:
                print(e)

            self.player.stopEvent += self.on_player_stop
            self.player.exitEvent += self.on_player_exit

    def on_player_stop(self, player):
        self.player = None

    def on_player_exit(self, player, exit_status):
        if self.expects_loading_exit:
            self.expects_loading_exit = False
        else:
            self.player = None

    def stop(self):
        if not self.player:
            return

        self.player.stop()
        self.player = None

    def pause(self):
        if not self.player:
            return

        self.player.play_pause()

    def seek_fraction(self, fraction):
        if not self.player:
            return

        duration = self.player.duration()
        self.player.set_position(fraction * duration)

    def set_volume(self, volume):
        if not self.player:
            return

        if volume > 10:
            volume = 10
        elif volume < 0:
            volume = 0

        self.player.set_volume(volume)

    def get_source(self):
        """ Get player source and remove media folder """
        source = self.player.get_source()
        if source.startswith(self.media_folder + "/"):
            return source[len(self.media_folder) + 1:]
        else:
            return source

    def status(self):
        if not self.player:
            return {
                'status': 'stopped',
                'source': None,
            }

        return {
            'status': self.player.playback_status(),
            'source': self.get_source(),
            'position': self.player.position(),
            'duration': self.player.duration(),
            'volume': self.player.volume(),
            'looping': self.looping,
        }
Exemplo n.º 7
0
class MyOMXPlayer:
    def __init__(self, config):
        """Create an instance of a video player that runs omxplayer in the
        background.
        """
        self._process = None
        self._player = None
        self._temp_directory = None
        self._load_config(config)

    def __del__(self):
        if self._temp_directory:
            shutil.rmtree(self._temp_directory)

    def _get_temp_directory(self):
        if not self._temp_directory:
            self._temp_directory = tempfile.mkdtemp()
        return self._temp_directory

    def _load_config(self, config):
        self._extensions = config.get('omxplayer', 'extensions') \
                                 .translate(str.maketrans('', '', ' \t\r\n.')) \
                                 .split(',')
        self._extra_args = config.get('omxplayer', 'extra_args').split()
        self._sound = config.get('omxplayer', 'sound').lower()
        assert self._sound in (
            'hdmi', 'local', 'both', 'alsa'
        ), 'Unknown omxplayer sound configuration value: {0} Expected hdmi, local, both or alsa.'.format(
            self._sound)
        self._alsa_hw_device = parse_hw_device(config.get('alsa', 'hw_device'))
        if self._alsa_hw_device != None and self._sound == 'alsa':
            self._sound = 'alsa:hw:{},{}'.format(self._alsa_hw_device[0],
                                                 self._alsa_hw_device[1])
        self._show_titles = config.getboolean('omxplayer', 'show_titles')
        if self._show_titles:
            title_duration = config.getint('omxplayer', 'title_duration')
            if title_duration >= 0:
                m, s = divmod(title_duration, 60)
                h, m = divmod(m, 60)
                self._subtitle_header = '00:00:00,00 --> {:d}:{:02d}:{:02d},00\n'.format(
                    h, m, s)
            else:
                self._subtitle_header = '00:00:00,00 --> 99:59:59,00\n'

    def supported_extensions(self):
        """Return list of supported file extensions."""
        return self._extensions

    def player_stop(self):
        self._player = None

    def play(self, movie, loop=None, vol=0):
        """Play the provided movie file, optionally looping it repeatedly."""
        self.stop(3)  # Up to 3 second delay to let the old player stop.
        # Assemble list of arguments.
        #args = ['omxplayer']
        args = []
        args.extend(['-o', self._sound])  # Add sound arguments.
        args.extend(self._extra_args)  # Add extra arguments from config.
        if vol is not 0:
            args.extend(['--vol', str(vol)])
        if loop is None:
            loop = movie.repeats
        if loop <= -1:
            args.append('--loop')  # Add loop parameter if necessary.
        #if self._show_titles and movie.title:
        #    srt_path = os.path.join(self._get_temp_directory(), 'video_looper.srt')
        #    with open(srt_path, 'w') as f:
        #        f.write(self._subtitle_header)
        #        f.write(movie.title)
        #    args.extend(['--subtitles', srt_path])
        #args.append(movie.filename)       # Add movie file path.
        # Run omxplayer process and direct standard output to /dev/null.
        #self._process = subprocess.Popen(args,
        #                                 stdout=open(os.devnull, 'wb'),
        #                                 close_fds=True)


#        OMXPlayer('path.mp4', args='--no-osd --no-keys -b')
        self._player = OMXPlayer(movie.filename,
                                 dbus_name='org.mpris.MediaPlayer2.omxplayer1',
                                 args=args)
        self._player.stopEvent = self.player_stop

    # if vol is not 0:
    #    self._player.set_volume(str(vol))

    def is_playing(self):
        """Return true if the video player is running, false otherwise."""
        #if self._process is None:
        #    return False
        #self._process.poll()
        #return self._process.returncode is None
        if self._player is None:
            return False
        try:
            if self._player.playback_status() is "Stopped":
                self._player = None
                return False
            else:
                return True
        except:
            self._player = None
            return False
        #if self._player.playback_status() is "Stopped":
        #    return False
        #return self._player.is_playing()
        return True

    def pause(self):
        #subprocess.call(['/home/pi/pi_video_looper/Adafruit_Video_Looper/dbuscontrol.sh', 'pause'])
        if self._player is not None:
            self._player.play_pause()

    def resume(self):
        #subprocess.call(['/home/pi/pi_video_looper/Adafruit_Video_Looper/dbuscontrol.sh', 'play'])
        if self._player is not None:
            self._player.play_pause()

    def stop(self, block_timeout_sec=0):
        """Stop the video player.  block_timeout_sec is how many seconds to
        block waiting for the player to stop before moving on.
        """
        # Stop the player if it's running.
        #if self._process is not None and self._process.returncode is None:
        # There are a couple processes used by omxplayer, so kill both
        # with a pkill command.
        #    subprocess.call(['pkill', '-9', 'omxplayer'])
        # If a blocking timeout was specified, wait up to that amount of time
        # for the process to stop.
        #start = time.time()
        #while self._process is not None and self._process.returncode is None:
        #    if (time.time() - start) >= block_timeout_sec:
        #        break
        #    time.sleep(0)
        # Let the process be garbage collected.
        #self._process = None
        if self._player is not None:
            self._player.quit()
        self._player = None

    @staticmethod
    def can_loop_count():
        return False
Exemplo n.º 8
0
class PlaybackController(object):
    def __init__(self):
        self.player = None
        self.queue = []
        self.current_playbackitem = None
        self.volume = 0.6

    def __str__(self):
        if self.current_playbackitem:
            return f"{self.get_status()} {self.current_playbackitem.get_title()}. {len(self.queue)} items in queue."
        else:
            return f"{self.get_status()}. {len(self.queue)} items in queue."

    def get_title(self):
        if self.current_playbackitem:
            return self.current_playbackitem.get_title()
        else:
            return "Not playing anything."

    def _on_omxplayer_exit(self, player, exit_status):
        log.info("OMXPlayer exit: {}".format(exit_status))
        self.player = None
        if exit_status == 0:
            self.current_playbackitem = None
            self._new_player()

    def _new_player(self):
        """Creates a new player by popping from queue."""
        log.info("Creating new OMXplayer.")
        if self.player is not None:
            self.player.quit()
        if self.current_playbackitem is None:
            if len(self.queue) == 0:
                raise ValueError("Nothing to play.")
            else:
                self.current_playbackitem = self.queue.pop(0)
        log.info("Creating player for video: {}".format(
            self.current_playbackitem))
        self.player = OMXPlayer(self.current_playbackitem.get_direct_url())
        self.player.set_volume(self.volume)
        self.player.exitEvent.subscribe(self._on_omxplayer_exit)

    def add_single_url(self, url):
        n_item = PlaybackItem(url)
        if n_item is not None:
            self.queue.append(n_item)
            return True

        raise ValueError("Could not get URL")

    def playlist(self, url):
        log.info("Adding every videos from playlist to queue.")
        ydl = youtube_dl.YoutubeDL({
            'logger': log,
            'extract_flat': 'in_playlist',
            'ignoreerrors': True,
        })
        with ydl:  # Downloading youtub-dl infos
            result = ydl.extract_info(url, download=False)
            for i in result['entries']:
                logger.info("queuing video")
                if i != result['entries'][0]:
                    try:
                        if "://" not in i['url']:
                            self.add_single_url("https://youtube.com/?v=" +
                                                i['url'])
                        else:
                            self.add_single_url(i['url'])
                    except Exception as e:
                        log.error("Could not enqueue " + i['url'])
                        log.error(e)

    def play(self):
        if self.get_status() == "Playing":
            log.debug("Playback already playing.")
            return
        if self.player is None and len(self.queue) > 0:
            self._new_player()
        else:
            log.error("Nothing to play!")

    def stop(self):
        if self.player is not None:
            self.player.stop()
            self.player = None

    def playpause(self):
        if self.player is None:
            log.error("No player running.")
            if len(self.queue) > 0:
                self.play()
        else:
            self.player.play_pause()

    def pause(self):
        if self.get_status() == "Paused":
            log.debug("Playback is already paused.")
            return

    def seek(self, seconds):
        if self.player is None:
            raise Exception("Player is not running")
        self.player.seek(seconds)

    def change_volume(self, increment):
        self.volume += increment
        if self.volume < 0.0:
            self.volume = 0.0
        elif self.volume > 1.0:
            self.volume = 1.0
        if self.player is not None:
            self.player.set_volume(self.volume)

    def get_volume(self):
        if self.player is not None:
            return self.player.volume()
        else:
            return self.volume

    def get_status(self):
        if self.player is None:
            return "Stopped"
        try:
            return self.player.playback_status()
        except OMXPlayerDeadError:
            log.error("OMXPlayer is dead.")
            self.player = None
            return "Stopped"

    def next_video(self):
        self.stop()
        self.current_playbackitem = None
        self._new_player()

    def shutdown(self):
        self.stop()