Esempio n. 1
0
 def __init__(self):
     super(MpvPlayer, self).__init__()
     self._mpv = MPV(ytdl=False,
                     input_default_bindings=True,
                     input_vo_keyboard=True)
     self._playlist = Playlist()
     self._playlist.song_changed.connect(self._on_song_changed)
Esempio n. 2
0
    def __init__(self):
        self.queue = [[
            '_KhsQ3nn6Kw',
            'Wankelmut & Emma Louise - My Head Is A Jungle (MK Remix)', '',
            True
        ]]
        self.current_track = ['vzYYW8V3Ibc', 'Nothing', 'Nothing', False]

        self.player = MPV(ytdl=True, video=False)
        self.youtube = YoutubeWrapper()

        sp_oauth = spotipy.oauth2.SpotifyOAuth(scope=config.SPOTIPY_SCOPE,
                                               cache_path=config.SPOTIPY_CACHE)

        self.spotify = spotipy.Spotify(auth_manager=sp_oauth)

        devices = self.spotify.devices()
        print(json.dumps(devices, sort_keys=True, indent=4))
        device_id = devices['devices'][0]['id']

        results = self.spotify.search(q='Airwaves', type='track')
        print(
            json.dumps(results['tracks']['items'][0], sort_keys=True,
                       indent=4))
        self.spotify.start_playback(
            device_id, uris=[results['tracks']['items'][0]['uri']])
Esempio n. 3
0
    def __init__(self, audio_device=b'auto', winid=None, *args, **kwargs):
        super(MpvPlayer, self).__init__(*args, **kwargs)
        # https://github.com/cosven/FeelUOwn/issues/246
        locale.setlocale(locale.LC_NUMERIC, 'C')
        mpvkwargs = {}
        if winid is not None:
            mpvkwargs['wid'] = winid
        mpvkwargs['vo'] = 'opengl-cb'
        # set log_handler if you want to debug
        # mpvkwargs['log_handler'] = self.__log_handler
        # mpvkwargs['msg_level'] = 'all=v'
        logger.info('libmpv version %s', _mpv_client_api_version())
        self._mpv = MPV(ytdl=False,
                        input_default_bindings=True,
                        input_vo_keyboard=True,
                        **mpvkwargs)
        _mpv_set_property_string(self._mpv.handle, b'audio-device',
                                 audio_device)
        # old version libmpv(for example: (1, 20)) should set option by using
        # _mpv_set_option_string, while newer version can use _mpv_set_property_string
        _mpv_set_option_string(self._mpv.handle, b'user-agent',
                               b'Mozilla/5.0 (Windows NT 10.0; Win64; x64)')

        #: if video_format changes to None, there is no video available
        self.video_format_changed = Signal()
    def __init__(self, mpv_commands_async: bool, **properties):
        super().__init__(**properties)
        self.mpv_commands_async = mpv_commands_async

        self._proc_addr_wrapper = OpenGlCbGetProcAddrFn(get_process_address)

        self.ctx = None
        self.mpv = MPV(input_default_bindings=True,
                       input_vo_keyboard=True,
                       osc=True
                       # log_handler=print,
                       # loglevel='debug'
                       )

        self.connect("realize", self.on_realize)
        self.connect("render", self.on_render)
        self.connect("unrealize", self.on_unrealize)

        self.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
        self.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
        self.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK)
        # self.add_events(Gdk.EventMask.KEY_PRESS_MASK)
        # self.add_events(Gdk.EventMask.STRUCTURE_MASK)
        # self.add_events(Gdk.EventMask.SCROLL_MASK)

        self.connect("motion-notify-event", self.on_mouse_move_event)
        self.connect("button-press-event", self.on_button_press_event)
        self.connect("button-release-event", self.on_button_release_event)
Esempio n. 5
0
    def __init__(self, filename):
        self.filename = filename

        self.mpv = MPV(input_default_bindings=True, input_vo_keyboard=True)
        self.mpv.pause = True
        self.mpv.play(self.filename)

        self.mpv.wait_for_property("length")
        self.length = self.mpv.length * 1000
Esempio n. 6
0
 def __init__(self, parent=None):
     super().__init__(parent=parent)
     self.mpv = MPV(vo='opengl-cb', ytdl=True)
     self.mpv_gl = _mpv_get_sub_api(self.mpv.handle,
                                    MpvSubApi.MPV_SUB_API_OPENGL_CB)
     self.on_update_c = OpenGlCbUpdateFn(self.on_update)
     self.on_update_fake_c = OpenGlCbUpdateFn(self.on_update_fake)
     self.get_proc_addr_c = OpenGlCbGetProcAddrFn(get_proc_addr)
     _mpv_opengl_cb_set_update_callback(self.mpv_gl, self.on_update_c, None)
     self.frameSwapped.connect(self.swapped, Qt.DirectConnection)
Esempio n. 7
0
    def __init__(self, audio_device=b'auto', *args, **kwargs):
        super(MpvPlayer, self).__init__()
        self._mpv = MPV(ytdl=False,
                        input_default_bindings=True,
                        input_vo_keyboard=True)

        _mpv_set_property_string(self._mpv.handle, b'audio-device',
                                 audio_device)

        self._playlist = Playlist()
        self._playlist.song_changed.connect(self._on_song_changed)
Esempio n. 8
0
class MpvWidget(QOpenGLWidget):
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.mpv = MPV(vo='opengl-cb', ytdl=True)
        self.mpv_gl = _mpv_get_sub_api(self.mpv.handle,
                                       MpvSubApi.MPV_SUB_API_OPENGL_CB)
        self.on_update_c = OpenGlCbUpdateFn(self.on_update)
        self.on_update_fake_c = OpenGlCbUpdateFn(self.on_update_fake)
        self.get_proc_addr_c = OpenGlCbGetProcAddrFn(get_proc_addr)
        _mpv_opengl_cb_set_update_callback(self.mpv_gl, self.on_update_c, None)
        self.frameSwapped.connect(self.swapped, Qt.DirectConnection)

    def initializeGL(self):
        _mpv_opengl_cb_init_gl(self.mpv_gl, None, self.get_proc_addr_c, None)

    def paintGL(self):
        # compatible with HiDPI display
        ratio = self.windowHandle().devicePixelRatio()
        w = int(self.width() * ratio)
        h = int(self.height() * ratio)
        _mpv_opengl_cb_draw(self.mpv_gl, self.defaultFramebufferObject(), w,
                            -h)

    @pyqtSlot()
    def maybe_update(self):
        if self.window().isMinimized():
            self.makeCurrent()
            self.paintGL()
            self.context().swapBuffers(self.context().surface())
            self.swapped()
            self.doneCurrent()
        else:
            self.update()

    def on_update(self, ctx=None):
        # HELP: maybeUpdate 中的部分逻辑需要在主线程中执行,
        # 而 QMetaObject.invokeMethod 似乎正好可以达到这个目标。
        # 我们将 maybe_update 标记为 pyqtSlot,这样才能正确的 invoke。
        QMetaObject.invokeMethod(self, 'maybe_update')

    def on_update_fake(self, ctx=None):
        pass

    def swapped(self):
        _mpv_opengl_cb_report_flip(self.mpv_gl, 0)

    def closeEvent(self, _):
        self.makeCurrent()
        if self.mpv_gl:
            _mpv_opengl_cb_set_update_callback(self.mpv_gl,
                                               self.on_update_fake_c, None)
        _mpv_opengl_cb_uninit_gl(self.mpv_gl)
        self.mpv.terminate()
Esempio n. 9
0
File: omp.py Progetto: McSinyx/comp
 def __new__(cls, entries, json_file, mode, mpv_vid, mpv_vo, ytdlf):
     self = super(Comp, cls).__new__(cls)
     self.play_backward, self.reading = False, False
     self.playing = -1
     self.json_file, self.mode, self.vid = json_file, mode, mpv_vid
     self.entries, self.played = entries, []
     self.playlist, self.search_res = iter(()), deque()
     self.mp = MPV(input_default_bindings=True,
                   input_vo_keyboard=True,
                   ytdl=True,
                   ytdl_format=ytdlf)
     return self
Esempio n. 10
0
class MpvPlayer(PlayerBase):
    def __init__(self, flags: Optional[str] = None) -> None:
        super().__init__()

        # Converting the flags passed by parameter (str) to a tuple
        flags = flags.split() if flags not in (None, '') else []
        # The audio is always muted, which is needed because not all the
        # youtube-dl videos are silent. The keep-open flag stops mpv from
        # closing after the video is over.
        flags.extend(['mute', 'keep-open'])

        args = {}
        if logging.root.level <= logging.INFO:
            args['log_handler'] = print
            args['loglevel'] = 'info'
        args['wid'] = str(int(self.winId()))
        args['vo'] = 'gpu,libmpv,x11'
        args['input_default_bindings'] = False
        args['config'] = False

        self._mpv = MPV(*flags, **args)

    def __del__(self) -> None:
        try:
            self._mpv.terminate()
        except AttributeError:
            pass

    @property
    def pause(self) -> bool:
        return self._mpv.pause

    @pause.setter
    def pause(self, do_pause: bool) -> None:
        logging.info("Playing/Pausing video")
        self._mpv.pause = do_pause

    @property
    def position(self) -> int:
        time = self._mpv.playback_time
        return round(time * 1000) if time is not None else 0

    @position.setter
    def position(self, ms: int) -> None:
        """
        Mpv will throw an error if the position is changed before the video
        starts, so this waits for 'seekable' to be set to True.
        """

        self._mpv.wait_for_property('seekable')
        logging.info("Position set to %d milliseconds", ms)
        self._mpv.seek(round(ms / 1000, 2), reference='absolute')

    def start_video(self, media: str, is_playing: bool = True) -> None:
        logging.info("Started new video")
        self._mpv.play(media)
        # Mpv starts automatically playing the video
        if not is_playing:
            self.pause = True
Esempio n. 11
0
    def __init__(self, flags: Optional[str] = None) -> None:
        super().__init__()

        # Converting the flags passed by parameter (str) to a tuple
        flags = flags.split() if flags not in (None, '') else []
        flags.extend(self.DEFAULT_FLAGS)

        args = {}
        if logging.root.level <= logging.INFO:
            args['log_handler'] = print
            args['loglevel'] = 'info'
        args['wid'] = str(int(self.winId()))  # sip.voidptr -> int -> str
        args.update(self.DEFAULT_ARGS)

        self._mpv = MPV(*flags, **args)
Esempio n. 12
0
    def __init__(self, filename):
        self.filename = filename
        self.open = True

        self.fbo = gl.glGenFramebuffers(1)
        gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.fbo)

        self.texture = gl.glGenTextures(1)
        gl.glBindTexture(gl.GL_TEXTURE_2D, self.texture)

        gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER,
                           gl.GL_LINEAR)
        gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER,
                           gl.GL_LINEAR)

        gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0,
                                  gl.GL_TEXTURE_2D, self.texture, 0)

        gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, 100, 100, 0, gl.GL_RGB,
                        gl.GL_UNSIGNED_BYTE, None)

        gl.glBindTexture(gl.GL_TEXTURE_2D, 0)
        gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0)

        self.playbackPos = (0, )
        self.volume = (0, )
        self.loop = 'inf'

        self.mpv = MPV(log_handler=print, loglevel='debug')

        def get_process_address(_, name):
            print(name)
            address = glfw.get_proc_address(name.decode('utf8'))
            return ctypes.cast(address, ctypes.c_void_p).value

        proc_addr_wrapper = OpenGlCbGetProcAddrFn(get_process_address)

        self.ctx = MpvRenderContext(
            self.mpv,
            'opengl',
            opengl_init_params={'get_proc_address': proc_addr_wrapper})

        self.mpv.play(self.filename)
        self.mpv.volume = 0
Esempio n. 13
0
class MPV(PlayerInterface, Logging):
    def __init__(self, args: tuple) -> None:
        self._player = Player(input_default_bindings=True,
                              input_vo_keyboard=True,
                              **args)

        def callback(name: str, handler: Callable) -> None:
            def wrap(*a: tuple, **kw: dict) -> None:
                handler(*a, **kw)

            self._player.event_callback(name)(wrap)

        callback('shutdown', self.event_shutdown)

    def stop(self):
        self._player.quit()
        self._player = None

    def pause(self):
        self._player.pause = not self._player.pause

    def osd(self, level):
        self._player.osd_level = level

    def osd_level(self):
        return self._player.osd_level

    @property
    def current_volume(self):
        return self._player.volume

    def volume(self, value):
        self._player.volume = value

    def __getattr__(self, name):
        try:
            return super().__getattr__(name)
        except TypeError:
            pass

    def event_shutdown(self, data, *a, **kw):
        pass

    @property
    def length(self):
        return self.duration

    def message(self, msg, duration):
        self._player.show_message(msg, duration)

    def show_progress(self):
        self._player.show_progress()
Esempio n. 14
0
    def __init__(self, args: tuple) -> None:
        self._player = Player(input_default_bindings=True,
                              input_vo_keyboard=True,
                              **args)

        def callback(name: str, handler: Callable) -> None:
            def wrap(*a: tuple, **kw: dict) -> None:
                handler(*a, **kw)

            self._player.event_callback(name)(wrap)

        callback('shutdown', self.event_shutdown)
Esempio n. 15
0
    def __init__(self, audio_device=b'auto', winid=None, *args, **kwargs):
        super(MpvPlayer, self).__init__(*args, **kwargs)
        # https://github.com/cosven/FeelUOwn/issues/246
        locale.setlocale(locale.LC_NUMERIC, 'C')
        mpvkwargs = {}
        if winid is not None:
            mpvkwargs['wid'] = winid
        mpvkwargs['vo'] = 'opengl-cb'
        # set log_handler if you want to debug
        # mpvkwargs['log_handler'] = self.__log_handler
        # mpvkwargs['msg_level'] = 'all=v'
        # the default version of libmpv on Ubuntu 18.04 is (1, 25)
        self._version = _mpv_client_api_version()
        self._mpv = MPV(ytdl=False,
                        input_default_bindings=True,
                        input_vo_keyboard=True,
                        **mpvkwargs)
        _mpv_set_property_string(self._mpv.handle, b'audio-device',
                                 audio_device)
        # old version libmpv(for example: (1, 20)) should set option by using
        # _mpv_set_option_string, while newer version can use _mpv_set_property_string
        _mpv_set_option_string(self._mpv.handle, b'user-agent',
                               b'Mozilla/5.0 (Windows NT 10.0; Win64; x64)')

        #: if video_format changes to None, there is no video available
        self.video_format_changed = Signal()

        self._mpv.observe_property(
            'time-pos',
            lambda name, position: self._on_position_changed(position))
        self._mpv.observe_property(
            'duration',
            lambda name, duration: self._on_duration_changed(duration))
        self._mpv.observe_property(
            'video-format',
            lambda name, vformat: self._on_video_format_changed(vformat))
        # self._mpv.register_event_callback(lambda event: self._on_event(event))
        self._mpv._event_callbacks.append(self._on_event)
        logger.debug('Player initialize finished.')
Esempio n. 16
0
class MpvPlayer(PlayerBase):
    # The audio is always muted, which is needed because not all the
    # youtube-dl videos are silent. The keep-open flag stops mpv from closing
    # after the video is over.
    DEFAULT_FLAGS = ['mute']
    DEFAULT_ARGS = {
        'vo': 'gpu,libmpv,x11',
        'config': False,
        'keep-open': 'always'
    }

    def __init__(self, flags: Optional[str] = None) -> None:
        super().__init__()

        # Converting the flags passed by parameter (str) to a tuple
        flags = flags.split() if flags not in (None, '') else []
        flags.extend(self.DEFAULT_FLAGS)

        args = {}
        if logging.root.level <= logging.INFO:
            args['log_handler'] = print
            args['loglevel'] = 'info'
        args['wid'] = str(int(self.winId()))  # sip.voidptr -> int -> str
        args.update(self.DEFAULT_ARGS)

        self._mpv = MPV(*flags, **args)

    @property
    def pause(self) -> bool:
        return self._mpv.pause

    @pause.setter
    def pause(self, do_pause: bool) -> None:
        logging.info("Playing/Pausing video")
        self._mpv.pause = do_pause

    @property
    def position(self) -> int:
        time = self._mpv.playback_time
        return round(time * 1000) if time is not None else 0

    def seek(self, ms: int, relative: bool = False) -> None:
        """
        Mpv will throw an error if the position is changed before the video
        starts, so this waits for 'seekable' to be set to True.
        """

        self._mpv.wait_for_property('seekable')
        logging.info("Position set to %d milliseconds", ms)
        self._mpv.seek(round(ms / 1000, 2),
                       reference='relative' if relative else 'absolute')

    def start_video(self, media: str, is_playing: bool = True) -> None:
        logging.info("Started new video")
        self._mpv.play(media)
        # Mpv starts automatically playing the video
        if not is_playing:
            self.pause = True
Esempio n. 17
0
    def init_player(self):

        def mpv_log(loglevel, component, message):
            self.print('Mpv log: [{}] {}: {}'.format(loglevel, component, message))

        mpv_args = []
        mpv_kw = {
            'wid': int(self.ui.video.winId()),
            'keep-open': 'yes',
            'rebase-start-time': 'no',
            'framedrop': 'no',
            'osd-level': '2',
            'osd-fractions': 'yes',
        }
        for opt in self.mpv_options:
            if '=' in opt:
                k, v = opt.split('=', 1)
                mpv_kw[k] = v
            else:
                mpv_args.append(opt)

        player = MPV(*mpv_args, log_handler=mpv_log, **mpv_kw)
        self.player = player
        player.pause = True

        def on_player_loaded():
            if self.ffmpeg_bin:
                self.check_ffmpeg_seek_problem()
            self.load_state()
            self.ui.loading.hide()
            self.state_loaded = True

        self.player_loaded.connect(on_player_loaded)

        def on_playback_len(s):
            self.playback_len = s
            player.unobserve_property('duration', on_playback_len)

        def on_playback_pos(s):
            if self.playback_pos is None:
                self.player_loaded.emit()
            self.playback_pos = s
            self.statusbar_update.emit()
            self.ui.seekbar.update()

        player.observe_property('time-pos', on_playback_pos)
        player.observe_property('duration', on_playback_len)
        player.play(self.filename)
Esempio n. 18
0
def mpv_extract_info(filename):
    """Return list of entries extracted from a path or URL using mpv. If
    an error occur during the extraction, return None.
    """
    mp = MPV(ytdl=True, vid=False)
    mp.play(filename)
    while mp.duration is None:
        sleep(0.25)
        if mp.playback_abort: return None
    info = {
        'filename': filename,
        'title': mp.media_title.decode(),
        'duration': mp.osd.duration,
        'error': False,
        'playing': False,
        'selected': False
    }
    mp.quit()
    return [info]
Esempio n. 19
0
import logging
import sys

from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
from mpv import MPV

# logging
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger()
logger.setLevel(logging.INFO)

mpv = MPV(ytdl=True, vo='null')


def start(update, context):
    update.message.reply_text("yo!")


def play(update, context):
    mpv.play(update.message.text)


def main():
    if len(sys.argv) != 2:
        print(f"usage: {sys.argv[0]} <token>")
        exit(1)

    updater = Updater(sys.argv[1], use_context=True)
Esempio n. 20
0
File: omp.py Progetto: McSinyx/comp
class Omp(object):
    """Omni Media Player meta object.

    Attributes:
        entries (list): list of all tracks
        json_file (str): path to save JSON playlist
        mode (str): the mode to pick and play tracks
        mp (MPV): an mpv instance
        play_backward (bool): flag show if to play the previous track
        play_list (list): list of tracks according to mode
        played (list): list of previously played tracks
        playing (int): index of playing track in played
        playlist (iterator): iterator of tracks according to mode
        search_res (iterator):  title-searched results
        vid (str): flag show if video output is enabled

    I/O handlers (defined by front-end):
        print_msg(message, error=False): print a message
        property_handler(name, val): called when a mpv property updated
        read_input(prompt): prompt for user input
        refresh(): update interface content
    """
    def __new__(cls, entries, json_file, mode, mpv_vid, mpv_vo, ytdlf):
        self = super(Comp, cls).__new__(cls)
        self.play_backward, self.reading = False, False
        self.playing = -1
        self.json_file, self.mode, self.vid = json_file, mode, mpv_vid
        self.entries, self.played = entries, []
        self.playlist, self.search_res = iter(()), deque()
        self.mp = MPV(input_default_bindings=True,
                      input_vo_keyboard=True,
                      ytdl=True,
                      ytdl_format=ytdlf)
        return self

    def __init__(self, entries, json_file, mode, mpv_vid, mpv_vo, ytdlf):
        if mpv_vo is not None: self.mp['vo'] = mpv_vo

        @self.mp.property_observer('mute')
        @self.mp.property_observer('pause')
        @self.mp.property_observer('time-pos')
        def observer(name, value):
            self.property_handler(name, value)

        self.mp.register_key_binding('q', lambda state, key: None)

    def __enter__(self):
        return self

    def update_play_list(self, pick):
        """Update the list of entries to be played."""
        if pick == 'current':
            self.play_list = [self.current()]
        elif pick == 'all':
            self.play_list = deque(self.entries)
            self.play_list.rotate(-self.idx())
        else:
            self.play_list = [i for i in self.entries if i.get('selected')]

    def update_playlist(self):
        """Update the playlist to be used by play function."""
        action, pick = self.mode.split('-')
        self.update_play_list(pick)
        if action == 'play':
            self.playlist = iter(self.play_list)
        elif action == 'repeat':
            self.playlist = cycle(self.play_list)
        else:
            self.playlist = iter(lambda: choice(self.play_list), None)
        if self.playing < -1: self.played = self.played[:self.playing + 1]

    def seek(self, amount, reference='relative', precision='default-precise'):
        """Wrap mp.seek with a try clause to avoid crash when nothing is
        being played.
        """
        try:
            self.mp.seek(amount, reference, precision)
        except:
            pass

    def next(self, force=False, backward=False):
        self.play_backward = backward
        if self.mp.idle_active:
            self.play(force)
        else:
            self.seek(100, 'absolute-percent')
            if force: self.mp.pause = False

    def search(self, backward=False):
        """Prompt then search for a pattern."""
        p = re.compile(self.gets('/'), re.IGNORECASE)
        entries = deque(self.entries)
        entries.rotate(-self.idx())
        self.search_res = deque(
            filter(lambda entry: p.search(entry['title']) is not None,
                   entries))
        if backward: self.search_res.reverse()
        if self.search_res:
            self.move(self.idx(self.search_res[0]) - self.idx())
        else:
            self.update_status(_("Pattern not found"), curses.color_pair(1))

    def next_search(self, backward=False):
        """Repeat previous search."""
        if self.search_res:
            self.search_res.rotate(1 if backward else -1)
            self.move(self.idx(self.search_res[0]) - self.idx())
        else:
            self.update_status(_("Pattern not found"), curses.color_pair(1))

    def dump_json(self):
        s = self.read_input(
            _("Save playlist to [{}]: ").format(self.json_file))
        self.json_file = abspath(expanduser(expandvars(s or self.json_file)))
        try:
            makedirs(dirname(self.json_file), exist_ok=True)
        except:
            errmsg = _("'{}': Can't open file for writing").format(
                self.json_file)
            self.print_msg(errmsg, error=True)
        else:
            with open(self.json_file, 'w') as f:
                json.dump(self.entries,
                          f,
                          ensure_ascii=False,
                          indent=2,
                          sort_keys=True)
            self.print_msg(_("'{}' written").format(self.json_file))

    def __exit__(self, exc_type, exc_value, traceback):
        self.mp.quit()
Esempio n. 21
0
class VideoPlayer:
    def terminate(self):
        self.ctx.free()
        self.mpv.terminate()

    def __init__(self, filename):
        self.filename = filename
        self.open = True

        self.fbo = gl.glGenFramebuffers(1)
        gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.fbo)

        self.texture = gl.glGenTextures(1)
        gl.glBindTexture(gl.GL_TEXTURE_2D, self.texture)

        gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER,
                           gl.GL_LINEAR)
        gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER,
                           gl.GL_LINEAR)

        gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0,
                                  gl.GL_TEXTURE_2D, self.texture, 0)

        gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, 100, 100, 0, gl.GL_RGB,
                        gl.GL_UNSIGNED_BYTE, None)

        gl.glBindTexture(gl.GL_TEXTURE_2D, 0)
        gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0)

        self.playbackPos = (0, )
        self.volume = (0, )
        self.loop = 'inf'

        self.mpv = MPV(log_handler=print, loglevel='debug')

        def get_process_address(_, name):
            print(name)
            address = glfw.get_proc_address(name.decode('utf8'))
            return ctypes.cast(address, ctypes.c_void_p).value

        proc_addr_wrapper = OpenGlCbGetProcAddrFn(get_process_address)

        self.ctx = MpvRenderContext(
            self.mpv,
            'opengl',
            opengl_init_params={'get_proc_address': proc_addr_wrapper})

        self.mpv.play(self.filename)
        self.mpv.volume = 0

    def render(self):

        videowindow, self.open = imgui.begin("Video window {}".format(
            self.filename),
                                             self.open,
                                             flags=imgui.WINDOW_NO_SCROLLBAR)

        w, h = imgui.get_window_size()

        if imgui.APPEARING:
            imgui.set_window_size(400, 300)

        w, h = imgui.core.get_content_region_available()
        w = int(max(w, 0))
        h = int(max(h - 85, 0))

        if not self.open:
            imgui.end()
            self.terminate()
            return

        if self.ctx.update() and w > 0 and h > 0:

            gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.fbo)
            gl.glBindTexture(gl.GL_TEXTURE_2D, self.texture)

            gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, w, h, 0, gl.GL_RGB,
                            gl.GL_UNSIGNED_BYTE, None)

            gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0)
            gl.glBindTexture(gl.GL_TEXTURE_2D, 0)

            self.ctx.render(flip_y=False,
                            opengl_fbo={
                                'w': w,
                                'h': h,
                                'fbo': self.fbo
                            })

        try:
            imgui.text("Filename: {} fbo: {} tex: {}".format(
                self.mpv.filename, self.fbo, self.texture))
        except:
            imgui.text("Filename: {} fbo: {} tex: {}".format(
                self.mpv.filename, self.fbo, self.texture))

        try:
            imgui.text("{0:.2f}s/{1:.2f}s ({2:.2f}s remaining)".format(
                self.mpv.time_pos, self.mpv.duration,
                self.mpv.playtime_remaining))
        except:
            imgui.text("Loading...")

        imgui.image(self.texture, w, h)

        imgui.push_item_width(-1)

        changed, values = imgui.slider_float("##Playback Percentage",
                                             *self.playbackPos,
                                             min_value=0.0,
                                             max_value=100.0,
                                             format="Playback Percentage %.0f",
                                             power=1.0)

        if changed and values:
            try:
                self.mpv.command('seek', values, 'absolute-percent')
            except:
                pass
            self.playbackPos = (values, )
        elif self.mpv.percent_pos:
            self.playbackPos = (self.mpv.percent_pos, )

        changed, values = imgui.slider_float("##Volume",
                                             *self.volume,
                                             min_value=0.0,
                                             max_value=100.0,
                                             format="Volume %.0f",
                                             power=1.0)

        if changed:
            self.mpv.volume = values
            self.volume = (values, )
        elif self.mpv.volume:
            self.volume = (self.mpv.volume, )

        imgui.end()
Esempio n. 22
0
class AudioPlayer:
    def __init__(self, filename):
        self.filename = filename

        self.mpv = MPV(input_default_bindings=True, input_vo_keyboard=True)
        self.mpv.pause = True
        self.mpv.play(self.filename)

        self.mpv.wait_for_property("length")
        self.length = self.mpv.length * 1000

    def position(self):
        return self.mpv.time_pos * 1000

    def progress(self):
        return self.position() / self.length

    def pause(self):
        self.mpv.pause = True

    def play(self):
        self.mpv.pause = False

    def toggle_pause(self):
        self.mpv.pause = not self.mpv.pause

    def seek_progress(self, progress):
        self.mpv.seek(self.mpv.length * progress, "absolute", "exact")

    def seek_relative(self, ms):
        self.mpv.time_pos += ms / 1000

    def observe_position(self, observer):
        def converting_observer(prop, value):
            observer(value * 1000)

        self.mpv.observe_property("time-pos", converting_observer)

    def __del__(self):
        # TODO may never be called, see https://github.com/RafeKettler/magicmethods/blob/master/magicmethods.pdf
        self.mpv.quit()
        self.mpv.terminate()