Added support for replaygain option

This commit is contained in:
Sumner Evans
2020-03-18 10:53:24 -06:00
parent 19d616fa13
commit 45ab5c0852
7 changed files with 91 additions and 18 deletions

View File

@@ -11,6 +11,7 @@ gi.require_version('Notify', '0.7')
from gi.repository import Gdk, GdkPixbuf, Gio, GLib, Gtk, Notify
from .cache_manager import CacheManager
from .config import ReplayGainType
from .dbus_manager import dbus_propagate, DBusManager
from .players import ChromecastPlayer, MPVPlayer, PlayerEvent
from .server.api_objects import Child, Directory, Playlist
@@ -431,6 +432,8 @@ class SublimeMusicApp(Gtk.Application):
'prefetch_amount'].get_value_as_int()
self.state.config.concurrent_download_limit = dialog.data[
'concurrent_download_limit'].get_value_as_int()
self.state.config.replay_gain = ReplayGainType.from_string(
dialog.data['replay_gain'].get_active_id())
self.state.save_config()
self.reset_state()
dialog.destroy()

View File

@@ -348,6 +348,7 @@ class CacheManager(metaclass=Singleton):
logging.info('Migrating cache to version 1.')
cover_art_re = re.compile(r'(\d+)_(\d+)')
abs_path = self.calculate_abs_path('cover_art/')
abs_path.mkdir(parents=True, exist_ok=True)
for cover_art_file in Path(abs_path).iterdir():
match = cover_art_re.match(cover_art_file.name)
if match:

View File

@@ -1,10 +1,29 @@
import logging
import os
from enum import Enum
from typing import Any, Dict, List, Optional
import keyring
class ReplayGainType(Enum):
NO = 0
TRACK = 1
ALBUM = 2
def as_string(self) -> str:
return ['no', 'track', 'album'][self.value]
@staticmethod
def from_string(replay_gain_type: str) -> 'ReplayGainType':
return {
'no': ReplayGainType.NO,
'disabled': ReplayGainType.NO,
'track': ReplayGainType.TRACK,
'album': ReplayGainType.ALBUM,
}[replay_gain_type.lower()]
class ServerConfiguration:
version: int
name: str
@@ -61,19 +80,23 @@ class AppConfiguration:
prefetch_amount: int = 3
concurrent_download_limit: int = 5
port_number: int = 8282
version: int = 2
version: int = 3
serve_over_lan: bool = True
replay_gain: ReplayGainType = ReplayGainType.NO
def to_json(self) -> Dict[str, Any]:
exclude = ('servers')
exclude = ('servers', 'replay_gain')
json_object = {
k: getattr(self, k)
for k in self.__annotations__.keys()
if k not in exclude
}
json_object.update({
'servers': [s.__dict__ for s in self.servers],
})
json_object.update(
{
'servers': [s.__dict__ for s in self.servers],
'replay_gain':
getattr(self, 'replay_gain', ReplayGainType.NO).value,
})
return json_object
def migrate(self):
@@ -85,7 +108,12 @@ class AppConfiguration:
logging.info('Setting serve_over_lan to True')
self.serve_over_lan = True
self.version = 2
if (getattr(self, 'version') or 0) < 3:
logging.info('Migrating app configuration to version 3.')
logging.info('Setting replay_gain to ReplayGainType.NO')
self.replay_gain = ReplayGainType.NO
self.version = 3
@property
def cache_location(self) -> str:

View File

@@ -123,11 +123,19 @@ class Player:
class MPVPlayer(Player):
def __init__(self, *args):
super().__init__(*args)
def __init__(
self,
on_timepos_change: Callable[[Optional[float]], None],
on_track_end: Callable[[], None],
on_player_event: Callable[[PlayerEvent], None],
config: AppConfiguration,
):
super().__init__(
on_timepos_change, on_track_end, on_player_event, config)
self.mpv = mpv.MPV()
self.mpv.audio_client_name = 'sublime-music'
self.mpv.replaygain = config.replay_gain.as_string()
self.progress_value_lock = threading.Lock()
self.progress_value_count = 0
self._muted = False
@@ -301,11 +309,7 @@ class ChromecastPlayer(Player):
config: AppConfiguration,
):
super().__init__(
on_timepos_change,
on_track_end,
on_player_event,
config,
)
on_timepos_change, on_track_end, on_player_event, config)
self._timepos = 0.0
self.time_incrementor_running = False
self._can_hotswap_source = False

View File

@@ -160,16 +160,22 @@ class ApplicationState:
os.makedirs(os.path.dirname(self.state_filename), exist_ok=True)
# Save the state
state_json = json.dumps(self.to_json(), indent=2, sort_keys=True)
if not state_json:
return
with open(self.state_filename, 'w+') as f:
f.write(json.dumps(self.to_json(), indent=2, sort_keys=True))
f.write(state_json)
def save_config(self):
# Make the necessary directories before writing the config.
os.makedirs(os.path.dirname(self.config_file), exist_ok=True)
config_json = json.dumps(
self.config.to_json(), indent=2, sort_keys=True)
if not config_json:
return
with open(self.config_file, 'w+') as f:
f.write(
json.dumps(self.config.to_json(), indent=2, sort_keys=True))
f.write(config_json)
def get_config(self, filename: str) -> AppConfiguration:
if not os.path.exists(filename):

View File

@@ -4,16 +4,20 @@ import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
TextFieldDescription = Tuple[str, str, bool]
BooleanFieldDescription = Tuple[str, str]
NumericFieldDescription = Tuple[str, str, Tuple[int, int, int], int]
OptionFieldDescription = Tuple[str, str, Tuple[str, ...]]
class EditFormDialog(Gtk.Dialog):
entity_name: str
title: str
initial_size: Tuple[int, int]
text_fields: List[Tuple[str, str, bool]] = []
boolean_fields: List[Tuple[str, str]] = []
text_fields: List[TextFieldDescription] = []
boolean_fields: List[BooleanFieldDescription] = []
numeric_fields: List[NumericFieldDescription] = []
option_fields: List[OptionFieldDescription] = []
extra_label: Optional[str] = None
extra_buttons: List[Gtk.Button] = []
@@ -75,6 +79,30 @@ class EditFormDialog(Gtk.Dialog):
i += 1
for label, value_field_name, options in self.option_fields:
entry_label = Gtk.Label(label=label + ':')
entry_label.set_halign(Gtk.Align.START)
content_grid.attach(entry_label, 0, i, 1, 1)
options_store = Gtk.ListStore(str)
for option in options:
options_store.append([option])
combo = Gtk.ComboBox.new_with_model(options_store)
combo.set_id_column(0)
renderer_text = Gtk.CellRendererText()
combo.pack_start(renderer_text, True)
combo.add_attribute(renderer_text, "text", 0)
field_value = getattr(existing_object, value_field_name)
if field_value:
combo.set_active(field_value.value)
content_grid.attach(combo, 1, i, 1, 1)
self.data[value_field_name] = combo
i += 1
# Add the boolean entries to the content area.
for label, value_field_name in self.boolean_fields:
entry_label = Gtk.Label(label=label + ':')

View File

@@ -41,6 +41,9 @@ class SettingsDialog(EditFormDialog):
5,
),
]
option_fields = [
('Replay Gain', 'replay_gain', ('Disabled', 'Track', 'Album')),
]
def __init__(self, *args, **kwargs):
self.extra_label = Gtk.Label(