Import libfluidsynth into the Ardour codebase
[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 Library General Public License
7  * as published by the Free Software Foundation; either version 2 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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library 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 /* WIN32 HACK - Flag used to differentiate between a file descriptor and a socket.
34  * Should work, so long as no SOCKET or file descriptor ends up with this bit set. - JG */
35 #define WIN32_SOCKET_FLAG       0x40000000
36
37 /* SCHED_FIFO priority for high priority timer threads */
38 #define FLUID_SYS_TIMER_HIGH_PRIO_LEVEL         10
39
40
41 typedef struct
42 {
43   fluid_thread_func_t func;
44   void *data;
45   int prio_level;
46 } fluid_thread_info_t;
47
48 struct _fluid_timer_t
49 {
50   long msec;
51   fluid_timer_callback_t callback;
52   void *data;
53   fluid_thread_t *thread;
54   int cont;
55   int auto_destroy;
56 };
57
58 struct _fluid_server_socket_t
59 {
60   fluid_socket_t socket;
61   fluid_thread_t *thread;
62   int cont;
63   fluid_server_func_t func;
64   void *data;
65 };
66
67
68 static int fluid_istream_gets(fluid_istream_t in, char* buf, int len);
69
70
71 static char fluid_errbuf[512];  /* buffer for error message */
72
73 static fluid_log_function_t fluid_log_function[LAST_LOG_LEVEL];
74 static void* fluid_log_user_data[LAST_LOG_LEVEL];
75 static int fluid_log_initialized = 0;
76
77 static char* fluid_libname = "fluidsynth";
78
79
80 void fluid_sys_config()
81 {
82   fluid_log_config();
83 }
84
85
86 unsigned int fluid_debug_flags = 0;
87
88 #if DEBUG
89 /*
90  * fluid_debug
91  */
92 int fluid_debug(int level, char * fmt, ...)
93 {
94   if (fluid_debug_flags & level) {
95     fluid_log_function_t fun;
96     va_list args;
97
98     va_start (args, fmt);
99     vsnprintf(fluid_errbuf, sizeof (fluid_errbuf), fmt, args);
100     va_end (args);
101
102     fun = fluid_log_function[FLUID_DBG];
103     if (fun != NULL) {
104       (*fun)(level, fluid_errbuf, fluid_log_user_data[FLUID_DBG]);
105     }
106   }
107   return 0;
108 }
109 #endif
110
111 /**
112  * Installs a new log function for a specified log level.
113  * @param level Log level to install handler for.
114  * @param fun Callback function handler to call for logged messages
115  * @param data User supplied data pointer to pass to log function
116  * @return The previously installed function.
117  */
118 fluid_log_function_t
119 fluid_set_log_function(int level, fluid_log_function_t fun, void* data)
120 {
121   fluid_log_function_t old = NULL;
122
123   if ((level >= 0) && (level < LAST_LOG_LEVEL)) {
124     old = fluid_log_function[level];
125     fluid_log_function[level] = fun;
126     fluid_log_user_data[level] = data;
127   }
128   return old;
129 }
130
131 /**
132  * Default log function which prints to the stderr.
133  * @param level Log level
134  * @param message Log message
135  * @param data User supplied data (not used)
136  */
137 void
138 fluid_default_log_function(int level, char* message, void* data)
139 {
140   FILE* out;
141
142 #if defined(WIN32)
143   out = stdout;
144 #else
145   out = stderr;
146 #endif
147
148   if (fluid_log_initialized == 0) {
149     fluid_log_config();
150   }
151
152   switch (level) {
153   case FLUID_PANIC:
154     FLUID_FPRINTF(out, "%s: panic: %s\n", fluid_libname, message);
155     break;
156   case FLUID_ERR:
157     FLUID_FPRINTF(out, "%s: error: %s\n", fluid_libname, message);
158     break;
159   case FLUID_WARN:
160     FLUID_FPRINTF(out, "%s: warning: %s\n", fluid_libname, message);
161     break;
162   case FLUID_INFO:
163     FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message);
164     break;
165   case FLUID_DBG:
166 #if DEBUG
167     FLUID_FPRINTF(out, "%s: debug: %s\n", fluid_libname, message);
168 #endif
169     break;
170   default:
171     FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message);
172     break;
173   }
174   fflush(out);
175 }
176
177 /*
178  * fluid_init_log
179  */
180 void
181 fluid_log_config(void)
182 {
183   if (fluid_log_initialized == 0) {
184
185     fluid_log_initialized = 1;
186
187     if (fluid_log_function[FLUID_PANIC] == NULL) {
188       fluid_set_log_function(FLUID_PANIC, fluid_default_log_function, NULL);
189     }
190
191     if (fluid_log_function[FLUID_ERR] == NULL) {
192       fluid_set_log_function(FLUID_ERR, fluid_default_log_function, NULL);
193     }
194
195     if (fluid_log_function[FLUID_WARN] == NULL) {
196       fluid_set_log_function(FLUID_WARN, fluid_default_log_function, NULL);
197     }
198
199     if (fluid_log_function[FLUID_INFO] == NULL) {
200       fluid_set_log_function(FLUID_INFO, fluid_default_log_function, NULL);
201     }
202
203     if (fluid_log_function[FLUID_DBG] == NULL) {
204       fluid_set_log_function(FLUID_DBG, fluid_default_log_function, NULL);
205     }
206   }
207 }
208
209 /**
210  * Print a message to the log.
211  * @param level Log level (#fluid_log_level).
212  * @param fmt Printf style format string for log message
213  * @param ... Arguments for printf 'fmt' message string
214  * @return Always returns #FLUID_FAILED
215  */
216 int
217 fluid_log(int level, const char* fmt, ...)
218 {
219   fluid_log_function_t fun = NULL;
220
221   va_list args;
222   va_start (args, fmt);
223   vsnprintf(fluid_errbuf, sizeof (fluid_errbuf), fmt, args);
224   va_end (args);
225
226   if ((level >= 0) && (level < LAST_LOG_LEVEL)) {
227     fun = fluid_log_function[level];
228     if (fun != NULL) {
229       (*fun)(level, fluid_errbuf, fluid_log_user_data[level]);
230     }
231   }
232   return FLUID_FAILED;
233 }
234
235 /**
236  * An improved strtok, still trashes the input string, but is portable and
237  * thread safe.  Also skips token chars at beginning of token string and never
238  * returns an empty token (will return NULL if source ends in token chars though).
239  * NOTE: NOT part of public API
240  * @internal
241  * @param str Pointer to a string pointer of source to tokenize.  Pointer gets
242  *   updated on each invocation to point to beginning of next token.  Note that
243  *   token char get's overwritten with a 0 byte.  String pointer is set to NULL
244  *   when final token is returned.
245  * @param delim String of delimiter chars.
246  * @return Pointer to the next token or NULL if no more tokens.
247  */
248 char *fluid_strtok (char **str, char *delim)
249 {
250   char *s, *d, *token;
251   char c;
252
253   if (str == NULL || delim == NULL || !*delim)
254   {
255     FLUID_LOG(FLUID_ERR, "Null pointer");
256     return NULL;
257   }
258
259   s = *str;
260   if (!s) return NULL;  /* str points to a NULL pointer? (tokenize already ended) */
261
262   /* skip delimiter chars at beginning of token */
263   do
264   {
265     c = *s;
266     if (!c)     /* end of source string? */
267     {
268       *str = NULL;
269       return NULL;
270     }
271
272     for (d = delim; *d; d++)    /* is source char a token char? */
273     {
274       if (c == *d)      /* token char match? */
275       {
276         s++;            /* advance to next source char */
277         break;
278       }
279     }
280   } while (*d);         /* while token char match */
281
282   token = s;            /* start of token found */
283
284   /* search for next token char or end of source string */
285   for (s = s+1; *s; s++)
286   {
287     c = *s;
288
289     for (d = delim; *d; d++)    /* is source char a token char? */
290     {
291       if (c == *d)      /* token char match? */
292       {
293         *s = '\0';      /* overwrite token char with zero byte to terminate token */
294         *str = s+1;     /* update str to point to beginning of next token */
295         return token;
296       }
297     }
298   }
299
300   /* we get here only if source string ended */
301   *str = NULL;
302   return token;
303 }
304
305 /*
306  * fluid_error
307  */
308 char*
309 fluid_error()
310 {
311   return fluid_errbuf;
312 }
313
314 /**
315  * Check if a file is a MIDI file.
316  * @param filename Path to the file to check
317  * @return TRUE if it could be a MIDI file, FALSE otherwise
318  *
319  * The current implementation only checks for the "MThd" header in the file.
320  * It is useful only to distinguish between SoundFont and MIDI files.
321  */
322 int
323 fluid_is_midifile(const char *filename)
324 {
325   FILE* fp = fopen(filename, "rb");
326   char id[4];
327
328   if (fp == NULL) {
329     return 0;
330   }
331   if (fread((void*) id, 1, 4, fp) != 4) {
332     fclose(fp);
333     return 0;
334   }
335   fclose(fp);
336
337   return strncmp(id, "MThd", 4) == 0;
338 }
339
340 /**
341  * Check if a file is a SoundFont file.
342  * @param filename Path to the file to check
343  * @return TRUE if it could be a SoundFont, FALSE otherwise
344  *
345  * The current implementation only checks for the "RIFF" header in the file.
346  * It is useful only to distinguish between SoundFont and MIDI files.
347  */
348 int
349 fluid_is_soundfont(const char *filename)
350 {
351   FILE* fp = fopen(filename, "rb");
352   char id[4];
353
354   if (fp == NULL) {
355     return 0;
356   }
357   if (fread((void*) id, 1, 4, fp) != 4) {
358     fclose(fp);
359     return 0;
360   }
361   fclose(fp);
362
363   return strncmp(id, "RIFF", 4) == 0;
364 }
365
366 /**
367  * Get time in milliseconds to be used in relative timing operations.
368  * @return Unix time in milliseconds.
369  */
370 unsigned int fluid_curtime(void)
371 {
372   static glong initial_seconds = 0;
373   GTimeVal timeval;
374
375   if (initial_seconds == 0) {
376     g_get_current_time (&timeval);
377     initial_seconds = timeval.tv_sec;
378   }
379
380   g_get_current_time (&timeval);
381
382   return (unsigned int)((timeval.tv_sec - initial_seconds) * 1000.0 + timeval.tv_usec / 1000.0);
383 }
384
385 /**
386  * Get time in microseconds to be used in relative timing operations.
387  * @return Unix time in microseconds.
388  */
389 double
390 fluid_utime (void)
391 {
392   GTimeVal timeval;
393
394   g_get_current_time (&timeval);
395
396   return (timeval.tv_sec * 1000000.0 + timeval.tv_usec);
397 }
398
399
400 #if defined(WIN32)      /* Windoze specific stuff */
401
402 void
403 fluid_thread_self_set_prio (int prio_level)
404 {
405   if (prio_level > 0)
406     SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
407 }
408
409
410 #elif defined(__OS2__)  /* OS/2 specific stuff */
411
412 void
413 fluid_thread_self_set_prio (int prio_level)
414 {
415   if (prio_level > 0)
416     DosSetPriority (PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MAXIMUM, 0);
417 }
418
419 #else   /* POSIX stuff..  Nice POSIX..  Good POSIX. */
420
421 void
422 fluid_thread_self_set_prio (int prio_level)
423 {
424   struct sched_param priority;
425
426   if (prio_level > 0)
427   {
428
429     memset(&priority, 0, sizeof(priority));
430     priority.sched_priority = prio_level;
431
432     if (pthread_setschedparam (pthread_self (), SCHED_FIFO, &priority) == 0) {
433       return;
434     }
435 #ifdef DBUS_SUPPORT
436 /* Try to gain high priority via rtkit */
437     
438     if (fluid_rtkit_make_realtime(0, prio_level) == 0) {
439       return;
440     }
441 #endif
442     FLUID_LOG(FLUID_WARN, "Failed to set thread to high priority");
443   }
444 }
445
446 #ifdef FPE_CHECK
447
448 /***************************************************************
449  *
450  *               Floating point exceptions
451  *
452  *  The floating point exception functions were taken from Ircam's
453  *  jMax source code. http://www.ircam.fr/jmax
454  *
455  *  FIXME: check in config for i386 machine
456  *
457  *  Currently not used. I leave the code here in case we want to pick
458  *  this up again some time later.
459  */
460
461 /* Exception flags */
462 #define _FPU_STATUS_IE    0x001  /* Invalid Operation */
463 #define _FPU_STATUS_DE    0x002  /* Denormalized Operand */
464 #define _FPU_STATUS_ZE    0x004  /* Zero Divide */
465 #define _FPU_STATUS_OE    0x008  /* Overflow */
466 #define _FPU_STATUS_UE    0x010  /* Underflow */
467 #define _FPU_STATUS_PE    0x020  /* Precision */
468 #define _FPU_STATUS_SF    0x040  /* Stack Fault */
469 #define _FPU_STATUS_ES    0x080  /* Error Summary Status */
470
471 /* Macros for accessing the FPU status word.  */
472
473 /* get the FPU status */
474 #define _FPU_GET_SW(sw) __asm__ ("fnstsw %0" : "=m" (*&sw))
475
476 /* clear the FPU status */
477 #define _FPU_CLR_SW() __asm__ ("fnclex" : : )
478
479 /* Purpose:
480  * Checks, if the floating point unit has produced an exception, print a message
481  * if so and clear the exception.
482  */
483 unsigned int fluid_check_fpe_i386(char* explanation)
484 {
485   unsigned int s;
486
487   _FPU_GET_SW(s);
488   _FPU_CLR_SW();
489
490   s &= _FPU_STATUS_IE | _FPU_STATUS_DE | _FPU_STATUS_ZE | _FPU_STATUS_OE | _FPU_STATUS_UE;
491
492   if (s)
493   {
494       FLUID_LOG(FLUID_WARN, "FPE exception (before or in %s): %s%s%s%s%s", explanation,
495                (s & _FPU_STATUS_IE) ? "Invalid operation " : "",
496                (s & _FPU_STATUS_DE) ? "Denormal number " : "",
497                (s & _FPU_STATUS_ZE) ? "Zero divide " : "",
498                (s & _FPU_STATUS_OE) ? "Overflow " : "",
499                (s & _FPU_STATUS_UE) ? "Underflow " : "");
500   }
501
502   return s;
503 }
504
505 /* Purpose:
506  * Clear floating point exception.
507  */
508 void fluid_clear_fpe_i386 (void)
509 {
510   _FPU_CLR_SW();
511 }
512
513 #endif  // ifdef FPE_CHECK
514
515
516 #endif  // #else    (its POSIX)
517
518
519 /***************************************************************
520  *
521  *               Profiling (Linux, i586 only)
522  *
523  */
524
525 #if WITH_PROFILING
526
527 fluid_profile_data_t fluid_profile_data[] =
528 {
529   { FLUID_PROF_WRITE,            "fluid_synth_write_*             ", 1e10, 0.0, 0.0, 0},
530   { FLUID_PROF_ONE_BLOCK,        "fluid_synth_one_block           ", 1e10, 0.0, 0.0, 0},
531   { FLUID_PROF_ONE_BLOCK_CLEAR,  "fluid_synth_one_block:clear     ", 1e10, 0.0, 0.0, 0},
532   { FLUID_PROF_ONE_BLOCK_VOICE,  "fluid_synth_one_block:one voice ", 1e10, 0.0, 0.0, 0},
533   { FLUID_PROF_ONE_BLOCK_VOICES, "fluid_synth_one_block:all voices", 1e10, 0.0, 0.0, 0},
534   { FLUID_PROF_ONE_BLOCK_REVERB, "fluid_synth_one_block:reverb    ", 1e10, 0.0, 0.0, 0},
535   { FLUID_PROF_ONE_BLOCK_CHORUS, "fluid_synth_one_block:chorus    ", 1e10, 0.0, 0.0, 0},
536   { FLUID_PROF_VOICE_NOTE,       "fluid_voice:note                ", 1e10, 0.0, 0.0, 0},
537   { FLUID_PROF_VOICE_RELEASE,    "fluid_voice:release             ", 1e10, 0.0, 0.0, 0},
538   { FLUID_PROF_LAST, "last", 1e100, 0.0, 0.0, 0}
539 };
540
541
542 void fluid_profiling_print(void)
543 {
544   int i;
545
546   printf("fluid_profiling_print\n");
547
548   FLUID_LOG(FLUID_INFO, "Estimated times: min/avg/max (micro seconds)");
549
550   for (i = 0; i < FLUID_PROF_LAST; i++) {
551     if (fluid_profile_data[i].count > 0) {
552       FLUID_LOG(FLUID_INFO, "%s: %.3f/%.3f/%.3f",
553                fluid_profile_data[i].description,
554                fluid_profile_data[i].min,
555                fluid_profile_data[i].total / fluid_profile_data[i].count,
556                fluid_profile_data[i].max);
557     } else {
558       FLUID_LOG(FLUID_DBG, "%s: no profiling available", fluid_profile_data[i].description);
559     }
560   }
561 }
562
563
564 #endif /* WITH_PROFILING */
565
566
567
568 /***************************************************************
569  *
570  *               Threads
571  *
572  */
573
574 #if OLD_GLIB_THREAD_API
575
576 /* Rather than inline this one, we just declare it as a function, to prevent
577  * GCC warning about inline failure. */
578 fluid_cond_t *
579 new_fluid_cond (void)
580 {
581   if (!g_thread_supported ()) g_thread_init (NULL);
582   return g_cond_new ();
583 }
584
585 #endif
586
587 static gpointer
588 fluid_thread_high_prio (gpointer data)
589 {
590   fluid_thread_info_t *info = data;
591
592   fluid_thread_self_set_prio (info->prio_level);
593
594   info->func (info->data);
595   FLUID_FREE (info);
596
597   return NULL;
598 }
599
600 /**
601  * Create a new thread.
602  * @param func Function to execute in new thread context
603  * @param data User defined data to pass to func
604  * @param prio_level Priority level.  If greater than 0 then high priority scheduling will
605  *   be used, with the given priority level (used by pthreads only).  0 uses normal scheduling.
606  * @param detach If TRUE, 'join' does not work and the thread destroys itself when finished.
607  * @return New thread pointer or NULL on error
608  */
609 fluid_thread_t *
610 new_fluid_thread (const char *name, fluid_thread_func_t func, void *data, int prio_level, int detach)
611 {
612   GThread *thread;
613   fluid_thread_info_t *info;
614   GError *err = NULL;
615
616   g_return_val_if_fail (func != NULL, NULL);
617
618 #if OLD_GLIB_THREAD_API
619   /* Make sure g_thread_init has been called.
620    * FIXME - Probably not a good idea in a shared library,
621    * but what can we do *and* remain backwards compatible? */
622   if (!g_thread_supported ()) g_thread_init (NULL);
623 #endif
624
625   if (prio_level > 0)
626   {
627     info = FLUID_NEW (fluid_thread_info_t);
628
629     if (!info)
630     {
631       FLUID_LOG(FLUID_ERR, "Out of memory");
632       return NULL;
633     }
634
635     info->func = func;
636     info->data = data;
637     info->prio_level = prio_level;
638 #if NEW_GLIB_THREAD_API
639     thread = g_thread_try_new (name, fluid_thread_high_prio, info, &err);
640 #else
641     thread = g_thread_create (fluid_thread_high_prio, info, detach == FALSE, &err);
642 #endif
643   }
644 #if NEW_GLIB_THREAD_API
645   else thread = g_thread_try_new (name, (GThreadFunc)func, data, &err);
646 #else
647   else thread = g_thread_create ((GThreadFunc)func, data, detach == FALSE, &err);
648 #endif
649
650   if (!thread)
651   {
652     FLUID_LOG(FLUID_ERR, "Failed to create the thread: %s",
653               fluid_gerror_message (err));
654     g_clear_error (&err);
655     return NULL;
656   }
657
658 #if NEW_GLIB_THREAD_API
659   if (detach) g_thread_unref (thread);  // Release thread reference, if caller wants to detach
660 #endif
661
662   return thread;
663 }
664
665 /**
666  * Frees data associated with a thread (does not actually stop thread).
667  * @param thread Thread to free
668  */
669 void
670 delete_fluid_thread(fluid_thread_t* thread)
671 {
672   /* Threads free themselves when they quit, nothing to do */
673 }
674
675 /**
676  * Join a thread (wait for it to terminate).
677  * @param thread Thread to join
678  * @return FLUID_OK
679  */
680 int
681 fluid_thread_join(fluid_thread_t* thread)
682 {
683   g_thread_join (thread);
684
685   return FLUID_OK;
686 }
687
688
689 static void
690 fluid_timer_run (void *data)
691 {
692   fluid_timer_t *timer;
693   int count = 0;
694   int cont;
695   long start;
696   long delay;
697
698   timer = (fluid_timer_t *)data;
699
700   /* keep track of the start time for absolute positioning */
701   start = fluid_curtime ();
702
703   while (timer->cont)
704   {
705     cont = (*timer->callback)(timer->data, fluid_curtime() - start);
706
707     count++;
708     if (!cont) break;
709
710     /* to avoid incremental time errors, calculate the delay between
711        two callbacks bringing in the "absolute" time (count *
712        timer->msec) */
713     delay = (count * timer->msec) - (fluid_curtime() - start);
714     if (delay > 0) g_usleep (delay * 1000);
715   }
716
717   FLUID_LOG (FLUID_DBG, "Timer thread finished");
718
719   if (timer->auto_destroy)
720     FLUID_FREE (timer);
721
722   return;
723 }
724
725 fluid_timer_t*
726 new_fluid_timer (int msec, fluid_timer_callback_t callback, void* data,
727                  int new_thread, int auto_destroy, int high_priority)
728 {
729   fluid_timer_t *timer;
730
731   timer = FLUID_NEW (fluid_timer_t);
732
733   if (timer == NULL)
734   {
735     FLUID_LOG (FLUID_ERR, "Out of memory");
736     return NULL;
737   }
738
739   timer->msec = msec;
740   timer->callback = callback;
741   timer->data = data;
742   timer->cont = TRUE ;
743   timer->thread = NULL;
744   timer->auto_destroy = auto_destroy;
745
746   if (new_thread)
747   {
748     timer->thread = new_fluid_thread ("timer", fluid_timer_run, timer, high_priority
749                                       ? FLUID_SYS_TIMER_HIGH_PRIO_LEVEL : 0, FALSE);
750     if (!timer->thread)
751     {
752       FLUID_FREE (timer);
753       return NULL;
754     }
755   }
756   else fluid_timer_run (timer);  /* Run directly, instead of as a separate thread */
757
758   return timer;
759 }
760
761 int
762 delete_fluid_timer (fluid_timer_t *timer)
763 {
764   int auto_destroy = timer->auto_destroy;
765
766   timer->cont = 0;
767   fluid_timer_join (timer);
768
769   /* Shouldn't access timer now if auto_destroy enabled, since it has been destroyed */
770
771   if (!auto_destroy) FLUID_FREE (timer);
772
773   return FLUID_OK;
774 }
775
776 int
777 fluid_timer_join (fluid_timer_t *timer)
778 {
779   int auto_destroy;
780
781   if (timer->thread)
782   {
783     auto_destroy = timer->auto_destroy;
784     fluid_thread_join (timer->thread);
785
786     if (!auto_destroy) timer->thread = NULL;
787   }
788
789   return FLUID_OK;
790 }
791
792
793 /***************************************************************
794  *
795  *               Sockets and I/O
796  *
797  */
798
799 /**
800  * Get standard in stream handle.
801  * @return Standard in stream.
802  */
803 fluid_istream_t
804 fluid_get_stdin (void)
805 {
806   return STDIN_FILENO;
807 }
808
809 /**
810  * Get standard output stream handle.
811  * @return Standard out stream.
812  */
813 fluid_ostream_t
814 fluid_get_stdout (void)
815 {
816   return STDOUT_FILENO;
817 }
818
819 /**
820  * Read a line from an input stream.
821  * @return 0 if end-of-stream, -1 if error, non zero otherwise
822  */
823 int
824 fluid_istream_readline (fluid_istream_t in, fluid_ostream_t out, char* prompt,
825                         char* buf, int len)
826 {
827 #if WITH_READLINE
828   if (in == fluid_get_stdin ())
829   {
830     char *line;
831
832     line = readline (prompt);
833
834     if (line == NULL)
835       return -1;
836
837     snprintf(buf, len, "%s", line);
838     buf[len - 1] = 0;
839
840     free(line);
841     return 1;
842   }
843   else
844 #endif
845   {
846     fluid_ostream_printf (out, "%s", prompt);
847     return fluid_istream_gets (in, buf, len);
848   }
849 }
850
851 /**
852  * Reads a line from an input stream (socket).
853  * @param in The input socket
854  * @param buf Buffer to store data to
855  * @param len Maximum length to store to buf
856  * @return 1 if a line was read, 0 on end of stream, -1 on error
857  */
858 static int
859 fluid_istream_gets (fluid_istream_t in, char* buf, int len)
860 {
861   char c;
862   int n;
863
864   buf[len - 1] = 0;
865
866   while (--len > 0)
867   {
868 #ifndef WIN32
869     n = read(in, &c, 1);
870     if (n == -1) return -1;
871 #else
872     /* Handle read differently depending on if its a socket or file descriptor */
873     if (!(in & WIN32_SOCKET_FLAG))
874     {
875       n = read(in, &c, 1);
876       if (n == -1) return -1;
877     }
878     else
879     {
880       n = recv(in & ~WIN32_SOCKET_FLAG, &c, 1, 0);
881       if (n == SOCKET_ERROR) return -1;
882     }
883 #endif
884
885     if (n == 0)
886     {
887       *buf++ = 0;
888       return 0;
889     }
890
891     if ((c == '\n'))
892     {
893       *buf++ = 0;
894       return 1;
895     }
896
897     /* Store all characters excluding CR */
898     if (c != '\r') *buf++ = c;
899   }
900
901   return -1;
902 }
903
904 /**
905  * Send a printf style string with arguments to an output stream (socket).
906  * @param out Output stream
907  * @param format printf style format string
908  * @param ... Arguments for the printf format string
909  * @return Number of bytes written or -1 on error
910  */
911 int
912 fluid_ostream_printf (fluid_ostream_t out, char* format, ...)
913 {
914   char buf[4096];
915   va_list args;
916   int len;
917
918   va_start (args, format);
919   len = vsnprintf (buf, 4095, format, args);
920   va_end (args);
921
922   if (len == 0)
923   {
924     return 0;
925   }
926
927   if (len < 0)
928   {
929     printf("fluid_ostream_printf: buffer overflow");
930     return -1;
931   }
932
933   buf[4095] = 0;
934
935 #ifndef WIN32
936   return write (out, buf, strlen (buf));
937 #else
938   {
939     int retval;
940
941     /* Handle write differently depending on if its a socket or file descriptor */
942     if (!(out & WIN32_SOCKET_FLAG))
943       return write(out, buf, strlen (buf));
944
945     /* Socket */
946     retval = send (out & ~WIN32_SOCKET_FLAG, buf, strlen (buf), 0);
947
948     return retval != SOCKET_ERROR ? retval : -1;
949   }
950 #endif
951 }
952
953 int fluid_server_socket_join(fluid_server_socket_t *server_socket)
954 {
955   return fluid_thread_join (server_socket->thread);
956 }
957
958
959 #ifndef WIN32           // Not win32?
960
961 #define SOCKET_ERROR -1
962
963 fluid_istream_t fluid_socket_get_istream (fluid_socket_t sock)
964 {
965   return sock;
966 }
967
968 fluid_ostream_t fluid_socket_get_ostream (fluid_socket_t sock)
969 {
970   return sock;
971 }
972
973 void fluid_socket_close(fluid_socket_t sock)
974 {
975   if (sock != INVALID_SOCKET)
976     close (sock);
977 }
978
979 static void
980 fluid_server_socket_run (void *data)
981 {
982   fluid_server_socket_t *server_socket = (fluid_server_socket_t *)data;
983   fluid_socket_t client_socket;
984 #ifdef IPV6
985   struct sockaddr_in6 addr;
986   char straddr[INET6_ADDRSTRLEN];
987 #else
988   struct sockaddr_in addr;
989   char straddr[INET_ADDRSTRLEN];
990 #endif
991   socklen_t addrlen = sizeof (addr);
992   int retval;
993   FLUID_MEMSET((char *)&addr, 0, sizeof(addr));
994
995   FLUID_LOG (FLUID_DBG, "Server listening for connections");
996
997   while (server_socket->cont)
998   {
999     client_socket = accept (server_socket->socket, (struct sockaddr *)&addr, &addrlen);
1000
1001     FLUID_LOG (FLUID_DBG, "New client connection");
1002
1003     if (client_socket == INVALID_SOCKET)
1004     {
1005       if (server_socket->cont)
1006         FLUID_LOG(FLUID_ERR, "Failed to accept connection");
1007
1008       server_socket->cont = 0;
1009       return;
1010     } else {
1011 #ifdef IPV6
1012       inet_ntop(AF_INET6, &addr.sin6_addr, straddr, sizeof(straddr));
1013 #else
1014       inet_ntop(AF_INET, &addr.sin_addr, straddr, sizeof(straddr));
1015 #endif
1016       retval = server_socket->func (server_socket->data, client_socket,
1017                                     straddr);
1018
1019       if (retval != 0)
1020         fluid_socket_close(client_socket);
1021     }
1022   }
1023
1024   FLUID_LOG(FLUID_DBG, "Server closing");
1025 }
1026
1027 fluid_server_socket_t*
1028 new_fluid_server_socket(int port, fluid_server_func_t func, void* data)
1029 {
1030   fluid_server_socket_t* server_socket;
1031 #ifdef IPV6
1032   struct sockaddr_in6 addr;
1033 #else
1034   struct sockaddr_in addr;
1035 #endif
1036   fluid_socket_t sock;
1037
1038   g_return_val_if_fail (func != NULL, NULL);
1039 #ifdef IPV6
1040   sock = socket(AF_INET6, SOCK_STREAM, 0);
1041   if (sock == INVALID_SOCKET) {
1042     FLUID_LOG(FLUID_ERR, "Failed to create server socket");
1043     return NULL;
1044   }
1045
1046   FLUID_MEMSET((char *)&addr, 0, sizeof(struct sockaddr_in6));
1047   addr.sin6_family = AF_INET6;
1048   addr.sin6_addr = in6addr_any;
1049   addr.sin6_port = htons(port);
1050 #else
1051
1052   sock = socket(AF_INET, SOCK_STREAM, 0);
1053   if (sock == INVALID_SOCKET) {
1054     FLUID_LOG(FLUID_ERR, "Failed to create server socket");
1055     return NULL;
1056   }
1057
1058   FLUID_MEMSET((char *)&addr, 0, sizeof(struct sockaddr_in));
1059   addr.sin_family = AF_INET;
1060   addr.sin_addr.s_addr = htonl(INADDR_ANY);
1061   addr.sin_port = htons(port);
1062 #endif
1063   if (bind(sock, (const struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR) {
1064     FLUID_LOG(FLUID_ERR, "Failed to bind server socket");
1065     fluid_socket_close(sock);
1066     return NULL;
1067   }
1068
1069   if (listen(sock, 10) == SOCKET_ERROR) {
1070     FLUID_LOG(FLUID_ERR, "Failed listen on server socket");
1071     fluid_socket_close(sock);
1072     return NULL;
1073   }
1074
1075   server_socket = FLUID_NEW(fluid_server_socket_t);
1076   if (server_socket == NULL) {
1077     FLUID_LOG(FLUID_ERR, "Out of memory");
1078     fluid_socket_close(sock);
1079     return NULL;
1080   }
1081
1082   server_socket->socket = sock;
1083   server_socket->func = func;
1084   server_socket->data = data;
1085   server_socket->cont = 1;
1086
1087   server_socket->thread = new_fluid_thread("server", fluid_server_socket_run, server_socket,
1088                                            0, FALSE);
1089   if (server_socket->thread == NULL) {
1090     FLUID_FREE(server_socket);
1091     fluid_socket_close(sock);
1092     return NULL;
1093   }
1094
1095   return server_socket;
1096 }
1097
1098 int delete_fluid_server_socket(fluid_server_socket_t* server_socket)
1099 {
1100   server_socket->cont = 0;
1101   if (server_socket->socket != INVALID_SOCKET) {
1102     fluid_socket_close(server_socket->socket);
1103   }
1104   if (server_socket->thread) {
1105     delete_fluid_thread(server_socket->thread);
1106   }
1107   FLUID_FREE(server_socket);
1108   return FLUID_OK;
1109 }
1110
1111
1112 #else           // Win32 is "special"
1113
1114
1115 #ifndef WIN32_LEAN_AND_MEAN
1116 #define WIN32_LEAN_AND_MEAN
1117 #endif
1118
1119 fluid_istream_t fluid_socket_get_istream (fluid_socket_t sock)
1120 {
1121   return sock | WIN32_SOCKET_FLAG;
1122 }
1123
1124 fluid_ostream_t fluid_socket_get_ostream (fluid_socket_t sock)
1125 {
1126   return sock | WIN32_SOCKET_FLAG;
1127 }
1128
1129 void fluid_socket_close (fluid_socket_t sock)
1130 {
1131   if (sock != INVALID_SOCKET)
1132     closesocket (sock);
1133 }
1134
1135 static void fluid_server_socket_run (void *data)
1136 {
1137   fluid_server_socket_t *server_socket = (fluid_server_socket_t *)data;
1138   fluid_socket_t client_socket;
1139 #ifdef IPV6
1140   struct sockaddr_in6 addr;
1141   char straddr[INET6_ADDRSTRLEN];
1142 #else
1143   struct sockaddr_in addr;
1144   char straddr[INET_ADDRSTRLEN];
1145 #endif
1146   socklen_t addrlen = sizeof (addr);
1147   int r;
1148   FLUID_MEMSET((char *)&addr, 0, sizeof(addr));
1149
1150   FLUID_LOG(FLUID_DBG, "Server listening for connections");
1151
1152   while (server_socket->cont)
1153   {
1154     client_socket = accept (server_socket->socket, (struct sockaddr *)&addr, &addrlen);
1155
1156     FLUID_LOG (FLUID_DBG, "New client connection");
1157
1158     if (client_socket == INVALID_SOCKET)
1159     {
1160       if (server_socket->cont)
1161         FLUID_LOG (FLUID_ERR, "Failed to accept connection: %ld", WSAGetLastError ());
1162
1163       server_socket->cont = 0;
1164       return;
1165     }
1166     else
1167     {
1168 #ifdef IPV6
1169       inet_ntop(AF_INET6, &addr.sin6_addr, straddr, sizeof(straddr));
1170 #else
1171       inet_ntop(AF_INET, &addr.sin_addr, straddr, sizeof(straddr));
1172 #endif
1173       r = server_socket->func (server_socket->data, client_socket,
1174                                straddr);
1175       if (r != 0)
1176         fluid_socket_close (client_socket);
1177     }
1178   }
1179
1180   FLUID_LOG (FLUID_DBG, "Server closing");
1181 }
1182
1183 fluid_server_socket_t*
1184 new_fluid_server_socket(int port, fluid_server_func_t func, void* data)
1185 {
1186   fluid_server_socket_t* server_socket;
1187 #ifdef IPV6
1188   struct sockaddr_in6 addr;
1189 #else
1190   struct sockaddr_in addr;
1191 #endif
1192
1193   fluid_socket_t sock;
1194   WSADATA wsaData;
1195   int retval;
1196
1197   g_return_val_if_fail (func != NULL, NULL);
1198
1199   // Win32 requires initialization of winsock
1200   retval = WSAStartup (MAKEWORD (2,2), &wsaData);
1201
1202   if (retval != 0)
1203   {
1204     FLUID_LOG(FLUID_ERR, "Server socket creation error: WSAStartup failed: %d", retval);
1205     return NULL;
1206   }
1207 #ifdef IPV6
1208   sock = socket (AF_INET6, SOCK_STREAM, 0);
1209   if (sock == INVALID_SOCKET)
1210   {
1211     FLUID_LOG (FLUID_ERR, "Failed to create server socket: %ld", WSAGetLastError ());
1212     WSACleanup ();
1213     return NULL;
1214   }
1215   addr.sin6_family = AF_INET6;
1216   addr.sin6_port = htons (port);
1217   addr.sin6_addr = in6addr_any;
1218 #else
1219
1220   sock = socket (AF_INET, SOCK_STREAM, 0);
1221
1222   if (sock == INVALID_SOCKET)
1223   {
1224     FLUID_LOG (FLUID_ERR, "Failed to create server socket: %ld", WSAGetLastError ());
1225     WSACleanup ();
1226     return NULL;
1227   }
1228
1229   addr.sin_family = AF_INET;
1230   addr.sin_port = htons (port);
1231   addr.sin_addr.s_addr = htonl (INADDR_ANY);
1232 #endif
1233   retval = bind (sock, (struct sockaddr *)&addr, sizeof (addr));
1234
1235   if (retval == SOCKET_ERROR)
1236   {
1237     FLUID_LOG (FLUID_ERR, "Failed to bind server socket: %ld", WSAGetLastError ());
1238     fluid_socket_close (sock);
1239     WSACleanup ();
1240     return NULL;
1241   }
1242
1243   if (listen (sock, SOMAXCONN) == SOCKET_ERROR)
1244   {
1245     FLUID_LOG (FLUID_ERR, "Failed to listen on server socket: %ld", WSAGetLastError ());
1246     fluid_socket_close (sock);
1247     WSACleanup ();
1248     return NULL;
1249   }
1250
1251   server_socket = FLUID_NEW (fluid_server_socket_t);
1252
1253   if (server_socket == NULL)
1254   {
1255     FLUID_LOG (FLUID_ERR, "Out of memory");
1256     fluid_socket_close (sock);
1257     WSACleanup ();
1258     return NULL;
1259   }
1260
1261   server_socket->socket = sock;
1262   server_socket->func = func;
1263   server_socket->data = data;
1264   server_socket->cont = 1;
1265
1266   server_socket->thread = new_fluid_thread("server", fluid_server_socket_run, server_socket,
1267                                            0, FALSE);
1268   if (server_socket->thread == NULL)
1269   {
1270     FLUID_FREE (server_socket);
1271     fluid_socket_close (sock);
1272     WSACleanup ();
1273     return NULL;
1274   }
1275
1276   return server_socket;
1277 }
1278
1279 int delete_fluid_server_socket(fluid_server_socket_t *server_socket)
1280 {
1281   server_socket->cont = 0;
1282
1283   if (server_socket->socket != INVALID_SOCKET)
1284     fluid_socket_close (server_socket->socket);
1285
1286   if (server_socket->thread)
1287     delete_fluid_thread (server_socket->thread);
1288
1289   FLUID_FREE (server_socket);
1290
1291   WSACleanup ();        // Should be called the same number of times as WSAStartup
1292
1293   return FLUID_OK;
1294 }
1295
1296 #endif