938c05cf22782d321d8b8d8c705e0f0606d44c64
[ardour.git] / libs / fluidsynth / src / fluid_sys.c
1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License
7  * as published by the Free Software Foundation; either version 2.1 of
8  * the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA
19  */
20
21 #include "fluid_sys.h"
22
23
24 #if WITH_READLINE
25 #include <readline/readline.h>
26 #include <readline/history.h>
27 #endif
28
29 #ifdef DBUS_SUPPORT
30 #include "fluid_rtkit.h"
31 #endif
32
33 #if HAVE_PTHREAD_H && !defined(WIN32)
34 // Do not include pthread on windows. It includes winsock.h, which collides with ws2tcpip.h from fluid_sys.h
35 // It isn't need on Windows anyway.
36 #include <pthread.h>
37 #endif
38
39 /* WIN32 HACK - Flag used to differentiate between a file descriptor and a socket.
40  * Should work, so long as no SOCKET or file descriptor ends up with this bit set. - JG */
41 #ifdef _WIN32
42 #define FLUID_SOCKET_FLAG      0x40000000
43 #else
44 #define FLUID_SOCKET_FLAG      0x00000000
45 #define SOCKET_ERROR           -1
46 #define INVALID_SOCKET         -1
47 #endif
48
49 /* SCHED_FIFO priority for high priority timer threads */
50 #define FLUID_SYS_TIMER_HIGH_PRIO_LEVEL         10
51
52
53 typedef struct
54 {
55     fluid_thread_func_t func;
56     void *data;
57     int prio_level;
58 } fluid_thread_info_t;
59
60 struct _fluid_timer_t
61 {
62     long msec;
63     fluid_timer_callback_t callback;
64     void *data;
65     fluid_thread_t *thread;
66     int cont;
67     int auto_destroy;
68 };
69
70 struct _fluid_server_socket_t
71 {
72     fluid_socket_t socket;
73     fluid_thread_t *thread;
74     int cont;
75     fluid_server_func_t func;
76     void *data;
77 };
78
79
80 static int fluid_istream_gets(fluid_istream_t in, char *buf, int len);
81
82 static fluid_log_function_t fluid_log_function[LAST_LOG_LEVEL] =
83 {
84     fluid_default_log_function,
85     fluid_default_log_function,
86     fluid_default_log_function,
87     fluid_default_log_function,
88     fluid_default_log_function
89 };
90 static void *fluid_log_user_data[LAST_LOG_LEVEL] = { NULL };
91
92 static const char fluid_libname[] = "fluidsynth";
93
94 /**
95  * Installs a new log function for a specified log level.
96  * @param level Log level to install handler for.
97  * @param fun Callback function handler to call for logged messages
98  * @param data User supplied data pointer to pass to log function
99  * @return The previously installed function.
100  */
101 fluid_log_function_t
102 fluid_set_log_function(int level, fluid_log_function_t fun, void *data)
103 {
104     fluid_log_function_t old = NULL;
105
106     if((level >= 0) && (level < LAST_LOG_LEVEL))
107     {
108         old = fluid_log_function[level];
109         fluid_log_function[level] = fun;
110         fluid_log_user_data[level] = data;
111     }
112
113     return old;
114 }
115
116 /**
117  * Default log function which prints to the stderr.
118  * @param level Log level
119  * @param message Log message
120  * @param data User supplied data (not used)
121  */
122 void
123 fluid_default_log_function(int level, const char *message, void *data)
124 {
125     FILE *out;
126
127 #if defined(WIN32)
128     out = stdout;
129 #else
130     out = stderr;
131 #endif
132
133     switch(level)
134     {
135     case FLUID_PANIC:
136         FLUID_FPRINTF(out, "%s: panic: %s\n", fluid_libname, message);
137         break;
138
139     case FLUID_ERR:
140         FLUID_FPRINTF(out, "%s: error: %s\n", fluid_libname, message);
141         break;
142
143     case FLUID_WARN:
144         FLUID_FPRINTF(out, "%s: warning: %s\n", fluid_libname, message);
145         break;
146
147     case FLUID_INFO:
148         FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message);
149         break;
150
151     case FLUID_DBG:
152 #if DEBUG
153         FLUID_FPRINTF(out, "%s: debug: %s\n", fluid_libname, message);
154 #endif
155         break;
156
157     default:
158         FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message);
159         break;
160     }
161
162     fflush(out);
163 }
164
165 /**
166  * Print a message to the log.
167  * @param level Log level (#fluid_log_level).
168  * @param fmt Printf style format string for log message
169  * @param ... Arguments for printf 'fmt' message string
170  * @return Always returns #FLUID_FAILED
171  */
172 int
173 fluid_log(int level, const char *fmt, ...)
174 {
175     if((level >= 0) && (level < LAST_LOG_LEVEL))
176     {
177         fluid_log_function_t fun = fluid_log_function[level];
178
179         if(fun != NULL)
180         {
181             char errbuf[1024];
182             
183             va_list args;
184             va_start(args, fmt);
185             FLUID_VSNPRINTF(errbuf, sizeof(errbuf), fmt, args);
186             va_end(args);
187         
188             (*fun)(level, errbuf, fluid_log_user_data[level]);
189         }
190     }
191
192     return FLUID_FAILED;
193 }
194
195 /**
196  * An improved strtok, still trashes the input string, but is portable and
197  * thread safe.  Also skips token chars at beginning of token string and never
198  * returns an empty token (will return NULL if source ends in token chars though).
199  * NOTE: NOT part of public API
200  * @internal
201  * @param str Pointer to a string pointer of source to tokenize.  Pointer gets
202  *   updated on each invocation to point to beginning of next token.  Note that
203  *   token char get's overwritten with a 0 byte.  String pointer is set to NULL
204  *   when final token is returned.
205  * @param delim String of delimiter chars.
206  * @return Pointer to the next token or NULL if no more tokens.
207  */
208 char *fluid_strtok(char **str, const char *delim)
209 {
210     char *s,  *token;
211                 const char *d;
212     char c;
213
214     if(str == NULL || delim == NULL || !*delim)
215     {
216         FLUID_LOG(FLUID_ERR, "Null pointer");
217         return NULL;
218     }
219
220     s = *str;
221
222     if(!s)
223     {
224         return NULL;    /* str points to a NULL pointer? (tokenize already ended) */
225     }
226
227     /* skip delimiter chars at beginning of token */
228     do
229     {
230         c = *s;
231
232         if(!c)  /* end of source string? */
233         {
234             *str = NULL;
235             return NULL;
236         }
237
238         for(d = delim; *d; d++) /* is source char a token char? */
239         {
240             if(c == *d) /* token char match? */
241             {
242                 s++;            /* advance to next source char */
243                 break;
244             }
245         }
246     }
247     while(*d);          /* while token char match */
248
249     token = s;          /* start of token found */
250
251     /* search for next token char or end of source string */
252     for(s = s + 1; *s; s++)
253     {
254         c = *s;
255
256         for(d = delim; *d; d++) /* is source char a token char? */
257         {
258             if(c == *d) /* token char match? */
259             {
260                 *s = '\0';      /* overwrite token char with zero byte to terminate token */
261                 *str = s + 1;   /* update str to point to beginning of next token */
262                 return token;
263             }
264         }
265     }
266
267     /* we get here only if source string ended */
268     *str = NULL;
269     return token;
270 }
271
272 /**
273  * Suspend the execution of the current thread for the specified amount of time.
274  * @param milliseconds to wait.
275  */
276 void fluid_msleep(unsigned int msecs)
277 {
278     g_usleep(msecs * 1000);
279 }
280
281 /**
282  * Get time in milliseconds to be used in relative timing operations.
283  * @return Unix time in milliseconds.
284  */
285 unsigned int fluid_curtime(void)
286 {
287     static glong initial_seconds = 0;
288     GTimeVal timeval;
289
290     if(initial_seconds == 0)
291     {
292         g_get_current_time(&timeval);
293         initial_seconds = timeval.tv_sec;
294     }
295
296     g_get_current_time(&timeval);
297
298     return (unsigned int)((timeval.tv_sec - initial_seconds) * 1000.0 + timeval.tv_usec / 1000.0);
299 }
300
301 /**
302  * Get time in microseconds to be used in relative timing operations.
303  * @return time in microseconds.
304  * Note: When used for profiling we need high precision clock given
305  * by g_get_monotonic_time()if available (glib version >= 2.53.3).
306  * If glib version is too old and in the case of Windows the function
307  * uses high precision performance counter instead of g_getmonotic_time().
308  */
309 double
310 fluid_utime(void)
311 {
312     double utime;
313
314 #if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 28
315     /* use high precision monotonic clock if available (g_monotonic_time().
316      * For Winfdows, if this clock is actually implemented as low prec. clock
317      * (i.e. in case glib is too old), high precision performance counter are
318      * used instead.
319      * see: https://bugzilla.gnome.org/show_bug.cgi?id=783340
320      */
321 #if defined(WITH_PROFILING) &&  defined(WIN32) &&\
322         /* glib < 2.53.3 */\
323         (GLIB_MINOR_VERSION <= 53 && (GLIB_MINOR_VERSION < 53 || GLIB_MICRO_VERSION < 3))
324     /* use high precision performance counter. */
325     static LARGE_INTEGER freq_cache = {0, 0};   /* Performance Frequency */
326     LARGE_INTEGER perf_cpt;
327
328     if(! freq_cache.QuadPart)
329     {
330         QueryPerformanceFrequency(&freq_cache);  /* Frequency value */
331     }
332
333     QueryPerformanceCounter(&perf_cpt); /* Counter value */
334     utime = perf_cpt.QuadPart * 1000000.0 / freq_cache.QuadPart; /* time in micros */
335 #else
336     utime = g_get_monotonic_time();
337 #endif
338 #else
339     /* fallback to less precise clock */
340     GTimeVal timeval;
341     g_get_current_time(&timeval);
342     utime = (timeval.tv_sec * 1000000.0 + timeval.tv_usec);
343 #endif
344
345     return utime;
346 }
347
348
349
350 #if defined(WIN32)      /* Windoze specific stuff */
351
352 void
353 fluid_thread_self_set_prio(int prio_level)
354 {
355     if(prio_level > 0)
356     {
357         SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
358     }
359 }
360
361
362 #elif defined(__OS2__)  /* OS/2 specific stuff */
363
364 void
365 fluid_thread_self_set_prio(int prio_level)
366 {
367     if(prio_level > 0)
368     {
369         DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MAXIMUM, 0);
370     }
371 }
372
373 #else   /* POSIX stuff..  Nice POSIX..  Good POSIX. */
374
375 void
376 fluid_thread_self_set_prio(int prio_level)
377 {
378     struct sched_param priority;
379
380     if(prio_level > 0)
381     {
382
383         memset(&priority, 0, sizeof(priority));
384         priority.sched_priority = prio_level;
385
386         if(pthread_setschedparam(pthread_self(), SCHED_FIFO, &priority) == 0)
387         {
388             return;
389         }
390
391 #ifdef DBUS_SUPPORT
392         /* Try to gain high priority via rtkit */
393
394         if(fluid_rtkit_make_realtime(0, prio_level) == 0)
395         {
396             return;
397         }
398
399 #endif
400         FLUID_LOG(FLUID_WARN, "Failed to set thread to high priority");
401     }
402 }
403
404 #ifdef FPE_CHECK
405
406 /***************************************************************
407  *
408  *               Floating point exceptions
409  *
410  *  The floating point exception functions were taken from Ircam's
411  *  jMax source code. http://www.ircam.fr/jmax
412  *
413  *  FIXME: check in config for i386 machine
414  *
415  *  Currently not used. I leave the code here in case we want to pick
416  *  this up again some time later.
417  */
418
419 /* Exception flags */
420 #define _FPU_STATUS_IE    0x001  /* Invalid Operation */
421 #define _FPU_STATUS_DE    0x002  /* Denormalized Operand */
422 #define _FPU_STATUS_ZE    0x004  /* Zero Divide */
423 #define _FPU_STATUS_OE    0x008  /* Overflow */
424 #define _FPU_STATUS_UE    0x010  /* Underflow */
425 #define _FPU_STATUS_PE    0x020  /* Precision */
426 #define _FPU_STATUS_SF    0x040  /* Stack Fault */
427 #define _FPU_STATUS_ES    0x080  /* Error Summary Status */
428
429 /* Macros for accessing the FPU status word.  */
430
431 /* get the FPU status */
432 #define _FPU_GET_SW(sw) __asm__ ("fnstsw %0" : "=m" (*&sw))
433
434 /* clear the FPU status */
435 #define _FPU_CLR_SW() __asm__ ("fnclex" : : )
436
437 /* Purpose:
438  * Checks, if the floating point unit has produced an exception, print a message
439  * if so and clear the exception.
440  */
441 unsigned int fluid_check_fpe_i386(char *explanation)
442 {
443     unsigned int s;
444
445     _FPU_GET_SW(s);
446     _FPU_CLR_SW();
447
448     s &= _FPU_STATUS_IE | _FPU_STATUS_DE | _FPU_STATUS_ZE | _FPU_STATUS_OE | _FPU_STATUS_UE;
449
450     if(s)
451     {
452         FLUID_LOG(FLUID_WARN, "FPE exception (before or in %s): %s%s%s%s%s", explanation,
453                   (s & _FPU_STATUS_IE) ? "Invalid operation " : "",
454                   (s & _FPU_STATUS_DE) ? "Denormal number " : "",
455                   (s & _FPU_STATUS_ZE) ? "Zero divide " : "",
456                   (s & _FPU_STATUS_OE) ? "Overflow " : "",
457                   (s & _FPU_STATUS_UE) ? "Underflow " : "");
458     }
459
460     return s;
461 }
462
463 /* Purpose:
464  * Clear floating point exception.
465  */
466 void fluid_clear_fpe_i386(void)
467 {
468     _FPU_CLR_SW();
469 }
470
471 #endif  // ifdef FPE_CHECK
472
473
474 #endif  // #else    (its POSIX)
475
476
477 /***************************************************************
478  *
479  *               Profiling (Linux, i586 only)
480  *
481  */
482
483 #if WITH_PROFILING
484 /* Profiling interface beetween profiling command shell and audio rendering API
485   (FluidProfile_0004.pdf- 3.2.2).
486   Macros are in defined in fluid_sys.h.
487 */
488
489 /*
490   -----------------------------------------------------------------------------
491   Shell task side |    Profiling interface              |  Audio task side
492   -----------------------------------------------------------------------------
493   profiling       |    Internal    |      |             |      Audio
494   command   <---> |<-- profling -->| Data |<--macros -->| <--> rendering
495   shell           |    API         |      |             |      API
496
497 */
498 /* default parameters for shell command "prof_start" in fluid_sys.c */
499 unsigned short fluid_profile_notes = 0; /* number of generated notes */
500 /* preset bank:0 prog:16 (organ) */
501 unsigned char fluid_profile_bank = FLUID_PROFILE_DEFAULT_BANK;
502 unsigned char fluid_profile_prog = FLUID_PROFILE_DEFAULT_PROG;
503
504 /* print mode */
505 unsigned char fluid_profile_print = FLUID_PROFILE_DEFAULT_PRINT;
506 /* number of measures */
507 unsigned short fluid_profile_n_prof = FLUID_PROFILE_DEFAULT_N_PROF;
508 /* measure duration in ms */
509 unsigned short fluid_profile_dur = FLUID_PROFILE_DEFAULT_DURATION;
510 /* lock between multiple-shell */
511 fluid_atomic_int_t fluid_profile_lock = 0;
512 /**/
513
514 /*----------------------------------------------
515   Profiling Data
516 -----------------------------------------------*/
517 unsigned char fluid_profile_status = PROFILE_STOP; /* command and status */
518 unsigned int fluid_profile_end_ticks = 0;          /* ending position (in ticks) */
519 fluid_profile_data_t fluid_profile_data[] =        /* Data duration */
520 {
521     {"synth_write_* ------------>", 1e10, 0.0, 0.0, 0, 0, 0},
522     {"synth_one_block ---------->", 1e10, 0.0, 0.0, 0, 0, 0},
523     {"synth_one_block:clear ---->", 1e10, 0.0, 0.0, 0, 0, 0},
524     {"synth_one_block:one voice->", 1e10, 0.0, 0.0, 0, 0, 0},
525     {"synth_one_block:all voices>", 1e10, 0.0, 0.0, 0, 0, 0},
526     {"synth_one_block:reverb --->", 1e10, 0.0, 0.0, 0, 0, 0},
527     {"synth_one_block:chorus --->", 1e10, 0.0, 0.0, 0, 0, 0},
528     {"voice:note --------------->", 1e10, 0.0, 0.0, 0, 0, 0},
529     {"voice:release ------------>", 1e10, 0.0, 0.0, 0, 0, 0}
530 };
531
532
533 /*----------------------------------------------
534   Internal profiling API
535 -----------------------------------------------*/
536 /* logging profiling data (used on synthesizer instance deletion) */
537 void fluid_profiling_print(void)
538 {
539     int i;
540
541     printf("fluid_profiling_print\n");
542
543     FLUID_LOG(FLUID_INFO, "Estimated times: min/avg/max (micro seconds)");
544
545     for(i = 0; i < FLUID_PROFILE_NBR; i++)
546     {
547         if(fluid_profile_data[i].count > 0)
548         {
549             FLUID_LOG(FLUID_INFO, "%s: %.3f/%.3f/%.3f",
550                       fluid_profile_data[i].description,
551                       fluid_profile_data[i].min,
552                       fluid_profile_data[i].total / fluid_profile_data[i].count,
553                       fluid_profile_data[i].max);
554         }
555         else
556         {
557             FLUID_LOG(FLUID_DBG, "%s: no profiling available",
558                       fluid_profile_data[i].description);
559         }
560     }
561 }
562
563 /* Macro that returns cpu load in percent (%)
564  * @dur: duration (micro second).
565  * @sample_rate: sample_rate used in audio driver (Hz).
566  * @n_amples: number of samples collected during 'dur' duration.
567 */
568 #define fluid_profile_load(dur,sample_rate,n_samples) \
569         (dur * sample_rate / n_samples / 10000.0)
570
571
572 /* prints cpu loads only
573 *
574 * @param sample_rate the sample rate of audio output.
575 * @param out output stream device.
576 *
577 * ------------------------------------------------------------------------------
578 * Cpu loads(%) (sr: 44100 Hz, sp: 22.68 microsecond) and maximum voices
579 * ------------------------------------------------------------------------------
580 * nVoices| total(%)|voices(%)| reverb(%)|chorus(%)| voice(%)|estimated maxVoices
581 * -------|---------|---------|----------|---------|---------|-------------------
582 *     250|   41.544|   41.544|     0.000|    0.000|    0.163|              612
583 */
584 static void fluid_profiling_print_load(double sample_rate, fluid_ostream_t out)
585 {
586     unsigned int n_voices; /* voices number */
587     static const char max_voices_not_available[] = "      not available";
588     const char *pmax_voices;
589     char max_voices_available[20];
590
591     /* First computes data to be printed */
592     double  total, voices, reverb, chorus, all_voices, voice;
593     /* voices number */
594     n_voices = fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].count ?
595                fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].n_voices /
596                fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].count : 0;
597
598     /* total load (%) */
599     total =  fluid_profile_data[FLUID_PROF_WRITE].count ?
600              fluid_profile_load(fluid_profile_data[FLUID_PROF_WRITE].total, sample_rate,
601                                 fluid_profile_data[FLUID_PROF_WRITE].n_samples) : 0;
602
603     /* reverb load (%) */
604     reverb = fluid_profile_data[FLUID_PROF_ONE_BLOCK_REVERB].count ?
605              fluid_profile_load(fluid_profile_data[FLUID_PROF_ONE_BLOCK_REVERB].total,
606                                 sample_rate,
607                                 fluid_profile_data[FLUID_PROF_ONE_BLOCK_REVERB].n_samples) : 0;
608
609     /* chorus load (%) */
610     chorus = fluid_profile_data[FLUID_PROF_ONE_BLOCK_CHORUS].count ?
611              fluid_profile_load(fluid_profile_data[FLUID_PROF_ONE_BLOCK_CHORUS].total,
612                                 sample_rate,
613                                 fluid_profile_data[FLUID_PROF_ONE_BLOCK_CHORUS].n_samples) : 0;
614
615     /* total voices load: total - reverb - chorus (%) */
616     voices = total - reverb - chorus;
617
618     /* One voice load (%): all_voices / n_voices. */
619     all_voices = fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].count ?
620                  fluid_profile_load(fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].total,
621                                     sample_rate,
622                                     fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].n_samples) : 0;
623
624     voice = n_voices ?  all_voices / n_voices : 0;
625
626     /* estimated maximum voices number */
627     if(voice > 0)
628     {
629         FLUID_SNPRINTF(max_voices_available, sizeof(max_voices_available),
630                        "%17d", (unsigned int)((100.0 - reverb - chorus) / voice));
631         pmax_voices = max_voices_available;
632     }
633     else
634     {
635         pmax_voices = max_voices_not_available;
636     }
637
638     /* Now prints data */
639     fluid_ostream_printf(out,
640                          " ------------------------------------------------------------------------------\n");
641     fluid_ostream_printf(out,
642                          " Cpu loads(%%) (sr:%6.0f Hz, sp:%6.2f microsecond) and maximum voices\n",
643                          sample_rate, 1000000.0 / sample_rate);
644     fluid_ostream_printf(out,
645                          " ------------------------------------------------------------------------------\n");
646     fluid_ostream_printf(out,
647                          " nVoices| total(%%)|voices(%%)| reverb(%%)|chorus(%%)| voice(%%)|estimated maxVoices\n");
648     fluid_ostream_printf(out,
649                          " -------|---------|---------|----------|---------|---------|-------------------\n");
650     fluid_ostream_printf(out,
651                          "%8d|%9.3f|%9.3f|%10.3f|%9.3f|%9.3f|%s\n", n_voices, total, voices,
652                          reverb, chorus, voice, pmax_voices);
653 }
654
655 /*
656 * prints profiling data (used by profile shell command: prof_start).
657 * The function is an internal profiling API between the "profile" command
658 * prof_start and audio rendering API (see FluidProfile_0004.pdf - 3.2.2).
659 *
660 * @param sample_rate the sample rate of audio output.
661 * @param out output stream device.
662 *
663 * When print mode is 1, the function prints all the informations (see below).
664 * When print mode is 0, the fonction prints only the cpu loads.
665 *
666 * ------------------------------------------------------------------------------
667 * Duration(microsecond) and cpu loads(%) (sr: 44100 Hz, sp: 22.68 microsecond)
668 * ------------------------------------------------------------------------------
669 * Code under profiling       |Voices|       Duration (microsecond)   |  Load(%)
670 *                            |   nbr|       min|       avg|       max|
671 * ---------------------------|------|--------------------------------|----------
672 * synth_write_* ------------>|   250|      3.91|   2188.82|   3275.00|  41.544
673 * synth_one_block ---------->|   250|   1150.70|   2273.56|   3241.47|  41.100
674 * synth_one_block:clear ---->|   250|      3.07|      4.62|     61.18|   0.084
675 * synth_one_block:one voice->|     1|      4.19|      9.02|   1044.27|   0.163
676 * synth_one_block:all voices>|   250|   1138.41|   2259.11|   3217.73|  40.839
677 * synth_one_block:reverb --->| no profiling available
678 * synth_one_block:chorus --->| no profiling available
679 * voice:note --------------->| no profiling available
680 * voice:release ------------>| no profiling available
681 * ------------------------------------------------------------------------------
682 * Cpu loads(%) (sr: 44100 Hz, sp: 22.68 microsecond) and maximum voices
683 * ------------------------------------------------------------------------------
684 * nVoices| total(%)|voices(%)| reverb(%)|chorus(%)| voice(%)|estimated maxVoices
685 * -------|---------|---------|----------|---------|---------|-------------------
686 *     250|   41.544|   41.544|     0.000|    0.000|    0.163|              612
687 */
688 void fluid_profiling_print_data(double sample_rate, fluid_ostream_t out)
689 {
690     int i;
691
692     if(fluid_profile_print)
693     {
694         /* print all details: Duration(microsecond) and cpu loads(%) */
695         fluid_ostream_printf(out,
696                              " ------------------------------------------------------------------------------\n");
697         fluid_ostream_printf(out,
698                              " Duration(microsecond) and cpu loads(%%) (sr:%6.0f Hz, sp:%6.2f microsecond)\n",
699                              sample_rate, 1000000.0 / sample_rate);
700         fluid_ostream_printf(out,
701                              " ------------------------------------------------------------------------------\n");
702         fluid_ostream_printf(out,
703                              " Code under profiling       |Voices|       Duration (microsecond)   |  Load(%%)\n");
704         fluid_ostream_printf(out,
705                              "                            |   nbr|       min|       avg|       max|\n");
706         fluid_ostream_printf(out,
707                              " ---------------------------|------|--------------------------------|----------\n");
708
709         for(i = 0; i < FLUID_PROFILE_NBR; i++)
710         {
711             unsigned int count = fluid_profile_data[i].count;
712
713             if(count > 0)
714             {
715                 /* data are available */
716
717                 if(FLUID_PROF_WRITE <= i && i <= FLUID_PROF_ONE_BLOCK_CHORUS)
718                 {
719                     double load = fluid_profile_load(fluid_profile_data[i].total, sample_rate,
720                                                      fluid_profile_data[i].n_samples);
721                     fluid_ostream_printf(out, " %s|%6d|%10.2f|%10.2f|%10.2f|%8.3f\n",
722                                          fluid_profile_data[i].description, /* code under profiling */
723                                          fluid_profile_data[i].n_voices / count, /* voices number */
724                                          fluid_profile_data[i].min,              /* minimum duration */
725                                          fluid_profile_data[i].total / count,    /* average duration */
726                                          fluid_profile_data[i].max,              /* maximum duration */
727                                          load);                                  /* cpu load */
728                 }
729                 else
730                 {
731                     /* note and release duration */
732                     fluid_ostream_printf(out, " %s|%6d|%10.0f|%10.0f|%10.0f|\n",
733                                          fluid_profile_data[i].description, /* code under profiling */
734                                          fluid_profile_data[i].n_voices / count,
735                                          fluid_profile_data[i].min,              /* minimum duration */
736                                          fluid_profile_data[i].total / count,    /* average duration */
737                                          fluid_profile_data[i].max);             /* maximum duration */
738                 }
739             }
740             else
741             {
742                 /* data aren't available */
743                 fluid_ostream_printf(out,
744                                      " %s| no profiling available\n", fluid_profile_data[i].description);
745             }
746         }
747     }
748
749     /* prints cpu loads only */
750     fluid_profiling_print_load(sample_rate, out);/* prints cpu loads */
751 }
752
753 /*
754  Returns true if the user cancels the current profiling measurement.
755  Actually this is implemented using the <ENTER> key. To add this functionality:
756  1) Adds #define FLUID_PROFILE_CANCEL in fluid_sys.h.
757  2) Adds the necessary code inside fluid_profile_is_cancel().
758
759  When FLUID_PROFILE_CANCEL is not defined, the function return FALSE.
760 */
761 int fluid_profile_is_cancel_req(void)
762 {
763 #ifdef FLUID_PROFILE_CANCEL
764
765 #if defined(WIN32)      /* Windows specific stuff */
766     /* Profile cancellation is supported for Windows */
767     /* returns TRUE if key <ENTER> is depressed */
768     return(GetAsyncKeyState(VK_RETURN) & 0x1);
769
770 #elif defined(__OS2__)  /* OS/2 specific stuff */
771     /* Profile cancellation isn't yet supported for OS2 */
772     /* For OS2, replaces the following  line with the function that returns
773     true when the keyboard key <ENTER> is depressed */
774     return FALSE; /* default value */
775
776 #else   /* POSIX stuff */
777     /* Profile cancellation is supported for Linux */
778     /* returns true is <ENTER> is depressed */
779     {
780         /* Here select() is used to poll the standard input to see if an input
781          is ready. As the standard input is usually buffered, the user
782          needs to depress <ENTER> to set the input to a "ready" state.
783         */
784         struct timeval tv;
785         fd_set fds;    /* just one fds need to be polled */
786         tv.tv_sec = 0; /* Setting both values to 0, means a 0 timeout */
787         tv.tv_usec = 0;
788         FD_ZERO(&fds); /* reset fds */
789         FD_SET(STDIN_FILENO, &fds); /* sets fds to poll standard input only */
790         select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv); /* polling */
791         return (FD_ISSET(0, &fds)); /* returns true if standard input is ready */
792     }
793 #endif /* OS stuff */
794
795 #else /* FLUID_PROFILE_CANCEL not defined */
796     return FALSE; /* default value */
797 #endif /* FLUID_PROFILE_CANCEL */
798 }
799
800 /**
801 * Returns status used in shell command "prof_start".
802 * The function is an internal profiling API between the "profile" command
803 * prof_start and audio rendering API (see FluidProfile_0004.pdf - 3.2.2).
804 *
805 * @return status
806 * - PROFILE_READY profiling data are ready.
807 * - PROFILE_RUNNING, profiling data are still under acquisition.
808 * - PROFILE_CANCELED, acquisition has been cancelled by the user.
809 * - PROFILE_STOP, no acquisition in progress.
810 *
811 * When status is PROFILE_RUNNING, the caller can do passive waiting, or other
812 * work before recalling the function later.
813 */
814 int fluid_profile_get_status(void)
815 {
816     /* Checks if user has requested to cancel the current measurement */
817     /* Cancellation must have precedence over other status */
818     if(fluid_profile_is_cancel_req())
819     {
820         fluid_profile_start_stop(0, 0); /* stops the measurement */
821         return PROFILE_CANCELED;
822     }
823
824     switch(fluid_profile_status)
825     {
826     case PROFILE_READY:
827         return PROFILE_READY; /* profiling data are ready */
828
829     case PROFILE_START:
830         return PROFILE_RUNNING;/* profiling data are under acquisition */
831
832     default:
833         return PROFILE_STOP;
834     }
835 }
836
837 /**
838 *  Starts or stops profiling measurement.
839 *  The function is an internal profiling API between the "profile" command
840 *  prof_start and audio rendering API (see FluidProfile_0004.pdf - 3.2.2).
841 *
842 *  @param end_tick end position of the measure (in ticks).
843 *  - If end_tick is greater then 0, the function starts a measure if a measure
844 *    isn't running. If a measure is already running, the function does nothing
845 *    and returns.
846 *  - If end_tick is 0, the function stops a measure.
847 *  @param clear_data,
848 *  - If clear_data is 0, the function clears fluid_profile_data before starting
849 *    a measure, otherwise, the data from the started measure will be accumulated
850 *    within fluid_profile_data.
851 */
852 void fluid_profile_start_stop(unsigned int end_ticks, short clear_data)
853 {
854     if(end_ticks)    /* This is a "start" request */
855     {
856         /* Checks if a measure is already running */
857         if(fluid_profile_status != PROFILE_START)
858         {
859             short i;
860             fluid_profile_end_ticks = end_ticks;
861
862             /* Clears profile data */
863             if(clear_data == 0)
864                 for(i = 0; i < FLUID_PROFILE_NBR; i++)
865                 {
866                     fluid_profile_data[i].min = 1e10;/* min sets to max value */
867                     fluid_profile_data[i].max = 0;   /* maximum sets to min value */
868                     fluid_profile_data[i].total = 0; /* total duration microsecond */
869                     fluid_profile_data[i].count = 0;    /* data count */
870                     fluid_profile_data[i].n_voices = 0; /* voices number */
871                     fluid_profile_data[i].n_samples = 0;/* audio samples number */
872                 }
873
874             fluid_profile_status = PROFILE_START;       /* starts profiling */
875         }
876
877         /* else do nothing when profiling is already started */
878     }
879     else /* This is a "stop" request */
880     {
881         /* forces the current running profile (if any) to stop */
882         fluid_profile_status = PROFILE_STOP;    /* stops profiling */
883     }
884 }
885
886 #endif /* WITH_PROFILING */
887
888 /***************************************************************
889  *
890  *               Threads
891  *
892  */
893
894 #if OLD_GLIB_THREAD_API
895
896 /* Rather than inline this one, we just declare it as a function, to prevent
897  * GCC warning about inline failure. */
898 fluid_cond_t *
899 new_fluid_cond(void)
900 {
901     if(!g_thread_supported())
902     {
903         g_thread_init(NULL);
904     }
905
906     return g_cond_new();
907 }
908
909 #endif
910
911 static gpointer
912 fluid_thread_high_prio(gpointer data)
913 {
914     fluid_thread_info_t *info = data;
915
916     fluid_thread_self_set_prio(info->prio_level);
917
918     info->func(info->data);
919     FLUID_FREE(info);
920
921     return NULL;
922 }
923
924 /**
925  * Create a new thread.
926  * @param func Function to execute in new thread context
927  * @param data User defined data to pass to func
928  * @param prio_level Priority level.  If greater than 0 then high priority scheduling will
929  *   be used, with the given priority level (used by pthreads only).  0 uses normal scheduling.
930  * @param detach If TRUE, 'join' does not work and the thread destroys itself when finished.
931  * @return New thread pointer or NULL on error
932  */
933 fluid_thread_t *
934 new_fluid_thread(const char *name, fluid_thread_func_t func, void *data, int prio_level, int detach)
935 {
936     GThread *thread;
937     fluid_thread_info_t *info = NULL;
938     GError *err = NULL;
939
940     g_return_val_if_fail(func != NULL, NULL);
941
942 #if OLD_GLIB_THREAD_API
943
944     /* Make sure g_thread_init has been called.
945      * FIXME - Probably not a good idea in a shared library,
946      * but what can we do *and* remain backwards compatible? */
947     if(!g_thread_supported())
948     {
949         g_thread_init(NULL);
950     }
951
952 #endif
953
954     if(prio_level > 0)
955     {
956         info = FLUID_NEW(fluid_thread_info_t);
957
958         if(!info)
959         {
960             FLUID_LOG(FLUID_ERR, "Out of memory");
961             return NULL;
962         }
963
964         info->func = func;
965         info->data = data;
966         info->prio_level = prio_level;
967 #if NEW_GLIB_THREAD_API
968         thread = g_thread_try_new(name, fluid_thread_high_prio, info, &err);
969 #else
970         thread = g_thread_create(fluid_thread_high_prio, info, detach == FALSE, &err);
971 #endif
972     }
973
974     else
975     {
976 #if NEW_GLIB_THREAD_API
977         thread = g_thread_try_new(name, (GThreadFunc)func, data, &err);
978 #else
979         thread = g_thread_create((GThreadFunc)func, data, detach == FALSE, &err);
980 #endif
981     }
982
983     if(!thread)
984     {
985         FLUID_LOG(FLUID_ERR, "Failed to create the thread: %s",
986                   fluid_gerror_message(err));
987         g_clear_error(&err);
988         FLUID_FREE(info);
989         return NULL;
990     }
991
992 #if NEW_GLIB_THREAD_API
993
994     if(detach)
995     {
996         g_thread_unref(thread);    // Release thread reference, if caller wants to detach
997     }
998
999 #endif
1000
1001     return thread;
1002 }
1003
1004 /**
1005  * Frees data associated with a thread (does not actually stop thread).
1006  * @param thread Thread to free
1007  */
1008 void
1009 delete_fluid_thread(fluid_thread_t *thread)
1010 {
1011     /* Threads free themselves when they quit, nothing to do */
1012 }
1013
1014 /**
1015  * Join a thread (wait for it to terminate).
1016  * @param thread Thread to join
1017  * @return FLUID_OK
1018  */
1019 int
1020 fluid_thread_join(fluid_thread_t *thread)
1021 {
1022     g_thread_join(thread);
1023
1024     return FLUID_OK;
1025 }
1026
1027
1028 static fluid_thread_return_t
1029 fluid_timer_run(void *data)
1030 {
1031     fluid_timer_t *timer;
1032     int count = 0;
1033     int cont;
1034     long start;
1035     long delay;
1036
1037     timer = (fluid_timer_t *)data;
1038
1039     /* keep track of the start time for absolute positioning */
1040     start = fluid_curtime();
1041
1042     while(timer->cont)
1043     {
1044         cont = (*timer->callback)(timer->data, fluid_curtime() - start);
1045
1046         count++;
1047
1048         if(!cont)
1049         {
1050             break;
1051         }
1052
1053         /* to avoid incremental time errors, calculate the delay between
1054            two callbacks bringing in the "absolute" time (count *
1055            timer->msec) */
1056         delay = (count * timer->msec) - (fluid_curtime() - start);
1057
1058         if(delay > 0)
1059         {
1060             fluid_msleep(delay);
1061         }
1062     }
1063
1064     FLUID_LOG(FLUID_DBG, "Timer thread finished");
1065
1066     if(timer->auto_destroy)
1067     {
1068         FLUID_FREE(timer);
1069     }
1070
1071     return FLUID_THREAD_RETURN_VALUE;
1072 }
1073
1074 fluid_timer_t *
1075 new_fluid_timer(int msec, fluid_timer_callback_t callback, void *data,
1076                 int new_thread, int auto_destroy, int high_priority)
1077 {
1078     fluid_timer_t *timer;
1079
1080     timer = FLUID_NEW(fluid_timer_t);
1081
1082     if(timer == NULL)
1083     {
1084         FLUID_LOG(FLUID_ERR, "Out of memory");
1085         return NULL;
1086     }
1087
1088     timer->msec = msec;
1089     timer->callback = callback;
1090     timer->data = data;
1091     timer->cont = TRUE ;
1092     timer->thread = NULL;
1093     timer->auto_destroy = auto_destroy;
1094
1095     if(new_thread)
1096     {
1097         timer->thread = new_fluid_thread("timer", fluid_timer_run, timer, high_priority
1098                                          ? FLUID_SYS_TIMER_HIGH_PRIO_LEVEL : 0, FALSE);
1099
1100         if(!timer->thread)
1101         {
1102             FLUID_FREE(timer);
1103             return NULL;
1104         }
1105     }
1106     else
1107     {
1108         fluid_timer_run(timer);   /* Run directly, instead of as a separate thread */
1109
1110         if(auto_destroy)
1111         {
1112             /* do NOT return freed memory */
1113             return NULL;
1114         }
1115     }
1116
1117     return timer;
1118 }
1119
1120 void
1121 delete_fluid_timer(fluid_timer_t *timer)
1122 {
1123     int auto_destroy;
1124     fluid_return_if_fail(timer != NULL);
1125
1126     auto_destroy = timer->auto_destroy;
1127
1128     timer->cont = 0;
1129     fluid_timer_join(timer);
1130
1131     /* Shouldn't access timer now if auto_destroy enabled, since it has been destroyed */
1132
1133     if(!auto_destroy)
1134     {
1135         FLUID_FREE(timer);
1136     }
1137 }
1138
1139 int
1140 fluid_timer_join(fluid_timer_t *timer)
1141 {
1142     int auto_destroy;
1143
1144     if(timer->thread)
1145     {
1146         auto_destroy = timer->auto_destroy;
1147         fluid_thread_join(timer->thread);
1148
1149         if(!auto_destroy)
1150         {
1151             timer->thread = NULL;
1152         }
1153     }
1154
1155     return FLUID_OK;
1156 }
1157
1158
1159 /***************************************************************
1160  *
1161  *               Sockets and I/O
1162  *
1163  */
1164
1165 /**
1166  * Get standard in stream handle.
1167  * @return Standard in stream.
1168  */
1169 fluid_istream_t
1170 fluid_get_stdin(void)
1171 {
1172     return STDIN_FILENO;
1173 }
1174
1175 /**
1176  * Get standard output stream handle.
1177  * @return Standard out stream.
1178  */
1179 fluid_ostream_t
1180 fluid_get_stdout(void)
1181 {
1182     return STDOUT_FILENO;
1183 }
1184
1185 /**
1186  * Read a line from an input stream.
1187  * @return 0 if end-of-stream, -1 if error, non zero otherwise
1188  */
1189 int
1190 fluid_istream_readline(fluid_istream_t in, fluid_ostream_t out, char *prompt,
1191                        char *buf, int len)
1192 {
1193 #if WITH_READLINE
1194
1195     if(in == fluid_get_stdin())
1196     {
1197         char *line;
1198
1199         line = readline(prompt);
1200
1201         if(line == NULL)
1202         {
1203             return -1;
1204         }
1205
1206         FLUID_SNPRINTF(buf, len, "%s", line);
1207         buf[len - 1] = 0;
1208
1209         if(buf[0] != '\0')
1210         {
1211             add_history(buf);
1212         }
1213
1214         free(line);
1215         return 1;
1216     }
1217     else
1218 #endif
1219     {
1220         fluid_ostream_printf(out, "%s", prompt);
1221         return fluid_istream_gets(in, buf, len);
1222     }
1223 }
1224
1225 /**
1226  * Reads a line from an input stream (socket).
1227  * @param in The input socket
1228  * @param buf Buffer to store data to
1229  * @param len Maximum length to store to buf
1230  * @return 1 if a line was read, 0 on end of stream, -1 on error
1231  */
1232 static int
1233 fluid_istream_gets(fluid_istream_t in, char *buf, int len)
1234 {
1235     char c;
1236     int n;
1237
1238     buf[len - 1] = 0;
1239
1240     while(--len > 0)
1241     {
1242 #ifndef WIN32
1243         n = read(in, &c, 1);
1244
1245         if(n == -1)
1246         {
1247             return -1;
1248         }
1249
1250 #else
1251
1252         /* Handle read differently depending on if its a socket or file descriptor */
1253         if(!(in & FLUID_SOCKET_FLAG))
1254         {
1255             // usually read() is supposed to return '\n' as last valid character of the user input
1256             // when compiled with compatibility for WinXP however, read() may return 0 (EOF) rather than '\n'
1257             // this would cause the shell to exit early
1258             n = read(in, &c, 1);
1259
1260             if(n == -1)
1261             {
1262                 return -1;
1263             }
1264         }
1265         else
1266         {
1267 #ifdef NETWORK_SUPPORT
1268             n = recv(in & ~FLUID_SOCKET_FLAG, &c, 1, 0);
1269             if(n == SOCKET_ERROR)
1270 #endif
1271             {
1272                 return -1;
1273             }
1274         }
1275
1276 #endif
1277
1278         if(n == 0)
1279         {
1280             *buf = 0;
1281             // return 1 if read from stdin, else 0, to fix early exit of shell
1282             return (in == STDIN_FILENO);
1283         }
1284
1285         if(c == '\n')
1286         {
1287             *buf = 0;
1288             return 1;
1289         }
1290
1291         /* Store all characters excluding CR */
1292         if(c != '\r')
1293         {
1294             *buf++ = c;
1295         }
1296     }
1297
1298     return -1;
1299 }
1300
1301 /**
1302  * Send a printf style string with arguments to an output stream (socket).
1303  * @param out Output stream
1304  * @param format printf style format string
1305  * @param ... Arguments for the printf format string
1306  * @return Number of bytes written or -1 on error
1307  */
1308 int
1309 fluid_ostream_printf(fluid_ostream_t out, const char *format, ...)
1310 {
1311     char buf[4096];
1312     va_list args;
1313     int len;
1314
1315     va_start(args, format);
1316     len = FLUID_VSNPRINTF(buf, 4095, format, args);
1317     va_end(args);
1318
1319     if(len == 0)
1320     {
1321         return 0;
1322     }
1323
1324     if(len < 0)
1325     {
1326         printf("fluid_ostream_printf: buffer overflow");
1327         return -1;
1328     }
1329
1330     buf[4095] = 0;
1331
1332 #ifndef WIN32
1333     return write(out, buf, FLUID_STRLEN(buf));
1334 #else
1335     {
1336         int retval;
1337
1338         /* Handle write differently depending on if its a socket or file descriptor */
1339         if(!(out & FLUID_SOCKET_FLAG))
1340         {
1341             return write(out, buf, (unsigned int)FLUID_STRLEN(buf));
1342         }
1343
1344 #ifdef NETWORK_SUPPORT
1345         /* Socket */
1346         retval = send(out & ~FLUID_SOCKET_FLAG, buf, (int)FLUID_STRLEN(buf), 0);
1347         return retval != SOCKET_ERROR ? retval : -1;
1348 #else
1349         return -1;
1350 #endif
1351     }
1352 #endif
1353 }
1354
1355 #ifdef NETWORK_SUPPORT
1356
1357 int fluid_server_socket_join(fluid_server_socket_t *server_socket)
1358 {
1359     return fluid_thread_join(server_socket->thread);
1360 }
1361
1362 static int fluid_socket_init(void)
1363 {
1364 #ifdef _WIN32
1365     WSADATA wsaData;
1366     int res = WSAStartup(MAKEWORD(2, 2), &wsaData);
1367
1368     if(res != 0)
1369     {
1370         FLUID_LOG(FLUID_ERR, "Server socket creation error: WSAStartup failed: %d", res);
1371         return FLUID_FAILED;
1372     }
1373
1374 #endif
1375
1376     return FLUID_OK;
1377 }
1378
1379 static void fluid_socket_cleanup(void)
1380 {
1381 #ifdef _WIN32
1382     WSACleanup();
1383 #endif
1384 }
1385
1386 static int fluid_socket_get_error(void)
1387 {
1388 #ifdef _WIN32
1389     return (int)WSAGetLastError();
1390 #else
1391     return errno;
1392 #endif
1393 }
1394
1395 fluid_istream_t fluid_socket_get_istream(fluid_socket_t sock)
1396 {
1397     return sock | FLUID_SOCKET_FLAG;
1398 }
1399
1400 fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock)
1401 {
1402     return sock | FLUID_SOCKET_FLAG;
1403 }
1404
1405 void fluid_socket_close(fluid_socket_t sock)
1406 {
1407     if(sock != INVALID_SOCKET)
1408     {
1409 #ifdef _WIN32
1410         closesocket(sock);
1411
1412 #else
1413         close(sock);
1414 #endif
1415     }
1416 }
1417
1418 static fluid_thread_return_t fluid_server_socket_run(void *data)
1419 {
1420     fluid_server_socket_t *server_socket = (fluid_server_socket_t *)data;
1421     fluid_socket_t client_socket;
1422 #ifdef IPV6_SUPPORT
1423     struct sockaddr_in6 addr;
1424 #else
1425     struct sockaddr_in addr;
1426 #endif
1427
1428 #ifdef HAVE_INETNTOP
1429 #ifdef IPV6_SUPPORT
1430     char straddr[INET6_ADDRSTRLEN];
1431 #else
1432     char straddr[INET_ADDRSTRLEN];
1433 #endif /* IPV6_SUPPORT */
1434 #endif /* HAVE_INETNTOP */
1435
1436     socklen_t addrlen = sizeof(addr);
1437     int r;
1438     FLUID_MEMSET((char *)&addr, 0, sizeof(addr));
1439
1440     FLUID_LOG(FLUID_DBG, "Server listening for connections");
1441
1442     while(server_socket->cont)
1443     {
1444         client_socket = accept(server_socket->socket, (struct sockaddr *)&addr, &addrlen);
1445
1446         FLUID_LOG(FLUID_DBG, "New client connection");
1447
1448         if(client_socket == INVALID_SOCKET)
1449         {
1450             if(server_socket->cont)
1451             {
1452                 FLUID_LOG(FLUID_ERR, "Failed to accept connection: %ld", fluid_socket_get_error());
1453             }
1454
1455             server_socket->cont = 0;
1456             return FLUID_THREAD_RETURN_VALUE;
1457         }
1458         else
1459         {
1460 #ifdef HAVE_INETNTOP
1461
1462 #ifdef IPV6_SUPPORT
1463             inet_ntop(AF_INET6, &addr.sin6_addr, straddr, sizeof(straddr));
1464 #else
1465             inet_ntop(AF_INET, &addr.sin_addr, straddr, sizeof(straddr));
1466 #endif
1467
1468             r = server_socket->func(server_socket->data, client_socket,
1469                                     straddr);
1470 #else
1471             r = server_socket->func(server_socket->data, client_socket,
1472                                     inet_ntoa(addr.sin_addr));
1473 #endif
1474
1475             if(r != 0)
1476             {
1477                 fluid_socket_close(client_socket);
1478             }
1479         }
1480     }
1481
1482     FLUID_LOG(FLUID_DBG, "Server closing");
1483
1484     return FLUID_THREAD_RETURN_VALUE;
1485 }
1486
1487 fluid_server_socket_t *
1488 new_fluid_server_socket(int port, fluid_server_func_t func, void *data)
1489 {
1490     fluid_server_socket_t *server_socket;
1491 #ifdef IPV6_SUPPORT
1492     struct sockaddr_in6 addr;
1493 #else
1494     struct sockaddr_in addr;
1495 #endif
1496
1497     fluid_socket_t sock;
1498
1499     fluid_return_val_if_fail(func != NULL, NULL);
1500
1501     if(fluid_socket_init() != FLUID_OK)
1502     {
1503         return NULL;
1504     }
1505
1506 #ifdef IPV6_SUPPORT
1507     sock = socket(AF_INET6, SOCK_STREAM, 0);
1508
1509     if(sock == INVALID_SOCKET)
1510     {
1511         FLUID_LOG(FLUID_ERR, "Failed to create server socket: %ld", fluid_socket_get_error());
1512         fluid_socket_cleanup();
1513         return NULL;
1514     }
1515
1516     FLUID_MEMSET(&addr, 0, sizeof(addr));
1517     addr.sin6_family = AF_INET6;
1518     addr.sin6_port = htons((uint16_t)port);
1519     addr.sin6_addr = in6addr_any;
1520 #else
1521
1522     sock = socket(AF_INET, SOCK_STREAM, 0);
1523
1524     if(sock == INVALID_SOCKET)
1525     {
1526         FLUID_LOG(FLUID_ERR, "Failed to create server socket: %ld", fluid_socket_get_error());
1527         fluid_socket_cleanup();
1528         return NULL;
1529     }
1530
1531     FLUID_MEMSET(&addr, 0, sizeof(addr));
1532     addr.sin_family = AF_INET;
1533     addr.sin_port = htons((uint16_t)port);
1534     addr.sin_addr.s_addr = htonl(INADDR_ANY);
1535 #endif
1536
1537     if(bind(sock, (const struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR)
1538     {
1539         FLUID_LOG(FLUID_ERR, "Failed to bind server socket: %ld", fluid_socket_get_error());
1540         fluid_socket_close(sock);
1541         fluid_socket_cleanup();
1542         return NULL;
1543     }
1544
1545     if(listen(sock, SOMAXCONN) == SOCKET_ERROR)
1546     {
1547         FLUID_LOG(FLUID_ERR, "Failed to listen on server socket: %ld", fluid_socket_get_error());
1548         fluid_socket_close(sock);
1549         fluid_socket_cleanup();
1550         return NULL;
1551     }
1552
1553     server_socket = FLUID_NEW(fluid_server_socket_t);
1554
1555     if(server_socket == NULL)
1556     {
1557         FLUID_LOG(FLUID_ERR, "Out of memory");
1558         fluid_socket_close(sock);
1559         fluid_socket_cleanup();
1560         return NULL;
1561     }
1562
1563     server_socket->socket = sock;
1564     server_socket->func = func;
1565     server_socket->data = data;
1566     server_socket->cont = 1;
1567
1568     server_socket->thread = new_fluid_thread("server", fluid_server_socket_run, server_socket,
1569                             0, FALSE);
1570
1571     if(server_socket->thread == NULL)
1572     {
1573         FLUID_FREE(server_socket);
1574         fluid_socket_close(sock);
1575         fluid_socket_cleanup();
1576         return NULL;
1577     }
1578
1579     return server_socket;
1580 }
1581
1582 void delete_fluid_server_socket(fluid_server_socket_t *server_socket)
1583 {
1584     fluid_return_if_fail(server_socket != NULL);
1585
1586     server_socket->cont = 0;
1587
1588     if(server_socket->socket != INVALID_SOCKET)
1589     {
1590         fluid_socket_close(server_socket->socket);
1591     }
1592
1593     if(server_socket->thread)
1594     {
1595         fluid_thread_join(server_socket->thread);
1596         delete_fluid_thread(server_socket->thread);
1597     }
1598
1599     FLUID_FREE(server_socket);
1600
1601     // Should be called the same number of times as fluid_socket_init()
1602     fluid_socket_cleanup();
1603 }
1604
1605 #endif // NETWORK_SUPPORT
1606
1607 FILE* fluid_file_open(const char* path, const char** errMsg)
1608 {
1609     static const char ErrExist[] = "File does not exist.";
1610     static const char ErrRegular[] = "File is not regular, refusing to open it.";
1611     static const char ErrNull[] = "File does not exists or insufficient permissions to open it.";
1612     
1613     FILE* handle = NULL;
1614     
1615     if(!g_file_test(path, G_FILE_TEST_EXISTS))
1616     {
1617         if(errMsg != NULL)
1618         {
1619             *errMsg = ErrExist;
1620         }
1621     }
1622     else if(!g_file_test(path, G_FILE_TEST_IS_REGULAR))
1623     {
1624         if(errMsg != NULL)
1625         {
1626             *errMsg = ErrRegular;
1627         }
1628     }
1629     else if((handle = FLUID_FOPEN(path, "rb")) == NULL)
1630     {
1631         if(errMsg != NULL)
1632         {
1633             *errMsg = ErrNull;
1634         }
1635     }
1636     
1637     return handle;
1638 }