From e4827d998e0c406f859562a0b69ba9ed15e5e3cc Mon Sep 17 00:00:00 2001 From: Dmitry Kann Date: Tue, 21 Jul 2020 11:01:26 +0200 Subject: [PATCH] Add Unix domain socket connectivity (resolves #10) --- internal/config/config.go | 17 +++++-- internal/player/connector.go | 10 ++-- internal/player/main-window.go | 3 +- internal/player/prefs.go | 30 ++++++++++-- resources/i18n/nl.po | 14 +++++- resources/i18n/ru.po | 14 +++++- resources/i18n/ymuse.pot | 12 +++++ resources/prefs.glade | 85 ++++++++++++++++++++++++++++------ 8 files changed, 157 insertions(+), 28 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index ac363eb..c61a1da 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -75,8 +75,10 @@ type StreamSpec struct { // Config represents (storable) application configuration type Config struct { - MpdHost string // MPD's IP address or hostname - MpdPort int // MPD's port number + MpdNetwork string // Network to use to connect to MPD, either 'tcp' or 'unix' + MpdSocketPath string // Path to the MPD's Unix socket (only if MpdNetwork == 'unix') + MpdHost string // MPD's IP address or hostname (only if MpdNetwork == 'tcp') + MpdPort int // MPD's port number (only if MpdNetwork == 'tcp') MpdPassword string // MPD's password (optional) MpdAutoConnect bool // Whether to automatically connect to MPD on startup MpdAutoReconnect bool // Whether to automatically reconnect to MPD after connection is lost @@ -112,6 +114,8 @@ func GetConfig() *Config { // newConfig initialises and returns a config instance with all the defaults func newConfig() *Config { return &Config{ + MpdNetwork: "tcp", + MpdSocketPath: os.Getenv("XDG_RUNTIME_DIR") + "/mpd/socket", MpdHost: os.Getenv("MPD_HOST"), MpdPort: util.AtoiDef(os.Getenv("MPD_PORT"), 6600), MpdPassword: "", @@ -167,9 +171,12 @@ func (c *Config) Load() { log.Debugf("Loaded configuration from %s", file) } -// MpdAddress returns the MPD address string constructed from host and port -func (c *Config) MpdAddress() string { - return fmt.Sprintf("%s:%d", c.MpdHost, c.MpdPort) +// MpdNetworkAddress returns the MPD network and the address string +func (c *Config) MpdNetworkAddress() (string, string) { + if c.MpdNetwork == "unix" { + return "unix", c.MpdSocketPath + } + return "tcp", fmt.Sprintf("%s:%d", c.MpdHost, c.MpdPort) } // Save writes out the config to the default file diff --git a/internal/player/connector.go b/internal/player/connector.go index dc415c8..b55ba3e 100644 --- a/internal/player/connector.go +++ b/internal/player/connector.go @@ -24,6 +24,7 @@ import ( // Connector encapsulates functionality for connecting to MPD and watch for its changes type Connector struct { + mpdNetwork string // MPD network mpdAddress string // MPD address mpdPassword string // MPD password stayConnected bool // Whether a connection is supposed to be kept alive @@ -62,7 +63,8 @@ func NewConnector(onStatusChange func(), onHeartbeat func(), onSubsystemChange f // Start initialises the connector // stayConnected: whether the connection must be automatically re-established when lost -func (c *Connector) Start(mpdAddress, mpdPassword string, stayConnected bool) { +func (c *Connector) Start(mpdNetwork, mpdAddress, mpdPassword string, stayConnected bool) { + c.mpdNetwork = mpdNetwork c.mpdAddress = mpdAddress c.mpdPassword = mpdPassword c.stayConnected = stayConnected @@ -201,8 +203,8 @@ func (c *Connector) doConnect(connect, heartbeat bool) { c.onStatusChange() // Try to connect - log.Debug("Connecting to MPD") - if client, err = mpd.DialAuthenticated("tcp", c.mpdAddress, c.mpdPassword); err == nil { + log.Debugf("Connecting to MPD (network=%v, address=%v)", c.mpdNetwork, c.mpdAddress) + if client, err = mpd.DialAuthenticated(c.mpdNetwork, c.mpdAddress, c.mpdPassword); err == nil { connected = true } else { err = errors.Errorf("DialAuthenticated() failed: %v", err) @@ -299,7 +301,7 @@ func (c *Connector) watch() { // If no watcher yet if mpdWatcher == nil { - watcher, err := mpd.NewWatcher("tcp", c.mpdAddress, c.mpdPassword) + watcher, err := mpd.NewWatcher(c.mpdNetwork, c.mpdAddress, c.mpdPassword) // Failed to connect if err != nil { log.Warning("Failed to watch MPD", err) diff --git a/internal/player/main-window.go b/internal/player/main-window.go index bca975b..d3a08ab 100644 --- a/internal/player/main-window.go +++ b/internal/player/main-window.go @@ -749,7 +749,8 @@ func (w *MainWindow) connect() { // Start connecting cfg := config.GetConfig() - w.connector.Start(cfg.MpdAddress(), cfg.MpdPassword, cfg.MpdAutoReconnect) + network, addr := cfg.MpdNetworkAddress() + w.connector.Start(network, addr, cfg.MpdPassword, cfg.MpdAutoReconnect) } // disconnect starts disconnecting from MPD diff --git a/internal/player/prefs.go b/internal/player/prefs.go index 9b0c2af..372a3e4 100644 --- a/internal/player/prefs.go +++ b/internal/player/prefs.go @@ -34,7 +34,14 @@ type queueCol struct { type PrefsDialog struct { PreferencesDialog *gtk.Dialog // General page widgets + MpdNetworkComboBox *gtk.ComboBoxText + MpdPathEntry *gtk.Entry + MpdPathLabel *gtk.Label MpdHostEntry *gtk.Entry + MpdHostLabel *gtk.Label + MpdHostLabelRemark *gtk.Label + MpdPortSpinButton *gtk.SpinButton + MpdPortLabel *gtk.Label MpdPortAdjustment *gtk.Adjustment MpdPasswordEntry *gtk.Entry MpdAutoConnectCheckButton *gtk.CheckButton @@ -107,11 +114,14 @@ func (d *PrefsDialog) onMap() { // Initialise widgets cfg := config.GetConfig() // General page + d.MpdNetworkComboBox.SetActiveID(cfg.MpdNetwork) + d.MpdPathEntry.SetText(cfg.MpdSocketPath) d.MpdHostEntry.SetText(cfg.MpdHost) d.MpdPortAdjustment.SetValue(float64(cfg.MpdPort)) d.MpdPasswordEntry.SetText(cfg.MpdPassword) d.MpdAutoConnectCheckButton.SetActive(cfg.MpdAutoConnect) d.MpdAutoReconnectCheckButton.SetActive(cfg.MpdAutoReconnect) + d.updateGeneralWidgets() // Interface page d.LibraryDefaultReplaceRadioButton.SetActive(cfg.TrackDefaultReplace) d.LibraryDefaultAppendRadioButton.SetActive(!cfg.TrackDefaultReplace) @@ -262,15 +272,16 @@ func (d *PrefsDialog) onSettingChange() { // Collect settings cfg := config.GetConfig() // General page - if s, err := d.MpdHostEntry.GetText(); !errCheck(err, "MpdHostEntry.GetText() failed") { - cfg.MpdHost = s - } + cfg.MpdNetwork = d.MpdNetworkComboBox.GetActiveID() + cfg.MpdSocketPath = util.EntryText(d.MpdPathEntry, "") + cfg.MpdHost = util.EntryText(d.MpdHostEntry, "") cfg.MpdPort = int(d.MpdPortAdjustment.GetValue()) if s, err := d.MpdPasswordEntry.GetText(); !errCheck(err, "MpdPasswordEntry.GetText() failed") { cfg.MpdPassword = s } cfg.MpdAutoConnect = d.MpdAutoConnectCheckButton.GetActive() cfg.MpdAutoReconnect = d.MpdAutoReconnectCheckButton.GetActive() + d.updateGeneralWidgets() // Interface page cfg.TrackDefaultReplace = d.LibraryDefaultReplaceRadioButton.GetActive() cfg.PlaylistDefaultReplace = d.PlaylistsDefaultReplaceRadioButton.GetActive() @@ -309,3 +320,16 @@ func (d *PrefsDialog) populateColumns() { } d.ColumnsListBox.ShowAll() } + +// updateGeneralWidgets updates widget states on the General tab +func (d *PrefsDialog) updateGeneralWidgets() { + network := d.MpdNetworkComboBox.GetActiveID() + unix, tcp := network == "unix", network == "tcp" + d.MpdPathEntry.SetVisible(unix) + d.MpdPathLabel.SetVisible(unix) + d.MpdHostEntry.SetVisible(tcp) + d.MpdHostLabel.SetVisible(tcp) + d.MpdHostLabelRemark.SetVisible(tcp) + d.MpdPortSpinButton.SetVisible(tcp) + d.MpdPortLabel.SetVisible(tcp) +} diff --git a/resources/i18n/nl.po b/resources/i18n/nl.po index 41ad02f..46ef4e5 100644 --- a/resources/i18n/nl.po +++ b/resources/i18n/nl.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-05-25 12:11+0200\n" -"PO-Revision-Date: 2020-06-23 10:45+0200\n" +"PO-Revision-Date: 2020-07-21 10:59+0200\n" "Last-Translator: Dmitry Kann \n" "Language-Team: \n" "Language: nl\n" @@ -398,6 +398,9 @@ msgstr "MPD Informatie" msgid "Name" msgstr "Naam" +msgid "Network:" +msgstr "Netwerk:" + msgid "New playlist name" msgstr "Nieuwe afspeellijst naam" @@ -452,6 +455,9 @@ msgstr "Wachtwoord:" msgid "Path" msgstr "Pad" +msgid "Path:" +msgstr "Pad:" + msgid "Pause or resume playback" msgstr "Afspelen pauzeren of hervatten" @@ -605,6 +611,9 @@ msgstr "Naar het Wachtrij tabblad" msgid "Switch to Streams tab" msgstr "Naar het Streams tabblad" +msgid "TCP" +msgstr "TCP" + msgid "Template error" msgstr "Sjabloonfout" @@ -644,6 +653,9 @@ msgstr "Tracktitel" msgid "Track" msgstr "Track" +msgid "Unix socket" +msgstr "Unix socket" + msgid "Unnamed" msgstr "Zonder naam" diff --git a/resources/i18n/ru.po b/resources/i18n/ru.po index 0008829..c050c2b 100644 --- a/resources/i18n/ru.po +++ b/resources/i18n/ru.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: Ymuse\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-05-25 12:11+0200\n" -"PO-Revision-Date: 2020-06-23 10:41+0200\n" +"PO-Revision-Date: 2020-07-21 10:57+0200\n" "Last-Translator: Dmitry Kann \n" "Language-Team: \n" "Language: ru\n" @@ -402,6 +402,9 @@ msgstr "Информация об MPD" msgid "Name" msgstr "Наименование" +msgid "Network:" +msgstr "Сеть:" + msgid "New playlist name" msgstr "Название нового плейлиста" @@ -458,6 +461,9 @@ msgstr "Пароль:" msgid "Path" msgstr "Путь" +msgid "Path:" +msgstr "Путь:" + msgid "Pause or resume playback" msgstr "Приостановить или возобновить воспроизведение" @@ -611,6 +617,9 @@ msgstr "Переключиться во вкладку «Очередь»" msgid "Switch to Streams tab" msgstr "Переключиться во вкладку «Потоки»" +msgid "TCP" +msgstr "TCP" + msgid "Template error" msgstr "Ошибка в шаблоне" @@ -650,6 +659,9 @@ msgstr "Название трека" msgid "Track" msgstr "Трек" +msgid "Unix socket" +msgstr "Unix-сокет" + msgid "Unnamed" msgstr "Безымянный" diff --git a/resources/i18n/ymuse.pot b/resources/i18n/ymuse.pot index 8406a8a..7d2c429 100644 --- a/resources/i18n/ymuse.pot +++ b/resources/i18n/ymuse.pot @@ -384,6 +384,9 @@ msgstr "" msgid "Name" msgstr "" +msgid "Network:" +msgstr "" + msgid "New playlist name" msgstr "" @@ -438,6 +441,9 @@ msgstr "" msgid "Path" msgstr "" +msgid "Path:" +msgstr "" + msgid "Pause or resume playback" msgstr "" @@ -591,6 +597,9 @@ msgstr "" msgid "Switch to Streams tab" msgstr "" +msgid "TCP" +msgstr "" + msgid "Template error" msgstr "" @@ -630,6 +639,9 @@ msgstr "" msgid "Track" msgstr "" +msgid "Unix socket" +msgstr "" + msgid "Unnamed" msgstr "" diff --git a/resources/prefs.glade b/resources/prefs.glade index b071508..4d38c1a 100644 --- a/resources/prefs.glade +++ b/resources/prefs.glade @@ -1,5 +1,5 @@ - + @@ -21,7 +21,7 @@ dialog True - + @@ -84,7 +84,7 @@ 0 - 0 + 2 @@ -95,11 +95,11 @@ 1 - 0 + 2 - + True False (leave empty for localhost) @@ -107,7 +107,7 @@ 2 - 0 + 2 @@ -120,7 +120,7 @@ 0 - 1 + 3 @@ -131,7 +131,7 @@ 1 - 1 + 3 @@ -144,7 +144,7 @@ 0 - 2 + 4 @@ -156,7 +156,7 @@ 1 - 2 + 4 @@ -170,7 +170,7 @@ 1 - 3 + 5 @@ -184,7 +184,7 @@ 1 - 4 + 6 @@ -200,9 +200,68 @@ 1 - 5 + 7 + + + True + True + + + + 1 + 1 + + + + + True + False + Path: + right + 1 + + + 0 + 1 + + + + + True + False + Network: + right + 1 + + + 0 + 0 + + + + + True + False + 1 + + Unix socket + TCP + + + + + 1 + 0 + + + + + + + +