Advertisement
Guest User

Untitled

a guest
Aug 9th, 2017
561
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 125.05 KB | None | 0 0
  1. diff --git a/README b/README
  2. index cd35424f..4803d147 100644
  3. --- a/README
  4. +++ b/README
  5. @@ -57,3 +57,55 @@ actual package names for your Linux distribution may vary.
  6.  2. licensing
  7.  
  8.  DeaDBeeF core uses ZLIB license. See COPYING in each subdirectory for details.
  9. +
  10. +
  11. +
  12. +
  13. +
  14. +---------------------------
  15. +
  16. +MinGW section
  17. +(please note, this whole source code tree is still a work in progress - no warranty provided)
  18. +
  19. +The needed libraries above will build and install almost out-of-the-box.
  20. +For jansson, download some recent version (>=2.8), because I committed a fix for mingw environment which allows the full test suite to complete.
  21. +
  22. +With recent versions of pthreads-win32 (installed with msys1/mingw) you'll have to comment out the declaration of timespec struct type (into pthread.h), since it is already declared in parts/time.h and having both will raise a compilation error. (seems this is not needed anymore...)
  23. +
  24. +You'll get a ready-to-go binary zip file with GTK+2.24.10 on www.gtk.org, it contains also every single dependency library needed for deadbeef (gdk, glib, gthread, pango, cairo, atk and so on) and they're all built as DLL.
  25. +Well, if you prefer GTK+3 or any other gtk release, feel free to try. Version 2 is what I used, since it is easy to go with.
  26. +
  27. +At the time of writing, I am quite confident a minimal deadbeef binary can be built with:
  28. +
  29. +./configure --disable-vtx --disable-gme --disable-sid --disable-adplug --disable-wildmidi --disable-psf --disable-dumb --disable-shn --disable-sc68 --disable-shellexec --disable-ffap --disable-nls --disable-converter
  30. +
  31. +It will support mpeg1/2 (if you install libmad and/or mpg123), aac (if you install faad2), vorbis (if you install libogg and libvorbis), musepack (it is shipped with deadbeef), flac (if you install flac), wavpack (if you install wavpack), sndfile (if you install libsndfile) and wma decoding (shipped) and resampling (if you install libsamplerate aka SecretRabbitCode). (maybe something else, disable what's unwanted)
  32. +
  33. +The default null output plugin will be built, and I added a nice feature simulating real audio output delay. Quite useful, sometimes.
  34. +The WaveOut output plugin version 1.0 is now ready and it can play sounds through any audio device your OS currently supports. The deadbeef preference window lets you choose among the devices detected by the plugin.
  35. +QUALITY: a few tests I run on Windows7 platform (NOT into a VM) revealed some audio artifact and far metallic echoes during playback. The same audio source sounds far better when played through DirectSound API (same hardware involved). Well, the WaveOut plugin has no flaws (none I'm aware of), IMHO this means the audio content is "enriched" with a light DSP by the audio driver in the latter case. After all, the WaveOut interface is pretty old and those kind of scenarios may push everyone in software migration. If I'll have some time, then I'll write a DirectSound output plugin, although the current WaveOut plugin works indeed.
  36. +
  37. +After the usual 'make' the main executable should be built (linking against wsock32 is needed).
  38. +Note: chances are that recent mingw compiler (gcc) creates an executable which needs an extra lib, called libgcc_s_dw2-1.dll.
  39. +Now, want a static deadbeef executable (I do) ? Then add the '-static' option to the compiler command line.
  40. +Have static and shared versions of pthreads libraries (I do) ? The default behaviour is to build against the shared version (dll) but you'll have to ship the library together with your executable. If this is not what you want, then add the '-D_PTW32_STATIC_LIB' definition to the preprocessor flags and you will get deadbeef.exe with no pthread dependency.
  41. +
  42. +Now, 'make install' will install the package and you will be able to run deadbeef but - nothing else will happen.
  43. +Why?
  44. +Plugins are missing! - well, they are yet to be built for windows environment, that is, they have to be built as dll libraries.
  45. +
  46. +This step is pretty easy - just annoying.
  47. +Go into the plugin directory (you have to follow this step for every plugin you want to build/install) and type:
  48. +
  49. +gcc -s -shared -o somethingplugin.dll *.o libdependency.a -Wl,-no-undefined -Wl,--enable-runtime-pseudo-reloc
  50. +
  51. +where somethingplugin.dll is the name of the output dll. Replace that *.o with the object files created by make (usually you'll find them into .libs/) and those libdependency.a with the library needed for the full linking process. For example, when linking the mp3 deconding library, mp3.dll, you will need to link libmad.a (and/or libmpg123.a) also (include their FULL path!).
  52. +Naming:  IT IS MANDATORY the dll has to be named as the plugin it contains (and case DOES matter)! If different, deadbeef won't find the entry point for the functions it searches it in.
  53. +The only exception is for gui plugins, they are named accordingly to the rules reported here https://github.com/Alexey-Yakovenko/deadbeef/wiki/Developing-your-own-plugin . Anyway, if in doubt, name the plugin exactly as its linux counterpart, just with .dll extension.
  54. +
  55. +Copy the dll file into the plugins/ directory and the whole game will play nicely.
  56. +
  57. +Have fun.
  58. +
  59. +Elio
  60. +
  61. diff --git a/conf.c b/conf.c
  62. index ab774e91..0b4fbaa5 100644
  63. --- a/conf.c
  64. +++ b/conf.c
  65. @@ -27,6 +27,10 @@
  66.  #endif
  67.  #include <stdio.h>
  68.  #include <stdint.h>
  69. +#ifdef __MINGW32__
  70. +#undef __STRICT_ANSI__
  71. +#undef _NO_OLDNAMES
  72. +#endif
  73.  #include <string.h>
  74.  #include <stdlib.h>
  75.  #include <limits.h>
  76. @@ -45,7 +49,7 @@
  77.  
  78.  static DB_conf_item_t *conf_items;
  79.  static int changed = 0;
  80. -static uintptr_t mutex;
  81. +static db_mutex_t mutex;
  82.  
  83.  void
  84.  conf_init (void) {
  85. @@ -83,7 +87,11 @@ conf_load (void) {
  86.      char fname[l + sizeof(configfile)];
  87.      memcpy (fname, dbconfdir, l);
  88.      memcpy (fname + l, configfile, sizeof (configfile));
  89. +#ifdef __MINGW32__
  90. +    FILE *fp = fopen (fname, "rb");
  91. +#else
  92.      FILE *fp = fopen (fname, "rt");
  93. +#endif
  94.      if (!fp) {
  95.          fprintf (stderr, "failed to load config file\n");
  96.          fp = fopen (fname, "w+b");
  97. @@ -104,6 +112,7 @@ conf_load (void) {
  98.      uint8_t *buffer = malloc (l+1);
  99.      if (l != fread (buffer, 1, l, fp)) {
  100.          free (buffer);
  101. +        fclose (fp);
  102.          fprintf (stderr, "failed to read entire config file to memory\n");
  103.          return -1;
  104.      }
  105. @@ -187,6 +196,10 @@ conf_save (void) {
  106.          }
  107.      }
  108.      fclose (fp);
  109. +#ifdef __MINGW32__
  110. +    if (unlink(str)!=0)
  111. +        fprintf (stderr, "deleting %s failed: %s\n", str, strerror (errno));
  112. +#endif
  113.      err = rename (tempfile, str);
  114.      if (err != 0) {
  115.          fprintf (stderr, "config rename %s -> %s failed: %s\n", tempfile, str, strerror (errno));
  116. diff --git a/deadbeef.h b/deadbeef.h
  117. index 72faa83b..5017c117 100644
  118. --- a/deadbeef.h
  119. +++ b/deadbeef.h
  120. @@ -29,6 +29,7 @@
  121.  #include <time.h>
  122.  #include <stdio.h>
  123.  #include <dirent.h>
  124. +#include "threading.h"
  125.  
  126.  #ifdef __cplusplus
  127.  extern "C" {
  128. @@ -598,21 +599,23 @@ typedef struct {
  129.      void (*quit) (void);
  130.  
  131.      // threading
  132. -    intptr_t (*thread_start) (void (*fn)(void *ctx), void *ctx);
  133. -    intptr_t (*thread_start_low_priority) (void (*fn)(void *ctx), void *ctx);
  134. -    int (*thread_join) (intptr_t tid);
  135. -    int (*thread_detach) (intptr_t tid);
  136. +    db_thread_t (*thread_start) (void (*fn)(void *ctx), void *ctx);
  137. +    db_thread_t (*thread_start_low_priority) (void (*fn)(void *ctx), void *ctx);
  138. +    int (*thread_join) (db_thread_t tid);
  139. +    int (*thread_detach) (db_thread_t tid);
  140. +    int (*thread_alive) (db_thread_t tid);
  141. +    void (*thread_wipeid) (db_thread_t *tid);
  142.      void (*thread_exit) (void *retval);
  143. -    uintptr_t (*mutex_create) (void);
  144. -    uintptr_t (*mutex_create_nonrecursive) (void);
  145. -    void (*mutex_free) (uintptr_t mtx);
  146. -    int (*mutex_lock) (uintptr_t mtx);
  147. -    int (*mutex_unlock) (uintptr_t mtx);
  148. -    uintptr_t (*cond_create) (void);
  149. -    void (*cond_free) (uintptr_t cond);
  150. -    int (*cond_wait) (uintptr_t cond, uintptr_t mutex);
  151. -    int (*cond_signal) (uintptr_t cond);
  152. -    int (*cond_broadcast) (uintptr_t cond);
  153. +    db_mutex_t (*mutex_create) (void);
  154. +    db_mutex_t (*mutex_create_nonrecursive) (void);
  155. +    void (*mutex_free) (db_mutex_t mtx);
  156. +    int (*mutex_lock) (db_mutex_t mtx);
  157. +    int (*mutex_unlock) (db_mutex_t mtx);
  158. +    db_cond_t (*cond_create) (void);
  159. +    void (*cond_free) (db_cond_t cond);
  160. +    int (*cond_wait) (db_cond_t cond, db_mutex_t mutex);
  161. +    int (*cond_signal) (db_cond_t cond);
  162. +    int (*cond_broadcast) (db_cond_t cond);
  163.  
  164.      /////// playlist management //////
  165.      void (*plt_ref) (ddb_playlist_t *plt);
  166. diff --git a/handler.c b/handler.c
  167. index 13dfec49..4ccd79ce 100644
  168. --- a/handler.c
  169. +++ b/handler.c
  170. @@ -24,13 +24,13 @@
  171.  
  172.    Alexey Yakovenko waker@users.sourceforge.net
  173.  */
  174. -#include "handler.h"
  175. +
  176.  #include <stdio.h>
  177.  #include <string.h>
  178.  #include <assert.h>
  179.  #include <stdlib.h>
  180. -#include "handler.h"
  181.  #include "threading.h"
  182. +#include "handler.h"
  183.  
  184.  typedef struct message_s {
  185.      uint32_t id;
  186. @@ -45,8 +45,8 @@ typedef struct handler_s {
  187.      message_t *mfree;
  188.      message_t *mqueue;
  189.      message_t *mqtail;
  190. -    uintptr_t mutex;
  191. -    uintptr_t cond;
  192. +    db_mutex_t mutex;
  193. +    db_cond_t cond;
  194.      message_t pool[1];
  195.  } handler_t;
  196.  
  197. diff --git a/junklib.c b/junklib.c
  198. index 6f8cbe48..d237b290 100644
  199. --- a/junklib.c
  200. +++ b/junklib.c
  201. @@ -30,10 +30,16 @@
  202.  #include "junklib.h"
  203.  #include <stdio.h>
  204.  #include <stdlib.h>
  205. +#ifdef __MINGW32__
  206. +#undef __STRICT_ANSI__
  207. +#undef _NO_OLDNAMES
  208. +#endif
  209.  #include <string.h>
  210.  #undef HAVE_ICI
  211.  #if HAVE_ICONV
  212. +#ifndef __MINGW32__
  213.    #define LIBICONV_PLUG
  214. +#endif
  215.    #include <iconv.h>
  216.  #elif HAVE_ICU
  217.    #warning icu
  218. @@ -586,7 +592,7 @@ junk_iconv (const char *in, int inlen, char *out, int outlen, const char *cs_in,
  219.      if (cd == (iconv_t)-1) {
  220.          return -1;
  221.      }
  222. -#ifdef __linux__
  223. +#if defined(__linux__) || defined(__MINGW32__)
  224.      char *pin = (char*)in;
  225.  #else
  226.      const char *pin = in;
  227. diff --git a/main.c b/main.c
  228. index d7471002..c5f066ac 100644
  229. --- a/main.c
  230. +++ b/main.c
  231. @@ -30,6 +30,9 @@
  232.  #include <stdio.h>
  233.  #include <stdint.h>
  234.  #include <string.h>
  235. +#ifdef __MINGW32__
  236. +#undef __STRICT_ANSI__ /* this will make stdlib.h declare the prototype for '_fullpath' */
  237. +#endif
  238.  #include <stdlib.h>
  239.  #include <stddef.h>
  240.  #include <time.h>
  241. @@ -37,7 +40,7 @@
  242.  #ifdef __linux__
  243.  #include <sys/prctl.h>
  244.  #endif
  245. -#ifndef __linux__
  246. +#if !defined(__linux__) && !defined(_POSIX_C_SOURCE)
  247.  #define _POSIX_C_SOURCE 1
  248.  #endif
  249.  #include <limits.h>
  250. @@ -45,11 +48,16 @@
  251.  #include <sys/stat.h>
  252.  #include <sys/types.h>
  253.  #include <sys/types.h>
  254. +#ifdef __MINGW32__
  255. +#include <winsock2.h>
  256. +#define DEFAULT_LISTENING_PORT    48879
  257. +#else
  258.  #include <sys/socket.h>
  259.  #include <sys/select.h>
  260.  #include <sys/un.h>
  261. -#include <sys/fcntl.h>
  262.  #include <sys/errno.h>
  263. +#endif
  264. +#include <sys/fcntl.h>
  265.  #include <signal.h>
  266.  #ifdef __GLIBC__
  267.  #include <execinfo.h>
  268. @@ -70,6 +78,9 @@
  269.  #endif
  270.  #include "playqueue.h"
  271.  #include "tf.h"
  272. +#ifdef __MINGW32__
  273. +#include "mingw32_layer.h"
  274. +#endif
  275.  
  276.  #ifndef PREFIX
  277.  #error PREFIX must be defined
  278. @@ -153,7 +164,13 @@ prepare_command_line (int argc, char *argv[], int *size) {
  279.          // if argument is a filename, try to resolve it
  280.          char resolved[PATH_MAX];
  281.          char *arg;
  282. +#ifdef __MINGW32__
  283. +        struct _stati64 dummy;
  284. +        realpath (argv[i], resolved);
  285. +        if ((!strncmp ("--", argv[i], 2) && !seen_ddash) || _stati64(argv[i], &dummy)) {
  286. +#else
  287.          if (!strncmp ("--", argv[i], 2) && !seen_ddash || !realpath (argv[i], resolved)) {
  288. +#endif
  289.              arg = argv[i];
  290.          }
  291.          else {
  292. @@ -200,7 +217,7 @@ server_exec_command_line (const char *cmdline, int len, char *sendback, int sbsi
  293.      const uint8_t *pend = cmdline + len;
  294.      int queue = 0;
  295.      while (parg < pend) {
  296. -        const char *parg_c = parg;
  297. +//        const char *parg_c = parg;
  298.          if (strlen (parg) >= 2 && parg[0] == '-' && parg[1] != '-') {
  299.              parg += strlen (parg);
  300.              parg++;
  301. @@ -403,8 +420,13 @@ server_exec_command_line (const char *cmdline, int len, char *sendback, int sbsi
  302.      return 0;
  303.  }
  304.  
  305. +#ifdef __MINGW32__
  306. +static struct sockaddr_in srv_local;
  307. +static struct sockaddr_in srv_remote;
  308. +#else
  309.  static struct sockaddr_un srv_local;
  310.  static struct sockaddr_un srv_remote;
  311. +#endif
  312.  static unsigned srv_socket;
  313.  
  314.  #if USE_ABSTRACT_SOCKET_NAME
  315. @@ -413,7 +435,17 @@ static char server_id[] = "\0deadbeefplayer";
  316.  
  317.  int
  318.  server_start (void) {
  319. +    int len;
  320. +
  321.      fprintf (stderr, "server_start\n");
  322. +#ifdef __MINGW32__
  323. +    srv_socket = socket (AF_INET, SOCK_STREAM, 0);
  324. +    unsigned long flags = 1;
  325. +    if (ioctlsocket(srv_socket, FIONBIO, &flags) == SOCKET_ERROR) {
  326. +        perror ("ioctlsocket FIONBIO");
  327. +        return -1;
  328. +    }
  329. +#else
  330.      srv_socket = socket (AF_UNIX, SOCK_STREAM, 0);
  331.      int flags;
  332.      flags = fcntl (srv_socket, F_GETFL,0);
  333. @@ -425,20 +457,30 @@ server_start (void) {
  334.          perror ("fcntl F_SETFL");
  335.          return -1;
  336.      }
  337. +#endif
  338.      memset (&srv_local, 0, sizeof (srv_local));
  339. +
  340. +#ifdef __MINGW32__
  341. +    srv_local.sin_family      = AF_INET;
  342. +    srv_local.sin_addr.s_addr = INADDR_ANY;
  343. +    srv_local.sin_port        = htons(DEFAULT_LISTENING_PORT);
  344. +
  345. +    len = sizeof(srv_local);
  346. +#else
  347.      srv_local.sun_family = AF_UNIX;
  348.  
  349.  #if USE_ABSTRACT_SOCKET_NAME
  350.      memcpy (srv_local.sun_path, server_id, sizeof (server_id));
  351. -    int len = offsetof(struct sockaddr_un, sun_path) + sizeof (server_id)-1;
  352. +    len = offsetof(struct sockaddr_un, sun_path) + sizeof (server_id)-1;
  353.  #else
  354.      char *socketdirenv = getenv ("DDB_SOCKET_DIR");
  355.      snprintf (srv_local.sun_path, sizeof (srv_local.sun_path), "%s/socket", socketdirenv ? socketdirenv : dbconfdir);
  356.      if (unlink(srv_local.sun_path) < 0) {
  357.          perror ("INFO: unlink socket");
  358.      }
  359. -    int len = offsetof(struct sockaddr_un, sun_path) + strlen (srv_local.sun_path);
  360. +    len = offsetof(struct sockaddr_un, sun_path) + strlen (srv_local.sun_path);
  361.  #endif
  362. +#endif /* __MINGW32__ */
  363.  
  364.      if (bind(srv_socket, (struct sockaddr *)&srv_local, len) < 0) {
  365.          perror ("bind");
  366. @@ -455,7 +497,11 @@ server_start (void) {
  367.  void
  368.  server_close (void) {
  369.      if (srv_socket) {
  370. +#ifdef __MINGW32__
  371. +        closesocket (srv_socket);
  372. +#else
  373.          close (srv_socket);
  374. +#endif
  375.          srv_socket = 0;
  376.      }
  377.  }
  378. @@ -480,7 +526,11 @@ read_entire_message (int sockfd, int *size) {
  379.  
  380.          int rd = recv(sockfd, buf + rdp, bufsize - rdp, 0);
  381.          if (rd < 0) {
  382. +#ifdef __MINGW32__
  383. +            if (WSAGetLastError() == WSAEWOULDBLOCK) {
  384. +#else
  385.              if (errno == EAGAIN) {
  386. +#endif
  387.                  usleep (50000);
  388.                  continue;
  389.              }
  390. @@ -503,7 +553,11 @@ server_update (void) {
  391.      int t = sizeof (srv_remote);
  392.      unsigned s2;
  393.      s2 = accept(srv_socket, (struct sockaddr *)&srv_remote, &t);
  394. +#ifdef __MINGW32__
  395. +    if (s2 == -1 && WSAGetLastError() != WSAEWOULDBLOCK) {
  396. +#else
  397.      if (s2 == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
  398. +#endif
  399.          perror("accept");
  400.          return -1;
  401.      }
  402. @@ -527,7 +581,11 @@ server_update (void) {
  403.          else {
  404.              send (s2, "", 1, 0);
  405.          }
  406. +#ifdef __MINGW32__
  407. +        closesocket (s2);
  408. +#else
  409.          close(s2);
  410. +#endif
  411.  
  412.          if (buf) {
  413.              free(buf);
  414. @@ -536,7 +594,7 @@ server_update (void) {
  415.      return 0;
  416.  }
  417.  
  418. -static uintptr_t server_tid;
  419. +static db_thread_t server_tid;
  420.  static int server_terminate;
  421.  
  422.  void
  423. @@ -728,7 +786,7 @@ restore_resume_state (void) {
  424.      }
  425.  }
  426.  
  427. -uintptr_t mainloop_tid;
  428. +db_thread_t mainloop_tid;
  429.  
  430.  DB_plugin_t *
  431.  plug_get_gui (void) {
  432. @@ -744,10 +802,10 @@ plug_get_gui (void) {
  433.  void
  434.  main_cleanup_and_quit (void) {
  435.      // terminate server and wait for completion
  436. -    if (server_tid) {
  437. +    if (thread_alive (server_tid)) {
  438.          server_terminate = 1;
  439.          thread_join (server_tid);
  440. -        server_tid = 0;
  441. +        thread_wipeid (&server_tid);
  442.      }
  443.  
  444.      // save config
  445. @@ -801,6 +859,9 @@ mainloop_thread (void *ctx) {
  446.  
  447.  int
  448.  main (int argc, char *argv[]) {
  449. +#ifdef __MINGW32__
  450. +    char current_dir[MAX_PATH];
  451. +#endif
  452.      int portable = 0;
  453.  #if STATICLINK
  454.      int staticlink = 1;
  455. @@ -808,6 +869,9 @@ main (int argc, char *argv[]) {
  456.      int staticlink = 0;
  457.  #endif
  458.  #if PORTABLE
  459. +#ifdef __MINGW32__
  460. +    GetCurrentDirectory(PATH_MAX, dbinstalldir);
  461. +#else
  462.      portable = 1;
  463.      if (!realpath (argv[0], dbinstalldir)) {
  464.          strcpy (dbinstalldir, argv[0]);
  465. @@ -820,6 +884,7 @@ main (int argc, char *argv[]) {
  466.          fprintf (stderr, "couldn't determine install folder from path %s\n", argv[0]);
  467.          exit (-1);
  468.      }
  469. +#endif /* __MINGW32__ */
  470.  #else
  471.      if (!realpath (argv[0], dbinstalldir)) {
  472.          strcpy (dbinstalldir, argv[0]);
  473. @@ -869,6 +934,13 @@ main (int argc, char *argv[]) {
  474.      prctl (PR_SET_NAME, "deadbeef-main", 0, 0, 0, 0);
  475.  #endif
  476.  
  477. +#ifdef __MINGW32__
  478. +    WSADATA wsaData;
  479. +    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
  480. +        fprintf(stderr, "Error with WSAStartup(), WinSock startup failed.\n");
  481. +    else
  482. +        fprintf(stderr, "WinSock init ok, library version %d.%d\n", HIBYTE(wsaData.wVersion), LOBYTE(wsaData.wVersion));
  483. +#endif
  484.  #if PORTABLE_FULL
  485.      if (snprintf (confdir, sizeof (confdir), "%s/config", dbinstalldir) > sizeof (confdir)) {
  486.          fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
  487. @@ -882,7 +954,11 @@ main (int argc, char *argv[]) {
  488.          return -1;
  489.      }
  490.  #else
  491. +#ifdef __MINGW32__
  492. +    char *homedir = getenv ("USERPROFILE");
  493. +#else
  494.      char *homedir = getenv ("HOME");
  495. +#endif
  496.      if (!homedir) {
  497.          fprintf (stderr, "unable to find home directory. stopping.\n");
  498.          return -1;
  499. @@ -941,7 +1017,12 @@ main (int argc, char *argv[]) {
  500.          mkdir (dbplugindir, 0755);
  501.      }
  502.      else {
  503. +#ifdef __MINGW32__
  504. +        GetCurrentDirectory(MAX_PATH, current_dir);
  505. +        if (snprintf (dbdocdir, sizeof (dbdocdir), "%s/doc", current_dir) > sizeof (dbdocdir)) {
  506. +#else
  507.          if (snprintf (dbdocdir, sizeof (dbdocdir), "%s", DOCDIR) > sizeof (dbdocdir)) {
  508. +#endif
  509.              fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
  510.              return -1;
  511.          }
  512. @@ -953,11 +1034,19 @@ main (int argc, char *argv[]) {
  513.                  return -1;
  514.              }
  515.          }
  516. +#ifdef __MINGW32__
  517. +        else if (snprintf (dbplugindir, sizeof (dbplugindir), "%s/plugins", current_dir) > sizeof (dbplugindir)) {
  518. +#else
  519.          else if (snprintf (dbplugindir, sizeof (dbplugindir), "%s/deadbeef", LIBDIR) > sizeof (dbplugindir)) {
  520. +#endif
  521.              fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
  522.              return -1;
  523.          }
  524. +#ifdef __MINGW32__
  525. +        if (snprintf (dbpixmapdir, sizeof (dbpixmapdir), "%s/pixmaps", current_dir) > sizeof (dbpixmapdir)) {
  526. +#else
  527.          if (snprintf (dbpixmapdir, sizeof (dbpixmapdir), "%s/share/deadbeef/pixmaps", PREFIX) > sizeof (dbpixmapdir)) {
  528. +#endif
  529.              fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
  530.              return -1;
  531.          }
  532. @@ -996,15 +1085,28 @@ main (int argc, char *argv[]) {
  533.  
  534.      // try to connect to remote player
  535.      int s, len;
  536. -    struct sockaddr_un remote;
  537.  
  538. +#ifdef __MINGW32__
  539. +    struct sockaddr_in remote;
  540. +    if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
  541. +#else
  542. +    struct sockaddr_un remote;
  543.      if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
  544. +#endif
  545.          perror("socket");
  546.          exit(1);
  547.      }
  548.  
  549.      memset (&remote, 0, sizeof (remote));
  550. +#ifdef __MINGW32__
  551. +    remote.sin_family      = AF_INET;
  552. +    remote.sin_addr.s_addr = inet_addr("127.0.0.1");
  553. +    remote.sin_port        = htons(DEFAULT_LISTENING_PORT);
  554. +
  555. +    len = sizeof(remote);
  556. +#else
  557.      remote.sun_family = AF_UNIX;
  558. +
  559.  #if USE_ABSTRACT_SOCKET_NAME
  560.      memcpy (remote.sun_path, server_id, sizeof (server_id));
  561.      len = offsetof(struct sockaddr_un, sun_path) + sizeof (server_id)-1;
  562. @@ -1013,6 +1115,7 @@ main (int argc, char *argv[]) {
  563.      snprintf (remote.sun_path, sizeof (remote.sun_path), "%s/socket", socketdirenv ? socketdirenv : dbconfdir);
  564.      len = offsetof(struct sockaddr_un, sun_path) + strlen (remote.sun_path);
  565.  #endif
  566. +#endif /* __MINGW32__ */
  567.      if (connect(s, (struct sockaddr *)&remote, len) == 0) {
  568.          // pass args to remote and exit
  569.          if (send(s, cmdline, size, 0) == -1) {
  570. @@ -1047,14 +1150,21 @@ main (int argc, char *argv[]) {
  571.          if (out) {
  572.              free (out);
  573.          }
  574. +#ifdef __MINGW32__
  575. +        closesocket (s);
  576. +#else
  577.          close (s);
  578. +#endif
  579.          exit (0);
  580.      }
  581.  //    else {
  582.  //        perror ("INFO: failed to connect to existing session:");
  583.  //    }
  584. +#ifdef __MINGW32__
  585. +    closesocket (s);
  586. +#else
  587.      close(s);
  588. -
  589. +#endif
  590.      // become a server
  591.      if (server_start () < 0) {
  592.          exit (-1);
  593. diff --git a/messagepump.c b/messagepump.c
  594. index e3f422b8..2b0d12db 100644
  595. --- a/messagepump.c
  596. +++ b/messagepump.c
  597. @@ -45,8 +45,8 @@ static message_t pool[MAX_MESSAGES];
  598.  static message_t *mfree;
  599.  static message_t *mqueue;
  600.  static message_t *mqtail;
  601. -static uintptr_t mutex;
  602. -static uintptr_t cond;
  603. +static db_mutex_t mutex;
  604. +static db_cond_t cond;
  605.  
  606.  static void
  607.  messagepump_reset (void);
  608. diff --git a/mingw32_layer.h b/mingw32_layer.h
  609. new file mode 100644
  610. index 00000000..ab0ed438
  611. --- /dev/null
  612. +++ b/mingw32_layer.h
  613. @@ -0,0 +1,39 @@
  614. +
  615. +#ifndef _MINGW32_LAYER_H_
  616. +#define _MINGW32_LAYER_H_
  617. +
  618. +#include <errno.h>
  619. +#include <dirent.h>
  620. +#include <malloc.h>
  621. +
  622. +
  623. +#define mkdir(X,Y)    mkdir(X)
  624. +#define realpath(X,Y) _fullpath(Y,X,PATH_MAX)
  625. +#define EWOULDBLOCK   EAGAIN
  626. +#define SHUT_WR       1
  627. +#define lstat         stat
  628. +
  629. +#define PROT_READ     0x1
  630. +#define PROT_WRITE    0x2
  631. +/* This flag is only available in WinXP+ */
  632. +#ifdef FILE_MAP_EXECUTE
  633. +#define PROT_EXEC     0x4
  634. +#else
  635. +#define PROT_EXEC        0x0
  636. +#define FILE_MAP_EXECUTE 0
  637. +#endif
  638. +
  639. +#define MAP_SHARED    0x01
  640. +#define MAP_PRIVATE   0x02
  641. +#define MAP_ANONYMOUS 0x20
  642. +#define MAP_ANON      MAP_ANONYMOUS
  643. +#define MAP_FAILED    ((void *) -1)
  644. +
  645. +
  646. +int scandir (const char *__dir, struct dirent ***__namelist, int (*__selector) (const struct dirent *), int (*__cmp) (const struct dirent **, const struct dirent **));
  647. +void *mmap(void *, size_t, int, int, int, off_t);
  648. +int munmap(void *, size_t);
  649. +char *strndup(char *, size_t);
  650. +char *strcasestr(const char *, const char *);
  651. +
  652. +#endif
  653. diff --git a/mingw32_mmap.c b/mingw32_mmap.c
  654. new file mode 100644
  655. index 00000000..856e60b2
  656. --- /dev/null
  657. +++ b/mingw32_mmap.c
  658. @@ -0,0 +1,102 @@
  659. +/* mmap() replacement for Windows
  660. + *
  661. + * Author: Mike Frysinger <vapier@gentoo.org>
  662. + * Placed into the public domain
  663. + *
  664. + * File edited by JimF, for proper integration into JtR
  665. + * edits placed into public domain.
  666. + */
  667. +
  668. +/* References:
  669. + * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx
  670. + * CloseHandle:       http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx
  671. + * MapViewOfFile:     http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx
  672. + * UnmapViewOfFile:   http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx
  673. + */
  674. +
  675. +#include <io.h>
  676. +#include <windows.h>
  677. +#include <sys/types.h>
  678. +#include "memdbg.h"
  679. +#include "mingw32_layer.h"
  680. +
  681. +#ifdef __USE_FILE_OFFSET64
  682. +# define DWORD_HI(x) (x >> 32)
  683. +# define DWORD_LO(x) ((x) & 0xffffffff)
  684. +#else
  685. +# define DWORD_HI(x) (0)
  686. +# define DWORD_LO(x) (x)
  687. +#endif
  688. +
  689. +void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
  690. +{
  691. +   DWORD flProtect;
  692. +   off_t end;
  693. +   HANDLE mmap_fd, h;
  694. +   DWORD dwDesiredAccess;
  695. +   void *ret;
  696. +
  697. +   if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
  698. +       return 0;
  699. +   if (fd == -1) {
  700. +       if (!(flags & MAP_ANON) || offset)
  701. +           return 0;
  702. +   } else if (flags & MAP_ANON)
  703. +       return 0;
  704. +
  705. +   if (prot & PROT_WRITE) {
  706. +       if (prot & PROT_EXEC)
  707. +           flProtect = PAGE_EXECUTE_READWRITE;
  708. +       else
  709. +           flProtect = PAGE_READWRITE;
  710. +   } else if (prot & PROT_EXEC) {
  711. +       if (prot & PROT_READ)
  712. +           flProtect = PAGE_EXECUTE_READ;
  713. +       else if (prot & PROT_EXEC)
  714. +           flProtect = PAGE_EXECUTE;
  715. +   } else
  716. +       flProtect = PAGE_READONLY;
  717. +
  718. +   end = length + offset;
  719. +   if (fd == -1)
  720. +       mmap_fd = INVALID_HANDLE_VALUE;
  721. +   else
  722. +       mmap_fd = (HANDLE)_get_osfhandle(fd);
  723. +   h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL);
  724. +   //h = CreateFileMapping(mmap_fd, NULL, flProtect, 0, 0, NULL);
  725. +   if (h == NULL) {
  726. +        /* we will log this at some time, once I know PROPER fixes */
  727. +       DWORD x = GetLastError();
  728. +       fprintf(stderr, "Error, CreateFileMapping failed, Error code %x\n", x);
  729. +       return 0;
  730. +   }
  731. +
  732. +   if (prot & PROT_WRITE)
  733. +       dwDesiredAccess = FILE_MAP_WRITE;
  734. +   else
  735. +       dwDesiredAccess = FILE_MAP_READ;
  736. +   if (prot & PROT_EXEC)
  737. +       dwDesiredAccess |= FILE_MAP_EXECUTE;
  738. +   if (flags & MAP_PRIVATE)
  739. +       dwDesiredAccess |= FILE_MAP_COPY;
  740. +
  741. +   ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length);
  742. +   //ret = MapViewOfFile(h, dwDesiredAccess, 0, 0, length);
  743. +   if (ret == NULL)  {
  744. +       /* we will log this at some time, once I know PROPER fixes */
  745. +       DWORD x = GetLastError();
  746. +       fprintf(stderr, "Error, MapViewOfFile failed, Error code %x\n", x);
  747. +       CloseHandle(h);
  748. +       ret = 0;
  749. +   }
  750. +   return ret;
  751. +}
  752. +
  753. +int munmap(void *addr, size_t length)
  754. +{
  755. +   return !(UnmapViewOfFile(addr));
  756. +   /* ruh-ro, we leaked handle from CreateFileMapping() ... */
  757. +}
  758. +
  759. +#undef DWORD_HI
  760. +#undef DWORD_LO
  761. diff --git a/mingw32_scandir.c b/mingw32_scandir.c
  762. new file mode 100644
  763. index 00000000..52d2a03c
  764. --- /dev/null
  765. +++ b/mingw32_scandir.c
  766. @@ -0,0 +1,102 @@
  767. +
  768. +#include <dirent.h>
  769. +#include <stdlib.h>
  770. +#include <string.h>
  771. +
  772. +int scandir (const char      *__dir,
  773. +             struct dirent ***__namelist,
  774. +             int            (*__selector) (const struct dirent *),
  775. +             int            (*__cmp) (const struct dirent **, const struct dirent **))
  776. +{
  777. +    int count = -1; /* this will store the scandir result - will be -1 for errors */
  778. +    DIR *curr_dir;
  779. +    struct dirent **templist;
  780. +
  781. +    if (__dir != NULL && __namelist != NULL)
  782. +    {
  783. +        curr_dir = opendir(__dir);
  784. +        if (curr_dir != NULL)
  785. +        {
  786. +            int to_be_added;
  787. +            struct dirent *direntry;
  788. +            int idx, jdx;
  789. +            struct dirent *temp;
  790. +
  791. +            count = 0;
  792. +
  793. +            /* start! */
  794. +            direntry = readdir(curr_dir);
  795. +            while (direntry != NULL)
  796. +            {
  797. +                /* an entry was found! */
  798. +                if (__selector != NULL)
  799. +                {
  800. +                    /* '__selector' is a function which returns 1 or 0 */
  801. +                    to_be_added = __selector(direntry);
  802. +                }
  803. +                else
  804. +                {
  805. +                    to_be_added = 1;
  806. +                }
  807. +
  808. +                if (to_be_added)
  809. +                {
  810. +                    /* this entry has to be added */
  811. +
  812. +                    /* realloc the pointer array */
  813. +                    templist = realloc(*__namelist, sizeof(struct dirent *)*(count+1));
  814. +                    if (templist == NULL)
  815. +                    {
  816. +                        /* no room for a new pointer! */
  817. +                        /* in this case '__namelist' still holds the pointer to the old untouched array
  818. +                           so it is still a consistent result to give back */
  819. +                        break;
  820. +                    }
  821. +                    /* reallocation was succesfull but 'templist' may be different from '*__namelist'
  822. +                       in case a relocation (and a copy) was required */
  823. +                    *__namelist = templist;
  824. +
  825. +                    /* claim room for the new item */
  826. +                    (*__namelist)[count] = (struct dirent *)malloc(sizeof(struct dirent));
  827. +                    if ((*__namelist)[count] == NULL)
  828. +                    {
  829. +                        /* memory allocation failed! */
  830. +                        break;
  831. +                    }
  832. +                    memcpy((*__namelist)[count], direntry, sizeof(struct dirent));
  833. +                    /* the entry got added to the array - now let's concern about sorting */
  834. +                    if (__cmp != NULL)
  835. +                    {
  836. +                        /* a sorting routine is provided */
  837. +                        if (count != 0)
  838. +                        {
  839. +                            /* scan the array for the right position */
  840. +                            idx = 0;
  841. +                            while (__cmp((const struct dirent **)&(*__namelist)[count],
  842. +                                         (const struct dirent **)&(*__namelist)[idx]) > 0)
  843. +                                idx++;
  844. +
  845. +                            if (idx < count) /* idx == count when the entry is already in its own right position */
  846. +                            {
  847. +                                /* this happens when the entry is NOT in the right position */
  848. +                                /* save the pointer of the new entry structure */
  849. +                                temp = (*__namelist)[count];
  850. +                                /* shift the tail of the array */
  851. +                                for (jdx=count; jdx>idx; jdx--)
  852. +                                {
  853. +                                    (*__namelist)[jdx] = (*__namelist)[jdx-1];
  854. +                                }
  855. +                                /* put the new entry in the 'idx' position */
  856. +                                (*__namelist)[idx] = temp;
  857. +                            }
  858. +                        }
  859. +                    }
  860. +                    count++;
  861. +                }
  862. +                direntry = readdir(curr_dir);
  863. +            }
  864. +            closedir(curr_dir);
  865. +        }
  866. +    }
  867. +    return count;
  868. +}
  869. diff --git a/mingw32_strcasestr.c b/mingw32_strcasestr.c
  870. new file mode 100644
  871. index 00000000..f58822eb
  872. --- /dev/null
  873. +++ b/mingw32_strcasestr.c
  874. @@ -0,0 +1,52 @@
  875. +
  876. +#include <stdio.h>
  877. +#include <string.h>
  878. +#include <ctype.h>
  879. +
  880. +
  881. +
  882. +char *strcasestr(const char *haystack, const char *needle)
  883. +{
  884. +    char *result = NULL;
  885. +    int needle_len, length;
  886. +    int idx, jdx;
  887. +
  888. +    if (haystack != NULL && needle != NULL)
  889. +    {
  890. +        needle_len = (int)strlen(needle);
  891. +        length = strlen(haystack) - needle_len;
  892. +        idx = 0;
  893. +        while ((result=strchr(&haystack[idx],tolower(needle[0])))!=NULL
  894. +               ||
  895. +               (result=strchr(&haystack[idx],toupper(needle[0])))!=NULL)
  896. +        {
  897. +            idx = (int)(result - haystack);
  898. +            if (idx > length)
  899. +            {
  900. +                /* needle cannot fit into remaining characters */
  901. +                result = NULL;
  902. +                break;
  903. +            }
  904. +            for (jdx=0; jdx<needle_len; jdx++)
  905. +            {
  906. +                if (tolower(result[jdx]) != tolower(needle[jdx]))
  907. +                {
  908. +                    break;
  909. +                }
  910. +            }
  911. +            if (jdx == needle_len)
  912. +            {
  913. +                /* we found needle! */
  914. +                break;
  915. +            }
  916. +            else
  917. +            {
  918. +                idx++;
  919. +            }
  920. +        }
  921. +    }
  922. +
  923. +    return result;
  924. +}
  925. +
  926. +
  927. diff --git a/mingw32_strndup.c b/mingw32_strndup.c
  928. new file mode 100644
  929. index 00000000..1bed4265
  930. --- /dev/null
  931. +++ b/mingw32_strndup.c
  932. @@ -0,0 +1,23 @@
  933. +
  934. +#include <malloc.h>
  935. +#include <string.h>
  936. +
  937. +char *strndup(char *buff, size_t bufflen)
  938. +{
  939. +    char *result = NULL;
  940. +
  941. +    if (strlen(buff)>bufflen)
  942. +    {
  943. +        if ((result=malloc(1+bufflen)) != NULL)
  944. +        {
  945. +            memcpy(result, buff, bufflen);
  946. +            result[bufflen] = 0;
  947. +        }
  948. +    }
  949. +    else
  950. +    {
  951. +        result = strdup(buff);
  952. +    }
  953. +
  954. +    return result;
  955. +}
  956. diff --git a/playlist.c b/playlist.c
  957. index 1397a9b0..e8af112e 100644
  958. --- a/playlist.c
  959. +++ b/playlist.c
  960. @@ -31,9 +31,15 @@
  961.  #  include <alloca.h>
  962.  #endif
  963.  #include <stdlib.h>
  964. +#ifdef __MINGW32__
  965. +#undef __STRICT_ANSI__
  966. +#undef _NO_OLDNAMES
  967. +#endif
  968.  #include <string.h>
  969.  #include <dirent.h>
  970. +#ifndef __MINGW32__
  971.  #include <fnmatch.h>
  972. +#endif
  973.  #include <stdio.h>
  974.  #include <ctype.h>
  975.  #include <sys/types.h>
  976. @@ -42,7 +48,7 @@
  977.  #include <assert.h>
  978.  #include <time.h>
  979.  #include <sys/time.h>
  980. -#ifndef __linux__
  981. +#if !defined(__linux__) && !defined(_POSIX_C_SOURCE)
  982.  #define _POSIX_C_SOURCE 1
  983.  #endif
  984.  #include <limits.h>
  985. @@ -66,6 +72,9 @@
  986.  #include "strdupa.h"
  987.  #include "tf.h"
  988.  #include "playqueue.h"
  989. +#ifdef __MINGW32__
  990. +#include "mingw32_layer.h"
  991. +#endif
  992.  
  993.  // disable custom title function, until we have new title formatting (0.7)
  994.  #define DISABLE_CUSTOM_TITLE
  995. @@ -106,7 +115,7 @@ static playlist_t *playlist = NULL; // current playlist
  996.  static int plt_loading = 0; // disable sending event about playlist switch, config regen, etc
  997.  
  998.  #if !DISABLE_LOCKING
  999. -static uintptr_t mutex;
  1000. +static db_mutex_t mutex;
  1001.  #endif
  1002.  
  1003.  #define LOCK {pl_lock();}
  1004. @@ -415,6 +424,10 @@ plt_add (int before, const char *title) {
  1005.                      fprintf (stderr, "error: failed to make path string for playlist file\n");
  1006.                      continue;
  1007.                  }
  1008. +#ifdef __MINGW32__
  1009. +                if (unlink(path2)!=0)
  1010. +                    fprintf (stderr, "deleting %s failed: %s\n", path2, strerror (errno));
  1011. +#endif
  1012.                  int err = rename (path1, path2);
  1013.                  if (err != 0) {
  1014.                      fprintf (stderr, "playlist rename failed: %s\n", strerror (errno));
  1015. @@ -462,6 +475,10 @@ plt_remove (int plt) {
  1016.                  fprintf (stderr, "error: failed to make path string for playlist file\n");
  1017.                  continue;
  1018.              }
  1019. +#ifdef __MINGW32__
  1020. +            if (unlink(path1)!=0)
  1021. +                fprintf (stderr, "deleting %s failed: %s\n", path1, strerror (errno));
  1022. +#endif
  1023.              int err = rename (path2, path1);
  1024.              if (err != 0) {
  1025.                  fprintf (stderr, "playlist rename failed: %s\n", strerror (errno));
  1026. @@ -695,7 +712,10 @@ plt_move (int from, int to) {
  1027.      int err = stat (path1, &st);
  1028.      if (!err) {
  1029.          trace ("rename %s->%s\n", path1, temp);
  1030. -
  1031. +#ifdef __MINGW32__
  1032. +        if (unlink(temp)!=0)
  1033. +            fprintf (stderr, "deleting %s failed: %s\n", temp, strerror (errno));
  1034. +#endif
  1035.          int err = rename (path1, temp);
  1036.          if (err != 0) {
  1037.              fprintf (stderr, "playlist rename %s->%s failed: %s\n", path1, temp, strerror (errno));
  1038. @@ -735,6 +755,10 @@ plt_move (int from, int to) {
  1039.          int err = stat (path2, &st);
  1040.          if (!err) {
  1041.              trace ("rename %s->%s\n", path2, path1);
  1042. +#ifdef __MINGW32__
  1043. +            if (unlink(path1)!=0)
  1044. +                fprintf (stderr, "deleting %s failed: %s\n", path1, strerror (errno));
  1045. +#endif
  1046.              int err = rename (path2, path1);
  1047.              if (err != 0) {
  1048.                  fprintf (stderr, "playlist rename %s->%s failed: %s\n", path2, path1, strerror (errno));
  1049. @@ -756,6 +780,10 @@ plt_move (int from, int to) {
  1050.          int err = stat (path1, &st);
  1051.          if (!err) {
  1052.              trace ("rename %s->%s\n", path1, path2);
  1053. +#ifdef __MINGW32__
  1054. +            if (unlink(path2)!=0)
  1055. +                fprintf (stderr, "deleting %s failed: %s\n", path2, strerror (errno));
  1056. +#endif
  1057.              int err = rename (path1, path2);
  1058.              if (err != 0) {
  1059.                  fprintf (stderr, "playlist rename %s->%s failed: %s\n", path1, path2, strerror (errno));
  1060. @@ -770,6 +798,10 @@ plt_move (int from, int to) {
  1061.          int err = stat (temp, &st);
  1062.          if (!err) {
  1063.              trace ("move %s->%s\n", temp, path1);
  1064. +#ifdef __MINGW32__
  1065. +            if (unlink(path1)!=0)
  1066. +                fprintf (stderr, "deleting %s failed: %s\n", path1, strerror (errno));
  1067. +#endif
  1068.              int err = rename (temp, path1);
  1069.              if (err != 0) {
  1070.                  fprintf (stderr, "playlist rename %s->%s failed: %s\n", temp, path1, strerror (errno));
  1071. @@ -1490,9 +1522,11 @@ plt_insert_dir_int (int visibility, playlist_t *playlist, DB_vfs_t *vfs, playIte
  1072.      if (!follow_symlinks && !vfs) {
  1073.          struct stat buf;
  1074.          lstat (dirname, &buf);
  1075. +#ifndef __MINGW32__
  1076.          if (S_ISLNK(buf.st_mode)) {
  1077.              return NULL;
  1078.          }
  1079. +#endif
  1080.      }
  1081.      struct dirent **namelist = NULL;
  1082.      int n;
  1083. @@ -2167,6 +2201,10 @@ plt_save (playlist_t *plt, playItem_t *first, playItem_t *last, const char *fnam
  1084.  
  1085.      UNLOCK;
  1086.      fclose (fp);
  1087. +#ifdef __MINGW32__
  1088. +    if (unlink(fname)!=0)
  1089. +        fprintf (stderr, "deleting %s failed: %s\n", fname, strerror (errno));
  1090. +#endif
  1091.      if (rename (tempfile, fname) != 0) {
  1092.          fprintf (stderr, "playlist rename %s -> %s failed: %s\n", tempfile, fname, strerror (errno));
  1093.          return -1;
  1094. diff --git a/plmeta.c b/plmeta.c
  1095. index 98ce3b19..350ea7ae 100644
  1096. --- a/plmeta.c
  1097. +++ b/plmeta.c
  1098. @@ -25,6 +25,10 @@
  1099.    Alexey Yakovenko waker@users.sourceforge.net
  1100.  */
  1101.  
  1102. +#ifdef __MINGW32__
  1103. +#undef __STRICT_ANSI__
  1104. +#undef _NO_OLDNAMES
  1105. +#endif
  1106.  #include <string.h>
  1107.  #include <stdlib.h>
  1108.  #include "playlist.h"
  1109. diff --git a/pltmeta.c b/pltmeta.c
  1110. index f0a4438d..75558458 100644
  1111. --- a/pltmeta.c
  1112. +++ b/pltmeta.c
  1113. @@ -25,6 +25,10 @@
  1114.    Alexey Yakovenko waker@users.sourceforge.net
  1115.  */
  1116.  
  1117. +#ifdef __MINGW32__
  1118. +#undef __STRICT_ANSI__
  1119. +#undef _NO_OLDNAMES
  1120. +#endif
  1121.  #include <string.h>
  1122.  #include <stdlib.h>
  1123.  #include "playlist.h"
  1124. diff --git a/plugins.c b/plugins.c
  1125. index eb79e7ad..2ae4c89a 100644
  1126. --- a/plugins.c
  1127. +++ b/plugins.c
  1128. @@ -29,10 +29,14 @@
  1129.  #include <assert.h>
  1130.  #include <stdio.h>
  1131.  #include <stdlib.h>
  1132. +#ifdef __MINGW32__
  1133. +#undef __STRICT_ANSI__
  1134. +#undef _NO_OLDNAMES
  1135. +#endif
  1136.  #include <string.h>
  1137.  #include <sys/stat.h>
  1138.  #include <unistd.h>
  1139. -#ifndef __linux__
  1140. +#if !defined(__linux__) && !defined(_POSIX_C_SOURCE)
  1141.  #define _POSIX_C_SOURCE 1
  1142.  #endif
  1143.  #include <limits.h>
  1144. @@ -58,6 +62,9 @@
  1145.  #include "tf.h"
  1146.  #include "playqueue.h"
  1147.  #include "sort.h"
  1148. +#ifdef __MINGW32__
  1149. +#include "mingw32_layer.h"
  1150. +#endif
  1151.  
  1152.  #define trace(...) { fprintf(stderr, __VA_ARGS__); }
  1153.  //#define trace(fmt,...)
  1154. @@ -67,8 +74,12 @@
  1155.  #if defined(HAVE_COCOAUI) || defined(OSX_APPBUNDLE)
  1156.  #define PLUGINEXT ".dylib"
  1157.  #else
  1158. +#ifdef __MINGW32__
  1159. +#define PLUGINEXT ".dll"
  1160. +#else
  1161.  #define PLUGINEXT ".so"
  1162.  #endif
  1163. +#endif
  1164.  
  1165.  const char *lowprio_plugin_ids[] = {
  1166.      "ffmpeg",
  1167. @@ -114,7 +125,7 @@ static DB_output_t *output_plugin = NULL;
  1168.  #define MAX_PLAYLIST_PLUGINS 10
  1169.  static DB_playlist_t *g_playlist_plugins[MAX_PLAYLIST_PLUGINS+1];
  1170.  
  1171. -static uintptr_t background_jobs_mutex;
  1172. +static db_mutex_t background_jobs_mutex;
  1173.  static int num_background_jobs;
  1174.  
  1175.  // deadbeef api
  1176. @@ -154,6 +165,8 @@ static DB_functions_t deadbeef_api = {
  1177.      .thread_start_low_priority = thread_start_low_priority,
  1178.      .thread_join = thread_join,
  1179.      .thread_detach = thread_detach,
  1180. +    .thread_alive = thread_alive,
  1181. +    .thread_wipeid = thread_wipeid,
  1182.      .thread_exit = thread_exit,
  1183.      .mutex_create = mutex_create,
  1184.      .mutex_create_nonrecursive = mutex_create_nonrecursive,
  1185. @@ -711,7 +724,7 @@ load_plugin (const char *plugdir, char *d_name, int l) {
  1186.  #if defined(ANDROID) || defined(HAVE_COCOAUI)
  1187.          return -1;
  1188.  #else
  1189. -        strcpy (fullname + strlen(fullname) - sizeof (PLUGINEXT)+1, ".fallback.so");
  1190. +        strcpy (fullname + strlen(fullname) - sizeof (PLUGINEXT)+1, ".fallback" PLUGINEXT);
  1191.          trace ("trying %s...\n", fullname);
  1192.          handle = dlopen (fullname, RTLD_NOW);
  1193.          if (!handle) {
  1194. @@ -923,7 +936,11 @@ plug_load_all (void) {
  1195.          strncpy (xdg_plugin_dir, xdg_local_home, sizeof (xdg_plugin_dir));
  1196.          xdg_plugin_dir[sizeof(xdg_plugin_dir)-1] = 0;
  1197.      } else {
  1198. +#ifdef __MINGW32__
  1199. +        char *homedir = getenv ("USERPROFILE");
  1200. +#else
  1201.          char *homedir = getenv ("HOME");
  1202. +#endif
  1203.  
  1204.          if (!homedir) {
  1205.              trace ("plug_load_all: warning: unable to find home directory\n");
  1206. @@ -933,7 +950,11 @@ plug_load_all (void) {
  1207.              // multilib support:
  1208.              // 1. load from lib$ARCH if present
  1209.              // 2. load from lib if present
  1210. +#ifdef __MINGW32__
  1211. +            int written = snprintf (xdg_plugin_dir, sizeof (xdg_plugin_dir), "%s/.config/deadbeef/plugins", homedir);
  1212. +#else
  1213.              int written = snprintf (xdg_plugin_dir, sizeof (xdg_plugin_dir), "%s/.local/lib/deadbeef", homedir);
  1214. +#endif
  1215.              if (written > sizeof (xdg_plugin_dir)) {
  1216.                  trace ("warning: XDG_LOCAL_HOME value is too long: %s. Ignoring.", xdg_local_home);
  1217.                  xdg_plugin_dir[0] = 0;
  1218. @@ -947,7 +968,11 @@ plug_load_all (void) {
  1219.      }
  1220.  
  1221.      // load from HOME 1st, than replace from installdir if needed
  1222. +#ifdef __MINGW32__
  1223. +    const char *plugins_dirs[] = { xdg_plugin_dir, dirname, NULL };
  1224. +#else
  1225.      const char *plugins_dirs[] = { xdg_plugin_dir_explicit_arch, xdg_plugin_dir, dirname, NULL };
  1226. +#endif
  1227.  
  1228.      // If xdg_plugin_dir and dirname is the same, we should avoid each plugin
  1229.      // to be load twice.
  1230. diff --git a/plugins/aac/aac.c b/plugins/aac/aac.c
  1231. index 471d0b47..60b703c5 100644
  1232. --- a/plugins/aac/aac.c
  1233. +++ b/plugins/aac/aac.c
  1234. @@ -17,6 +17,10 @@
  1235.      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  1236.  */
  1237.  
  1238. +#ifdef __MINGW32__
  1239. +#undef __STRICT_ANSI__
  1240. +#undef _NO_OLDNAMES
  1241. +#endif
  1242.  #include <string.h>
  1243.  #include <stdio.h>
  1244.  #include <unistd.h>
  1245. @@ -28,6 +32,9 @@
  1246.  #include <math.h>
  1247.  #include "../../deadbeef.h"
  1248.  #include "aac_parser.h"
  1249. +#ifdef __MINGW32__
  1250. +#include "mingw32_layer.h"
  1251. +#endif
  1252.  
  1253.  #include "mp4ff.h"
  1254.  
  1255. diff --git a/plugins/adplug/adplug/a2m.h b/plugins/adplug/adplug/a2m.h
  1256. index e21d1dff..432f6935 100644
  1257. --- a/plugins/adplug/adplug/a2m.h
  1258. +++ b/plugins/adplug/adplug/a2m.h
  1259. @@ -55,7 +55,11 @@ private:
  1260.  #define ADPLUG_A2M_CODESPERRANGE   (ADPLUG_A2M_MAXCOPY - ADPLUG_A2M_MINCOPY + 1)
  1261.  #define ADPLUG_A2M_MAXCHAR     (ADPLUG_A2M_FIRSTCODE + ADPLUG_A2M_COPYRANGES * ADPLUG_A2M_CODESPERRANGE - 1)
  1262.  #define ADPLUG_A2M_TWICEMAX        (2 * ADPLUG_A2M_MAXCHAR + 1)
  1263. -
  1264. +#ifdef __MINGW32__
  1265. +#ifdef MAXCHAR
  1266. +#undef MAXCHAR
  1267. +#endif
  1268. +#endif
  1269.    static const unsigned int MAXFREQ, MINCOPY, MAXCOPY, COPYRANGES,
  1270.      CODESPERRANGE, TERMINATE, FIRSTCODE, MAXCHAR, SUCCMAX, TWICEMAX, ROOT,
  1271.      MAXBUF, MAXDISTANCE, MAXSIZE;
  1272. diff --git a/plugins/adplug/adplug/fmopl.c b/plugins/adplug/adplug/fmopl.c
  1273. index 04912bc0..730e855b 100644
  1274. --- a/plugins/adplug/adplug/fmopl.c
  1275. +++ b/plugins/adplug/adplug/fmopl.c
  1276. @@ -596,7 +596,7 @@ static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE )
  1277.         OPL->AR_TABLE[i] = rate / ARRATE;
  1278.         OPL->DR_TABLE[i] = rate / DRRATE;
  1279.     }
  1280. -   for (i = 60;i < 76;i++)
  1281. +   for (i = 61;i <=74;i++)
  1282.     {
  1283.         OPL->AR_TABLE[i] = EG_AED-1;
  1284.         OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
  1285. diff --git a/plugins/adplug/adplug/mid.cpp b/plugins/adplug/adplug/mid.cpp
  1286. index 5c13b144..090a3993 100644
  1287. --- a/plugins/adplug/adplug/mid.cpp
  1288. +++ b/plugins/adplug/adplug/mid.cpp
  1289. @@ -870,7 +870,7 @@ void CmidPlayer::rewind(int subsong)
  1290.      adlib_mode=ADLIB_MELODIC;
  1291.      for (i=0; i<128; i++)
  1292.          for (j=0; j<16; j++)
  1293. -            myinsbank[i][j]=midi_fm_instruments[i][j];
  1294. +            myinsbank[i][j]=midi_fm_instruments[i][j < 14 ? j : 0];
  1295.     for (i=0; i<16; i++)
  1296.          {
  1297.          ch[i].inum=0;
  1298. diff --git a/plugins/artwork/artwork.c b/plugins/artwork/artwork.c
  1299. index b1b3ded0..92361f38 100644
  1300. --- a/plugins/artwork/artwork.c
  1301. +++ b/plugins/artwork/artwork.c
  1302. @@ -27,12 +27,22 @@
  1303.  #endif
  1304.  #include <stdio.h>
  1305.  #include <stdlib.h>
  1306. +#ifdef __MINGW32__
  1307. +#undef __STRICT_ANSI__
  1308. +#undef _NO_OLDNAMES
  1309. +#endif
  1310.  #include <string.h>
  1311.  #include <ctype.h>
  1312.  #include <libgen.h>
  1313.  #include <dirent.h>
  1314.  #include <unistd.h>
  1315. +#ifndef __MINGW32__
  1316.  #include <fnmatch.h>
  1317. +#else
  1318. +#define NAME_MAX FILENAME_MAX
  1319. +#define WINSHLWAPI
  1320. +#include <shlwapi.h>
  1321. +#endif
  1322.  #include <pthread.h>
  1323.  #include <errno.h>
  1324.  #include <sys/stat.h>
  1325. @@ -60,6 +70,9 @@
  1326.  #include "wos.h"
  1327.  #include "cache.h"
  1328.  #include "artwork.h"
  1329. +#ifdef __MINGW32__
  1330. +#include "../../mingw32_layer.h"
  1331. +#endif
  1332.  
  1333.  //#define trace(...) { fprintf (stderr, __VA_ARGS__); }
  1334.  #define trace(...)
  1335. @@ -88,9 +101,9 @@ typedef struct cover_query_s {
  1336.  static cover_query_t *queue;
  1337.  static cover_query_t *queue_tail;
  1338.  static int terminate;
  1339. -static intptr_t tid;
  1340. -static uintptr_t queue_mutex;
  1341. -static uintptr_t queue_cond;
  1342. +static db_thread_t tid;
  1343. +static db_mutex_t queue_mutex;
  1344. +static db_cond_t queue_cond;
  1345.  
  1346.  static int artwork_enable_embedded;
  1347.  static int artwork_enable_local;
  1348. @@ -1124,12 +1137,16 @@ static char *filter_custom_mask = NULL;
  1349.  static int
  1350.  filter_custom (const struct dirent *f)
  1351.  {
  1352. +#ifdef __MINGW32__
  1353. +    return ((PathMatchSpec(f->d_name, filter_custom_mask)==TRUE)? 0 : 1);
  1354. +#else
  1355.  // FNM_CASEFOLD is not defined on solaris. On other platforms it is.
  1356.  // It should be safe to define it as FNM_INGORECASE if it isn't defined.
  1357.  #ifndef FNM_CASEFOLD
  1358.  #define FNM_CASEFOLD FNM_IGNORECASE
  1359.  #endif
  1360.      return !fnmatch (filter_custom_mask, f->d_name, FNM_CASEFOLD);
  1361. +#endif
  1362.  }
  1363.  
  1364.  static char *
  1365. @@ -2075,7 +2092,7 @@ artwork_get_actions (DB_playItem_t *it)
  1366.  static int
  1367.  artwork_plugin_stop (void)
  1368.  {
  1369. -    if (tid) {
  1370. +    if (deadbeef->thread_alive (tid)) {
  1371.          trace ("Stopping fetcher thread ... \n");
  1372.          deadbeef->mutex_lock (queue_mutex);
  1373.          queue_clear ();
  1374. @@ -2089,7 +2106,7 @@ artwork_plugin_stop (void)
  1375.          }
  1376.          deadbeef->mutex_unlock (queue_mutex);
  1377.          deadbeef->thread_join (tid);
  1378. -        tid = 0;
  1379. +        deadbeef->thread_wipeid (&tid);
  1380.          trace ("Fetcher thread stopped\n");
  1381.      }
  1382.      if (queue_mutex) {
  1383. @@ -2131,7 +2148,7 @@ artwork_plugin_start (void)
  1384.      if (queue_mutex && queue_cond) {
  1385.          tid = deadbeef->thread_start_low_priority (fetcher_thread, NULL);
  1386.      }
  1387. -    if (!tid) {
  1388. +    if (deadbeef->thread_alive (tid)) {
  1389.          artwork_plugin_stop ();
  1390.          return -1;
  1391.      }
  1392. diff --git a/plugins/artwork/artwork_internal.c b/plugins/artwork/artwork_internal.c
  1393. index f035d3dd..d091ff38 100644
  1394. --- a/plugins/artwork/artwork_internal.c
  1395. +++ b/plugins/artwork/artwork_internal.c
  1396. @@ -26,6 +26,10 @@
  1397.      #include "../../config.h"
  1398.  #endif
  1399.  #include <stdlib.h>
  1400. +#ifdef __MINGW32__
  1401. +#undef __STRICT_ANSI__
  1402. +#undef _NO_OLDNAMES
  1403. +#endif
  1404.  #include <string.h>
  1405.  #include <libgen.h>
  1406.  #include <errno.h>
  1407. @@ -35,6 +39,9 @@
  1408.  #include <limits.h>
  1409.  #include "../../deadbeef.h"
  1410.  #include "artwork_internal.h"
  1411. +#ifdef __MINGW32__
  1412. +#include "../../mingw32_layer.h"
  1413. +#endif
  1414.  
  1415.  //#define trace(...) { fprintf(stderr, __VA_ARGS__); }
  1416.  #define trace(...)
  1417. @@ -42,7 +49,7 @@
  1418.  extern DB_functions_t *deadbeef;
  1419.  
  1420.  static DB_FILE *http_request;
  1421. -static uintptr_t http_mutex;
  1422. +static db_mutex_t http_mutex;
  1423.  
  1424.  static DB_FILE *
  1425.  new_http_request (const char *url)
  1426. diff --git a/plugins/artwork/cache.c b/plugins/artwork/cache.c
  1427. index e178d81f..fe3e70f5 100644
  1428. --- a/plugins/artwork/cache.c
  1429. +++ b/plugins/artwork/cache.c
  1430. @@ -32,19 +32,25 @@
  1431.  #include <unistd.h>
  1432.  #include <pthread.h>
  1433.  #include <sys/stat.h>
  1434. +#ifdef __MINGW32__
  1435. +#undef __STRICT_ANSI__
  1436. +#endif
  1437.  #include <limits.h>
  1438.  #include "artwork_internal.h"
  1439.  #include "../../deadbeef.h"
  1440. +#ifdef __MINGW32__
  1441. +#include "../../mingw32_layer.h"
  1442. +#endif
  1443.  
  1444.  //#define trace(...) { fprintf(stderr, __VA_ARGS__); }
  1445.  #define trace(...)
  1446.  
  1447.  extern DB_functions_t *deadbeef;
  1448.  
  1449. -static uintptr_t files_mutex;
  1450. -static intptr_t tid;
  1451. -static uintptr_t thread_mutex;
  1452. -static uintptr_t thread_cond;
  1453. +static db_mutex_t files_mutex;
  1454. +static db_thread_t tid;
  1455. +static db_mutex_t thread_mutex;
  1456. +static db_cond_t thread_cond;
  1457.  static int terminate;
  1458.  static int32_t cache_expiry_seconds;
  1459.  
  1460. @@ -204,13 +210,13 @@ void cache_configchanged (void)
  1461.  
  1462.  void stop_cache_cleaner (void)
  1463.  {
  1464. -    if (tid) {
  1465. +    if (deadbeef->thread_alive (tid)) {
  1466.          deadbeef->mutex_lock (thread_mutex);
  1467.          terminate = 1;
  1468.          deadbeef->cond_signal (thread_cond);
  1469.          deadbeef->mutex_unlock (thread_mutex);
  1470.          deadbeef->thread_join (tid);
  1471. -        tid = 0;
  1472. +        deadbeef->thread_wipeid (&tid);
  1473.          trace ("Cache cleaner thread stopped\n");
  1474.      }
  1475.  
  1476. @@ -242,7 +248,7 @@ int start_cache_cleaner (void)
  1477.          trace ("Cache cleaner thread started\n");
  1478.      }
  1479.  
  1480. -    if (!tid) {
  1481. +    if (deadbeef->thread_alive (tid)) {
  1482.          stop_cache_cleaner ();
  1483.          return -1;
  1484.      }
  1485. diff --git a/plugins/cdda/cdda.c b/plugins/cdda/cdda.c
  1486. index 9ef085d2..79891de3 100644
  1487. --- a/plugins/cdda/cdda.c
  1488. +++ b/plugins/cdda/cdda.c
  1489. @@ -658,13 +658,13 @@ insert_disc (ddb_playlist_t *plt, DB_playItem_t *after, const char *path, const
  1490.          if (!(got_cdtext && prefer_cdtext) && enable_cddb) {
  1491.              trace("cdda: querying freedb...\n");
  1492.              tid = deadbeef->thread_start(cddb_thread, p);
  1493. -            if (tid) {
  1494. +            if (deadbeef->thread_alive (tid)) {
  1495.                  deadbeef->thread_detach(tid);
  1496.              }
  1497.          }
  1498.      }
  1499.  
  1500. -    if (!tid) {
  1501. +    if (!deadbeef->thread_alive (tid)) {
  1502.          cleanup_thread_params(p);
  1503.      }
  1504.  
  1505. diff --git a/plugins/converter/converter.c b/plugins/converter/converter.c
  1506. index 71b86a94..8c796aad 100644
  1507. --- a/plugins/converter/converter.c
  1508. +++ b/plugins/converter/converter.c
  1509. @@ -29,6 +29,10 @@
  1510.  #endif
  1511.  #include <stdlib.h>
  1512.  #include <limits.h>
  1513. +#ifdef __MINGW32__
  1514. +#undef __STRICT_ANSI__
  1515. +#undef _NO_OLDNAMES
  1516. +#endif
  1517.  #include <string.h>
  1518.  #include <sys/types.h>
  1519.  #include <sys/stat.h>
  1520. @@ -39,6 +43,9 @@
  1521.  #include "converter.h"
  1522.  #include "../../deadbeef.h"
  1523.  #include "../../strdupa.h"
  1524. +#ifdef __MINGW32__
  1525. +#include "../../mingw32_layer.h"
  1526. +#endif
  1527.  
  1528.  #ifndef __linux__
  1529.  #define O_LARGEFILE 0
  1530. diff --git a/plugins/dca/bitstream.c b/plugins/dca/bitstream.c
  1531. index f77cbc70..baef9874 100644
  1532. --- a/plugins/dca/bitstream.c
  1533. +++ b/plugins/dca/bitstream.c
  1534. @@ -27,6 +27,9 @@
  1535.  
  1536.  #include <stdio.h>
  1537.  #include <inttypes.h>
  1538. +#ifdef __MINGW32__
  1539. +#include <stdlib.h>  /* for the needed 'llabs' */
  1540. +#endif
  1541.  
  1542.  #include "dca.h"
  1543.  #include "dca_internal.h"
  1544. diff --git a/plugins/dca/downmix.c b/plugins/dca/downmix.c
  1545. index ff02127f..33b488d8 100644
  1546. --- a/plugins/dca/downmix.c
  1547. +++ b/plugins/dca/downmix.c
  1548. @@ -27,6 +27,9 @@
  1549.  
  1550.  #include <string.h>
  1551.  #include <inttypes.h>
  1552. +#ifdef __MINGW32__
  1553. +#include <stdlib.h>  /* for the needed 'llabs' */
  1554. +#endif
  1555.  
  1556.  #include "dca.h"
  1557.  #include "dca_internal.h"
  1558. diff --git a/plugins/dsp_libsrc/src.c b/plugins/dsp_libsrc/src.c
  1559. index f3103d11..c1a80de4 100644
  1560. --- a/plugins/dsp_libsrc/src.c
  1561. +++ b/plugins/dsp_libsrc/src.c
  1562. @@ -20,6 +20,9 @@
  1563.  #include <stdlib.h>
  1564.  #include <string.h>
  1565.  #include <assert.h>
  1566. +#ifdef __MINGW32__
  1567. +#undef __STRICT_ANSI__
  1568. +#endif
  1569.  #include "../../deadbeef.h"
  1570.  #include "src.h"
  1571.  
  1572. diff --git a/plugins/ffap/ffap.c b/plugins/ffap/ffap.c
  1573. index 5102c8c4..8c698131 100644
  1574. --- a/plugins/ffap/ffap.c
  1575. +++ b/plugins/ffap/ffap.c
  1576. @@ -38,6 +38,9 @@
  1577.  #include <assert.h>
  1578.  #include <math.h>
  1579.  #include "../../deadbeef.h"
  1580. +#ifdef __MINGW32__
  1581. +#include <malloc.h>
  1582. +#endif
  1583.  
  1584.  #ifdef TARGET_ANDROID
  1585.  int posix_memalign (void **memptr, size_t alignment, size_t size) {
  1586. @@ -734,8 +737,13 @@ ffap_init (DB_fileinfo_t *_info, DB_playItem_t *it)
  1587.          if (!ape_filter_orders[info->ape_ctx.fset][i])
  1588.              break;
  1589.          info->ape_ctx.filterbuf_size[i] = (ape_filter_orders[info->ape_ctx.fset][i] * 3 + HISTORY_SIZE) * 4;
  1590. +#ifdef __MINGW32__
  1591. +        info->ape_ctx.filterbuf[i] = __mingw_aligned_malloc(16, info->ape_ctx.filterbuf_size[i]);
  1592. +        if (info->ape_ctx.filterbuf[i] == NULL ) {
  1593. +#else
  1594.          int err = posix_memalign ((void **)&info->ape_ctx.filterbuf[i], 16, info->ape_ctx.filterbuf_size[i]);
  1595.          if (err) {
  1596. +#endif
  1597.              trace ("ffap: out of memory (posix_memalign)\n");
  1598.              return -1;
  1599.          }
  1600. diff --git a/plugins/flac/flac.c b/plugins/flac/flac.c
  1601. index 9399970b..ff4b8e36 100644
  1602. --- a/plugins/flac/flac.c
  1603. +++ b/plugins/flac/flac.c
  1604. @@ -33,6 +33,11 @@
  1605.  #ifdef HAVE_CONFIG_H
  1606.  #include <config.h>
  1607.  #endif
  1608. +#ifdef __MINGW32__
  1609. +#undef __STRICT_ANSI__
  1610. +#undef _NO_OLDNAMES
  1611. +#include <malloc.h>
  1612. +#endif
  1613.  #include <string.h>
  1614.  #include <stdio.h>
  1615.  #include <stdlib.h>
  1616. diff --git a/plugins/gme/cgme.c b/plugins/gme/cgme.c
  1617. index dff30c5b..655d5452 100644
  1618. --- a/plugins/gme/cgme.c
  1619. +++ b/plugins/gme/cgme.c
  1620. @@ -27,6 +27,10 @@
  1621.  #include <stdio.h>
  1622.  #include <fcntl.h>
  1623.  #include <stdlib.h>
  1624. +#ifdef __MINGW32__
  1625. +#undef __STRICT_ANSI__
  1626. +#undef _NO_OLDNAMES
  1627. +#endif
  1628.  #include <string.h>
  1629.  #include <math.h>
  1630.  #include "gme/gme.h"
  1631. @@ -89,7 +93,7 @@ read_gzfile (const char *fname, char **buffer, int *size) {
  1632.                  tmp = "/tmp";
  1633.              }
  1634.              char nm[PATH_MAX];
  1635. -#if defined(ANDROID) || defined(STATICLINK)
  1636. +#if defined(ANDROID) || defined(STATICLINK) || defined(__MINGW32__)
  1637.              snprintf (nm, sizeof (nm), "%s/ddbgmeXXXXXX", tmp);
  1638.              fd = mkstemp (nm);
  1639.  #else
  1640. diff --git a/plugins/gme/game-music-emu-0.6pre/gme/Data_Reader.cpp b/plugins/gme/game-music-emu-0.6pre/gme/Data_Reader.cpp
  1641. index bb5cd52d..ce6c0e0c 100644
  1642. --- a/plugins/gme/game-music-emu-0.6pre/gme/Data_Reader.cpp
  1643. +++ b/plugins/gme/game-music-emu-0.6pre/gme/Data_Reader.cpp
  1644. @@ -4,7 +4,15 @@
  1645.  
  1646.  #include "blargg_endian.h"
  1647.  #include "blargg_common.h"
  1648. +#ifdef __MINGW32__
  1649. +#define __USE_MINGW_FSEEK         /* request mingw internal implementation of fseeko64 */
  1650. +#endif
  1651.  #include <stdio.h>
  1652. +#ifdef __MINGW32__
  1653. +#define off_t   off64_t
  1654. +#define fseeko  fseeko64
  1655. +#define ftello  ftello64
  1656. +#endif
  1657.  #include <errno.h>
  1658.  
  1659.  #if BLARGG_UTF8_PATHS
  1660. diff --git a/plugins/gme/game-music-emu-0.6pre/gme/blargg_source.h b/plugins/gme/game-music-emu-0.6pre/gme/blargg_source.h
  1661. index d7145097..180cba8d 100644
  1662. --- a/plugins/gme/game-music-emu-0.6pre/gme/blargg_source.h
  1663. +++ b/plugins/gme/game-music-emu-0.6pre/gme/blargg_source.h
  1664. @@ -65,7 +65,7 @@ static inline void blargg_dprintf_( const char [], ... ) { }
  1665.  #include <stdio.h>
  1666.  #undef  dprintf
  1667.  #define dprintf (1) ? (void) 0 : blargg_dprintf_
  1668. -#ifndef _WIN32
  1669. +#if !defined(_WIN32) || defined(__MINGW32__)
  1670.  #include <stdio.h>
  1671.  static inline void blargg_dprintf_( const char * fmt, ... )
  1672.  {
  1673. diff --git a/plugins/gtkui/actionhandlers.c b/plugins/gtkui/actionhandlers.c
  1674. index 9680f54a..a02e4603 100644
  1675. --- a/plugins/gtkui/actionhandlers.c
  1676. +++ b/plugins/gtkui/actionhandlers.c
  1677. @@ -25,6 +25,10 @@
  1678.  #endif
  1679.  
  1680.  #include <stdlib.h>
  1681. +#ifdef __MINGW32__
  1682. +#undef __STRICT_ANSI__
  1683. +#undef _NO_OLDNAMES
  1684. +#endif
  1685.  #include <string.h>
  1686.  #include <gtk/gtk.h>
  1687.  #include <unistd.h>
  1688. @@ -772,7 +776,7 @@ action_load_playlist_handler_cb (void *data) {
  1689.          gchar *fname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dlg));
  1690.          gtk_widget_destroy (dlg);
  1691.          if (fname) {
  1692. -            uintptr_t tid = deadbeef->thread_start (load_playlist_thread, fname);
  1693. +            db_thread_t tid = deadbeef->thread_start (load_playlist_thread, fname);
  1694.              deadbeef->thread_detach (tid);
  1695.          }
  1696.      }
  1697. diff --git a/plugins/gtkui/actions.c b/plugins/gtkui/actions.c
  1698. index c8e4edd8..9eb2ce9e 100644
  1699. --- a/plugins/gtkui/actions.c
  1700. +++ b/plugins/gtkui/actions.c
  1701. @@ -22,6 +22,10 @@
  1702.  */
  1703.  
  1704.  #include <stdio.h>
  1705. +#ifdef __MINGW32__
  1706. +#undef __STRICT_ANSI__
  1707. +#undef _NO_OLDNAMES
  1708. +#endif
  1709.  #include <string.h>
  1710.  #include <stdlib.h>
  1711.  
  1712. diff --git a/plugins/gtkui/callbacks.c b/plugins/gtkui/callbacks.c
  1713. index 25d2f07f..c21c8e6a 100644
  1714. --- a/plugins/gtkui/callbacks.c
  1715. +++ b/plugins/gtkui/callbacks.c
  1716. @@ -25,6 +25,9 @@
  1717.  #  include <config.h>
  1718.  #endif
  1719.  
  1720. +#ifdef __MINGW32__
  1721. +#undef __STRICT_ANSI__
  1722. +#endif
  1723.  #include <gtk/gtk.h>
  1724.  #include <math.h>
  1725.  #include <stdlib.h>
  1726. @@ -33,7 +36,7 @@
  1727.  #include <assert.h>
  1728.  #include <ctype.h>
  1729.  #include <gdk/gdkkeysyms.h>
  1730. -#ifndef __APPLE__
  1731. +#if !defined(__APPLE__) && !defined(__MINGW32__)
  1732.  #include <X11/Xlib.h>
  1733.  #endif
  1734.  #include "../../gettext.h"
  1735. diff --git a/plugins/gtkui/coverart.c b/plugins/gtkui/coverart.c
  1736. index 590dfc71..35b57db6 100644
  1737. --- a/plugins/gtkui/coverart.c
  1738. +++ b/plugins/gtkui/coverart.c
  1739. @@ -22,6 +22,10 @@
  1740.  */
  1741.  
  1742.  #include <sys/time.h>
  1743. +#ifdef __MINGW32__
  1744. +#undef __STRICT_ANSI__
  1745. +#undef _NO_OLDNAMES
  1746. +#endif
  1747.  #include <string.h>
  1748.  #include <stdlib.h>
  1749.  #include <pthread.h>
  1750. @@ -76,9 +80,9 @@ typedef struct load_query_s {
  1751.  } load_query_t;
  1752.  
  1753.  static int terminate;
  1754. -static uintptr_t mutex;
  1755. -static uintptr_t cond;
  1756. -static uintptr_t tid;
  1757. +static db_mutex_t mutex;
  1758. +static db_cond_t cond;
  1759. +static db_thread_t tid;
  1760.  static load_query_t *queue;
  1761.  static load_query_t *tail;
  1762.  
  1763. @@ -664,14 +668,14 @@ void
  1764.  cover_art_free (void) {
  1765.      trace ("coverart: terminating cover art loader...\n");
  1766.  
  1767. -    if (tid) {
  1768. +    if (deadbeef->thread_alive (tid)) {
  1769.          deadbeef->mutex_lock(mutex);
  1770.          terminate = 1;
  1771.          trace("coverart: sending terminate signal to art loader thread...\n");
  1772.          deadbeef->cond_signal(cond);
  1773.          deadbeef->mutex_unlock(mutex);
  1774.          deadbeef->thread_join(tid);
  1775. -        tid = 0;
  1776. +        deadbeef->thread_wipeid (&tid);
  1777.      }
  1778.  
  1779.      while (queue) {
  1780. diff --git a/plugins/gtkui/ddblistview.c b/plugins/gtkui/ddblistview.c
  1781. index 64e530e9..20f86519 100644
  1782. --- a/plugins/gtkui/ddblistview.c
  1783. +++ b/plugins/gtkui/ddblistview.c
  1784. @@ -29,6 +29,10 @@
  1785.  #include <math.h>
  1786.  #include <stdlib.h>
  1787.  #include <time.h>
  1788. +#ifdef __MINGW32__
  1789. +#undef __STRICT_ANSI__
  1790. +#undef _NO_OLDNAMES
  1791. +#endif
  1792.  #include <string.h>
  1793.  #include <unistd.h>
  1794.  #include <ctype.h>
  1795. diff --git a/plugins/gtkui/dspconfig.c b/plugins/gtkui/dspconfig.c
  1796. index 60fd7127..b315dc64 100644
  1797. --- a/plugins/gtkui/dspconfig.c
  1798. +++ b/plugins/gtkui/dspconfig.c
  1799. @@ -25,9 +25,15 @@
  1800.  #  include <config.h>
  1801.  #endif
  1802.  
  1803. +#ifdef __MINGW32__
  1804. +#undef __STRICT_ANSI__
  1805. +#endif
  1806.  #include <gtk/gtk.h>
  1807.  #include <math.h>
  1808.  #include <stdlib.h>
  1809. +#ifdef __MINGW32__
  1810. +#undef _NO_OLDNAMES
  1811. +#endif
  1812.  #include <string.h>
  1813.  #include <unistd.h>
  1814.  #include <assert.h>
  1815. @@ -39,6 +45,9 @@
  1816.  #include "../../deadbeef.h"
  1817.  #include "gtkui.h"
  1818.  #include "pluginconf.h"
  1819. +#ifdef __MINGW32__
  1820. +#include "mingw32_layer.h"
  1821. +#endif
  1822.  
  1823.  static ddb_dsp_context_t *chain;
  1824.  static GtkWidget *prefwin;
  1825. diff --git a/plugins/gtkui/fileman.c b/plugins/gtkui/fileman.c
  1826. index 0a074185..5b8e2f64 100644
  1827. --- a/plugins/gtkui/fileman.c
  1828. +++ b/plugins/gtkui/fileman.c
  1829. @@ -112,7 +112,7 @@ add_dirs_worker (void *data) {
  1830.  
  1831.  void
  1832.  gtkui_add_dirs (GSList *lst) {
  1833. -    intptr_t tid = deadbeef->thread_start (add_dirs_worker, lst);
  1834. +    db_thread_t tid = deadbeef->thread_start (add_dirs_worker, lst);
  1835.      deadbeef->thread_detach (tid);
  1836.  }
  1837.  
  1838. @@ -124,7 +124,7 @@ add_files_worker (void *data) {
  1839.  
  1840.  void
  1841.  gtkui_add_files (struct _GSList *lst) {
  1842. -    intptr_t tid = deadbeef->thread_start (add_files_worker, lst);
  1843. +    db_thread_t tid = deadbeef->thread_start (add_files_worker, lst);
  1844.      deadbeef->thread_detach (tid);
  1845.  }
  1846.  
  1847. @@ -144,7 +144,7 @@ gtkui_open_files (struct _GSList *lst) {
  1848.      deadbeef->pl_clear ();
  1849.      deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
  1850.  
  1851. -    intptr_t tid = deadbeef->thread_start (open_files_worker, lst);
  1852. +    db_thread_t tid = deadbeef->thread_start (open_files_worker, lst);
  1853.      deadbeef->thread_detach (tid);
  1854.  }
  1855.  
  1856. @@ -297,6 +297,6 @@ gtkui_receive_fm_drop (DB_playItem_t *before, char *mem, int length) {
  1857.      }
  1858.      data->drop_before = before;
  1859.      // since it happens in separate thread, we need to addref
  1860. -    intptr_t tid = deadbeef->thread_start (fmdrop_worker, data);
  1861. +    db_thread_t tid = deadbeef->thread_start (fmdrop_worker, data);
  1862.      deadbeef->thread_detach (tid);
  1863.  }
  1864. diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c
  1865. index 8a3dd6b0..83e8a0c0 100644
  1866. --- a/plugins/gtkui/gtkui.c
  1867. +++ b/plugins/gtkui/gtkui.c
  1868. @@ -27,6 +27,10 @@
  1869.  #ifdef HAVE_CONFIG_H
  1870.  #include "../../config.h"
  1871.  #endif
  1872. +#ifdef __MINGW32__
  1873. +#undef __STRICT_ANSI__
  1874. +#undef _NO_OLDNAMES
  1875. +#endif
  1876.  #include <string.h>
  1877.  #include <stdlib.h>
  1878.  #include <math.h>
  1879. @@ -57,11 +61,13 @@
  1880.  #include "gtkui_api.h"
  1881.  #include "wingeom.h"
  1882.  #include "widgets.h"
  1883. +#ifndef __MINGW32__
  1884.  #ifndef __APPLE__
  1885.  #include "X11/Xlib.h"
  1886.  #else
  1887.  #include "retina.h"
  1888.  #endif
  1889. +#endif
  1890.  #include "actionhandlers.h"
  1891.  #include "hotkeys.h"
  1892.  #include "../hotkeys/hotkeys.h"
  1893. @@ -547,7 +553,11 @@ gtkui_update_status_icon (gpointer unused) {
  1894.  
  1895.      if (!gtk_icon_theme_has_icon(theme, icon_name)) {
  1896.          char iconpath[1024];
  1897. +#ifdef __MINGW32__
  1898. +        snprintf (iconpath, sizeof (iconpath), "%s/deadbeef.png", deadbeef->get_pixmap_dir ());
  1899. +#else
  1900.          snprintf (iconpath, sizeof (iconpath), "%s/deadbeef.png", deadbeef->get_prefix ());
  1901. +#endif
  1902.          trayicon = gtk_status_icon_new_from_file(iconpath);
  1903.      }
  1904.      else {
  1905. @@ -1054,7 +1064,11 @@ gtkui_thread (void *ctx) {
  1906.      else {
  1907.          // try loading icon from $prefix/deadbeef.png (for static build)
  1908.          char iconpath[1024];
  1909. +#ifdef __MINGW32__
  1910. +        snprintf (iconpath, sizeof (iconpath), "%s/deadbeef.png", deadbeef->get_pixmap_dir ());
  1911. +#else
  1912.          snprintf (iconpath, sizeof (iconpath), "%s/deadbeef.png", deadbeef->get_prefix ());
  1913. +#endif
  1914.          gtk_window_set_icon_from_file (GTK_WINDOW (mainwin), iconpath, NULL);
  1915.      }
  1916.  
  1917. diff --git a/plugins/gtkui/hotkeys.c b/plugins/gtkui/hotkeys.c
  1918. index e9ef508d..a0fbc2aa 100644
  1919. --- a/plugins/gtkui/hotkeys.c
  1920. +++ b/plugins/gtkui/hotkeys.c
  1921. @@ -49,6 +49,10 @@ typedef struct
  1922.  #  include <config.h>
  1923.  #endif
  1924.  #include <gtk/gtk.h>
  1925. +#ifdef __MINGW32__
  1926. +#undef __STRICT_ANSI__
  1927. +#undef _NO_OLDNAMES
  1928. +#endif
  1929.  #include <string.h>
  1930.  #include <stdlib.h>
  1931.  #include "../../gettext.h"
  1932. @@ -57,7 +61,7 @@ typedef struct
  1933.  #include "interface.h"
  1934.  #include "../libparser/parser.h"
  1935.  #include "../hotkeys/hotkeys.h"
  1936. -#ifndef __APPLE__
  1937. +#if !defined(__APPLE__) && !defined(__MINGW32__)
  1938.  #include <X11/Xlib.h> // only for the KeySym type
  1939.  #endif
  1940.  #include "hotkeys.h"
  1941. diff --git a/plugins/gtkui/mainplaylist.c b/plugins/gtkui/mainplaylist.c
  1942. index a02a55ee..53616ff7 100644
  1943. --- a/plugins/gtkui/mainplaylist.c
  1944. +++ b/plugins/gtkui/mainplaylist.c
  1945. @@ -25,6 +25,10 @@
  1946.  #  include <config.h>
  1947.  #endif
  1948.  #include <stdlib.h>
  1949. +#ifdef __MINGW32__
  1950. +#undef __STRICT_ANSI__
  1951. +#undef _NO_OLDNAMES
  1952. +#endif
  1953.  #include <string.h>
  1954.  #include "../../gettext.h"
  1955.  #include "../libparser/parser.h"
  1956. diff --git a/plugins/gtkui/plcommon.c b/plugins/gtkui/plcommon.c
  1957. index 27b3faff..86c62445 100644
  1958. --- a/plugins/gtkui/plcommon.c
  1959. +++ b/plugins/gtkui/plcommon.c
  1960. @@ -22,6 +22,10 @@
  1961.  */
  1962.  
  1963.  #include <stdlib.h>
  1964. +#ifdef __MINGW32__
  1965. +#undef __STRICT_ANSI__
  1966. +#undef _NO_OLDNAMES
  1967. +#endif
  1968.  #include <string.h>
  1969.  #include <unistd.h>
  1970.  #include <gdk/gdkkeysyms.h>
  1971. diff --git a/plugins/gtkui/prefwin.c b/plugins/gtkui/prefwin.c
  1972. index 2d753040..855f3b73 100644
  1973. --- a/plugins/gtkui/prefwin.c
  1974. +++ b/plugins/gtkui/prefwin.c
  1975. @@ -25,6 +25,10 @@
  1976.  #  include <config.h>
  1977.  #endif
  1978.  #include <gtk/gtk.h>
  1979. +#ifdef __MINGW32__
  1980. +#undef __STRICT_ANSI__
  1981. +#undef _NO_OLDNAMES
  1982. +#endif
  1983.  #include <string.h>
  1984.  #include <assert.h>
  1985.  #include <stdlib.h>
  1986. diff --git a/plugins/gtkui/search.c b/plugins/gtkui/search.c
  1987. index ab570f36..3ea0fba5 100644
  1988. --- a/plugins/gtkui/search.c
  1989. +++ b/plugins/gtkui/search.c
  1990. @@ -29,6 +29,10 @@
  1991.  #include <gdk/gdkkeysyms.h>
  1992.  #include <math.h>
  1993.  #include <stdlib.h>
  1994. +#ifdef __MINGW32__
  1995. +#undef __STRICT_ANSI__
  1996. +#undef _NO_OLDNAMES
  1997. +#endif
  1998.  #include <string.h>
  1999.  #include "../../gettext.h"
  2000.  
  2001. diff --git a/plugins/gtkui/trkproperties.c b/plugins/gtkui/trkproperties.c
  2002. index f90ad6cf..e83fcfef 100644
  2003. --- a/plugins/gtkui/trkproperties.c
  2004. +++ b/plugins/gtkui/trkproperties.c
  2005. @@ -26,6 +26,10 @@
  2006.  #endif
  2007.  #include <gtk/gtk.h>
  2008.  #include <gdk/gdkkeysyms.h>
  2009. +#ifdef __MINGW32__
  2010. +#undef __STRICT_ANSI__
  2011. +#undef _NO_OLDNAMES
  2012. +#endif
  2013.  #include <string.h>
  2014.  #include <math.h>
  2015.  #include <assert.h>
  2016. @@ -723,7 +727,7 @@ on_write_tags_clicked                  (GtkButton       *button,
  2017.      gtk_window_set_transient_for (GTK_WINDOW (progressdlg), GTK_WINDOW (trackproperties));
  2018.  
  2019.      // start new thread for writing metadata
  2020. -    intptr_t tid = deadbeef->thread_start (write_meta_worker, NULL);
  2021. +    db_thread_t tid = deadbeef->thread_start (write_meta_worker, NULL);
  2022.      deadbeef->thread_detach (tid);
  2023.  }
  2024.  
  2025. diff --git a/plugins/gtkui/widgets.c b/plugins/gtkui/widgets.c
  2026. index 198a8666..58f5860f 100644
  2027. --- a/plugins/gtkui/widgets.c
  2028. +++ b/plugins/gtkui/widgets.c
  2029. @@ -22,6 +22,10 @@
  2030.  */
  2031.  
  2032.  #include <stdlib.h>
  2033. +#ifdef __MINGW32__
  2034. +#undef __STRICT_ANSI__
  2035. +#undef _NO_OLDNAMES
  2036. +#endif
  2037.  #include <string.h>
  2038.  #include <assert.h>
  2039.  #include <math.h>
  2040. @@ -155,7 +159,7 @@ typedef struct {
  2041.      float *samples;
  2042.      int nsamples;
  2043.      int resized;
  2044. -    intptr_t mutex;
  2045. +    db_mutex_t mutex;
  2046.      cairo_surface_t *surf;
  2047.  } w_scope_t;
  2048.  
  2049. diff --git a/plugins/hotkeys/hotkeys.c b/plugins/hotkeys/hotkeys.c
  2050. index 1485dfbc..b930c19b 100644
  2051. --- a/plugins/hotkeys/hotkeys.c
  2052. +++ b/plugins/hotkeys/hotkeys.c
  2053. @@ -504,7 +504,7 @@ static int
  2054.  hotkeys_connect (void) {
  2055.  #ifndef __APPLE__
  2056.      finished = 0;
  2057. -    loop_tid = 0;
  2058. +    deadbeef->thread_wipeid (&loop_tid);
  2059.      disp = XOpenDisplay (NULL);
  2060.      if (!disp)
  2061.      {
  2062. @@ -533,7 +533,7 @@ hotkeys_connect (void) {
  2063.  static int
  2064.  hotkeys_disconnect (void) {
  2065.  #ifndef __APPLE__
  2066. -    if (loop_tid) {
  2067. +    if (deadbeef->thread_alive (loop_tid)) {
  2068.          finished = 1;
  2069.          deadbeef->thread_join (loop_tid);
  2070.      }
  2071. diff --git a/plugins/lastfm/lastfm.c b/plugins/lastfm/lastfm.c
  2072. index c5ec862e..5813c1c1 100644
  2073. --- a/plugins/lastfm/lastfm.c
  2074. +++ b/plugins/lastfm/lastfm.c
  2075. @@ -789,7 +789,7 @@ lastfm_stop (void) {
  2076.          deadbeef->cond_signal (lfm_cond);
  2077.          trace ("waiting for thread to finish\n");
  2078.          deadbeef->thread_join (lfm_tid);
  2079. -        lfm_tid = 0;
  2080. +        deadbeef->thread_wipeid (&lfm_tid);
  2081.          deadbeef->cond_free (lfm_cond);
  2082.          deadbeef->mutex_free (lfm_mutex);
  2083.      }
  2084. diff --git a/plugins/libmp4ff/mp4ff_int_types.h b/plugins/libmp4ff/mp4ff_int_types.h
  2085. index 15e7fd60..5fcbc05c 100644
  2086. --- a/plugins/libmp4ff/mp4ff_int_types.h
  2087. +++ b/plugins/libmp4ff/mp4ff_int_types.h
  2088. @@ -1,11 +1,11 @@
  2089.  #ifndef _MP4FF_INT_TYPES_H_
  2090.  #define _MP4FF_INT_TYPES_H_
  2091.  
  2092. -#if defined (_WIN32)
  2093. +#if defined (_WIN32) && !defined(__MINGW32__)
  2094.  
  2095. -#ifdef __MINGW32__
  2096. -#include <stdlib.h>
  2097. -#endif /* #ifdef __MINGW32__ */
  2098. +//#ifdef __MINGW32__
  2099. +//#include <stdlib.h>
  2100. +//#endif /* #ifdef __MINGW32__ */
  2101.  
  2102.  typedef signed char int8_t;
  2103.  typedef unsigned char uint8_t;
  2104. diff --git a/plugins/liboggedit/oggedit_flac.c b/plugins/liboggedit/oggedit_flac.c
  2105. index 8a238f72..c80252fe 100644
  2106. --- a/plugins/liboggedit/oggedit_flac.c
  2107. +++ b/plugins/liboggedit/oggedit_flac.c
  2108. @@ -30,6 +30,9 @@
  2109.  #include <stdlib.h>
  2110.  #include <string.h>
  2111.  #include <unistd.h>
  2112. +#ifdef __MINGW32__
  2113. +#undef __STRICT_ANSI__
  2114. +#endif
  2115.  #include <limits.h>
  2116.  #include "oggedit_internal.h"
  2117.  
  2118. diff --git a/plugins/liboggedit/oggedit_internal.c b/plugins/liboggedit/oggedit_internal.c
  2119. index a7a6acda..73c1777e 100644
  2120. --- a/plugins/liboggedit/oggedit_internal.c
  2121. +++ b/plugins/liboggedit/oggedit_internal.c
  2122. @@ -29,6 +29,10 @@
  2123.  #endif
  2124.  #include <stdio.h>
  2125.  #include <stdlib.h>
  2126. +#ifdef __MINGW32__
  2127. +#undef __STRICT_ANSI__
  2128. +#undef _NO_OLDNAMES
  2129. +#endif
  2130.  #include <string.h>
  2131.  #include <unistd.h>
  2132.  #include <libgen.h>
  2133. @@ -36,6 +40,9 @@
  2134.  #include <sys/stat.h>
  2135.  #include <limits.h>
  2136.  #include "oggedit_internal.h"
  2137. +#ifdef __MINGW32__
  2138. +#include "mingw32_layer.h"
  2139. +#endif
  2140.  
  2141.  static char *cat_string(char *dest, const char *src, const char *sep)
  2142.  {
  2143. diff --git a/plugins/liboggedit/oggedit_opus.c b/plugins/liboggedit/oggedit_opus.c
  2144. index bdf46124..b4478dc5 100644
  2145. --- a/plugins/liboggedit/oggedit_opus.c
  2146. +++ b/plugins/liboggedit/oggedit_opus.c
  2147. @@ -30,6 +30,9 @@
  2148.  #include <stdlib.h>
  2149.  #include <string.h>
  2150.  #include <unistd.h>
  2151. +#ifdef __MINGW32__
  2152. +#undef __STRICT_ANSI__
  2153. +#endif
  2154.  #include <limits.h>
  2155.  #include "oggedit_internal.h"
  2156.  
  2157. diff --git a/plugins/liboggedit/oggedit_utils.c b/plugins/liboggedit/oggedit_utils.c
  2158. index e01d8294..4fd42471 100644
  2159. --- a/plugins/liboggedit/oggedit_utils.c
  2160. +++ b/plugins/liboggedit/oggedit_utils.c
  2161. @@ -29,6 +29,10 @@
  2162.  #endif
  2163.  #include <stdlib.h>
  2164.  #include <stdint.h>
  2165. +#ifdef __MINGW32__
  2166. +#undef __STRICT_ANSI__
  2167. +#undef _NO_OLDNAMES
  2168. +#endif
  2169.  #include <string.h>
  2170.  #include <ctype.h>
  2171.  #include "oggedit_internal.h"
  2172. diff --git a/plugins/liboggedit/oggedit_vorbis.c b/plugins/liboggedit/oggedit_vorbis.c
  2173. index 9ea0474b..f4c06b5f 100644
  2174. --- a/plugins/liboggedit/oggedit_vorbis.c
  2175. +++ b/plugins/liboggedit/oggedit_vorbis.c
  2176. @@ -30,6 +30,9 @@
  2177.  #include <stdlib.h>
  2178.  #include <string.h>
  2179.  #include <unistd.h>
  2180. +#ifdef __MINGW32__
  2181. +#undef __STRICT_ANSI__
  2182. +#endif
  2183.  #include <limits.h>
  2184.  #include "oggedit_internal.h"
  2185.  
  2186. diff --git a/plugins/m3u/m3u.c b/plugins/m3u/m3u.c
  2187. index af942739..84253f2b 100644
  2188. --- a/plugins/m3u/m3u.c
  2189. +++ b/plugins/m3u/m3u.c
  2190. @@ -24,12 +24,19 @@
  2191.  #ifdef HAVE_CONFIG_H
  2192.  #  include "../../config.h"
  2193.  #endif
  2194. +#ifdef __MINGW32__
  2195. +#undef __STRICT_ANSI__
  2196. +#undef _NO_OLDNAMES
  2197. +#endif
  2198.  #include <string.h>
  2199.  #include <stdlib.h>
  2200.  #include <limits.h>
  2201.  #include <math.h> // for ceil
  2202.  
  2203.  #include "../../deadbeef.h"
  2204. +#ifdef __MINGW32__
  2205. +#include "mingw32_layer.h"
  2206. +#endif
  2207.  
  2208.  //#define trace(...) { fprintf(stderr, __VA_ARGS__); }
  2209.  #define trace(fmt,...)
  2210. diff --git a/plugins/mms/libmms/mms.c b/plugins/mms/libmms/mms.c
  2211. index b23130fe..5c3d56d9 100644
  2212. --- a/plugins/mms/libmms/mms.c
  2213. +++ b/plugins/mms/libmms/mms.c
  2214. @@ -28,11 +28,25 @@
  2215.  #include "config.h"
  2216.  #endif
  2217.  
  2218. -#include <unistd.h>
  2219. -#include <stdio.h>
  2220. +#ifdef __MINGW32__
  2221. +#define __USE_MINGW_FSEEK         /* request mingw internal implementation of fseeko64 */
  2222. +#undef __STRICT_ANSI__
  2223. +#undef _NO_OLDNAMES
  2224. +#define WINVER 0x0501
  2225. +#include <winsock2.h>
  2226. +#include <ws2tcpip.h>
  2227. +#else
  2228.  #include <sys/socket.h>
  2229.  #include <netinet/in.h>
  2230.  #include <netdb.h>
  2231. +#endif
  2232. +#include <unistd.h>
  2233. +#include <stdio.h>
  2234. +#ifdef __MINGW32__
  2235. +#define off_t   __int64
  2236. +#define fseeko  fseeko64
  2237. +#define ftello  ftello64
  2238. +#endif
  2239.  #include <string.h>
  2240.  #include <sys/types.h>
  2241.  #include <sys/stat.h>
  2242. @@ -51,6 +65,14 @@
  2243.  extern DB_functions_t *deadbeef;
  2244.  #endif
  2245.  
  2246. +#ifdef __MINGW32__
  2247. +#include "../../../mingw32_layer.h"
  2248. +#define MSG_DONTWAIT  0   /* useless when you set all your sockets as 'non-blocking' */
  2249. +#define EINPROGRESS   WSAEINPROGRESS
  2250. +#define EALREADY      WSAEALREADY
  2251. +#define EISCONN       WSAEISCONN
  2252. +#endif
  2253. +
  2254.  /********** logging **********/
  2255.  #define lprintf(...) if (getenv("LIBMMS_DEBUG")) fprintf(stderr, __VA_ARGS__)
  2256.  
  2257. @@ -256,7 +278,12 @@ static int fallback_io_tcp_connect(void *data, const char *host, int port, int *
  2258.      return -1;
  2259.    }
  2260.  
  2261. +#ifdef __MINGW32__
  2262. +  unsigned long flags = 1;
  2263. +  if (ioctlsocket(s, FIONBIO, &flags) == SOCKET_ERROR) {
  2264. +#else
  2265.    if (fcntl (s, F_SETFL, fcntl (s, F_GETFL) | O_NONBLOCK) == -1) {
  2266. +#endif
  2267.      lprintf("mms: failed to set socket flags: %s\n", strerror(errno));
  2268.      return -1;
  2269.    }
  2270. @@ -326,7 +353,11 @@ static int fallback_io_tcp_connect(void *data, const char *host, int port, int *
  2271.        freeaddrinfo(res);
  2272.    }
  2273.  #endif
  2274. +#ifdef __MINGW32__
  2275. +  closesocket(s);
  2276. +#else
  2277.    close(s);
  2278. +#endif
  2279.    return -1;
  2280.  }
  2281.  
  2282. @@ -1390,7 +1421,11 @@ mms_t *mms_connect (mms_io_t *io, void *data, const char *url, int bandwidth, in
  2283.  
  2284.  fail:
  2285.    if (this->s != -1)
  2286. +#ifdef __MINGW32__
  2287. +    closesocket (this->s);
  2288. +#else
  2289.      close (this->s);
  2290. +#endif
  2291.    if (this->url)
  2292.      free(this->url);
  2293.    if (this->guri)
  2294. @@ -1873,7 +1908,11 @@ off_t mms_seek (mms_io_t *io, mms_t *this, off_t offset, int origin) {
  2295.  
  2296.  void mms_close (mms_t *this) {
  2297.    if (this->s != -1)
  2298. +#ifdef __MINGW32__
  2299. +    closesocket (this->s);
  2300. +#else
  2301.      close (this->s);
  2302. +#endif
  2303.    if (this->url)
  2304.      free(this->url);
  2305.    if (this->guri)
  2306. diff --git a/plugins/mms/libmms/mmsh.c b/plugins/mms/libmms/mmsh.c
  2307. index 0606ac53..084bfac2 100644
  2308. --- a/plugins/mms/libmms/mmsh.c
  2309. +++ b/plugins/mms/libmms/mmsh.c
  2310. @@ -34,12 +34,28 @@
  2311.  #include "config.h"
  2312.  #endif
  2313.  
  2314. +#ifdef __MINGW32__
  2315. +#undef __STRICT_ANSI__
  2316. +#endif
  2317.  #include <unistd.h>
  2318. -#include <stdio.h>
  2319.  #include <stdlib.h>
  2320. +#ifdef __MINGW32__
  2321. +#define __USE_MINGW_FSEEK         /* request mingw internal implementation of fseeko64 */
  2322. +#undef __STRICT_ANSI__
  2323. +#undef _NO_OLDNAMES
  2324. +#include <winsock2.h>
  2325. +#define EINPROGRESS   WSAEINPROGRESS
  2326. +#else
  2327.  #include <sys/socket.h>
  2328.  #include <netinet/in.h>
  2329.  #include <netdb.h>
  2330. +#endif
  2331. +#include <stdio.h>
  2332. +#ifdef __MINGW32__
  2333. +#define off_t   off64_t
  2334. +#define fseeko  fseeko64
  2335. +#define ftello  ftello64
  2336. +#endif
  2337.  #include <string.h>
  2338.  #include <sys/types.h>
  2339.  #include <sys/stat.h>
  2340. @@ -266,7 +282,12 @@ static int fallback_io_tcp_connect(void *data, const char *host, int port, int *
  2341.      return -1;
  2342.    }
  2343.  
  2344. +#ifdef __MINGW32__
  2345. +  unsigned long flags = 1;
  2346. +  if (ioctlsocket(s, FIONBIO, &flags) == SOCKET_ERROR) {
  2347. +#else
  2348.    if (fcntl (s, F_SETFL, fcntl (s, F_GETFL) & ~O_NONBLOCK) == -1) {
  2349. +#endif
  2350.      lprintf("mmsh: failed to set socket flags: %s\n", strerror(errno));
  2351.      return -1;
  2352.    }
  2353. @@ -286,7 +307,11 @@ static int fallback_io_tcp_connect(void *data, const char *host, int port, int *
  2354.      
  2355.      return s;
  2356.    }
  2357. +#ifdef __MINGW32__
  2358. +  closesocket(s);
  2359. +#else
  2360.    close(s);
  2361. +#endif
  2362.    return -1;
  2363.  }
  2364.  
  2365. @@ -847,7 +872,11 @@ static int mmsh_connect_int (mms_io_t *io, mmsh_t *this, off_t seek, uint32_t ti
  2366.    
  2367.    /* Close exisiting connection (if any) and connect */
  2368.    if (this->s != -1)
  2369. +#ifdef __MINGW32__
  2370. +    closesocket(this->s);
  2371. +#else
  2372.      close(this->s);
  2373. +#endif
  2374.  
  2375.    if (mmsh_tcp_connect(io, this)) {
  2376.      return 0;
  2377. @@ -878,7 +907,11 @@ static int mmsh_connect_int (mms_io_t *io, mmsh_t *this, off_t seek, uint32_t ti
  2378.    if (!this->packet_length || !this->num_stream_ids)
  2379.      goto fail;
  2380.    
  2381. +#ifdef __MINGW32__
  2382. +  closesocket(this->s);
  2383. +#else
  2384.    close(this->s);
  2385. +#endif
  2386.  
  2387.    /* choose the best quality for the audio stream */
  2388.    /* i've never seen more than one audio stream */
  2389. @@ -1012,7 +1045,11 @@ static int mmsh_connect_int (mms_io_t *io, mmsh_t *this, off_t seek, uint32_t ti
  2390.    }
  2391.    return 1;
  2392.  fail:
  2393. +#ifdef __MINGW32__
  2394. +  closesocket(this->s);
  2395. +#else
  2396.    close(this->s);
  2397. +#endif
  2398.    this->s = -1;
  2399.    return 0;
  2400.  }
  2401. @@ -1133,7 +1170,11 @@ fail:
  2402.    if (uri)
  2403.      gnet_uri_delete(uri);
  2404.    if (this->s != -1)
  2405. +#ifdef __MINGW32__
  2406. +    closesocket(this->s);
  2407. +#else
  2408.      close(this->s);
  2409. +#endif
  2410.    if (this->url)
  2411.      free(this->url);
  2412.    if (this->proxy_url)
  2413. @@ -1362,7 +1403,11 @@ off_t mmsh_seek (mms_io_t *io, mmsh_t *this, off_t offset, int origin) {
  2414.            this->packet_length  != orig_asf_packet_len) {
  2415.          lprintf("mmsh: AIIEEE asf header or packet length changed on re-open for seek\n");
  2416.          /* Its a different stream, so its useless! */
  2417. +#ifdef __MINGW32__
  2418. +        closesocket (this->s);
  2419. +#else
  2420.          close (this->s);
  2421. +#endif
  2422.          this->s = -1;
  2423.          return this->current_pos = -1;
  2424.        }
  2425. @@ -1404,7 +1449,11 @@ off_t mmsh_seek (mms_io_t *io, mmsh_t *this, off_t offset, int origin) {
  2426.          this->packet_length  != orig_asf_packet_len) {
  2427.        lprintf("mmsh: AIIEEE asf header or packet length changed on re-open for seek\n");
  2428.        /* Its a different stream, so its useless! */
  2429. +#ifdef __MINGW32__
  2430. +      closesocket (this->s);
  2431. +#else
  2432.        close (this->s);
  2433. +#endif
  2434.        this->s = -1;
  2435.        return this->current_pos = -1;
  2436.      }
  2437. @@ -1456,7 +1505,11 @@ int mmsh_time_seek (mms_io_t *io, mmsh_t *this, double time_sec) {
  2438.        this->packet_length  != orig_asf_packet_len) {
  2439.      lprintf("mmsh: AIIEEE asf header or packet length changed on re-open for seek\n");
  2440.      /* Its a different stream, so its useless! */
  2441. +#ifdef __MINGW32__
  2442. +    closesocket (this->s);
  2443. +#else
  2444.      close (this->s);
  2445. +#endif
  2446.      this->s = -1;
  2447.      this->current_pos = -1;
  2448.      return 0;
  2449. @@ -1474,7 +1527,11 @@ int mmsh_time_seek (mms_io_t *io, mmsh_t *this, double time_sec) {
  2450.  
  2451.  void mmsh_close (mmsh_t *this) {
  2452.    if (this->s != -1)
  2453. +#ifdef __MINGW32__
  2454. +    closesocket(this->s);
  2455. +#else
  2456.      close(this->s);
  2457. +#endif
  2458.    if (this->url)
  2459.      free(this->url);
  2460.    if (this->proxy_url)
  2461. diff --git a/plugins/mms/libmms/mmsio.h b/plugins/mms/libmms/mmsio.h
  2462. index 376e6736..f897993e 100644
  2463. --- a/plugins/mms/libmms/mmsio.h
  2464. +++ b/plugins/mms/libmms/mmsio.h
  2465. @@ -3,6 +3,11 @@
  2466.  
  2467.  #define LIBMMS_HAVE_64BIT_OFF_T 1
  2468.  
  2469. +#ifdef __MINGW32__
  2470. +#undef __STRICT_ANSI__
  2471. +#include <sys/types.h>
  2472. +#define mms_off_t off64_t
  2473. +#else
  2474.  /* On 64 bit file offset capable systems, libmms' configure script adds
  2475.     -D_FILE_OFFSET_BITS=64 to the CFLAGS. This causes off_t to be 64 bit,
  2476.     When an app which includes this header file gets compiled without
  2477. @@ -13,6 +18,7 @@
  2478.  #else
  2479.  #define mms_off_t off_t
  2480.  #endif
  2481. +#endif /* __MINGW32__ */
  2482.  
  2483.  #ifdef __cplusplus
  2484.  extern "C" {
  2485. diff --git a/plugins/mms/libmms/uri.c b/plugins/mms/libmms/uri.c
  2486. index 38bb8dba..2756508e 100644
  2487. --- a/plugins/mms/libmms/uri.c
  2488. +++ b/plugins/mms/libmms/uri.c
  2489. @@ -18,6 +18,10 @@
  2490.   */
  2491.  
  2492.  /* FIXME: #include "gnet-private.h" */
  2493. +#ifdef __MINGW32__
  2494. +#undef __STRICT_ANSI__
  2495. +#undef _NO_OLDNAMES
  2496. +#endif
  2497.  #include <string.h>
  2498.  #include <stdlib.h>
  2499.  #include <ctype.h>
  2500. diff --git a/plugins/mms/mmsplug.c b/plugins/mms/mmsplug.c
  2501. index da07dc2a..17bbdc13 100644
  2502. --- a/plugins/mms/mmsplug.c
  2503. +++ b/plugins/mms/mmsplug.c
  2504. @@ -21,6 +21,10 @@
  2505.      3. This notice may not be removed or altered from any source distribution.
  2506.  */
  2507.  
  2508. +#ifdef __MINGW32__
  2509. +#undef __STRICT_ANSI__
  2510. +#undef _NO_OLDNAMES
  2511. +#endif
  2512.  #include "../../deadbeef.h"
  2513.  #include <stdio.h>
  2514.  #include <stdlib.h>
  2515. diff --git a/plugins/mp3/mp3.c b/plugins/mp3/mp3.c
  2516. index a206c85f..c920efeb 100644
  2517. --- a/plugins/mp3/mp3.c
  2518. +++ b/plugins/mp3/mp3.c
  2519. @@ -22,6 +22,9 @@
  2520.  */
  2521.  
  2522.  #include <string.h>
  2523. +#ifdef __MINGW32__
  2524. +#undef __STRICT_ANSI__
  2525. +#endif
  2526.  #include <stdio.h>
  2527.  #include <assert.h>
  2528.  #include <stdlib.h>
  2529. diff --git a/plugins/nullout/nullout.c b/plugins/nullout/nullout.c
  2530. old mode 100644
  2531. new mode 100755
  2532. index b98dc3d0..2e6e09b1
  2533. --- a/plugins/nullout/nullout.c
  2534. +++ b/plugins/nullout/nullout.c
  2535. @@ -30,18 +30,22 @@
  2536.  #include <string.h>
  2537.  #include "../../deadbeef.h"
  2538.  
  2539. -//#define trace(...) { fprintf(stderr, __VA_ARGS__); }
  2540. +#define NULLOUT_AUDIO_BLOCK_DURATION                   32 /* ms */
  2541. +
  2542. +//#define trace(...) { fprintf(stderr, __VA_ARGS__); fflush(stderr);}
  2543.  #define trace(fmt,...)
  2544.  
  2545.  static DB_output_t plugin;
  2546.  DB_functions_t *deadbeef;
  2547.  
  2548. -static intptr_t null_tid;
  2549. +static db_thread_t null_tid;
  2550.  static int null_terminate;
  2551.  static int state;
  2552. +static int nullout_simulate = 0;
  2553. +int bytesread, block_size;
  2554.  
  2555. -static void
  2556. -pnull_callback (char *stream, int len);
  2557. +//static void
  2558. +//pnull_callback (char *stream, int len);
  2559.  
  2560.  static void
  2561.  pnull_thread (void *context);
  2562. @@ -71,14 +75,27 @@ int
  2563.  pnull_init (void) {
  2564.      trace ("pnull_init\n");
  2565.      state = OUTPUT_STATE_STOPPED;
  2566. +    nullout_simulate = deadbeef->conf_get_int ("null.simulate", 0);
  2567.      null_terminate = 0;
  2568.      null_tid = deadbeef->thread_start (pnull_thread, NULL);
  2569.      return 0;
  2570.  }
  2571.  
  2572. +static int
  2573. +null_message (uint32_t id, uintptr_t ctx, uint32_t p1, uint32_t p2) {
  2574. +    switch (id) {
  2575. +    case DB_EV_CONFIGCHANGED:
  2576. +        nullout_simulate = deadbeef->conf_get_int ("null.simulate", 0);
  2577. +        break;
  2578. +    }
  2579. +    return 0;
  2580. +}
  2581. +
  2582.  int
  2583.  pnull_setformat (ddb_waveformat_t *fmt) {
  2584.      memcpy (&plugin.fmt, fmt, sizeof (ddb_waveformat_t));
  2585. +    block_size = (plugin.fmt.bps*plugin.fmt.samplerate*plugin.fmt.channels)*NULLOUT_AUDIO_BLOCK_DURATION/8000;
  2586. +    trace("nullout: new format sr %d ch %d bps %d - block_size=%d\n",plugin.fmt.samplerate,plugin.fmt.channels,plugin.fmt.bps,block_size);
  2587.      return 0;
  2588.  }
  2589.  
  2590. @@ -86,11 +103,11 @@ int
  2591.  pnull_free (void) {
  2592.      trace ("pnull_free\n");
  2593.      if (!null_terminate) {
  2594. -        if (null_tid) {
  2595. +        if (deadbeef->thread_alive (null_tid)) {
  2596.              null_terminate = 1;
  2597.              deadbeef->thread_join (null_tid);
  2598.          }
  2599. -        null_tid = 0;
  2600. +        deadbeef->thread_wipeid (&null_tid);
  2601.          state = OUTPUT_STATE_STOPPED;
  2602.          null_terminate = 0;
  2603.      }
  2604. @@ -99,7 +116,7 @@ pnull_free (void) {
  2605.  
  2606.  int
  2607.  pnull_play (void) {
  2608. -    if (!null_tid) {
  2609. +    if (!deadbeef->thread_alive (null_tid)) {
  2610.          pnull_init ();
  2611.      }
  2612.      state = OUTPUT_STATE_PLAYING;
  2613. @@ -132,6 +149,7 @@ pnull_unpause (void) {
  2614.      return 0;
  2615.  }
  2616.  
  2617. +#if 0
  2618.  static int
  2619.  pnull_get_endianness (void) {
  2620.  #if WORDS_BIGENDIAN
  2621. @@ -140,9 +158,14 @@ pnull_get_endianness (void) {
  2622.      return 0;
  2623.  #endif
  2624.  }
  2625. +#endif
  2626.  
  2627.  static void
  2628.  pnull_thread (void *context) {
  2629. +#define AUDIO_BUFFER_SIZE (4*1024)
  2630. +    char buf[AUDIO_BUFFER_SIZE];
  2631. +    int playable=0;
  2632. +    float sleep_time;
  2633.  #ifdef __linux__
  2634.      prctl (PR_SET_NAME, "deadbeef-null", 0, 0, 0, 0);
  2635.  #endif
  2636. @@ -151,27 +174,47 @@ pnull_thread (void *context) {
  2637.              break;
  2638.          }
  2639.          if (state != OUTPUT_STATE_PLAYING) {
  2640. -            usleep (10000);
  2641. +            usleep (16000);
  2642.              continue;
  2643.          }
  2644.  
  2645. -        char buf[4096];
  2646. -        pnull_callback (buf, 1024);
  2647. +        //pnull_callback (buf, AUDIO_BUFFER_SIZE);
  2648. +        /* receiving audio data */
  2649. +        do
  2650. +        {
  2651. +            bytesread = 0;
  2652. +            if(deadbeef->streamer_ok_to_read(AUDIO_BUFFER_SIZE))
  2653. +            {
  2654. +                bytesread = deadbeef->streamer_read (buf, AUDIO_BUFFER_SIZE);
  2655. +                playable += bytesread;
  2656. +            }
  2657. +        }
  2658. +        while(bytesread > 0 && playable < block_size);
  2659. +        /* 'consuming' audio data */
  2660. +        if (nullout_simulate)
  2661. +        {
  2662. +            sleep_time = 8000000.0/plugin.fmt.samplerate*((playable<block_size)?playable:block_size)/plugin.fmt.channels/plugin.fmt.bps;
  2663. +            playable = (playable<block_size)? 0 : (playable%block_size);
  2664. +            usleep((int)sleep_time);
  2665. +        }
  2666.      }
  2667.  }
  2668.  
  2669. +#if 0
  2670.  static void
  2671.  pnull_callback (char *stream, int len) {
  2672.      if (!deadbeef->streamer_ok_to_read (len)) {
  2673.          memset (stream, 0, len);
  2674. +        bytesread = 0;
  2675.          return;
  2676.      }
  2677. -    int bytesread = deadbeef->streamer_read (stream, len);
  2678. +    bytesread = deadbeef->streamer_read (stream, len);
  2679.  
  2680.      if (bytesread < len) {
  2681.          memset (stream + bytesread, 0, len-bytesread);
  2682.      }
  2683.  }
  2684. +#endif
  2685.  
  2686.  int
  2687.  pnull_get_state (void) {
  2688. @@ -194,12 +237,16 @@ nullout_load (DB_functions_t *api) {
  2689.      return DB_PLUGIN (&plugin);
  2690.  }
  2691.  
  2692. +static const char settings_dlg[] =
  2693. +    "property \"Simulate audio output\" checkbox null.simulate 0;\n"
  2694. +;
  2695. +
  2696.  // define plugin interface
  2697.  static DB_output_t plugin = {
  2698.      .plugin.api_vmajor = 1,
  2699.      .plugin.api_vminor = 0,
  2700.      .plugin.version_major = 1,
  2701. -    .plugin.version_minor = 0,
  2702. +    .plugin.version_minor = 1,
  2703.      .plugin.type = DB_PLUGIN_OUTPUT,
  2704.      .plugin.id = "nullout",
  2705.      .plugin.name = "Null output plugin",
  2706. @@ -229,6 +276,8 @@ static DB_output_t plugin = {
  2707.      .plugin.website = "http://deadbeef.sf.net",
  2708.      .plugin.start = null_start,
  2709.      .plugin.stop = null_stop,
  2710. +    .plugin.configdialog = settings_dlg,
  2711. +    .plugin.message = null_message,
  2712.      .init = pnull_init,
  2713.      .free = pnull_free,
  2714.      .setformat = pnull_setformat,
  2715. diff --git a/plugins/pltbrowser/pltbrowser.c b/plugins/pltbrowser/pltbrowser.c
  2716. index 009c3ca3..8bcd6051 100644
  2717. --- a/plugins/pltbrowser/pltbrowser.c
  2718. +++ b/plugins/pltbrowser/pltbrowser.c
  2719. @@ -23,6 +23,10 @@
  2720.  #include "../../deadbeef.h"
  2721.  #include <gtk/gtk.h>
  2722.  #include <stdlib.h>
  2723. +#ifdef __MINGW32__
  2724. +#undef __STRICT_ANSI__
  2725. +#undef _NO_OLDNAMES
  2726. +#endif
  2727.  #include <string.h>
  2728.  #ifdef HAVE_CONFIG_H
  2729.  #include "../../config.h"
  2730. diff --git a/plugins/pulse/pulse.c b/plugins/pulse/pulse.c
  2731. index a2dca968..b18efe11 100644
  2732. --- a/plugins/pulse/pulse.c
  2733. +++ b/plugins/pulse/pulse.c
  2734. @@ -220,12 +220,12 @@ static int pulse_free(void)
  2735.  {
  2736.      trace("pulse_free\n");
  2737.  
  2738. -    if (!pulse_tid) {
  2739. +    if (!deadbeef->thread_alive (pulse_tid)) {
  2740.          return 0;
  2741.      }
  2742.  
  2743.      intptr_t tid = pulse_tid;
  2744. -    pulse_tid = 0;
  2745. +    deadbeef->thread_wipeid (&pulse_tid);
  2746.      pulse_terminate = 1;
  2747.      deadbeef->thread_join(tid);
  2748.  
  2749. @@ -242,7 +242,7 @@ static int pulse_free(void)
  2750.  static int pulse_play(void)
  2751.  {
  2752.      trace ("pulse_play\n");
  2753. -    if (!pulse_tid)
  2754. +    if (!deadbeef->thread_alive (pulse_tid))
  2755.      {
  2756.          if (pulse_init () < 0)
  2757.          {
  2758. diff --git a/plugins/supereq/supereq.c b/plugins/supereq/supereq.c
  2759. index e701a94a..219357b8 100644
  2760. --- a/plugins/supereq/supereq.c
  2761. +++ b/plugins/supereq/supereq.c
  2762. @@ -34,7 +34,7 @@ typedef struct {
  2763.      float preamp;
  2764.      void *paramsroot;
  2765.      int params_changed;
  2766. -    uintptr_t mutex;
  2767. +    db_mutex_t mutex;
  2768.      SuperEqState state;
  2769.      int enabled;
  2770.  } ddb_supereq_ctx_t;
  2771. diff --git a/plugins/vfs_curl/vfs_curl.c b/plugins/vfs_curl/vfs_curl.c
  2772. index 40049e42..55650345 100644
  2773. --- a/plugins/vfs_curl/vfs_curl.c
  2774. +++ b/plugins/vfs_curl/vfs_curl.c
  2775. @@ -66,7 +66,7 @@ typedef struct {
  2776.      int32_t remaining; // remaining bytes in buffer read from stream
  2777.      int64_t skipbytes;
  2778.      intptr_t tid; // thread id which does http requests
  2779. -    intptr_t mutex;
  2780. +    db_mutex_t mutex;
  2781.      uint8_t nheaderpackets;
  2782.      char *content_type;
  2783.      CURL *curl;
  2784. @@ -793,7 +793,7 @@ http_close (DB_FILE *stream) {
  2785.      HTTP_FILE *fp = (HTTP_FILE *)stream;
  2786.  
  2787.      http_abort (stream);
  2788. -    if (fp->tid) {
  2789. +    if (deadbeef->thread_alive (fp->tid)) {
  2790.          deadbeef->thread_join (fp->tid);
  2791.      }
  2792.      http_cancel_abort ((DB_FILE *)fp);
  2793. @@ -813,7 +813,7 @@ http_read (void *ptr, size_t size, size_t nmemb, DB_FILE *stream) {
  2794.          errno = ECONNABORTED;
  2795.          return 0;
  2796.      }
  2797. -    if (!fp->tid) {
  2798. +    if (!deadbeef->thread_alive (fp->tid)) {
  2799.          http_start_streamer (fp);
  2800.      }
  2801.  
  2802. @@ -899,7 +899,7 @@ http_seek (DB_FILE *stream, int64_t offset, int whence) {
  2803.          trace ("vfs_curl: can't seek in curl stream relative to EOF\n");
  2804.          return -1;
  2805.      }
  2806. -    if (!fp->tid) {
  2807. +    if (!deadbeef->thread_alive (fp->tid)) {
  2808.          if (offset == 0 && (whence == SEEK_SET || whence == SEEK_CUR)) {
  2809.              return 0;
  2810.          }
  2811. @@ -956,7 +956,7 @@ http_rewind (DB_FILE *stream) {
  2812.      trace ("http_rewind\n");
  2813.      assert (stream);
  2814.      HTTP_FILE *fp = (HTTP_FILE *)stream;
  2815. -    if (fp->tid) {
  2816. +    if (deadbeef->thread_alive (fp->tid)) {
  2817.          deadbeef->mutex_lock (fp->mutex);
  2818.          fp->status = STATUS_SEEK;
  2819.          http_stream_reset (fp);
  2820. @@ -974,7 +974,7 @@ http_getlength (DB_FILE *stream) {
  2821.          trace ("length: -1\n");
  2822.          return -1;
  2823.      }
  2824. -    if (!fp->tid) {
  2825. +    if (!deadbeef->thread_alive (fp->tid)) {
  2826.          http_start_streamer (fp);
  2827.      }
  2828.      while (fp->status == STATUS_INITIAL) {
  2829. @@ -995,7 +995,7 @@ http_get_content_type (DB_FILE *stream) {
  2830.      if (fp->gotheader) {
  2831.          return fp->content_type;
  2832.      }
  2833. -    if (!fp->tid) {
  2834. +    if (!deadbeef->thread_alive (fp->tid)) {
  2835.          http_start_streamer (fp);
  2836.      }
  2837.      trace ("http_get_content_type waiting for response...\n");
  2838. diff --git a/plugins/vfs_zip/vfs_zip.c b/plugins/vfs_zip/vfs_zip.c
  2839. index 792baefe..0ff56db4 100644
  2840. --- a/plugins/vfs_zip/vfs_zip.c
  2841. +++ b/plugins/vfs_zip/vfs_zip.c
  2842. @@ -22,6 +22,9 @@
  2843.  */
  2844.  
  2845.  #include <string.h>
  2846. +#ifdef __MINGW32__
  2847. +#define ZIP_STATIC
  2848. +#endif
  2849.  #include <zip.h>
  2850.  #include <stdlib.h>
  2851.  #include <assert.h>
  2852. diff --git a/plugins/vorbis/vorbis.c b/plugins/vorbis/vorbis.c
  2853. index aad220cf..5e26d6df 100644
  2854. --- a/plugins/vorbis/vorbis.c
  2855. +++ b/plugins/vorbis/vorbis.c
  2856. @@ -24,6 +24,11 @@
  2857.  #ifdef HAVE_CONFIG_H
  2858.      #include <config.h>
  2859.  #endif
  2860. +#ifdef __MINGW32__
  2861. +#undef __STRICT_ANSI__
  2862. +#undef _NO_OLDNAMES
  2863. +#include <malloc.h>
  2864. +#endif
  2865.  #include <string.h>
  2866.  #include <stdlib.h>
  2867.  #include <limits.h>
  2868. diff --git a/plugins/vtx/vtxfile.c b/plugins/vtx/vtxfile.c
  2869. index 04978a08..3ddc0b31 100644
  2870. --- a/plugins/vtx/vtxfile.c
  2871. +++ b/plugins/vtx/vtxfile.c
  2872. @@ -5,7 +5,12 @@
  2873.  #include <ctype.h>
  2874.  #include <unistd.h>
  2875.  
  2876. +#ifdef __MINGW32__
  2877. +#include <windows.h>
  2878. +#include "../../mingw32_layer.h"
  2879. +#else
  2880.  #include <sys/mman.h>
  2881. +#endif
  2882.  #include <sys/stat.h>
  2883.  #include <fcntl.h>
  2884.  
  2885. @@ -213,7 +218,13 @@ ayemu_vtx_t * ayemu_vtx_header_from_file(const char *filename)
  2886.  {
  2887.    ayemu_vtx_t *ret;
  2888.    size_t size;
  2889. +#ifdef __MINGW32__
  2890. +  SYSTEM_INFO si;
  2891. +  GetSystemInfo(&si);
  2892. +  const size_t page_size = (size_t) si.dwPageSize;
  2893. +#else
  2894.    const size_t page_size = (size_t) sysconf (_SC_PAGESIZE);
  2895. +#endif
  2896.    int fd;
  2897.    struct stat st;
  2898.  
  2899. @@ -252,7 +263,13 @@ ayemu_vtx_t * ayemu_vtx_header_from_file(const char *filename)
  2900.  ayemu_vtx_t * ayemu_vtx_load_from_file(const char *filename)
  2901.  {
  2902.    size_t size;
  2903. +#ifdef __MINGW32__
  2904. +  SYSTEM_INFO si;
  2905. +  GetSystemInfo(&si);
  2906. +  const size_t page_size = (size_t) si.dwPageSize;
  2907. +#else
  2908.    const size_t page_size = (size_t) sysconf (_SC_PAGESIZE);
  2909. +#endif
  2910.    int fd;
  2911.    struct stat st;
  2912.    ayemu_vtx_t *ret;
  2913. diff --git a/plugins/waveout/COPYING b/plugins/waveout/COPYING
  2914. new file mode 100644
  2915. index 00000000..d0aecd3a
  2916. --- /dev/null
  2917. +++ b/plugins/waveout/COPYING
  2918. @@ -0,0 +1,20 @@
  2919. +WaveOut output plugin for DeaDBeeF Player
  2920. +Copyright (C) 2016 Elio Blanca
  2921. +
  2922. +This software is provided 'as-is', without any express or implied
  2923. +warranty.  In no event will the authors be held liable for any damages
  2924. +arising from the use of this software.
  2925. +
  2926. +Permission is granted to anyone to use this software for any purpose,
  2927. +including commercial applications, and to alter it and redistribute it
  2928. +freely, subject to the following restrictions:
  2929. +
  2930. +1. The origin of this software must not be misrepresented; you must not
  2931. +   claim that you wrote the original software. If you use this software
  2932. +   in a product, an acknowledgment in the product documentation would be
  2933. +   appreciated but is not required.
  2934. +
  2935. +2. Altered source versions must be plainly marked as such, and must not be
  2936. +   misrepresented as being the original software.
  2937. +
  2938. +3. This notice may not be removed or altered from any source distribution.
  2939. diff --git a/plugins/waveout/waveout.c b/plugins/waveout/waveout.c
  2940. new file mode 100644
  2941. index 00000000..b4e46aaa
  2942. --- /dev/null
  2943. +++ b/plugins/waveout/waveout.c
  2944. @@ -0,0 +1,671 @@
  2945. +/*
  2946. +    waveout output plugin for DeaDBeeF Player
  2947. +    Copyright (C) 2016-2017 Elio Blanca
  2948. +
  2949. +    This software is provided 'as-is', without any express or implied
  2950. +    warranty.  In no event will the authors be held liable for any damages
  2951. +    arising from the use of this software.
  2952. +
  2953. +    Permission is granted to anyone to use this software for any purpose,
  2954. +    including commercial applications, and to alter it and redistribute it
  2955. +    freely, subject to the following restrictions:
  2956. +
  2957. +    1. The origin of this software must not be misrepresented; you must not
  2958. +       claim that you wrote the original software. If you use this software
  2959. +       in a product, an acknowledgment in the product documentation would be
  2960. +       appreciated but is not required.
  2961. +
  2962. +    2. Altered source versions must be plainly marked as such, and must not be
  2963. +       misrepresented as being the original software.
  2964. +
  2965. +    3. This notice may not be removed or altered from any source distribution.
  2966. +*/
  2967. +
  2968. +#ifdef __MINGW32__
  2969. +
  2970. +/* some functions will require WindowsXP at least */
  2971. +#define WINVER 0x0501
  2972. +
  2973. +#define __USE_MINGW_ANSI_STDIO 1
  2974. +
  2975. +
  2976. +#define AUDIO_BUFFER_NO                                    10  /* max number of audio blocks */
  2977. +/* block buffers have to be large enough to maintain at least 20 ms of music (maybe 25?), else stuttering may be heard */
  2978. +#define AUDIO_BUFFER_DURATION                              25  /* ms of audio data per block */
  2979. +/* cannot rely on time measures below 10 ms because we are really close to the NT default time granularity (1/64 s),
  2980. +   so even the sound card driver may behave oddly */
  2981. +
  2982. +
  2983. +#define AUDIO_BUFFER_MAXIMUM_REQ                            6  /* kilobytes per millisecond */
  2984. +/* 1 ms of a 192 KHz 7.1 (32 bit/sample) stream require 6 kB */
  2985. +/* this is the most demanding audio stream I can think of, so I'll use this as reference */
  2986. +/* in case of more challenging streams, then less audio blocks will be used, so everything will work anyway */
  2987. +
  2988. +/* max size reserved for audio buffers - rarely used */
  2989. +#define AUDIO_BUFFER_SIZE          (AUDIO_BUFFER_NO*AUDIO_BUFFER_MAXIMUM_REQ*AUDIO_BUFFER_DURATION*1024)
  2990. +
  2991. +#define CHARACTER_SPACE                                   ' '
  2992. +#define CHARACTER_UNDERSCORE                              '_'
  2993. +
  2994. +
  2995. +#include <unistd.h>
  2996. +
  2997. +#include <windows.h>
  2998. +#include <mmreg.h>
  2999. +#include "../../deadbeef.h"
  3000. +
  3001. +//#define trace(...) { fprintf(stderr, __VA_ARGS__); fflush(stderr); }
  3002. +#define trace(fmt,...)
  3003. +
  3004. +/* both found on the internet... */
  3005. +static const GUID  KSDATAFORMAT_SUBTYPE_PCM =        {0x00000001,0x0000,0x0010,{0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71}};
  3006. +static const GUID  KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003,0x0000,0x0010,{0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71}};
  3007. +
  3008. +static DB_output_t plugin;
  3009. +DB_functions_t *deadbeef;
  3010. +
  3011. +/* waveOut device number and description */
  3012. +static unsigned int waveout_device;
  3013. +static char setup_dev[MAXPNAMELEN]="default";
  3014. +
  3015. +static db_thread_t waveout_tid;
  3016. +static int wave_terminate, state;
  3017. +static int audio_blocks_sent, audio_block_write_index;
  3018. +static int bytesread, bytes_per_block, avail_audio_buffers;
  3019. +static WAVEFORMATEXTENSIBLE wave_format;
  3020. +static HWAVEOUT device_handle;
  3021. +static WAVEHDR waveout_headers[AUDIO_BUFFER_NO];
  3022. +static CRITICAL_SECTION waveoutCS;
  3023. +static void *audio_data;
  3024. +
  3025. +char audio_format_change_pending;
  3026. +
  3027. +
  3028. +static void
  3029. +pwaveout_thread (void *context);
  3030. +
  3031. +int
  3032. +pwaveout_stop (void);
  3033. +
  3034. +static void
  3035. +remove_blanks (char *buffer, int len)
  3036. +{
  3037. +    int idx;
  3038. +
  3039. +    if (buffer != NULL && len > 0)
  3040. +    {
  3041. +        for (idx=0; idx<len; idx++)
  3042. +        {
  3043. +            if (buffer[idx] == CHARACTER_SPACE)
  3044. +                buffer[idx] = CHARACTER_UNDERSCORE;
  3045. +        }
  3046. +    }
  3047. +}
  3048. +
  3049. +int
  3050. +pwaveout_init (void)
  3051. +{
  3052. +    trace("pwaveout_init\n");
  3053. +    state = OUTPUT_STATE_STOPPED;
  3054. +    wave_terminate = 0;
  3055. +
  3056. +    return 0;
  3057. +}
  3058. +
  3059. +static int
  3060. +waveout_message (uint32_t id, uintptr_t ctx, uint32_t p1, uint32_t p2)
  3061. +{
  3062. +    int num_devices, idx;
  3063. +    WAVEOUTCAPS woc;
  3064. +    char my_dev[MAXPNAMELEN];
  3065. +    const char *current_dev;
  3066. +    unsigned int new_wdevice;
  3067. +
  3068. +    switch (id) {
  3069. +        case DB_EV_CONFIGCHANGED:
  3070. +        new_wdevice = waveout_device;
  3071. +        current_dev = deadbeef->conf_get_str_fast ("alsa_soundcard", "default");
  3072. +
  3073. +        if (strcmp(current_dev, "default") == 0)
  3074. +        {
  3075. +            trace("waveout_message: default device WAVE_MAPPER\n");
  3076. +            new_wdevice = WAVE_MAPPER;
  3077. +        }
  3078. +        else
  3079. +        {
  3080. +            num_devices = waveOutGetNumDevs();
  3081. +            if (num_devices != 0)
  3082. +            {
  3083. +                for (idx=0; idx<num_devices; idx++)
  3084. +                {
  3085. +                    if (waveOutGetDevCaps(idx, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR)
  3086. +                    {
  3087. +                        memcpy(my_dev, woc.szPname, MAXPNAMELEN);
  3088. +                        remove_blanks(my_dev, MAXPNAMELEN);
  3089. +                        if (strcmp(my_dev, current_dev) == 0)
  3090. +                        {
  3091. +                            trace("waveout_message: device match %s\n",my_dev);
  3092. +                            memcpy(setup_dev, my_dev, MAXPNAMELEN);
  3093. +                            new_wdevice = idx;
  3094. +                            break;
  3095. +                        }
  3096. +                    }
  3097. +                }
  3098. +            }
  3099. +        }
  3100. +
  3101. +        /* new device? */
  3102. +        if (waveout_device != new_wdevice)
  3103. +        {
  3104. +            /* replace wave device */
  3105. +            waveout_device = new_wdevice;
  3106. +            /* re-init output plugin */
  3107. +            trace ("waveout_message: config option changed, restarting\n");
  3108. +            deadbeef->sendmessage (DB_EV_REINIT_SOUND, 0, 0, 0);
  3109. +        }
  3110. +        break;
  3111. +#if 0
  3112. +        case DB_EV_SONGSTARTED:
  3113. +        if (/* notification balloon requested */)
  3114. +        {
  3115. +        }
  3116. +        break;
  3117. +#endif
  3118. +    }
  3119. +    return 0;
  3120. +}
  3121. +
  3122. +int
  3123. +pwaveout_setformat (ddb_waveformat_t *fmt)
  3124. +{
  3125. +    int result = 0;
  3126. +    MMRESULT openresult;
  3127. +
  3128. +    trace("pwaveout_setformat\n");
  3129. +
  3130. +    memcpy (&plugin.fmt, fmt, sizeof (ddb_waveformat_t));
  3131. +    trace("pwaveout_setformat: new settings sr %d ch %d bps %d channelmask=%08X\n",plugin.fmt.samplerate,plugin.fmt.channels,plugin.fmt.bps,fmt->channelmask);
  3132. +
  3133. +    wave_format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
  3134. +    wave_format.Format.nChannels = plugin.fmt.channels;
  3135. +    wave_format.Format.nSamplesPerSec = plugin.fmt.samplerate;
  3136. +    wave_format.Format.wBitsPerSample = plugin.fmt.bps;
  3137. +    wave_format.Format.nBlockAlign = wave_format.Format.nChannels * wave_format.Format.wBitsPerSample / 8;
  3138. +    wave_format.Format.nAvgBytesPerSec = wave_format.Format.nSamplesPerSec * wave_format.Format.nBlockAlign;
  3139. +    wave_format.Format.cbSize = 22;
  3140. +    wave_format.Samples.wValidBitsPerSample = wave_format.Format.wBitsPerSample;
  3141. +    wave_format.SubFormat = (fmt->is_float)? KSDATAFORMAT_SUBTYPE_IEEE_FLOAT : KSDATAFORMAT_SUBTYPE_PCM;
  3142. +    /* set channel mask */
  3143. +    wave_format.dwChannelMask = 0;
  3144. +    if (fmt->channelmask & DDB_SPEAKER_FRONT_LEFT)
  3145. +        wave_format.dwChannelMask |= SPEAKER_FRONT_LEFT;
  3146. +    if (fmt->channelmask & DDB_SPEAKER_FRONT_RIGHT)
  3147. +        wave_format.dwChannelMask |= SPEAKER_FRONT_RIGHT;
  3148. +    if (fmt->channelmask & DDB_SPEAKER_FRONT_CENTER)
  3149. +        wave_format.dwChannelMask |= SPEAKER_FRONT_CENTER;
  3150. +    if (fmt->channelmask & DDB_SPEAKER_LOW_FREQUENCY)
  3151. +        wave_format.dwChannelMask |= SPEAKER_LOW_FREQUENCY;
  3152. +    if (fmt->channelmask & DDB_SPEAKER_BACK_LEFT)
  3153. +        wave_format.dwChannelMask |= SPEAKER_BACK_LEFT;
  3154. +    if (fmt->channelmask & DDB_SPEAKER_BACK_RIGHT)
  3155. +        wave_format.dwChannelMask |= SPEAKER_BACK_RIGHT;
  3156. +    if (fmt->channelmask & DDB_SPEAKER_FRONT_LEFT_OF_CENTER)
  3157. +        wave_format.dwChannelMask |= SPEAKER_FRONT_LEFT_OF_CENTER;
  3158. +    if (fmt->channelmask & DDB_SPEAKER_FRONT_RIGHT_OF_CENTER)
  3159. +        wave_format.dwChannelMask |= SPEAKER_FRONT_RIGHT_OF_CENTER;
  3160. +    if (fmt->channelmask & DDB_SPEAKER_BACK_CENTER)
  3161. +        wave_format.dwChannelMask |= SPEAKER_BACK_CENTER;
  3162. +    if (fmt->channelmask & DDB_SPEAKER_SIDE_LEFT)
  3163. +        wave_format.dwChannelMask |= SPEAKER_SIDE_LEFT;
  3164. +    if (fmt->channelmask & DDB_SPEAKER_SIDE_RIGHT)
  3165. +        wave_format.dwChannelMask |= SPEAKER_SIDE_RIGHT;
  3166. +    if (fmt->channelmask & DDB_SPEAKER_TOP_CENTER)
  3167. +        wave_format.dwChannelMask |= SPEAKER_TOP_CENTER;
  3168. +    if (fmt->channelmask & DDB_SPEAKER_TOP_FRONT_LEFT)
  3169. +        wave_format.dwChannelMask |= SPEAKER_TOP_FRONT_LEFT;
  3170. +    if (fmt->channelmask & DDB_SPEAKER_TOP_FRONT_CENTER)
  3171. +        wave_format.dwChannelMask |= SPEAKER_TOP_FRONT_CENTER;
  3172. +    if (fmt->channelmask & DDB_SPEAKER_TOP_FRONT_RIGHT)
  3173. +        wave_format.dwChannelMask |= SPEAKER_TOP_FRONT_RIGHT;
  3174. +    if (fmt->channelmask & DDB_SPEAKER_TOP_BACK_LEFT)
  3175. +        wave_format.dwChannelMask |= SPEAKER_TOP_BACK_LEFT;
  3176. +    if (fmt->channelmask & DDB_SPEAKER_TOP_BACK_CENTER)
  3177. +        wave_format.dwChannelMask |= SPEAKER_TOP_BACK_CENTER;
  3178. +    if (fmt->channelmask & DDB_SPEAKER_TOP_BACK_RIGHT)
  3179. +        wave_format.dwChannelMask |= SPEAKER_TOP_BACK_RIGHT;
  3180. +
  3181. +
  3182. +    if (state == OUTPUT_STATE_STOPPED && audio_blocks_sent == 0)
  3183. +    {
  3184. +        openresult = waveOutOpen(NULL, waveout_device, (WAVEFORMATEX *)&wave_format, 0, 0, WAVE_FORMAT_QUERY);
  3185. +        if (openresult != MMSYSERR_NOERROR)
  3186. +        {
  3187. +            trace("pwaveout_setformat: audio format not supported by the selected device (result=%d)\n",openresult);
  3188. +            memset((void *)&wave_format, 0, sizeof(WAVEFORMATEXTENSIBLE));
  3189. +            result = -1;
  3190. +        }
  3191. +        else
  3192. +        {
  3193. +            trace("pwaveout_setformat: new format supported\n");
  3194. +        }
  3195. +    }
  3196. +    else
  3197. +    {
  3198. +        /* cannot query the audio device just now - promise we'll do this later */
  3199. +        trace("pwaveout_setformat: audio format query deferred\n");
  3200. +        audio_format_change_pending = 1;
  3201. +    }
  3202. +    return result;
  3203. +}
  3204. +
  3205. +int
  3206. +pwaveout_free (void)
  3207. +{
  3208. +    trace("pwaveout_free\n");
  3209. +    if (!wave_terminate)
  3210. +    {
  3211. +        if (deadbeef->thread_alive(waveout_tid))
  3212. +        {
  3213. +            wave_terminate = 1;
  3214. +            trace("pwaveout_free: waiting for thread join...\n");
  3215. +            deadbeef->thread_join(waveout_tid);
  3216. +            trace("pwaveout_free: thread join done\n");
  3217. +        }
  3218. +        state = OUTPUT_STATE_STOPPED;
  3219. +        wave_terminate = 0;
  3220. +    }
  3221. +    return 0;
  3222. +}
  3223. +
  3224. +void CALLBACK waveOutProc(HWAVEOUT  hwo,
  3225. +                          UINT      uMsg,
  3226. +                          DWORD_PTR dwInstance,
  3227. +                          DWORD_PTR dwParam1,
  3228. +                          DWORD_PTR dwParam2)
  3229. +{
  3230. +    if (hwo == device_handle && uMsg == WOM_DONE)
  3231. +    {
  3232. +        EnterCriticalSection(&waveoutCS);
  3233. +        audio_blocks_sent--;
  3234. +        LeaveCriticalSection(&waveoutCS);
  3235. +        /* DON'T DO THIS! */
  3236. +        /* Calling waveOutAnything functions from within this callback will cause a deadlock! */
  3237. +        //waveOutUnprepareHeader(device_handle, (LPWAVEHDR)dwParam1, sizeof(WAVEHDR));
  3238. +    }
  3239. +}
  3240. +
  3241. +int
  3242. +pwaveout_play (void)
  3243. +{
  3244. +    int result = -1;
  3245. +
  3246. +    trace("pwaveout_play\n");
  3247. +    if (!deadbeef->thread_alive(waveout_tid))
  3248. +    {
  3249. +        waveout_tid = deadbeef->thread_start(pwaveout_thread, NULL);
  3250. +    }
  3251. +    if (deadbeef->thread_alive(waveout_tid))
  3252. +    {
  3253. +        if (wave_format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
  3254. +        {
  3255. +            if (audio_blocks_sent)
  3256. +            {
  3257. +                trace("pwaveout_play: DANGEROUS audio_blocks_sent=%d\n",audio_blocks_sent);
  3258. +            }
  3259. +            /* device setup is ok, let's open */
  3260. +            if (waveOutOpen(&device_handle, waveout_device, (WAVEFORMATEX *)&wave_format, (DWORD_PTR)waveOutProc, 0, CALLBACK_FUNCTION) == MMSYSERR_NOERROR)
  3261. +            {
  3262. +                /* let's dance! - setup buffers */
  3263. +                bytes_per_block     = wave_format.Format.nAvgBytesPerSec * AUDIO_BUFFER_DURATION / 1000;
  3264. +                avail_audio_buffers = AUDIO_BUFFER_SIZE / bytes_per_block;
  3265. +                if (avail_audio_buffers > AUDIO_BUFFER_NO) avail_audio_buffers = AUDIO_BUFFER_NO;
  3266. +
  3267. +                audio_block_write_index = 0;
  3268. +                result = 0;
  3269. +                state = OUTPUT_STATE_PLAYING;
  3270. +                trace("pwaveout_play: go! (bytes_per_block=%d)\n",bytes_per_block);
  3271. +            }
  3272. +        }
  3273. +    }
  3274. +    return result;
  3275. +}
  3276. +
  3277. +int
  3278. +pwaveout_stop (void)
  3279. +{
  3280. +    int idx;
  3281. +
  3282. +    trace("pwaveout_stop\n");
  3283. +
  3284. +    if (device_handle != NULL)
  3285. +    {
  3286. +        if (state == OUTPUT_STATE_PAUSED)
  3287. +            /* cannot close a paused device */
  3288. +            waveOutRestart(device_handle);
  3289. +
  3290. +        /* inhibit pwaveout_thread from sending more audio blocks to the device */
  3291. +        state = OUTPUT_STATE_STOPPED;
  3292. +        waveOutReset(device_handle);
  3293. +        /* ensure pwaveout_thread catches the new state */
  3294. +        __mingw_sleep(0, AUDIO_BUFFER_DURATION*1000000);
  3295. +
  3296. +        if (audio_blocks_sent)
  3297. +        {
  3298. +            trace("pwaveout_stop: audio_blocks_sent = %d\n",audio_blocks_sent);
  3299. +            do
  3300. +            {
  3301. +                __mingw_sleep(0, AUDIO_BUFFER_DURATION*1000000);
  3302. +                trace(".");
  3303. +            }
  3304. +            while(audio_blocks_sent != 0);
  3305. +            trace("\n");
  3306. +        }
  3307. +
  3308. +        /* unprepare waveheaders and free resources */
  3309. +        for (idx=0; idx<AUDIO_BUFFER_NO; idx++)
  3310. +        {
  3311. +            if (waveout_headers[idx].dwFlags & WHDR_PREPARED)
  3312. +                waveOutUnprepareHeader(device_handle, &waveout_headers[idx], sizeof(WAVEHDR));
  3313. +        }
  3314. +    }
  3315. +
  3316. +    state = OUTPUT_STATE_STOPPED;
  3317. +
  3318. +    deadbeef->streamer_reset(1);
  3319. +
  3320. +    return 0;
  3321. +}
  3322. +
  3323. +int
  3324. +pwaveout_pause (void)
  3325. +{
  3326. +    trace("pwaveout_pause\n");
  3327. +    if (state == OUTPUT_STATE_STOPPED) {
  3328. +        return -1;
  3329. +    }
  3330. +
  3331. +    if (state == OUTPUT_STATE_PLAYING)
  3332. +    {
  3333. +        waveOutPause(device_handle);
  3334. +        state = OUTPUT_STATE_PAUSED;
  3335. +    }
  3336. +    return 0;
  3337. +}
  3338. +
  3339. +int
  3340. +pwaveout_unpause (void)
  3341. +{
  3342. +    trace("pwaveout_unpause\n");
  3343. +
  3344. +    if (state == OUTPUT_STATE_PAUSED)
  3345. +    {
  3346. +        waveOutRestart(device_handle);
  3347. +        state = OUTPUT_STATE_PLAYING;
  3348. +    }
  3349. +    return 0;
  3350. +}
  3351. +
  3352. +
  3353. +static void
  3354. +pwaveout_thread (void *context)
  3355. +{
  3356. +    MMRESULT mmresult;
  3357. +    int idx;
  3358. +
  3359. +    trace("pwaveout_thread started\n");
  3360. +
  3361. +    while (1)
  3362. +    {
  3363. +        if (wave_terminate)
  3364. +            break;
  3365. +
  3366. +        if (state != OUTPUT_STATE_PLAYING && !audio_format_change_pending)
  3367. +        {
  3368. +            __mingw_sleep(0, AUDIO_BUFFER_DURATION*1000000); /* __mingw_sleep(seconds, nanoseconds) */
  3369. +        }
  3370. +        else
  3371. +        {
  3372. +            /* is the device full? */
  3373. +            if (audio_blocks_sent >= avail_audio_buffers)
  3374. +                /* idle wait */
  3375. +                __mingw_sleep(0, AUDIO_BUFFER_DURATION*1000000);
  3376. +
  3377. +            /* 'consuming' audio data */
  3378. +            if (deadbeef->streamer_ok_to_read(bytes_per_block)
  3379. +                &&
  3380. +                audio_blocks_sent < avail_audio_buffers
  3381. +                &&
  3382. +                !audio_format_change_pending)
  3383. +            {
  3384. +                bytesread = deadbeef->streamer_read(audio_data+audio_block_write_index*bytes_per_block, bytes_per_block);
  3385. +                if (bytesread > 0)
  3386. +                {
  3387. +                    /* I cannot "unprepare" into the callback, so this seems a good place to do it */
  3388. +                    if (waveout_headers[audio_block_write_index].dwFlags & WHDR_PREPARED)
  3389. +                        waveOutUnprepareHeader(device_handle, &waveout_headers[audio_block_write_index], sizeof(WAVEHDR));
  3390. +                    waveout_headers[audio_block_write_index].dwBufferLength = bytesread;
  3391. +                    waveout_headers[audio_block_write_index].lpData =         audio_data+audio_block_write_index*bytes_per_block;
  3392. +                    waveout_headers[audio_block_write_index].dwFlags =        0;
  3393. +
  3394. +                    mmresult = waveOutPrepareHeader(device_handle, &waveout_headers[audio_block_write_index], sizeof(WAVEHDR));
  3395. +                    if (mmresult == MMSYSERR_NOERROR)
  3396. +                    {
  3397. +                        waveOutWrite(device_handle, &waveout_headers[audio_block_write_index], sizeof(WAVEHDR));
  3398. +                        EnterCriticalSection(&waveoutCS);
  3399. +                        audio_blocks_sent++;
  3400. +                        LeaveCriticalSection(&waveoutCS);
  3401. +                        audio_block_write_index = (audio_block_write_index+1) % avail_audio_buffers;
  3402. +                    }
  3403. +                }
  3404. +                else
  3405. +                {
  3406. +                    trace("pwaveout_thread: read nothing\n");
  3407. +                }
  3408. +            }
  3409. +            if (audio_blocks_sent == 0 && audio_format_change_pending)
  3410. +            {
  3411. +                trace("pwaveout_thread: there is a format change pending\n");
  3412. +
  3413. +                /* handle the format change... */
  3414. +                mmresult = waveOutOpen(&device_handle, waveout_device, (WAVEFORMATEX *)&wave_format, (DWORD_PTR)waveOutProc, 0, CALLBACK_FUNCTION);
  3415. +                if (mmresult != MMSYSERR_NOERROR)
  3416. +                {
  3417. +                    /* FATAL! cannot continue playback */
  3418. +                    trace("pwaveout_thread: FATAL audio format not supported by the selected device (result=%d)\n",mmresult);
  3419. +                    memset((void *)&wave_format, 0, sizeof(WAVEFORMATEXTENSIBLE));
  3420. +                    //result = -1;
  3421. +                    break;
  3422. +                }
  3423. +                else
  3424. +                {
  3425. +                    /* let's dance! - setup buffers */
  3426. +                    bytes_per_block     = wave_format.Format.nAvgBytesPerSec * AUDIO_BUFFER_DURATION / 1000;
  3427. +                    avail_audio_buffers = AUDIO_BUFFER_SIZE / bytes_per_block;
  3428. +                    if (avail_audio_buffers > AUDIO_BUFFER_NO) avail_audio_buffers = AUDIO_BUFFER_NO;
  3429. +
  3430. +                    audio_block_write_index = 0;
  3431. +                    trace("pwaveout_thread: format change done (bytes_per_block=%d)\n",bytes_per_block);
  3432. +                }
  3433. +
  3434. +                audio_format_change_pending = 0;
  3435. +            }
  3436. +        }
  3437. +    }
  3438. +
  3439. +    /* closing operations */
  3440. +
  3441. +    if (device_handle != NULL)
  3442. +    {
  3443. +        /* stop playback */
  3444. +        waveOutReset(device_handle);
  3445. +        while (audio_blocks_sent)
  3446. +            __mingw_sleep(0, AUDIO_BUFFER_DURATION*1000000);
  3447. +
  3448. +        for (idx=0; idx<AUDIO_BUFFER_NO; idx++)
  3449. +        {
  3450. +            /* free resources still locked */
  3451. +            if (waveout_headers[idx].dwFlags & WHDR_PREPARED)
  3452. +                waveOutUnprepareHeader(device_handle, &waveout_headers[idx], sizeof(WAVEHDR));
  3453. +        }
  3454. +        /* close the device */
  3455. +        waveOutClose(device_handle);
  3456. +    }
  3457. +
  3458. +    /* clean the thread ID struct - pretty ugly doin' this here, but useful */
  3459. +    waveout_tid.p = NULL; waveout_tid.x = 0;
  3460. +
  3461. +    trace("pwaveout_thread terminating\n");
  3462. +}
  3463. +
  3464. +int
  3465. +pwaveout_get_state (void) {
  3466. +    //trace("pwaveout_get_state\n"); /* this routine is called several times a second, so too much logging */
  3467. +    return state;
  3468. +}
  3469. +
  3470. +
  3471. +/*
  3472. + * 'start' is the very first function called after loading
  3473. + */
  3474. +int
  3475. +waveout_start (void) {
  3476. +    int result = 0;
  3477. +
  3478. +    trace("waveout_start\n");
  3479. +    state = OUTPUT_STATE_STOPPED;
  3480. +    audio_blocks_sent = 0;
  3481. +    audio_format_change_pending = 0;
  3482. +    device_handle = NULL;
  3483. +    waveout_device = WAVE_MAPPER;
  3484. +    waveout_tid.p = NULL; waveout_tid.x = 0;
  3485. +
  3486. +    if (waveOutGetNumDevs() != 0)
  3487. +    {
  3488. +        /* let's allocate enough room for needed audio data */
  3489. +        audio_data = malloc(AUDIO_BUFFER_SIZE);
  3490. +        if (audio_data != NULL)
  3491. +        {
  3492. +            InitializeCriticalSection(&waveoutCS);
  3493. +            trace("waveout_start: setup successful\n");
  3494. +        }
  3495. +        else
  3496. +            /* memory allocation failed - fatal */
  3497. +            result = -1;
  3498. +    }
  3499. +    else
  3500. +        /* no audio devices detected - communicate this failure */
  3501. +        result = -1;
  3502. +
  3503. +    return result;
  3504. +}
  3505. +
  3506. +
  3507. +static void
  3508. +pwaveout_enumdevices (void (*callback)(const char *name, const char *desc, void *), void *userdata)
  3509. +{
  3510. +    int idx, num_devices;
  3511. +    WAVEOUTCAPS woc;
  3512. +    char desc[MAXPNAMELEN];
  3513. +
  3514. +    num_devices = waveOutGetNumDevs();
  3515. +    if (num_devices != 0)
  3516. +    {
  3517. +        /* there is at least an audio output device */
  3518. +        for (idx=0; idx<num_devices; idx++)
  3519. +        {
  3520. +            if (waveOutGetDevCaps(idx, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR)
  3521. +            {
  3522. +                memcpy(desc, woc.szPname, MAXPNAMELEN);
  3523. +
  3524. +                /* clean the name in order to save it into config file */
  3525. +                remove_blanks(desc, MAXPNAMELEN);
  3526. +
  3527. +                callback (desc, woc.szPname, userdata);
  3528. +                trace("pwaveout_enumdevices: '%s %s'\n", desc, woc.szPname);
  3529. +            }
  3530. +            else
  3531. +            {
  3532. +                callback ("(no_description)", "(no description)", userdata);
  3533. +                trace("pwaveout_enumdevices: '(no_description) (no description)'\n");
  3534. +            }
  3535. +        }
  3536. +    }
  3537. +}
  3538. +
  3539. +
  3540. +/*
  3541. + * 'stop' is the very last function called before closing the output plugin
  3542. + * this is the best place for freeing resources
  3543. + */
  3544. +int
  3545. +waveout_stop (void) {
  3546. +    trace("waveout_stop\n");
  3547. +    free(audio_data);
  3548. +    DeleteCriticalSection(&waveoutCS);
  3549. +    return 0;
  3550. +}
  3551. +
  3552. +DB_plugin_t *
  3553. +waveout_load (DB_functions_t *api) {
  3554. +    trace("waveout_load\n");
  3555. +    deadbeef = api;
  3556. +    return DB_PLUGIN (&plugin);
  3557. +}
  3558. +
  3559. +
  3560. +// define plugin interface
  3561. +static DB_output_t plugin = {
  3562. +    .plugin.type = DB_PLUGIN_OUTPUT,
  3563. +    .plugin.api_vmajor = 1,
  3564. +    .plugin.api_vminor = 9,
  3565. +    .plugin.version_major = 1,
  3566. +    .plugin.version_minor = 0,
  3567. +    .plugin.id = "waveout",
  3568. +    .plugin.name = "WaveOut output plugin",
  3569. +    .plugin.descr = "Output plugin for the WaveOut interface\non Windows(R) OSs.\nRequires Windows XP at least.",
  3570. +    .plugin.copyright =
  3571. +    "WaveOut output plugin for DeaDBeeF Player\n"
  3572. +    "Copyright (C) 2016-2017 Elio Blanca\n"
  3573. +    "\n"
  3574. +    "This software is provided 'as-is', without any express or implied\n"
  3575. +    "warranty.  In no event will the authors be held liable for any damages\n"
  3576. +    "arising from the use of this software.\n"
  3577. +    "\n"
  3578. +    "Permission is granted to anyone to use this software for any purpose,\n"
  3579. +    "including commercial applications, and to alter it and redistribute it\n"
  3580. +    "freely, subject to the following restrictions:\n"
  3581. +    "\n"
  3582. +    "1. The origin of this software must not be misrepresented; you must not\n"
  3583. +    "   claim that you wrote the original software. If you use this software\n"
  3584. +    "   in a product, an acknowledgement in the product documentation would be\n"
  3585. +    "   appreciated but is not required.\n"
  3586. +    "\n"
  3587. +    "2. Altered source versions must be plainly marked as such, and must not be\n"
  3588. +    "   misrepresented as being the original software.\n"
  3589. +    "\n"
  3590. +    "3. This notice may not be removed or altered from any source distribution.\n",
  3591. +    .plugin.website = "https://github.com/eblanca/deadbeef-0.7.2",
  3592. +    .plugin.command = NULL,
  3593. +    .plugin.start = waveout_start,
  3594. +    .plugin.stop = waveout_stop,
  3595. +    .plugin.connect = NULL,
  3596. +    .plugin.disconnect = NULL,
  3597. +    .plugin.exec_cmdline = NULL,
  3598. +    .plugin.get_actions = NULL,
  3599. +    .plugin.message = waveout_message,
  3600. +    .plugin.configdialog = NULL,
  3601. +    .init = pwaveout_init,
  3602. +    .free = pwaveout_free,
  3603. +    .setformat = pwaveout_setformat,
  3604. +    .play = pwaveout_play,
  3605. +    .stop = pwaveout_stop,
  3606. +    .pause = pwaveout_pause,
  3607. +    .unpause = pwaveout_unpause,
  3608. +    .state = pwaveout_get_state,
  3609. +    .enum_soundcards = pwaveout_enumdevices,
  3610. +    .fmt = {.samplerate = 44100, .channels = 2, .bps = 16, .channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT},
  3611. +    /* waveOut API has the waveOutGetVolume and waveOutSetVolume interfaces: fix this? */
  3612. +    .has_volume = 0
  3613. +};
  3614. +#endif /* __MINGW32__ */
  3615. +
  3616. diff --git a/plugins/wavpack/wavpack.c b/plugins/wavpack/wavpack.c
  3617. index 0b9f9aca..7180501c 100644
  3618. --- a/plugins/wavpack/wavpack.c
  3619. +++ b/plugins/wavpack/wavpack.c
  3620. @@ -37,6 +37,9 @@
  3621.  #include <stdlib.h>
  3622.  #include <math.h>
  3623.  #include "../../deadbeef.h"
  3624. +#ifdef __MINGW32__
  3625. +#include <malloc.h>
  3626. +#endif
  3627.  
  3628.  #define min(x,y) ((x)<(y)?(x):(y))
  3629.  #define max(x,y) ((x)>(y)?(x):(y))
  3630. diff --git a/plugins/wildmidi/src/wildmidi_lib.c b/plugins/wildmidi/src/wildmidi_lib.c
  3631. index 26bf72ac..0283722c 100644
  3632. --- a/plugins/wildmidi/src/wildmidi_lib.c
  3633. +++ b/plugins/wildmidi/src/wildmidi_lib.c
  3634. @@ -150,6 +150,10 @@
  3635.  #include <stdarg.h>
  3636.  #include <stdio.h>
  3637.  #include <stdlib.h>
  3638. +#ifdef __MINGW32__
  3639. +#undef __STRICT_ANSI__
  3640. +#undef _NO_OLDNAMES
  3641. +#endif
  3642.  #include <string.h>
  3643.  #include <sys/stat.h>
  3644.  #include <sys/types.h>
  3645. diff --git a/streamer.c b/streamer.c
  3646. index e73bb994..5b029e57 100644
  3647. --- a/streamer.c
  3648. +++ b/streamer.c
  3649. @@ -25,6 +25,10 @@
  3650.    Alexey Yakovenko waker@users.sourceforge.net
  3651.  */
  3652.  #include <stdlib.h>
  3653. +#ifdef __MINGW32__
  3654. +#undef __STRICT_ANSI__
  3655. +#undef _NO_OLDNAMES
  3656. +#endif
  3657.  #include <string.h>
  3658.  #include <stdio.h>
  3659.  #include <assert.h>
  3660. @@ -52,6 +56,9 @@
  3661.  #include "plugins/libparser/parser.h"
  3662.  #include "strdupa.h"
  3663.  #include "playqueue.h"
  3664. +#ifdef __MINGW32__
  3665. +#include "mingw32_layer.h"
  3666. +#endif
  3667.  
  3668.  //#define trace(...) { fprintf(stderr, __VA_ARGS__); }
  3669.  #define trace(fmt,...)
  3670. @@ -72,7 +79,7 @@ streamer_read_async (char *bytes, int size);
  3671.  static int
  3672.  streamer_set_output_format (void);
  3673.  
  3674. -static intptr_t streamer_tid;
  3675. +static db_thread_t streamer_tid;
  3676.  static ddb_dsp_context_t *dsp_chain;
  3677.  static float dsp_ratio = 1;
  3678.  
  3679. @@ -118,9 +125,9 @@ static ringbuf_t streamer_ringbuf;
  3680.  static char streambuffer[STREAM_BUFFER_SIZE];
  3681.  
  3682.  static int bytes_until_next_song = 0;
  3683. -static uintptr_t mutex;
  3684. -static uintptr_t currtrack_mutex;
  3685. -static uintptr_t wdl_mutex; // wavedata listener
  3686. +static db_mutex_t mutex;
  3687. +static db_mutex_t currtrack_mutex;
  3688. +static db_mutex_t wdl_mutex; // wavedata listener
  3689.  
  3690.  static int nextsong = -1;
  3691.  static int nextsong_pstate = -1;
  3692. @@ -855,7 +862,7 @@ typedef struct ctmap_s {
  3693.  
  3694.  static ctmap_t *streamer_ctmap;
  3695.  static char conf_network_ctmapping[2048];
  3696. -static uintptr_t ctmap_mutex;
  3697. +static db_mutex_t ctmap_mutex;
  3698.  
  3699.  static void
  3700.  ctmap_init_mutex (void) {
  3701. @@ -2063,6 +2070,10 @@ streamer_dsp_chain_save_internal (const char *fname, ddb_dsp_context_t *chain) {
  3702.      }
  3703.  
  3704.      fclose (fp);
  3705. +#ifdef __MINGW32__
  3706. +    if (unlink(fname)!=0)
  3707. +        fprintf (stderr, "deleting %s failed: %s\n", fname, strerror (errno));
  3708. +#endif
  3709.      if (rename (tempfile, fname) != 0) {
  3710.          fprintf (stderr, "dspconfig rename %s -> %s failed: %s\n", tempfile, fname, strerror (errno));
  3711.          return -1;
  3712. diff --git a/threading.h b/threading.h
  3713. index 62ea44b6..7f606378 100644
  3714. --- a/threading.h
  3715. +++ b/threading.h
  3716. @@ -27,52 +27,68 @@
  3717.  #ifndef __THREADING_H
  3718.  #define __THREADING_H
  3719.  
  3720. +#ifdef __MINGW32__
  3721. +#include <pthread.h>
  3722. +typedef pthread_t       db_thread_t;
  3723. +typedef pthread_mutex_t *db_mutex_t;
  3724. +typedef pthread_cond_t  *db_cond_t;
  3725. +#else
  3726.  #include <stdint.h>
  3727. +#define db_thread_t intptr_t
  3728. +#define db_mutex_t  uintptr_t
  3729. +#define db_cond_t   uintptr_t
  3730. +#endif
  3731.  
  3732. -intptr_t
  3733. +db_thread_t//intptr_t
  3734.  thread_start (void (*fn)(void *ctx), void *ctx);
  3735.  
  3736. -intptr_t
  3737. +db_thread_t//intptr_t
  3738.  thread_start_low_priority (void (*fn)(void *ctx), void *ctx);
  3739.  
  3740.  int
  3741. -thread_join (intptr_t tid);
  3742. +thread_join (db_thread_t/*intptr_t*/ tid);
  3743. +
  3744. +int
  3745. +thread_detach (db_thread_t/*intptr_t*/ tid);
  3746.  
  3747.  int
  3748. -thread_detach (intptr_t tid);
  3749. +thread_alive (db_thread_t/*intptr_t*/ tid);
  3750. +
  3751. +void
  3752. +thread_wipeid (db_thread_t *tid);
  3753.  
  3754.  void
  3755.  thread_exit (void *retval);
  3756.  
  3757. -uintptr_t
  3758. +db_mutex_t//uintptr_t
  3759.  mutex_create (void);
  3760.  
  3761. -uintptr_t
  3762. +db_mutex_t//uintptr_t
  3763.  mutex_create_nonrecursive (void);
  3764.  
  3765.  void
  3766. -mutex_free (uintptr_t mtx);
  3767. +mutex_free (db_mutex_t/*uintptr_t*/ mtx);
  3768.  
  3769.  int
  3770. -mutex_lock (uintptr_t mtx);
  3771. +mutex_lock (db_mutex_t/*uintptr_t*/ mtx);
  3772.  
  3773.  int
  3774. -mutex_unlock (uintptr_t mtx);
  3775. +mutex_unlock (db_mutex_t/*uintptr_t*/ mtx);
  3776.  
  3777. -uintptr_t
  3778. +db_cond_t//uintptr_t
  3779.  cond_create (void);
  3780.  
  3781.  void
  3782. -cond_free (uintptr_t cond);
  3783. +cond_free (db_cond_t/*uintptr_t*/ cond);
  3784.  
  3785.  int
  3786. -cond_wait (uintptr_t cond, uintptr_t mutex);
  3787. +cond_wait (db_cond_t/*uintptr_t*/ cond, db_mutex_t/*uintptr_t*/ mutex);
  3788.  
  3789.  int
  3790. -cond_signal (uintptr_t cond);
  3791. +cond_signal (db_cond_t/*uintptr_t*/ cond);
  3792.  
  3793.  int
  3794. -cond_broadcast (uintptr_t cond);
  3795. +cond_broadcast (db_cond_t/*uintptr_t*/ cond);
  3796.  
  3797.  #endif
  3798.  
  3799. diff --git a/threading_pthread.c b/threading_pthread.c
  3800. index ab9381db..698750e6 100644
  3801. --- a/threading_pthread.c
  3802. +++ b/threading_pthread.c
  3803. @@ -34,30 +34,48 @@
  3804.  #include <config.h>
  3805.  #endif
  3806.  
  3807. -intptr_t
  3808. +db_thread_t
  3809.  thread_start (void (*fn)(void *ctx), void *ctx) {
  3810.      pthread_t tid;
  3811.      pthread_attr_t attr;
  3812.      int s = pthread_attr_init (&attr);
  3813.      if (s != 0) {
  3814.          fprintf (stderr, "pthread_attr_init failed: %s\n", strerror (s));
  3815. +#ifdef __MINGW32__
  3816. +        tid.p = NULL;
  3817. +        tid.x = 0;
  3818. +        return tid;
  3819. +#else
  3820.          return 0;
  3821. +#endif
  3822.      }
  3823.  
  3824.      s = pthread_create (&tid, &attr, (void *(*)(void *))fn, (void*)ctx);
  3825.      if (s != 0) {
  3826.          fprintf (stderr, "pthread_create failed: %s\n", strerror (s));
  3827. +#ifdef __MINGW32__
  3828. +        tid.p = NULL;
  3829. +        tid.x = 0;
  3830. +        return tid;
  3831. +#else
  3832.          return 0;
  3833. +#endif
  3834.      }
  3835.      s = pthread_attr_destroy (&attr);
  3836.      if (s != 0) {
  3837.          fprintf (stderr, "pthread_attr_destroy failed: %s\n", strerror (s));
  3838. +#ifdef __MINGW32__
  3839. +        tid.p = NULL;
  3840. +        tid.x = 0;
  3841. +        return tid;
  3842. +#else
  3843.          return 0;
  3844. +#endif
  3845.      }
  3846.      return tid;
  3847.  }
  3848.  
  3849. -intptr_t
  3850. +db_thread_t
  3851.  thread_start_low_priority (void (*fn)(void *ctx), void *ctx) {
  3852.  #if defined(__linux__) && !defined(ANDROID)
  3853.      pthread_t tid;
  3854. @@ -104,7 +122,7 @@ thread_start_low_priority (void (*fn)(void *ctx), void *ctx) {
  3855.  }
  3856.  
  3857.  int
  3858. -thread_join (intptr_t tid) {
  3859. +thread_join (db_thread_t tid) {
  3860.      void *retval;
  3861.      int s = pthread_join ((pthread_t)tid, &retval);
  3862.      if (s) {
  3863. @@ -115,7 +133,7 @@ thread_join (intptr_t tid) {
  3864.  }
  3865.  
  3866.  int
  3867. -thread_detach (intptr_t tid) {
  3868. +thread_detach (db_thread_t tid) {
  3869.      int s = pthread_detach ((pthread_t)tid);
  3870.      if (s) {
  3871.          fprintf (stderr, "pthread_detach failed: %s\n", strerror (s));
  3872. @@ -124,12 +142,30 @@ thread_detach (intptr_t tid) {
  3873.      return 0;
  3874.  }
  3875.  
  3876. +int
  3877. +thread_alive (db_thread_t tid) {
  3878. +    return (pthread_kill (tid, 0) == 0);
  3879. +}
  3880. +
  3881. +void
  3882. +thread_wipeid (db_thread_t *tid) {
  3883. +    if (tid != NULL)
  3884. +    {
  3885. +#ifdef __MINGW32__
  3886. +        tid->p = NULL;
  3887. +        tid->x = 0;
  3888. +#else
  3889. +        *tid = 0;
  3890. +#endif
  3891. +    }
  3892. +}
  3893. +
  3894.  void
  3895.  thread_exit (void *retval) {
  3896.      pthread_exit (retval);
  3897.  }
  3898.  
  3899. -uintptr_t
  3900. +db_mutex_t
  3901.  mutex_create_nonrecursive (void) {
  3902.      pthread_mutex_t *mtx = malloc (sizeof (pthread_mutex_t));
  3903.      pthread_mutexattr_t attr = {0};
  3904. @@ -138,13 +174,17 @@ mutex_create_nonrecursive (void) {
  3905.      int err = pthread_mutex_init (mtx, &attr);
  3906.      if (err != 0) {
  3907.          fprintf (stderr, "pthread_mutex_init failed: %s\n", strerror (err));
  3908. +#ifdef __MINGW32__
  3909. +        return NULL;
  3910. +#else
  3911.          return 0;
  3912. +#endif
  3913.      }
  3914.      pthread_mutexattr_destroy (&attr);
  3915. -    return (uintptr_t)mtx;
  3916. +    return (db_mutex_t)mtx;
  3917.  }
  3918.  
  3919. -uintptr_t
  3920. +db_mutex_t
  3921.  mutex_create (void) {
  3922.      pthread_mutex_t *mtx = malloc (sizeof (pthread_mutex_t));
  3923.      pthread_mutexattr_t attr = {0};
  3924. @@ -153,21 +193,25 @@ mutex_create (void) {
  3925.      int err = pthread_mutex_init (mtx, &attr);
  3926.      if (err != 0) {
  3927.          fprintf (stderr, "pthread_mutex_init failed: %s\n", strerror (err));
  3928. +#ifdef __MINGW32__
  3929. +        return NULL;
  3930. +#else
  3931.          return 0;
  3932. +#endif
  3933.      }
  3934.      pthread_mutexattr_destroy (&attr);
  3935. -    return (uintptr_t)mtx;
  3936. +    return (db_mutex_t)mtx;
  3937.  }
  3938.  
  3939.  void
  3940. -mutex_free (uintptr_t _mtx) {
  3941. +mutex_free (db_mutex_t _mtx) {
  3942.      pthread_mutex_t *mtx = (pthread_mutex_t *)_mtx;
  3943.      pthread_mutex_destroy (mtx);
  3944.      free (mtx);
  3945.  }
  3946.  
  3947.  int
  3948. -mutex_lock (uintptr_t _mtx) {
  3949. +mutex_lock (db_mutex_t _mtx) {
  3950.      pthread_mutex_t *mtx = (pthread_mutex_t *)_mtx;
  3951.      int err = pthread_mutex_lock (mtx);
  3952.      if (err != 0) {
  3953. @@ -177,7 +221,7 @@ mutex_lock (uintptr_t _mtx) {
  3954.  }
  3955.  
  3956.  int
  3957. -mutex_unlock (uintptr_t _mtx) {
  3958. +mutex_unlock (db_mutex_t _mtx) {
  3959.      pthread_mutex_t *mtx = (pthread_mutex_t *)_mtx;
  3960.      int err = pthread_mutex_unlock (mtx);
  3961.      if (err != 0) {
  3962. @@ -186,19 +230,23 @@ mutex_unlock (uintptr_t _mtx) {
  3963.      return err;
  3964.  }
  3965.  
  3966. -uintptr_t
  3967. +db_cond_t
  3968.  cond_create (void) {
  3969.      pthread_cond_t *cond = malloc (sizeof (pthread_cond_t));
  3970.      int err = pthread_cond_init (cond, NULL);
  3971.      if (err != 0) {
  3972.          fprintf (stderr, "pthread_cond_init failed: %s\n", strerror (err));
  3973. +#ifdef __MINGW32__
  3974. +        return NULL;
  3975. +#else
  3976.          return 0;
  3977. +#endif
  3978.      }
  3979. -    return (uintptr_t)cond;
  3980. +    return (db_cond_t)cond;
  3981.  }
  3982.  
  3983.  void
  3984. -cond_free (uintptr_t c) {
  3985. +cond_free (db_cond_t c) {
  3986.      if (c) {
  3987.          pthread_cond_t *cond = (pthread_cond_t *)c;
  3988.          pthread_cond_destroy (cond);
  3989. @@ -207,7 +255,7 @@ cond_free (uintptr_t c) {
  3990.  }
  3991.  
  3992.  int
  3993. -cond_wait (uintptr_t c, uintptr_t m) {
  3994. +cond_wait (db_cond_t c, db_mutex_t m) {
  3995.      pthread_cond_t *cond = (pthread_cond_t *)c;
  3996.      pthread_mutex_t *mutex = (pthread_mutex_t *)m;
  3997.      int err = mutex_lock (m);
  3998. @@ -222,7 +270,7 @@ cond_wait (uintptr_t c, uintptr_t m) {
  3999.  }
  4000.  
  4001.  int
  4002. -cond_signal (uintptr_t c) {
  4003. +cond_signal (db_cond_t c) {
  4004.      pthread_cond_t *cond = (pthread_cond_t *)c;
  4005.      int err = pthread_cond_signal (cond);
  4006.      if (err != 0) {
  4007. @@ -232,7 +280,7 @@ cond_signal (uintptr_t c) {
  4008.  }
  4009.  
  4010.  int
  4011. -cond_broadcast (uintptr_t c) {
  4012. +cond_broadcast (db_cond_t c) {
  4013.      pthread_cond_t *cond = (pthread_cond_t *)c;
  4014.      int err = pthread_cond_broadcast (cond);
  4015.      if (err != 0) {
  4016. diff --git a/utf8.c b/utf8.c
  4017. index f3f13093..35ce8205 100644
  4018. --- a/utf8.c
  4019. +++ b/utf8.c
  4020. @@ -45,7 +45,9 @@
  4021.  #include "utf8.h"
  4022.  #include "u8_lc_map.h"
  4023.  #include "u8_uc_map.h"
  4024. -
  4025. +#ifdef __MINGW32__
  4026. +#include <malloc.h>
  4027. +#endif
  4028.  static const uint32_t offsetsFromUTF8[6] = {
  4029.      0x00000000UL, 0x00003080UL, 0x000E2080UL,
  4030.      0x03C82080UL, 0xFA082080UL, 0x82082080UL
  4031. diff --git a/vfs.c b/vfs.c
  4032. index 2be32dea..47495dbe 100644
  4033. --- a/vfs.c
  4034. +++ b/vfs.c
  4035. @@ -24,6 +24,10 @@
  4036.  
  4037.    Alexey Yakovenko waker@users.sourceforge.net
  4038.  */
  4039. +#ifdef __MINGW32__
  4040. +#undef __STRICT_ANSI__
  4041. +#undef _NO_OLDNAMES
  4042. +#endif
  4043.  #include <string.h>
  4044.  #include <stdio.h>
  4045.  #include "vfs.h"
  4046. diff --git a/vfs_stdio.c b/vfs_stdio.c
  4047. index 7e6e6b7b..b1ec439b 100644
  4048. --- a/vfs_stdio.c
  4049. +++ b/vfs_stdio.c
  4050. @@ -25,6 +25,9 @@
  4051.    Alexey Yakovenko waker@users.sourceforge.net
  4052.  */
  4053.  #include "deadbeef.h"
  4054. +#ifdef __MINGW32__
  4055. +#define __USE_MINGW_FSEEK         /* request mingw internal implementation of fseeko64 */
  4056. +#endif
  4057.  #include <stdio.h>
  4058.  #include <stdlib.h>
  4059.  #include <assert.h>
  4060. @@ -35,9 +38,16 @@
  4061.  #include <unistd.h>
  4062.  
  4063.  #ifndef __linux__
  4064. +#ifdef __MINGW32__
  4065. +#define off_t   off64_t
  4066. +#define fseeko  fseeko64
  4067. +#define ftello  ftello64
  4068. +#define USE_STDIO
  4069. +#else
  4070.  #define off64_t off_t
  4071.  #define lseek64 lseek
  4072. -#define O_LARGEFILE 0
  4073. +#endif /* __MINGW32__ */
  4074. +#define O_LARGEFILE 0      /* this is a linux extension, anyway set this to 0 is the same as O_RDONLY */
  4075.  #endif
  4076.  
  4077.  //#define USE_STDIO
  4078. @@ -98,6 +108,7 @@ stdio_close (DB_FILE *stream) {
  4079.      free (stream);
  4080.  }
  4081.  
  4082. +#ifndef USE_STDIO
  4083.  static int
  4084.  fillbuffer (STDIO_FILE *f) {
  4085.      assert (f->bufremaining >= 0);
  4086. @@ -111,6 +122,7 @@ fillbuffer (STDIO_FILE *f) {
  4087.      }
  4088.      return f->bufremaining;
  4089.  }
  4090. +#endif
  4091.  
  4092.  static size_t
  4093.  stdio_read (void *ptr, size_t size, size_t nmemb, DB_FILE *stream) {
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement