emmental/rind/audio/widgets.py

162 lines
4.6 KiB
Python

# Copyright 2019 (c) Anna Schumaker.
from . import artwork
from . import autopause
from . import playbin
from .. import gtk
import curds
from gi.repository import Gdk, GLib, Gst
NEXT_TRACK = None
SEEK_STEP = 10
def on_next(button):
track = NEXT_TRACK
if track == None:
track = curds.playlist.next()
if track != None:
playbin.set_uri(track.path, Gst.State.PLAYING)
Next = gtk.Builder.get_object("next_button")
Next.connect("clicked", on_next)
Next.connect("can-activate-accel", gtk.can_activate_accel)
def on_previous(button):
track = curds.playlist.previous()
if track != None:
playbin.set_uri(track.path, Gst.State.PLAYING)
Previous = gtk.Builder.get_object("previous_button")
Previous.connect("clicked", on_previous)
Previous.connect("can-activate-accel", gtk.can_activate_accel)
def on_play(button):
playbin.play()
Play = gtk.Builder.get_object("play_button")
Play.connect("clicked", on_play)
Play.connect("can-activate-accel", gtk.can_activate_accel)
def on_pause(button):
playbin.pause()
Pause = gtk.Builder.get_object("pause_button")
Pause.connect("clicked", on_pause)
Pause.connect("can-activate-accel", gtk.can_activate_accel)
def on_seek(range, scroll, value):
playbin.seek_percent(value)
Progress = gtk.Builder.get_object("progress_scale")
Progress.connect("change-value", on_seek)
def on_key_press(widget, event):
ctrl = event.state & Gdk.ModifierType.CONTROL_MASK
key = Gdk.keyval_name(event.keyval)
if ctrl and key in ("Left", "Right"):
step = SEEK_STEP if key == "Right" else -SEEK_STEP
playbin.seek_step(step)
return True
return False
gtk.Window.connect("key-press-event", on_key_press)
def on_volume_changed(button, value):
playbin.set_volume(value)
Volume = gtk.Builder.get_object("volume_button")
Volume.connect("value-changed", on_volume_changed)
Title = gtk.Builder.get_object("title")
Artist = gtk.Builder.get_object("artist")
def on_eos(message):
track = curds.playlist.next()
if track != None:
state = autopause.decrement()
playbin.set_uri(track.path, state)
def on_state_change(message):
if message.src == playbin.Playbin:
(old, new, pending) = message.parse_state_changed()
Play.set_visible( new != Gst.State.PLAYING)
Pause.set_visible(new == Gst.State.PLAYING)
if new != Gst.State.PLAYING and new != Gst.State.PAUSED:
set_tag_markup(Title, "Emmental")
set_tag_markup(Artist, "The Cheesy Music Player")
autopause.state_changed(new)
def on_stream_start(message):
global NEXT_TRACK
NEXT_TRACK = None
curds.notify.notify("stream-start")
def set_tag_markup(label, text):
markup = GLib.markup_escape_text(text)
label.set_markup(f"<big>{markup}</big>")
def on_each_tag(taglist, name):
if name == "image":
(res, sample) = taglist.get_sample(name)
buffer = sample.get_buffer()
(res, map) = buffer.map(Gst.MapFlags.READ)
artwork.set_image(map.data)
buffer.unmap(map)
elif name in [ "artist", "title" ]:
(valid, value) = taglist.get_string(name)
if valid and name == "artist":
set_tag_markup(Artist, f"by {value}")
elif valid and name == "title":
set_tag_markup(Title, value)
def on_message(bus, message):
if message.type == Gst.MessageType.EOS:
on_eos(message)
elif message.type == Gst.MessageType.STATE_CHANGED:
on_state_change(message)
elif message.type == Gst.MessageType.STREAM_START:
on_stream_start(message)
elif message.type == Gst.MessageType.TAG:
message.parse_tag().foreach(on_each_tag)
playbin.Bus.connect("message", on_message)
def on_about_to_finish(pbin):
global NEXT_TRACK
if not autopause.about_to_pause():
NEXT_TRACK = curds.playlist.next()
if NEXT_TRACK:
playbin.set_uri(NEXT_TRACK.path)
autopause.decrement()
playbin.Playbin.connect("about-to-finish", on_about_to_finish)
Position = gtk.Builder.get_object("position")
Remaining = gtk.Builder.get_object("remaining")
def timestr(nanoseconds):
(m, s) = divmod(round(nanoseconds / Gst.SECOND), 60)
return f"{m:02}:{s:02}"
def on_timeout():
Position.set_text( timestr(playbin.position()))
Remaining.set_text(timestr(playbin.remaining()))
Progress.get_adjustment().set_value(playbin.progress())
return GLib.SOURCE_CONTINUE
GLib.timeout_add(100, on_timeout)
def reset():
global NEXT_TRACK
global SEEK_STEP
set_tag_markup(Title, "Emmental")
set_tag_markup(Artist, "The Cheesy Music Player")
Play.show()
Pause.hide()
Volume.set_value(100)
NEXT_TRACK = None
SEEK_STEP = 10