From eef7ba48ddb060c14caa5be27faeabe6f82b3e08 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 24 Jan 2014 16:14:05 +0100 Subject: Win32Main: move to win32/ --- .gitignore | 2 +- Makefile.am | 12 +-- configure.ac | 2 +- src/Win32Main.cxx | 173 ------------------------------------------- src/win/mpd.ico | Bin 353118 -> 0 bytes src/win/mpd_win32_rc.rc.in | 34 --------- src/win32/Win32Main.cxx | 173 +++++++++++++++++++++++++++++++++++++++++++ src/win32/mpd.ico | Bin 0 -> 353118 bytes src/win32/mpd_win32_rc.rc.in | 34 +++++++++ 9 files changed, 215 insertions(+), 215 deletions(-) delete mode 100644 src/Win32Main.cxx delete mode 100644 src/win/mpd.ico delete mode 100644 src/win/mpd_win32_rc.rc.in create mode 100644 src/win32/Win32Main.cxx create mode 100644 src/win32/mpd.ico create mode 100644 src/win32/mpd_win32_rc.rc.in diff --git a/.gitignore b/.gitignore index 3c8552099..9b052a29f 100644 --- a/.gitignore +++ b/.gitignore @@ -40,7 +40,7 @@ tags .#* .stgit* src/dsd2pcm/dsd2pcm -src/win/mpd_win32_rc.rc +src/win32/mpd_win32_rc.rc doc/doxygen.conf doc/protocol.html doc/protocol diff --git a/Makefile.am b/Makefile.am index debdbab40..87ca79a70 100644 --- a/Makefile.am +++ b/Makefile.am @@ -155,7 +155,7 @@ src_mpd_SOURCES = \ src/IOThread.cxx src/IOThread.hxx \ src/Main.cxx src/Main.hxx \ src/Instance.cxx src/Instance.hxx \ - src/Win32Main.cxx \ + src/win32/Win32Main.cxx \ src/GlobalEvents.cxx src/GlobalEvents.hxx \ src/unix/SignalHandlers.cxx src/unix/SignalHandlers.hxx \ src/unix/Daemon.cxx src/unix/Daemon.hxx \ @@ -218,14 +218,14 @@ src_mpd_SOURCES = \ # Windows resource file # -src/win/mpd_win32_rc.$(OBJEXT): src/win/mpd_win32_rc.rc +src/win32/mpd_win32_rc.$(OBJEXT): src/win32/mpd_win32_rc.rc $(WINDRES) -i $< -o $@ if HAVE_WINDOWS -noinst_DATA = src/win/mpd_win32_rc.rc +noinst_DATA = src/win32/mpd_win32_rc.rc -src_mpd_DEPENDENCIES = src/win/mpd_win32_rc.$(OBJEXT) -src_mpd_LDFLAGS = -Wl,src/win/mpd_win32_rc.$(OBJEXT) +src_mpd_DEPENDENCIES = src/win32/mpd_win32_rc.$(OBJEXT) +src_mpd_LDFLAGS = -Wl,src/win32/mpd_win32_rc.$(OBJEXT) endif if ENABLE_DESPOTIFY @@ -1755,4 +1755,4 @@ EXTRA_DIST = $(doc_DATA) autogen.sh \ test/test_archive_zzip.sh \ $(wildcard scripts/*.sh) \ $(man_MANS) $(DOCBOOK_FILES) doc/mpdconf.example doc/doxygen.conf \ - src/win/mpd_win32_rc.rc.in src/win/mpd.ico + src/win32/mpd_win32_rc.rc.in src/win32/mpd.ico diff --git a/configure.ac b/configure.ac index 13ff64ba7..1bed0727d 100644 --- a/configure.ac +++ b/configure.ac @@ -85,7 +85,7 @@ linux*) mingw32* | windows*) AC_CONFIG_FILES([ - src/win/mpd_win32_rc.rc + src/win32/mpd_win32_rc.rc ]) AC_CHECK_TOOL(WINDRES, windres) AM_CPPFLAGS="$AM_CPPFLAGS -DWIN32_LEAN_AND_MEAN" diff --git a/src/Win32Main.cxx b/src/Win32Main.cxx deleted file mode 100644 index 75a1e9a23..000000000 --- a/src/Win32Main.cxx +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "Main.hxx" - -#ifdef WIN32 - -#include "Compiler.h" -#include "GlobalEvents.hxx" -#include "system/FatalError.hxx" - -#include -#include - -#include - -#include - -static int service_argc; -static char **service_argv; -static char service_name[] = ""; -static std::atomic_bool running; -static SERVICE_STATUS_HANDLE service_handle; - -static void WINAPI -service_main(DWORD argc, CHAR *argv[]); - -static SERVICE_TABLE_ENTRY service_registry[] = { - {service_name, service_main}, - {nullptr, nullptr} -}; - -static void -service_notify_status(DWORD status_code) -{ - SERVICE_STATUS current_status; - - current_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - current_status.dwControlsAccepted = status_code == SERVICE_START_PENDING - ? 0 - : SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP; - - current_status.dwCurrentState = status_code; - current_status.dwWin32ExitCode = NO_ERROR; - current_status.dwCheckPoint = 0; - current_status.dwWaitHint = 1000; - - SetServiceStatus(service_handle, ¤t_status); -} - -static DWORD WINAPI -service_dispatcher(gcc_unused DWORD control, gcc_unused DWORD event_type, - gcc_unused void *event_data, gcc_unused void *context) -{ - switch (control) { - case SERVICE_CONTROL_SHUTDOWN: - case SERVICE_CONTROL_STOP: - GlobalEvents::Emit(GlobalEvents::SHUTDOWN); - return NO_ERROR; - default: - return NO_ERROR; - } -} - -static void WINAPI -service_main(gcc_unused DWORD argc, gcc_unused CHAR *argv[]) -{ - DWORD error_code; - gchar* error_message; - - service_handle = - RegisterServiceCtrlHandlerEx(service_name, - service_dispatcher, nullptr); - - if (service_handle == 0) { - error_code = GetLastError(); - error_message = g_win32_error_message(error_code); - FormatFatalError("RegisterServiceCtrlHandlerEx() failed: %s", - error_message); - } - - service_notify_status(SERVICE_START_PENDING); - mpd_main(service_argc, service_argv); - service_notify_status(SERVICE_STOPPED); -} - -static BOOL WINAPI -console_handler(DWORD event) -{ - switch (event) { - case CTRL_C_EVENT: - case CTRL_CLOSE_EVENT: - if (running.load()) { - // Recent msdn docs that process is terminated - // if this function returns TRUE. - // We initiate correct shutdown sequence (if possible). - // Once main() returns CRT will terminate our process - // regardless our thread is still active. - // If this did not happen within 3 seconds - // let's shutdown anyway. - GlobalEvents::Emit(GlobalEvents::SHUTDOWN); - // Under debugger it's better to wait indefinitely - // to allow debugging of shutdown code. - Sleep(IsDebuggerPresent() ? INFINITE : 3000); - } - // If we're not running main loop there is no chance for - // clean shutdown. - std::exit(EXIT_FAILURE); - return TRUE; - default: - return FALSE; - } -} - -int win32_main(int argc, char *argv[]) -{ - DWORD error_code; - gchar* error_message; - - service_argc = argc; - service_argv = argv; - - if (StartServiceCtrlDispatcher(service_registry)) - return 0; /* run as service successefully */ - - error_code = GetLastError(); - if (error_code == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { - /* running as console app */ - running.store(false); - SetConsoleTitle("Music Player Daemon"); - SetConsoleCtrlHandler(console_handler, TRUE); - return mpd_main(argc, argv); - } - - error_message = g_win32_error_message(error_code); - FormatFatalError("StartServiceCtrlDispatcher() failed: %s", - error_message); -} - -void win32_app_started() -{ - if (service_handle != 0) - service_notify_status(SERVICE_RUNNING); - else - running.store(true); -} - -void win32_app_stopping() -{ - if (service_handle != 0) - service_notify_status(SERVICE_STOP_PENDING); - else - running.store(false); -} - -#endif diff --git a/src/win/mpd.ico b/src/win/mpd.ico deleted file mode 100644 index 86fd9fe43..000000000 Binary files a/src/win/mpd.ico and /dev/null differ diff --git a/src/win/mpd_win32_rc.rc.in b/src/win/mpd_win32_rc.rc.in deleted file mode 100644 index a31118a0c..000000000 --- a/src/win/mpd_win32_rc.rc.in +++ /dev/null @@ -1,34 +0,0 @@ -#include - -#define VERSION_NUMBER @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_REVISION@,@VERSION_EXTRA@ -#define VERSION_NUMBER_STR "@VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_REVISION@,@VERSION_EXTRA@" - -MPD_ICON ICON "@top_srcdir@/src/win/mpd.ico" - -1 VERSIONINFO -FILETYPE VFT_APP -FILEOS VOS__WINDOWS32 -PRODUCTVERSION VERSION_NUMBER - -FILEVERSION VERSION_NUMBER -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "Music Player Daemon Project" - VALUE "ProductName", "Music Player Daemon" - VALUE "ProductVersion", VERSION_NUMBER_STR - VALUE "InternalName", "mpd" - VALUE "OriginalFilename", "mpd.exe" - VALUE "FileVersion", "@VERSION@" - VALUE "FileDescription", "Music Player Daemon @VERSION@" - VALUE "LegalCopyright", "Copyright \251 The Music Player Daemon Project" - END - END - - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END diff --git a/src/win32/Win32Main.cxx b/src/win32/Win32Main.cxx new file mode 100644 index 000000000..75a1e9a23 --- /dev/null +++ b/src/win32/Win32Main.cxx @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2003-2014 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Main.hxx" + +#ifdef WIN32 + +#include "Compiler.h" +#include "GlobalEvents.hxx" +#include "system/FatalError.hxx" + +#include +#include + +#include + +#include + +static int service_argc; +static char **service_argv; +static char service_name[] = ""; +static std::atomic_bool running; +static SERVICE_STATUS_HANDLE service_handle; + +static void WINAPI +service_main(DWORD argc, CHAR *argv[]); + +static SERVICE_TABLE_ENTRY service_registry[] = { + {service_name, service_main}, + {nullptr, nullptr} +}; + +static void +service_notify_status(DWORD status_code) +{ + SERVICE_STATUS current_status; + + current_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + current_status.dwControlsAccepted = status_code == SERVICE_START_PENDING + ? 0 + : SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP; + + current_status.dwCurrentState = status_code; + current_status.dwWin32ExitCode = NO_ERROR; + current_status.dwCheckPoint = 0; + current_status.dwWaitHint = 1000; + + SetServiceStatus(service_handle, ¤t_status); +} + +static DWORD WINAPI +service_dispatcher(gcc_unused DWORD control, gcc_unused DWORD event_type, + gcc_unused void *event_data, gcc_unused void *context) +{ + switch (control) { + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + GlobalEvents::Emit(GlobalEvents::SHUTDOWN); + return NO_ERROR; + default: + return NO_ERROR; + } +} + +static void WINAPI +service_main(gcc_unused DWORD argc, gcc_unused CHAR *argv[]) +{ + DWORD error_code; + gchar* error_message; + + service_handle = + RegisterServiceCtrlHandlerEx(service_name, + service_dispatcher, nullptr); + + if (service_handle == 0) { + error_code = GetLastError(); + error_message = g_win32_error_message(error_code); + FormatFatalError("RegisterServiceCtrlHandlerEx() failed: %s", + error_message); + } + + service_notify_status(SERVICE_START_PENDING); + mpd_main(service_argc, service_argv); + service_notify_status(SERVICE_STOPPED); +} + +static BOOL WINAPI +console_handler(DWORD event) +{ + switch (event) { + case CTRL_C_EVENT: + case CTRL_CLOSE_EVENT: + if (running.load()) { + // Recent msdn docs that process is terminated + // if this function returns TRUE. + // We initiate correct shutdown sequence (if possible). + // Once main() returns CRT will terminate our process + // regardless our thread is still active. + // If this did not happen within 3 seconds + // let's shutdown anyway. + GlobalEvents::Emit(GlobalEvents::SHUTDOWN); + // Under debugger it's better to wait indefinitely + // to allow debugging of shutdown code. + Sleep(IsDebuggerPresent() ? INFINITE : 3000); + } + // If we're not running main loop there is no chance for + // clean shutdown. + std::exit(EXIT_FAILURE); + return TRUE; + default: + return FALSE; + } +} + +int win32_main(int argc, char *argv[]) +{ + DWORD error_code; + gchar* error_message; + + service_argc = argc; + service_argv = argv; + + if (StartServiceCtrlDispatcher(service_registry)) + return 0; /* run as service successefully */ + + error_code = GetLastError(); + if (error_code == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { + /* running as console app */ + running.store(false); + SetConsoleTitle("Music Player Daemon"); + SetConsoleCtrlHandler(console_handler, TRUE); + return mpd_main(argc, argv); + } + + error_message = g_win32_error_message(error_code); + FormatFatalError("StartServiceCtrlDispatcher() failed: %s", + error_message); +} + +void win32_app_started() +{ + if (service_handle != 0) + service_notify_status(SERVICE_RUNNING); + else + running.store(true); +} + +void win32_app_stopping() +{ + if (service_handle != 0) + service_notify_status(SERVICE_STOP_PENDING); + else + running.store(false); +} + +#endif diff --git a/src/win32/mpd.ico b/src/win32/mpd.ico new file mode 100644 index 000000000..86fd9fe43 Binary files /dev/null and b/src/win32/mpd.ico differ diff --git a/src/win32/mpd_win32_rc.rc.in b/src/win32/mpd_win32_rc.rc.in new file mode 100644 index 000000000..e5312dc78 --- /dev/null +++ b/src/win32/mpd_win32_rc.rc.in @@ -0,0 +1,34 @@ +#include + +#define VERSION_NUMBER @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_REVISION@,@VERSION_EXTRA@ +#define VERSION_NUMBER_STR "@VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_REVISION@,@VERSION_EXTRA@" + +MPD_ICON ICON "@top_srcdir@/src/win32/mpd.ico" + +1 VERSIONINFO +FILETYPE VFT_APP +FILEOS VOS__WINDOWS32 +PRODUCTVERSION VERSION_NUMBER + +FILEVERSION VERSION_NUMBER +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", "Music Player Daemon Project" + VALUE "ProductName", "Music Player Daemon" + VALUE "ProductVersion", VERSION_NUMBER_STR + VALUE "InternalName", "mpd" + VALUE "OriginalFilename", "mpd.exe" + VALUE "FileVersion", "@VERSION@" + VALUE "FileDescription", "Music Player Daemon @VERSION@" + VALUE "LegalCopyright", "Copyright \251 The Music Player Daemon Project" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END -- cgit v1.2.3