Added setting to control the output device in libVLC
This commit is contained in:
parent
b254a4eb1b
commit
1fcdd51358
@ -2,14 +2,16 @@
|
|||||||
|
|
||||||
## Version 0.6
|
## Version 0.6
|
||||||
|
|
||||||
* Updated VLC libraries and plugins to version 3.0.7.
|
* Added a settings dialog for the application, from this dialog you will be able to find some general settings, available for MusicDL, and service's settings. Every service defines certain specific settings.
|
||||||
|
* When transcoding to mp3, the default bitrate now will be 320 KBPS instead of 192.
|
||||||
* Added a new and experimental extractor for supporting tidal.
|
* Added a new and experimental extractor for supporting tidal.
|
||||||
* Take into account that this extractor requires you to have a paid account on tidal. Depending in the account level, you will be able to play and download music in high quality or lossless audio. MusicDL will handle both, though at the current moment, only downloading of lossless audio is implemented.
|
* Take into account that this extractor requires you to have a paid account on tidal. Depending in the account level, you will be able to play and download music in high quality or lossless audio. MusicDL will handle both. Lossless audio will be downloaded as flac files, and high quality audio will be downloaded as transcoded 320 KBPS mp3.
|
||||||
* There is a new search mode supported in this service. You can retrieve all work for a certain artist by using the protocol artist://, plus the name of the artist you want to retrieve. For example, artist://The beatles will retrieve everything made by the beatles available in the service. The search results will be grouped by albums, compilations and singles, in this order.
|
* There is a new search mode supported in this service. You can retrieve all work for a certain artist by using the protocol artist://, plus the name of the artist you want to retrieve. For example, artist://The beatles will retrieve everything made by the beatles available in the service. The search results will be grouped by albums, compilations and singles, in this order. Depending in the amount of results to display, this may take a long time.
|
||||||
* Due to recent problems with mail.ru and unavailable content in most cases, the service has been removed from MusicDL.
|
* Due to recent problems with mail.ru and unavailable content in most cases, the service has been removed from MusicDL.
|
||||||
* YouTube:
|
* YouTube:
|
||||||
* Fixed a long standing issue with playback of some elements, due to Youtube sending encrypted versions of these videos. Now playback should be better.
|
* Fixed a long standing issue with playback of some elements, due to Youtube sending encrypted versions of these videos. Now playback should be better.
|
||||||
* Updated YoutubeDL to version 2019.6.7
|
* Updated YoutubeDL to version 2019.6.7
|
||||||
|
* Now it is possible to load 50 items for searches as opposed to the previous 20 items limit. This setting can be controlled in the service's preferences
|
||||||
* zaycev.net:
|
* zaycev.net:
|
||||||
* Fixed extractor for searching and playing music in zaycev.net.
|
* Fixed extractor for searching and playing music in zaycev.net.
|
||||||
* Unfortunately, it seems this service works only in the russian Federation and some other CIS countries due to copyright reasons.
|
* Unfortunately, it seems this service works only in the russian Federation and some other CIS countries due to copyright reasons.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
[main]
|
[main]
|
||||||
volume = integer(default=50)
|
volume = integer(default=50)
|
||||||
language = string(default="system")
|
language = string(default="system")
|
||||||
|
output_device = string(default="")
|
||||||
|
|
||||||
[services]
|
[services]
|
||||||
[[tidal]]
|
[[tidal]]
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import config
|
import config
|
||||||
from utils import get_extractors
|
from utils import get_extractors
|
||||||
from wxUI.configuration import configurationDialog
|
from wxUI.configuration import configurationDialog
|
||||||
|
from . import player
|
||||||
|
|
||||||
class configuration(object):
|
class configuration(object):
|
||||||
|
|
||||||
@ -12,10 +13,16 @@ class configuration(object):
|
|||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
def create_config(self):
|
def create_config(self):
|
||||||
self.view.create_general()
|
self.output_devices = player.player.get_output_devices()
|
||||||
|
self.view.create_general(output_devices=[i["name"] for i in self.output_devices])
|
||||||
|
current_output_device = config.app["main"]["output_device"]
|
||||||
|
for i in self.output_devices:
|
||||||
|
# here we must compare against the str version of the vlc's device identifier.
|
||||||
|
if str(i["id"]) == current_output_device:
|
||||||
|
self.view.set_value("general", "output_device", i["name"])
|
||||||
|
break
|
||||||
extractors = get_extractors()
|
extractors = get_extractors()
|
||||||
for i in extractors:
|
for i in extractors:
|
||||||
print(i)
|
|
||||||
if hasattr(i, "settings"):
|
if hasattr(i, "settings"):
|
||||||
panel = getattr(i, "settings")(self.view.notebook)
|
panel = getattr(i, "settings")(self.view.notebook)
|
||||||
self.view.notebook.AddPage(panel, panel.name)
|
self.view.notebook.AddPage(panel, panel.name)
|
||||||
@ -25,6 +32,18 @@ class configuration(object):
|
|||||||
self.view.realize()
|
self.view.realize()
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
|
selected_output_device = self.view.get_value("general", "output_device")
|
||||||
|
selected_device_id = None
|
||||||
|
for i in self.output_devices:
|
||||||
|
# Vlc returns everything as bytes object whereas WX works with string objects, so I need to convert the wx returned string to bytes before
|
||||||
|
# Otherwise the comparison will be false.
|
||||||
|
# toDo: Check if utf-8 would be enough or we'd have to use the fylesystem encode for handling this.
|
||||||
|
if i["name"] == bytes(selected_output_device, "utf-8"):
|
||||||
|
selected_device_id = i["id"]
|
||||||
|
break
|
||||||
|
if config.app["main"]["output_device"] != selected_device_id:
|
||||||
|
config.app["main"]["output_device"] = selected_device_id
|
||||||
|
player.player.set_output_device(config.app["main"]["output_device"])
|
||||||
for i in range(0, self.view.notebook.GetPageCount()):
|
for i in range(0, self.view.notebook.GetPageCount()):
|
||||||
page = self.view.notebook.GetPage(i)
|
page = self.view.notebook.GetPage(i)
|
||||||
if hasattr(page, "save"):
|
if hasattr(page, "save"):
|
||||||
|
@ -5,6 +5,7 @@ import random
|
|||||||
import vlc
|
import vlc
|
||||||
import logging
|
import logging
|
||||||
import config
|
import config
|
||||||
|
import time
|
||||||
from pubsub import pub
|
from pubsub import pub
|
||||||
from utils import call_threaded
|
from utils import call_threaded
|
||||||
|
|
||||||
@ -33,6 +34,27 @@ class audioPlayer(object):
|
|||||||
self.event_manager.event_attach(vlc.EventType.MediaPlayerEndReached, self.end_callback)
|
self.event_manager.event_attach(vlc.EventType.MediaPlayerEndReached, self.end_callback)
|
||||||
self.event_manager.event_attach(vlc.EventType.MediaPlayerEncounteredError, self.playback_error)
|
self.event_manager.event_attach(vlc.EventType.MediaPlayerEncounteredError, self.playback_error)
|
||||||
log.debug("Bound media playback events.")
|
log.debug("Bound media playback events.")
|
||||||
|
# configure output device
|
||||||
|
self.set_output_device(config.app["main"]["output_device"])
|
||||||
|
|
||||||
|
def get_output_devices(self):
|
||||||
|
""" Retrieve enabled output devices so we can switch or use those later. """
|
||||||
|
log.debug("Retrieving output devices...")
|
||||||
|
devices = []
|
||||||
|
mods = self.player.audio_output_device_enum()
|
||||||
|
if mods:
|
||||||
|
mod = mods
|
||||||
|
while mod:
|
||||||
|
mod = mod.contents
|
||||||
|
devices.append(dict(id=mod.device, name=mod.description))
|
||||||
|
mod = mod.next
|
||||||
|
vlc.libvlc_audio_output_device_list_release(mods)
|
||||||
|
return devices
|
||||||
|
|
||||||
|
def set_output_device(self, device_id):
|
||||||
|
""" Set Output device to be ued in LibVLC"""
|
||||||
|
log.debug("Setting output audio device to {device}...".format(device=device_id,))
|
||||||
|
self.player.audio_output_device_set(None, device_id)
|
||||||
|
|
||||||
def play(self, item):
|
def play(self, item):
|
||||||
self.stopped = True
|
self.stopped = True
|
||||||
@ -142,4 +164,5 @@ class audioPlayer(object):
|
|||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.event_manager.event_detach(vlc.EventType.MediaPlayerEndReached)
|
self.event_manager.event_detach(vlc.EventType.MediaPlayerEndReached)
|
||||||
|
if hasattr(self, "event_manager"):
|
||||||
self.event_manager.event_detach(vlc.EventType.MediaPlayerEncounteredError, self.playback_error)
|
self.event_manager.event_detach(vlc.EventType.MediaPlayerEncounteredError, self.playback_error)
|
@ -3,9 +3,15 @@ import wx
|
|||||||
import widgetUtils
|
import widgetUtils
|
||||||
|
|
||||||
class general(wx.Panel, widgetUtils.BaseDialog):
|
class general(wx.Panel, widgetUtils.BaseDialog):
|
||||||
def __init__(self, panel):
|
def __init__(self, panel, output_devices=[]):
|
||||||
super(general, self).__init__(panel)
|
super(general, self).__init__(panel)
|
||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
output_device_label = wx.StaticText(self, wx.NewId(), _("Output device"))
|
||||||
|
self.output_device = wx.ComboBox(self, wx.NewId(), choices=output_devices, value=output_devices[0], style=wx.CB_READONLY)
|
||||||
|
output_device_box = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
|
output_device_box.Add(output_device_label, 0, wx.ALL, 5)
|
||||||
|
output_device_box.Add(self.output_device, 0, wx.ALL, 5)
|
||||||
|
sizer.Add(output_device_box, 0, wx.ALL, 5)
|
||||||
self.SetSizer(sizer)
|
self.SetSizer(sizer)
|
||||||
|
|
||||||
class configurationDialog(widgetUtils.BaseDialog):
|
class configurationDialog(widgetUtils.BaseDialog):
|
||||||
@ -16,8 +22,8 @@ class configurationDialog(widgetUtils.BaseDialog):
|
|||||||
self.sizer = wx.BoxSizer(wx.VERTICAL)
|
self.sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
self.notebook = wx.Treebook(self.panel)
|
self.notebook = wx.Treebook(self.panel)
|
||||||
|
|
||||||
def create_general(self):
|
def create_general(self, output_devices=[]):
|
||||||
self.general = general(self.notebook)
|
self.general = general(self.notebook, output_devices=output_devices)
|
||||||
self.notebook.AddPage(self.general, _("General"))
|
self.notebook.AddPage(self.general, _("General"))
|
||||||
self.general.SetFocus()
|
self.general.SetFocus()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user