emmental/audio/controls.py

136 lines
4.1 KiB
Python

# Copyright 2021 (c) Anna Schumaker.
from gi.repository import Gtk
from . import scale
class ControlButton(Gtk.Button):
def __init__(self, player, icon):
Gtk.Button.__init__(self)
self.add_css_class("large-icons")
self.set_icon_name(icon)
self.player = player
class PreviousButton(ControlButton):
def __init__(self, player):
ControlButton.__init__(self, player, "media-skip-backward")
def do_clicked(self):
self.player.previous()
class NextButton(ControlButton):
def __init__(self, player):
ControlButton.__init__(self, player, "media-skip-forward")
def do_clicked(self):
self.player.next()
class PlayPauseButton(ControlButton):
def __init__(self, player):
ControlButton.__init__(self, player, "media-playback-start")
self.player.connect("playback-start", self.playback_start)
self.player.connect("playback-paused", self.playback_paused)
def do_clicked(self):
self.player.playpause()
def playback_start(self, player):
self.set_icon_name("media-playback-pause")
def playback_paused(self, player):
self.set_icon_name("media-playback-start")
class ControlScaleBox(scale.ScaleButtonBox):
def __init__(self, scalectrl):
icon = Gtk.Image()
icon.add_css_class("large-icons")
scalectrl.connect("value-changed", self.on_value_changed, icon)
scale.ScaleButtonBox.__init__(self, scalectrl)
self.on_value_changed(scalectrl, icon)
self.prepend(icon)
def on_value_changed(self, scale, icon):
pass
class AutoPauseControlBox(ControlScaleBox):
def __init__(self, apscale):
apscale.unparent()
ControlScaleBox.__init__(self, apscale)
def on_value_changed(self, scale, icon):
name = "start" if scale.get_value() == -1 else "pause"
icon.set_from_icon_name(f"media-playback-{name}")
class VolumeControlBox(ControlScaleBox):
def __init__(self, player):
ControlScaleBox.__init__(self, scale.VolumeScale(player))
def on_value_changed(self, scale, icon):
value = scale.get_value()
if value == 0: name = "muted"
elif value <= 1/3: name = "low"
elif value <= 2/3: name = "medium"
else: name = "high"
icon.set_from_icon_name(f"audio-volume-{name}-symbolic")
class ControlsPopover(Gtk.Popover):
def __init__(self, player, apscale):
Gtk.Popover.__init__(self)
self.box = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
self.box.append(AutoPauseControlBox(apscale))
self.box.append(VolumeControlBox(player))
self.set_child(self.box)
class MenuIcon(Gtk.Overlay):
def __init__(self, apscale):
Gtk.Overlay.__init__(self)
self.icon = Gtk.Image.new_from_icon_name("pan-down-symbolic")
self.icon.set_margin_top(5)
self.label = Gtk.Label()
self.label.set_markup("<small> </small>")
self.label.set_yalign(0)
apscale.connect("value-changed", self.on_value_changed)
self.add_overlay(self.icon)
self.add_overlay(self.label)
def on_value_changed(self, scale):
value = int(scale.get_value())
text = str(value) if value > -1 else " "
self.label.set_markup(f"<small>{text}</small>")
class MenuButton(Gtk.ToggleButton):
def __init__(self, player, apscale):
Gtk.ToggleButton.__init__(self)
self.popover = ControlsPopover(player, apscale)
self.popover.set_parent(self)
self.popover.connect("closed", self.on_popover_closed)
self.set_child(MenuIcon(apscale))
def do_toggled(self):
if self.get_active():
self.popover.popup()
else:
self.popover.popdown()
def on_popover_closed(self, popover):
self.set_active(False)
class AudioControls(Gtk.Box):
def __init__(self, player, apscale):
Gtk.Box.__init__(self)
self.add_css_class("linked")
self.append(PreviousButton(player))
self.append(PlayPauseButton(player))
self.append(NextButton(player))
self.append(MenuButton(player, apscale))