diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index 194f60891..c3e130f5b 100755
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -44,6 +44,21 @@
{a8776591-b7ad-4f6f-a927-c4bfaaa1e8c8}
+
+ {fe28fe15-6cf7-40e0-bec5-9ca46932d279}
+
+
+ {dd68aae0-9c01-4915-a4b3-c5e5b5ff8058}
+
+
+ {578b0af6-0dc3-4a69-a784-5e0293a5708a}
+
+
+ {a39a447a-65ad-465c-839d-b96cc4a8e2e9}
+
+
+ {d35af273-0f2b-4669-aa83-d7eee8c2c5c5}
+
@@ -201,30 +216,6 @@
src\audio
-
- src\sdk
-
-
- src\sdk
-
-
- src\sdk
-
-
- src\sdk
-
-
- src\sdk
-
-
- src\sdk
-
-
- src\sdk
-
-
- src\sdk
-
src\io
@@ -258,15 +249,9 @@
src\plugin
-
- src\sdk
-
src\sdk
-
- src\sdk
-
src
@@ -294,36 +279,15 @@
src\support
-
- src\sdk
-
-
- src\sdk
-
src\audio
-
- src\sdk
-
-
- src\sdk
-
-
- src\sdk
-
-
- src\sdk
-
src
src\sdk
-
- src\sdk
-
src\library\track
@@ -366,21 +330,9 @@
src\library\track
-
- src\sdk
-
-
- src\sdk
-
src\sdk
-
- src\sdk
-
-
- src\sdk
-
src\library\query\local
@@ -405,9 +357,6 @@
src\library\query\local
-
- src\sdk
-
src\library\query\local
@@ -417,15 +366,6 @@
src\plugin
-
- src\sdk
-
-
- src\sdk
-
-
- src\sdk
-
src\library\metadata
@@ -438,23 +378,98 @@
src\i18n
-
- src\sdk
-
-
- src\sdk
-
src\library\query\local
-
- src\sdk
-
-
- src\sdk
-
src\sdk
+
+ src\sdk\audio
+
+
+ src\sdk\audio
+
+
+ src\sdk\audio
+
+
+ src\sdk\audio
+
+
+ src\sdk\audio
+
+
+ src\sdk\audio
+
+
+ src\sdk\io
+
+
+ src\sdk\io
+
+
+ src\sdk\vis
+
+
+ src\sdk\vis
+
+
+ src\sdk\vis
+
+
+ src\sdk\library
+
+
+ src\sdk\audio
+
+
+ src\sdk\library
+
+
+ src\sdk\audio
+
+
+ src\sdk\audio
+
+
+ src\sdk\indexer
+
+
+ src\sdk\indexer
+
+
+ src\sdk\indexer
+
+
+ src\sdk\library
+
+
+ src\sdk\library
+
+
+ src\sdk\library
+
+
+ src\sdk\library
+
+
+ src\sdk\library
+
+
+ src\sdk\library
+
+
+ src\sdk\library
+
+
+ src\sdk\library
+
+
+ src\sdk\library
+
+
+ src\sdk\library
+
\ No newline at end of file
diff --git a/src/musikbox/Main.cpp b/src/musikbox/Main.cpp
index 0cdfe11d6..755a44593 100644
--- a/src/musikbox/Main.cpp
+++ b/src/musikbox/Main.cpp
@@ -143,6 +143,7 @@ int main(int argc, char* argv[]) {
#ifdef WIN32
app.SetIcon(IDI_ICON1);
+ app.SetSingleInstanceId("musikbox");
#endif
/* fire up the indexer if configured to run on startup */
if (prefs->GetBool(musik::core::prefs::keys::SyncOnStartup, true)) {
diff --git a/src/musikbox/app/overlay/ServerOverlay.cpp b/src/musikbox/app/overlay/ServerOverlay.cpp
index 30e927bce..2fb6697b8 100644
--- a/src/musikbox/app/overlay/ServerOverlay.cpp
+++ b/src/musikbox/app/overlay/ServerOverlay.cpp
@@ -64,24 +64,27 @@ static const char* KEY_PASSWORD = "password";
#define DEFAULT_HEIGHT 17
#define DEFAULT_WIDTH 45
-#define STYLE_OVERLAY_LABEL(x) \
- x->SetContentColor(CURSESPP_OVERLAY_CONTENT);
+static void applyLabelOverlayStyle(TextLabel& label) {
+ label.SetContentColor(CURSESPP_OVERLAY_CONTENT);
+}
-#define STYLE_OVERLAY_CHECKBOX(x) \
- x->SetContentColor(CURSESPP_OVERLAY_CONTENT); \
- x->SetFocusedContentColor(CURSESPP_OVERLAY_TEXT_FOCUSED);
+static void applyCheckboxOverlayStyle(Checkbox& cb) {
+ cb.SetContentColor(CURSESPP_OVERLAY_CONTENT);
+ cb.SetFocusedContentColor(CURSESPP_OVERLAY_TEXT_FOCUSED);
+}
-#define STYLE_OVERLAY_INPUT(x) \
- if (x->GetStyle() == TextInput::StyleBox) { \
- x->SetFrameColor(CURSESPP_OVERLAY_FRAME); \
- x->SetContentColor(CURSESPP_OVERLAY_CONTENT); \
- x->SetFocusedFrameColor(CURSESPP_OVERLAY_INPUT_FRAME); \
- x->SetFocusedContentColor(CURSESPP_OVERLAY_CONTENT); \
- } \
- else { \
- x->SetContentColor(CURSESPP_OVERLAY_CONTENT); \
- x->SetFocusedContentColor(CURSESPP_OVERLAY_TEXT_FOCUSED); \
+static void applyInputOverlayStyle(TextInput& input) {
+ if (input.GetStyle() == TextInput::StyleBox) {
+ input.SetFrameColor(CURSESPP_OVERLAY_FRAME);
+ input.SetContentColor(CURSESPP_OVERLAY_CONTENT);
+ input.SetFocusedFrameColor(CURSESPP_OVERLAY_INPUT_FRAME);
+ input.SetFocusedContentColor(CURSESPP_OVERLAY_CONTENT);
}
+ else {
+ input.SetContentColor(CURSESPP_OVERLAY_CONTENT);
+ input.SetFocusedContentColor(CURSESPP_OVERLAY_TEXT_FOCUSED);
+ }
+}
#define RIGHT(x) (x->GetX() + x->GetWidth())
#define TEXT_WIDTH(x) ((int) u8cols(x->GetText()))
@@ -183,18 +186,18 @@ void ServerOverlay::InitViews() {
this->pwInput.reset(new TextInput(TextInput::StyleLine, IInput::InputPassword));
/* style 'em */
- STYLE_OVERLAY_LABEL(this->titleLabel);
- STYLE_OVERLAY_CHECKBOX(this->enableWssCb);
- STYLE_OVERLAY_LABEL(this->wssPortLabel);
- STYLE_OVERLAY_INPUT(this->wssPortInput);
- STYLE_OVERLAY_CHECKBOX(this->enableHttpCb);
- STYLE_OVERLAY_LABEL(this->httpPortLabel);
- STYLE_OVERLAY_INPUT(this->httpPortInput);
- STYLE_OVERLAY_CHECKBOX(this->enableSyncTransCb);
- STYLE_OVERLAY_LABEL(this->transCacheLabel);
- STYLE_OVERLAY_INPUT(this->transCacheInput);
- STYLE_OVERLAY_LABEL(this->pwLabel);
- STYLE_OVERLAY_INPUT(this->pwInput);
+ applyLabelOverlayStyle(*this->titleLabel);
+ applyCheckboxOverlayStyle(*this->enableWssCb);
+ applyLabelOverlayStyle(*this->wssPortLabel);
+ applyInputOverlayStyle(*this->wssPortInput);
+ applyCheckboxOverlayStyle(*this->enableHttpCb);
+ applyLabelOverlayStyle(*this->httpPortLabel);
+ applyInputOverlayStyle(*this->httpPortInput);
+ applyCheckboxOverlayStyle(*this->enableSyncTransCb);
+ applyLabelOverlayStyle(*this->transCacheLabel);
+ applyInputOverlayStyle(*this->transCacheInput);
+ applyLabelOverlayStyle(*this->pwLabel);
+ applyInputOverlayStyle(*this->pwInput);
/* add 'em */
this->AddWindow(this->titleLabel);
diff --git a/src/musikbox/cursespp/App.cpp b/src/musikbox/cursespp/App.cpp
index 47939fd4b..4d1697e2e 100755
--- a/src/musikbox/cursespp/App.cpp
+++ b/src/musikbox/cursespp/App.cpp
@@ -137,6 +137,10 @@ void App::SetIcon(int resourceId) {
win32::SetIcon(resourceId);
}
}
+
+void App::SetSingleInstanceId(const std::string& uniqueId) {
+ this->uniqueId = uniqueId;
+}
#endif
void App::SetMinimizeToTray(bool minimizeToTray) {
@@ -183,6 +187,17 @@ void App::OnResized() {
}
void App::Run(ILayoutPtr layout) {
+#ifdef WIN32
+ if (this->uniqueId.size()) {
+ win32::EnableSingleInstance(uniqueId);
+
+ if (win32::AlreadyRunning()) {
+ win32::ShowOtherInstance();
+ return;
+ }
+ }
+#endif
+
Colors::Init(this->colorMode);
if (this->colorTheme.size()) {
diff --git a/src/musikbox/cursespp/App.h b/src/musikbox/cursespp/App.h
index d1c901b39..af2f801c2 100755
--- a/src/musikbox/cursespp/App.h
+++ b/src/musikbox/cursespp/App.h
@@ -62,6 +62,7 @@ namespace cursespp {
#ifdef WIN32
void SetIcon(int resourceId);
+ void SetSingleInstanceId(const std::string& uniqueId);
#endif
void Run(ILayoutPtr layout);
@@ -110,6 +111,7 @@ namespace cursespp {
#ifdef WIN32
int iconId;
+ std::string uniqueId;
#endif
};
}
diff --git a/src/musikbox/cursespp/Win32Util.cpp b/src/musikbox/cursespp/Win32Util.cpp
index 5cd79843a..56cdfb9ef 100644
--- a/src/musikbox/cursespp/Win32Util.cpp
+++ b/src/musikbox/cursespp/Win32Util.cpp
@@ -35,6 +35,7 @@
#pragma once
#include "stdafx.h"
+#include "Win32Util.h"
#include
#include
#include
@@ -42,6 +43,7 @@
#ifdef WIN32
#define WM_TRAYICON (WM_USER + 2000)
+#define WM_SHOW_OTHER_INSTANCE (WM_USER + 2001)
static std::basic_string className = L"Curses_App";
static HWND mainWindow = nullptr;
@@ -50,8 +52,10 @@ static std::unique_ptr trayIcon;
static bool minimizeToTray = false, minimizedToTray = false;
static std::string appTitle;
static HICON icon16 = nullptr, icon32 = nullptr;
+static HANDLE runningMutex;
+static DWORD runningMutexLastError = 0;
-static void findMainWindow() {
+static HWND findThisProcessMainWindow() {
static TCHAR buffer[256];
if (mainWindow == nullptr) {
@@ -64,12 +68,39 @@ static void findMainWindow() {
GetClassName(hWnd, buffer, sizeof(buffer));
if (className == std::basic_string(buffer)) {
mainWindow = hWnd;
- return;
+ return hWnd;
}
}
hWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
}
}
+
+ return nullptr;
+}
+
+static HWND findOtherProcessMainWindow() {
+ static TCHAR buffer[256];
+
+ DWORD dwProcID = GetCurrentProcessId();
+ HWND hWnd = GetTopWindow(GetDesktopWindow());
+
+ while (hWnd) {
+ DWORD dwWndProcID = 0;
+ GetWindowThreadProcessId(hWnd, &dwWndProcID);
+ if (dwWndProcID != dwProcID) { /* not in this process */
+ GetClassName(hWnd, buffer, sizeof(buffer));
+ if (className == std::basic_string(buffer)) {
+ ::GetWindowText(hWnd, buffer, sizeof(buffer));
+ if (appTitle == u16to8(buffer)) { /* title must match*/
+ return hWnd;
+ }
+ }
+ }
+
+ hWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
+ }
+
+ return nullptr;
}
static HICON loadIcon(int resourceId, int size) {
@@ -97,6 +128,19 @@ static void initTrayIcon(HWND hwnd) {
}
}
+static void restoreFromTray(HWND hwnd) {
+ Shell_NotifyIcon(NIM_DELETE, trayIcon.get());
+ minimizedToTray = false;
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+
+}
+
+static void resetMutex() {
+ CloseHandle(runningMutex);
+ runningMutex = nullptr;
+ runningMutexLastError = 0;
+}
+
static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, UINT_PTR id, DWORD_PTR data) {
if (minimizeToTray) {
if ((msg == WM_SIZE && wparam == SIZE_MINIMIZED) ||
@@ -117,41 +161,49 @@ static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
if (msg == WM_TRAYICON) {
if (LOWORD(lparam) == WM_LBUTTONUP) {
- Shell_NotifyIcon(NIM_DELETE, trayIcon.get());
- minimizedToTray = false;
- ShowWindow(hwnd, SW_SHOWNORMAL);
+ restoreFromTray(hwnd);
return 1;
}
}
+ if (msg == WM_SHOW_OTHER_INSTANCE) {
+ cursespp::win32::ShowMainWindow();
+ restoreFromTray(hwnd);
+ return 1;
+ }
+
+ if (msg == WM_QUIT) {
+ resetMutex();
+ }
+
return DefSubclassProc(hwnd, msg, wparam, lparam);
}
namespace cursespp {
namespace win32 {
void ShowMainWindow() {
- findMainWindow();
+ findThisProcessMainWindow();
if (mainWindow) {
ShowWindow(mainWindow, SW_SHOWNORMAL);
}
}
void HideMainWindow() {
- findMainWindow();
+ findThisProcessMainWindow();
if (mainWindow) {
ShowWindow(mainWindow, SW_HIDE);
}
}
void Minimize() {
- findMainWindow();
+ findThisProcessMainWindow();
if (mainWindow) {
ShowWindow(mainWindow, SW_SHOWMINIMIZED);
}
}
HWND GetMainWindow() {
- findMainWindow();
+ findThisProcessMainWindow();
return mainWindow;
}
@@ -177,6 +229,29 @@ namespace cursespp {
void SetAppTitle(const std::string& title) {
appTitle = title;
}
+
+ bool AlreadyRunning() {
+ return !IsDebuggerPresent() && (runningMutexLastError == ERROR_ALREADY_EXISTS);
+ }
+
+ void ShowOtherInstance() {
+ HWND otherHwnd = findOtherProcessMainWindow();
+ if (otherHwnd) {
+ SendMessage(otherHwnd, WM_SHOW_OTHER_INSTANCE, 0, 0);
+ ::SetForegroundWindow(otherHwnd);
+ }
+ }
+
+ void EnableSingleInstance(const std::string& uniqueId) {
+ if (uniqueId.size() && !runningMutex) {
+ std::string mutexName = "cursespp::" + uniqueId;
+ runningMutex = CreateMutexA(nullptr, false, mutexName.c_str());
+ runningMutexLastError = GetLastError();
+ }
+ else {
+ resetMutex();
+ }
+ }
}
}
diff --git a/src/musikbox/cursespp/Win32Util.h b/src/musikbox/cursespp/Win32Util.h
index 5e12a64d5..0615a63fc 100644
--- a/src/musikbox/cursespp/Win32Util.h
+++ b/src/musikbox/cursespp/Win32Util.h
@@ -48,6 +48,9 @@ namespace cursespp {
void SetIcon(int resourceId);
void SetAppTitle(const std::string& title);
void SetMinimizeToTray(bool enabled);
+ void EnableSingleInstance(const std::string& uniqueId);
+ bool AlreadyRunning();
+ void ShowOtherInstance();
}
}
diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/playback/PlayerWrapper.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/playback/PlayerWrapper.kt
index b54eb4cf3..0d6cf03f6 100644
--- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/playback/PlayerWrapper.kt
+++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/playback/PlayerWrapper.kt
@@ -95,7 +95,7 @@ abstract class PlayerWrapper {
if (preDuckGlobalVolume != DUCK_NONE) {
preDuckGlobalVolume = volume
- volume = volume * DUCK_COEF
+ volume *= DUCK_COEF
}
if (volume != globalVolume) {