Esempio n. 1
0
 def play(self, start = None, end = None, cb = (), play = True, timed = False): # For cb, None means no cb, so use something else for "no change".
     self.pitch.set_property('tempo', self.speed)
     self.offset = self.track['files'][self.track['media']][1] * 1000.
     if cb != ():
         self.cb = cb
     if end is None:
         end = self.endtarget
     if end is not None and start is not None and end < start:
         end = None
     self.endtarget = end
     if play is None:
         play = self.playing()
     if end is not None and end < self.offset + self.media_duration:
         if self.set_endtarget:
             self.set_endtarget(end)
         end -= self.offset
     elif self.set_endtarget:
         self.set_endtarget(end)
     if start is not None and start < self.offset:
         wait = -1 *(start - self.offset)
         loop = GLib.MainLoop()
         start = self.offset
         if self.timeout != None: 
             GLib.source_remove(self.timeout) #Only do one timeout at a time to prevent wierd re-starting issues
             self.timeout = None 
         if self.playing(): 
             self.pause(True) 
         self.timeout = GLib.timeout_add(wait, lambda _: self.play(start = start, end=end, cb=cb,play=play, timed = True), None)
         self.countdown_end = time.time() + wait/1000.
         return True
     logging.debug("start {}, offset {}, duration {}, play {}".format(start, self.offset, self.media_duration, play))
     if start is not None and start < self.offset + self.media_duration:
         logging.debug("Actually playing because start is not none")
         start -= self.offset
         start /= self.speed
         if end is not None:
             end /= self.speed
         self.pause()
         self.pipeline.get_state(Gst.CLOCK_TIME_NONE)
         if end is not None and (start is None or end > start):
             ret = self.pipeline.seek(1.0, Gst.Format(Gst.Format.TIME), Gst.SeekFlags.ACCURATE | Gst.SeekFlags.FLUSH, Gst.SeekType.SET, start * Gst.MSECOND, Gst.SeekType.SET, end * Gst.MSECOND)
             if not ret:
                 ret = self.pipeline.seek_simple(Gst.Format.TIME, Gst.SeekFlags.KEY_UNIT | Gst.SeekFlags.FLUSH, start * Gst.MSECOND)
                 logging.warning("Simple seeking")
                 #self.playbin.seek_simple(Gst.Format.TIME,  Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, seek_time_secs * Gst.SECOND) 
         else:
             ret = self.pipeline.seek(1.0, Gst.Format(Gst.Format.TIME), Gst.SeekFlags.ACCURATE | Gst.SeekFlags.FLUSH, Gst.SeekType.SET, start * Gst.MSECOND, Gst.SeekType.END, 0)
             if not ret:
                 ret = self.pipeline.seek_simple(Gst.Format.TIME, Gst.SeekFlags.KEY_UNIT|Gst.SeekFlags.ACCURATE | Gst.SeekFlags.FLUSH, start * Gst.MSECOND)
                 logging.warning("Simple seeking")
         if not ret:
             logging.warning("Seeking not allowed by gstreamer")
     if play:
         self.pause(False)
     if timed:
         self.timeout = None
         self.countdown_end = None
         return False #Bit wierd, but makes this function possible to be used as a oneshot timer.
Esempio n. 2
0
def play_audio_from_file(file_path, queue=False):
    """ Audio media """
    if hasattr(play_audio_from_file, 'player') and \
       play_audio_from_file.player:
        if queue:
            if hasattr(play_audio_from_file, 'queue'):
                if play_audio_from_file.queue and \
                   file_path in play_audio_from_file.queue:
                    # if we already have that file in the queue
                    # we'll just update the timer.
                    if hasattr(play_audio_from_file, 'queue_timeout'):
                        time.sleep(0.01)
                        GObject.source_remove(
                            play_audio_from_file.queue_timeout)
                        f = Gst.Format(Gst.Format.TIME)
                        duration = play_audio_from_file.player.query_duration(
                            f)[0]
                        timeout = duration / 1000000000.
                        play_audio_from_file.queue_timeout = \
                            GObject.timeout_add(int(timeout * 1000), \
                                            play_audio_from_file, file_path)
                        return
            else:
                play_audio_from_file.queue = []

            time.sleep(0.01)
            f = Gst.Format(Gst.Format.TIME)
            duration = play_audio_from_file.player.query_duration(f)[0]
            timeout = duration / 1000000000.
            play_audio_from_file.queue_timeout = GObject.timeout_add( \
                        int(timeout * 1000), play_audio_from_file, file_path)
            play_audio_from_file.queue.append(file_path)
            return
        else:
            play_audio_from_file.player.set_state(Gst.State.NULL)

    else:
        Gst.init(None)

    play_audio_from_file.player = Gst.parse_launch (
                    'filesrc location=%s ! oggdemux ! vorbisdec ! ' \
                    'audioconvert ! alsasink' % (file_path))

    if not play_audio_from_file.player:
        _logger.warning('unable to play audio file %s' % (file_path))

    else:
        play_audio_from_file.player.set_state(Gst.State.PLAYING)
Esempio n. 3
0
 def get_duration_seek_ns(self):
     try:
         position = self.player.query_duration(Gst.Format(Gst.Format.TIME))
         return position[1]
     except Exception, e:
         logging.warn("GET query_duration: " + str(e))
         return -1
Esempio n. 4
0
    def time(self):
        """Returns a tuple containing (position, length) where both
        values are integers in seconds. If no stream is available,
        returns (0, 0).
        """
        fmt = Gst.Format(Gst.Format.TIME)
        try:
            posq = self.player.query_position(fmt)
            if not posq[0]:
                raise QueryError("query_position failed")
            pos = posq[1] / (10**9)

            lengthq = self.player.query_duration(fmt)
            if not lengthq[0]:
                raise QueryError("query_duration failed")
            length = lengthq[1] / (10**9)

            self.cached_time = (pos, length)
            return (pos, length)

        except QueryError:
            # Stream not ready. For small gaps of time, for instance
            # after seeking, the time values are unavailable. For this
            # reason, we cache recent.
            if self.playing and self.cached_time:
                return self.cached_time
            else:
                return (0, 0)
Esempio n. 5
0
 def seek_seconds(self, seconds):
     if not seconds:
         return
     logging.info("Start with seconds " + str(seconds))
     seek_ns = (float(seconds) + 0.0) * self.NANO_SECONDS
     logging.info("SEC SEEK SEC " + str(seek_ns))
     self.player.seek_simple(Gst.Format(Gst.Format.TIME), Gst.SeekFlags.FLUSH, seek_ns)
Esempio n. 6
0
    def seek(self, percent, offset=0):
        if not self.bean:
            return None
        seek_ns = self.duration_sec * (percent + offset) / 100 * self.NANO_SECONDS

        if self.bean.start_sec and self.bean.start_sec > 0:
            seek_ns += float(self.bean.start_sec) * self.NANO_SECONDS

        self.player.seek_simple(Gst.Format(Gst.Format.TIME), Gst.SeekFlags.FLUSH, seek_ns)
Esempio n. 7
0
 def update(self):
     self.pipeline.get_state(Gst.CLOCK_TIME_NONE) 
     do_callback = False
     try:
         pos = self.pipeline.query_position(Gst.Format(Gst.Format.TIME))[1] / Gst.MSECOND * self.speed + self.offset
     except:
         self.end()
     self.set_pos(pos) # if self.speed <= 1 else pos / self.speed)
     return True
Esempio n. 8
0
 def get_pos(self):
     if self.timeout != None:
         if not self.playing():
             return -1000*(self.countdown_end - time.time())
     self.pipeline.get_state(Gst.CLOCK_TIME_NONE)
     try:
         pos = self.pipeline.query_position(Gst.Format(Gst.Format.TIME))[1] / Gst.MSECOND * self.speed + self.offset
     except:
         return 0
     return pos #if self.speed <= 1 else pos / self.speed
Esempio n. 9
0
    def seek(self, position):
        """Seeks to position (in seconds)."""
        cur_pos, cur_len = self.time()
        if position > cur_len:
            self.stop()
            return

        fmt = Gst.Format(Gst.Format.TIME)
        ns = position * 10**9  # convert to nanoseconds
        self.player.seek_simple(fmt, Gst.SeekFlags.FLUSH, ns)

        # save new cached time
        self.cached_time = (position, cur_len)
Esempio n. 10
0
 def get_duration(cls, filename): #Class method so we can check a files duration without instantiating everything
     cls.prober.set_property('uri', 'file://' + url.pathname2url(os.path.realpath(filename)))
     cls.probe_pipeline.set_state(Gst.State.PAUSED)
     cls.probe_pipeline.get_state(Gst.CLOCK_TIME_NONE)
     if any([bugged in filename for bugged in ["mp3","wav","m4a"]]):
         time.sleep (0.125) #https://www.ruby-forum.com/topic/1232772
     try:
         ret = cls.probe_pipeline.query_duration(Gst.Format(Gst.Format.TIME))[1] / Gst.MSECOND
     except:
         #import traceback
         #traceback.print_exc()
         logging.warning('Not using file "%s"' % os.path.realpath(filename))
         ret = None
     cls.probe_pipeline.set_state(Gst.State.NULL)
     return ret
Esempio n. 11
0
def build_and_run(pipelinefunc, name, segment=None, **pipelinefunc_kwargs):
    for key, value in pipelinefunc_kwargs.items():
        print("{0} = {1}".format(key, value))
    print >> sys.stderr, "=== Running Test %s ===" % name
    mainloop = GObject.MainLoop()
    pipeline = Gst.Pipeline(name=name)
    handler = MultiChannelHandler(mainloop,
                                  pipeline,
                                  output="./",
                                  instrument=None)
    pipeline = pipelinefunc(pipeline, name, handler, **pipelinefunc_kwargs)
    if segment is not None:
        if pipeline.set_state(
                Gst.State.PAUSED) == Gst.StateChangeReturn.FAILURE:
            raise RuntimeError("pipeline failed to enter PLAYING state")
        pipeline.seek(1.0, Gst.Format(Gst.Format.TIME), Gst.SeekFlags.FLUSH,
                      Gst.SeekType.SET, segment[0].ns(), Gst.SeekType.SET,
                      segment[1].ns())
    if pipeline.set_state(Gst.State.PLAYING) == Gst.StateChangeReturn.FAILURE:
        raise RuntimeError("pipeline failed to enter PLAYING state")
    mainloop.run()
Esempio n. 12
0
#!/usr/bin/env python

import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst

Gst.init(None)

player = Gst.ElementFactory.make("playbin", "player")
fakesink = Gst.ElementFactory.make("fakesink", "fakesink")
player.set_property("video-sink", fakesink)
player.set_property(
    "uri", "file:///home/cpd/Devel/Python/PyFiddle/Audio/mpthreetest.mp3")

format = Gst.Format(Gst.Format.TIME)
duration = player.query_duration(format)[0]
Esempio n. 13
0
    def get_duration(self) -> Optional[float]:
        pos = self.source.query_duration(Gst.Format(Gst.Format.TIME))
        if not pos[0]:
            return None

        return pos[1] / 1e9
Esempio n. 14
0
import multiprocessing
import os
import queue
import time
import urllib
import urllib.request

import gi  # pylint: disable=import-error
gi.require_version('Gst', '1.0')
from gi.repository import GLib, Gst  # pylint: disable=import-error,wrong-import-position


Gst.init(None)

_LOGGER = logging.getLogger(__name__)
_FORMAT_TIME = Gst.Format(Gst.Format.TIME)
_NANOSEC_MULT = 10 ** 9

STATE_IDLE = 'idle'
STATE_PLAYING = 'playing'
STATE_PAUSED = 'paused'
TASK_PLAY = 'play'
TASK_PAUSE = 'pause'
TASK_STOP = 'stop'
TASK_MEDIA = 'media'
TASK_SET_POSITION = 'set_position'
TASK_SET_VOLUME = 'set_volume'
ATTR_STATE = 'state'
ATTR_VOLUME = 'volume'
ATTR_POSITION = 'position'
ATTR_DURATION = 'duration'
Esempio n. 15
0
 def seek_ns(self, ns):
     if not ns:
         return
     logging.info("SEC ns " + str(ns))
     self.player.seek_simple(Gst.Format(Gst.Format.TIME),
                             Gst.SeekFlags.FLUSH, ns)
Esempio n. 16
0
    def __init__(self, instance):
        Gtk.VBox.__init__(self)
        Loggable.__init__(self)

        self.log("Init PreviewWidget")
        self.connect('destroy', self._destroy_cb)

        self.settings = instance.settings
        self.preview_cache = {}
        self.preview_cache_errors = {}

        self.discoverer = Discoverer.new(Gst.SECOND)

        #playbin for play pics
        self.player = Gst.ElementFactory.make("playbin", "preview-player")
        bus = self.player.get_bus()
        bus.add_signal_watch()
        bus.connect('message', self._bus_message_cb)
        bus.enable_sync_message_emission()
        bus.connect('sync-message::element', self._sync_message_cb)
        bus.connect('message::tag', self._tag_found_cb)
        self.__videosink = self.player.get_property("video-sink")
        self.__fakesink = Gst.ElementFactory.make("fakesink", "fakesink")

        #some global variables for preview handling
        self.is_playing = False
        self.time_format = Gst.Format(Gst.Format.TIME)
        self.original_dims = (PREVIEW_WIDTH, PREVIEW_HEIGHT)
        self.countinuous_seek = False
        self.slider_being_used = False
        self.current_selected_uri = ""
        self.current_preview_type = ""
        self.description = ""
        self.tags = {}

        # Gui elements:
        # Drawing area for video output
        self.preview_video = ViewerWidget()
        self.preview_video.modify_bg(Gtk.StateType.NORMAL,
                                     self.preview_video.get_style().black)
        self.pack_start(self.preview_video, False, True, 0)

        # An image for images and audio
        self.preview_image = Gtk.Image()
        self.preview_image.set_size_request(self.settings.FCpreviewWidth,
                                            self.settings.FCpreviewHeight)
        self.preview_image.show()
        self.pack_start(self.preview_image, False, True, 0)

        # Play button
        self.bbox = Gtk.HBox()
        self.play_button = Gtk.ToolButton(Gtk.STOCK_MEDIA_PLAY)
        self.play_button.connect("clicked", self._on_start_stop_clicked_cb)
        self.bbox.pack_start(self.play_button, False, True, 0)

        #Scale for position handling
        self.pos_adj = Gtk.Adjustment()
        self.seeker = Gtk.Scale.new(Gtk.Orientation.HORIZONTAL, self.pos_adj)
        self.seeker.connect('button-press-event', self._on_seeker_press_cb)
        self.seeker.connect('button-release-event', self._on_seeker_press_cb)
        self.seeker.connect('motion-notify-event', self._on_motion_notify_cb)
        self.seeker.set_draw_value(False)
        self.seeker.show()
        self.bbox.pack_start(self.seeker, True, True, 0)

        # Zoom buttons
        self.b_zoom_in = Gtk.ToolButton(Gtk.STOCK_ZOOM_IN)
        self.b_zoom_in.connect("clicked", self._on_zoom_clicked_cb, 1)
        self.b_zoom_out = Gtk.ToolButton(Gtk.STOCK_ZOOM_OUT)
        self.b_zoom_out.connect("clicked", self._on_zoom_clicked_cb, -1)
        self.bbox.pack_start(self.b_zoom_in, False, True, 0)
        self.bbox.pack_start(self.b_zoom_out, False, True, 0)
        self.bbox.show_all()
        self.pack_start(self.bbox, False, False, 0)

        # Label for metadata tags
        self.l_tags = Gtk.Label()
        self.l_tags.set_justify(Gtk.Justification.LEFT)
        self.l_tags.set_ellipsize(Pango.EllipsizeMode.END)
        self.l_tags.show()
        self.pack_start(self.l_tags, False, False, 0)

        # Error handling
        vbox = Gtk.VBox()
        vbox.set_spacing(SPACING)
        self.l_error = Gtk.Label(label=_("PiTiVi can not preview this file."))
        self.b_details = Gtk.Button(_("More info"))
        self.b_details.connect('clicked', self._on_b_details_clicked_cb)
        vbox.pack_start(self.l_error, True, True, 0)
        vbox.pack_start(self.b_details, False, False, 0)
        vbox.show()
        self.pack_start(vbox, False, False, 0)
Esempio n. 17
0
_ = lambda s: s  # may be add gettext later

NAME = "Play it Slowly"
VERSION = "1.5.1"
WEBSITE = "http://29a.ch/playitslowly/"

if sys.platform == "win32":
    CONFIG_PATH = os.path.expanduser("~/playitslowly.json")
else:
    XDG_CONFIG_HOME = os.path.expanduser(
        os.environ.get("XDG_CONFIG_HOME", "~/.config"))
    if not os.path.exists(XDG_CONFIG_HOME):
        os.mkdir(XDG_CONFIG_HOME)
    CONFIG_PATH = os.path.join(XDG_CONFIG_HOME, "playitslowly.json")

TIME_FORMAT = Gst.Format(Gst.Format.TIME)


def in_pathlist(filename, paths=os.environ.get("PATH").split(os.pathsep)):
    """check if an application is somewhere in $PATH"""
    return any(os.path.exists(os.path.join(path, filename)) for path in paths)


class Config(dict):
    """Very simple json config file"""
    def __init__(self, path=None):
        dict.__init__(self)
        self.path = path

    def load(self):
        with open(self.path, encoding="utf-8") as f: