source: roaraudio/libroaross/libroaross.c @ 4380:9e0d335e4c4e

Last change on this file since 4380:9e0d335e4c4e was 4380:9e0d335e4c4e, checked in by phi, 14 years ago

some cleanup

File size: 54.9 KB
RevLine 
[3138]1//libroaross.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
[3517]21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
[3138]23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "roaraudio.h"
[3261]37#include "libroarlight/libroarlight.h"
[3138]38
39#if defined(ROAR_HAVE_OSS_BSD) || defined(ROAR_HAVE_OSS)
40#if defined(__OpenBSD__) || defined(__NetBSD__)
41#include <soundcard.h>
42#else
43#include <sys/soundcard.h>
44#endif
45#include <sys/ioctl.h>
46
47#ifdef ROAR_HAVE_H_SYS_TYPES
48#include <sys/types.h>
49#endif
50
51#ifdef ROAR_HAVE_H_FCNTL
52#include <fcntl.h>
53#endif
54
55#ifdef ROAR_HAVE_H_UNISTD
56#include <unistd.h>
57#endif
58
59#include <sys/stat.h>
[3139]60#include <dlfcn.h>
[3778]61#include <stdarg.h>
[3139]62
63#if defined(RTLD_NEXT)
64#define REAL_LIBC RTLD_NEXT
65#else
66#define REAL_LIBC ((void *) -1L)
67#endif
[3138]68
[3164]69#ifndef ENOTSUP
70#define ENOTSUP ENOSYS
71#endif
72
[3873]73#ifndef O_DIRECTORY
74#define O_DIRECTORY 0
75#endif
76
[3892]77#ifndef O_DIRECT
78#define O_DIRECT 0
79#endif
80
[3872]81#ifndef O_LARGEFILE
82#define O_LARGEFILE 0
83#endif
84
85#ifndef O_NOATIME
86#define O_NOATIME 0
87#endif
88
[3868]89#define _O_PARA_DIR (O_RDONLY|O_WRONLY|O_RDWR)
90#define _O_PARA_IGN (O_DIRECT|O_APPEND|O_LARGEFILE|O_NOATIME|O_NOCTTY|O_TRUNC)
91
[3166]92#if defined(ROAR_OS_NETBSD) && defined(ioctl)
93#define IOCTL_IS_ALIAS
94#endif
95
[3167]96#ifdef ROAR_OS_FREEBSD
[3891]97#define _VA_ARGS_MODE_T int
98#else
99#define _VA_ARGS_MODE_T mode_t
[3167]100#endif
101
[3890]102#ifdef ROAR_OS_FREEBSD
103#define _CREAT_ARG_PATHNAME path
104#else
105#define _CREAT_ARG_PATHNAME pathname
106#endif
107
[3169]108#ifdef ROAR_OS_NETBSD
109#define IOCTL() int _oss_ioctl __P((int fd, unsigned long com, void *argp))
[3171]110#define map_args int __fd = fd; unsigned long int __request = com
[3180]111#elif defined(ROAR_TARGET_CYGWIN)
112#define IOCTL() int ioctl (int __fd, int __cmd, ...)
113#define map_args unsigned long int __request = __cmd; void * argp
114#define va_argp
115#define ioctl_lastarg __cmd
[3169]116#else
117#define IOCTL() int ioctl (int __fd, unsigned long int __request, ...)
[3171]118#define map_args void * argp
[3169]119#define va_argp
[3180]120#define ioctl_lastarg __request
[3169]121#endif
122
[3153]123#define OSS_VOLUME_SCALE 100
124
[3138]125#define _MAX_POINTER  8
126
[3140]127// handle type:
[3663]128#define HT_NONE       0 /* Unused object */
129#define HT_STREAM     1 /* Stream with no specal handling needed */
130#define HT_MIXER      2 /* Mixer device */
131#define HT_WAVEFORM   3 /* Waveform device */
132#define HT_MIDI       4 /* MIDI device */
133#define HT_DMX        5 /* DMX512/DMX4Linux device */
134#define HT_VIO        6 /* General VIO object */
[3666]135#define HT_STATIC     7 /* Static file */
[3140]136
[3138]137struct session {
138 int refc;
139 struct roar_connection con;
140};
141
142static struct session _session = {.refc = 0};
143
144struct handle {
145 int refc; // refrence counter
146 struct session * session;
[3140]147 int type;
[3780]148 int sysio_flags;
[3140]149 struct roar_stream    stream;
150 struct roar_vio_calls stream_vio;
[3144]151 int                   stream_dir;
[3140]152 int                   stream_opened;
[3178]153 size_t                stream_buffersize;
154 size_t                readc, writec;
[3246]155 size_t                pos;
[3666]156 union {
157  struct {
158   char * data;
159   size_t len;
160  } sf;
161 } userdata;
[3138]162};
163
164static struct {
165 int     (*open)(const char *pathname, int flags, mode_t mode);
166 int     (*close)(int fd);
167 ssize_t (*write)(int fd, const void *buf, size_t count);
168 ssize_t (*read)(int fd, void *buf, size_t count);
[3166]169#ifndef IOCTL_IS_ALIAS
[3146]170 int     (*ioctl)(int d, int request, ...);
[3166]171#endif
[3246]172 off_t   (*lseek)(int fildes, off_t offset, int whence);
[3264]173 FILE   *(*fopen)(const char *path, const char *mode);
[3657]174 int     (*dup)(int oldfd);
175 int     (*dup2)(int oldfd, int newfd);
[3771]176 int     (*select)(int nfds, fd_set *readfds, fd_set *writefds,
177                   fd_set *exceptfds, struct timeval *timeout);
[3778]178 int     (*fcntl)(int fd, int cmd, ...);
[3782]179 int     (*access)(const char *pathname, int mode);
[3866]180 int     (*open64)(const char *__file, int __oflag, ...);
[3890]181 int     (*creat)(const char *_CREAT_ARG_PATHNAME, mode_t mode);
[3880]182 int     (*stat)(const char *path, struct stat *buf);
183 int     (*fstat)(int filedes, struct stat *buf);
184 int     (*lstat)(const char *path, struct stat *buf);
[3138]185} _os;
186
[3150]187static struct {
188 struct {
189  int volume;
190  int pcm;
191  int line;
192  int line1;
193  int line2;
194  int line3;
195  int digital1;
196  int digital2;
197  int digital3;
198 } sid;
199} _mix_settings = {
200                   .sid = {
201                           .volume   = -1,
202                           .pcm      = -1,
203                           .line     =  0,
204                           .line1    =  1,
205                           .line2    =  2,
206                           .line3    =  3,
207                           .digital1 =  1,
208                           .digital2 =  2,
209                           .digital3 =  3
210                          }
211                  };
212
[3140]213static struct pointer {
[3138]214 int fh;
215 struct handle * handle;
216} _ptr[_MAX_POINTER];
217
[3662]218
[3666]219static char _sf__dev_sndstat[] =
220 "Sound Driver:RoarAudio\n"
221 "Config options: 0\n"
222 "\n"
223 "Installed drivers:\n"
224 "Type 10: RoarAudio emulation\n"
225 "\n"
226 "Card config:\n"
227 "\n"
228 "Audio devices:\n"
229 "0: RoarAudio OSS emulation (DUPLEX)\n"
230 "\n"
231 "Midi devices:\n"
232 "0: RoarAudio OSS emulation MIDI\n"
233 "\n"
234 "Timers:\n"
235 "\n"
236 "Mixers:\n"
237 "0: RoarAudio OSS emulation Mixer\n"
238;
239
[3662]240static struct devices {
241  char * prefix;
242  int type;
[3666]243  size_t len;
244  void * userdata;
[3870]245  struct handle * (*open)(const char * file, int flags, mode_t mode, struct devices * ptr);
[3662]246} _device_list[] = {
[4008]247 {"/dev/dsp",           HT_WAVEFORM,  0, NULL, NULL},
248 {"/dev/dsp?",          HT_WAVEFORM,  0, NULL, NULL},
249 {"/dev/audio",         HT_WAVEFORM,  0, NULL, NULL},
250 {"/dev/audio?",        HT_WAVEFORM,  0, NULL, NULL},
251 {"/dev/sound/dsp",     HT_WAVEFORM,  0, NULL, NULL},
252 {"/dev/sound/dsp?",    HT_WAVEFORM,  0, NULL, NULL},
253 {"/dev/sound/audio",   HT_WAVEFORM,  0, NULL, NULL},
254 {"/dev/sound/audio?",  HT_WAVEFORM,  0, NULL, NULL},
255 {"/dev/mixer",         HT_MIXER,     0, NULL, NULL},
256 {"/dev/mixer?",        HT_MIXER,     0, NULL, NULL},
257 {"/dev/sound/mixer",   HT_MIXER,     0, NULL, NULL},
258 {"/dev/sound/mixer?",  HT_MIXER,     0, NULL, NULL},
259 {"/dev/midi",          HT_MIDI,      0, NULL, NULL},
260 {"/dev/midi?",         HT_MIDI,      0, NULL, NULL},
261 {"/dev/rmidi",         HT_MIDI,      0, NULL, NULL},
262 {"/dev/rmidi?",        HT_MIDI,      0, NULL, NULL},
263 {"/dev/sound/midi",    HT_MIDI,      0, NULL, NULL},
264 {"/dev/sound/midi?",   HT_MIDI,      0, NULL, NULL},
265 {"/dev/sound/rmidi",   HT_MIDI,      0, NULL, NULL},
266 {"/dev/sound/rmidi?",  HT_MIDI,      0, NULL, NULL},
267 {"/dev/dmx",           HT_DMX,       0, NULL, NULL},
268 {"/dev/dmx?",          HT_DMX,       0, NULL, NULL},
269 {"/dev/misc/dmx",      HT_DMX,       0, NULL, NULL},
270 {"/dev/misc/dmx?",     HT_DMX,       0, NULL, NULL},
271 {"/dev/dmxin",         HT_DMX,       0, NULL, NULL},
272 {"/dev/dmxin?",        HT_DMX,       0, NULL, NULL},
273 {"/dev/misc/dmxin",    HT_DMX,       0, NULL, NULL},
274 {"/dev/misc/dmxin?",   HT_DMX,       0, NULL, NULL},
[3870]275 {"/dev/sndstat",       HT_STATIC,    sizeof(_sf__dev_sndstat)-1, _sf__dev_sndstat, NULL},
[3662]276#ifdef ROAR_DEFAULT_OSS_DEV
[3870]277 {ROAR_DEFAULT_OSS_DEV, HT_WAVEFORM,  0, NULL, NULL},
[3662]278#endif
[4380]279#ifdef ROAR_DEFAULT_OSS_MIX_DEV
280 {ROAR_DEFAULT_OSS_MIX_DEV, HT_MIXER, 0, NULL, NULL},
281#endif
[3870]282 {NULL, HT_NONE, 0, NULL, NULL},
[3662]283};
284
[3849]285
286static int _update_nonblock (struct handle * handle);
287
[3138]288static void _init_os (void) {
289 memset(&_os, 0, sizeof(_os));
[3139]290
[3775]291 // if call roar_dl_getsym() here all applications will segfaul.
292 // why?
293
[3772]294 _os.open   = dlsym(REAL_LIBC, "open");
295 _os.close  = dlsym(REAL_LIBC, "close");
296 _os.write  = dlsym(REAL_LIBC, "write");
297 _os.read   = dlsym(REAL_LIBC, "read");
[3166]298#ifndef IOCTL_IS_ALIAS
[3772]299 _os.ioctl  = dlsym(REAL_LIBC, "ioctl");
[3166]300#endif
[3772]301 _os.lseek  = dlsym(REAL_LIBC, "lseek");
302 _os.fopen  = dlsym(REAL_LIBC, "fopen");
303 _os.dup    = dlsym(REAL_LIBC, "dup");
304 _os.dup2   = dlsym(REAL_LIBC, "dup2");
305 _os.select = dlsym(REAL_LIBC, "select");
[3778]306 _os.fcntl  = dlsym(REAL_LIBC, "fcntl");
[3782]307 _os.access = dlsym(REAL_LIBC, "access");
[3866]308 _os.open64 = dlsym(REAL_LIBC, "open64");
[3871]309 _os.creat  = dlsym(REAL_LIBC, "creat");
[3880]310 _os.stat   = dlsym(REAL_LIBC, "stat");
311 _os.fstat  = dlsym(REAL_LIBC, "fstat");
312 _os.lstat  = dlsym(REAL_LIBC, "lstat");
[3138]313}
314
315static void _init_ptr (void) {
316 int i;
317
318 for (i = 0; i < _MAX_POINTER; i++) {
319  _ptr[i].fh = -1;
320 }
321}
322
323static void _init (void) {
324 static int inited = 0;
325
326 if ( !inited ) {
327  _init_os();
328  _init_ptr();
[3771]329  roar_vio_select(NULL, 0, NULL, NULL);
[3138]330  inited++;
331 }
332}
333
[3157]334static void _find_volume_sid (struct session * session) {
335 int i;
336 int num;
337 int id[ROAR_STREAMS_MAX];
338 struct roar_stream s;
339 char name[1024];
340
341 ROAR_DBG("_find_volume_sid(session=%p) = ?", session);
342
343 if ( (num = roar_list_streams(&(session->con), id, ROAR_STREAMS_MAX)) == -1 ) {
344  return;
345 }
346
347 for (i = 0; i < num; i++) {
348  if ( roar_get_stream(&(session->con), &s, id[i]) == -1 )
349   continue;
350
351  if ( s.dir != ROAR_DIR_MIXING )
352   continue;
353
354  if ( roar_stream_get_name(&(session->con), &s, name, 1024) == -1 )
355   continue;
356
357  if ( !strcasecmp(name, "Waveform Mixer") ) {
358   _mix_settings.sid.volume = id[i];
359   ROAR_DBG("_find_volume_sid(session=%p): found waveform mixer at sid %i", session, id[i]);
360   ROAR_DBG("_find_volume_sid(session=%p) = (void)", session);
361   return;
362  }
363 }
364}
365
[3138]366static int _open_dummy (void) {
367 int p[2];
368
[4078]369 ROAR_DBG("_open_dummy(void) = ?");
370
[3138]371 if ( pipe(p) == -1 )
372  return -1;
373
374 close(p[1]);
375
[4078]376 ROAR_DBG("_open_dummy(void) = %i", p[0]);
[3138]377 return p[0];
378}
379
380static struct session * _open_session (char * server, char * name) {
[3652]381 struct session * ses = &_session;
382 int new_session = getenv("ROAR_OSS_NEW_SESSION") == NULL ? 0 : 1;
383
[3183]384 ROAR_DBG("_open_session(server='%s', name='%s') = ?", server, name);
385 ROAR_DBG("_open_session(server='%s', name='%s'): _session.refc=%i", server, name, _session.refc);
386
[3652]387 if ( new_session ) {
[3850]388  ses = roar_mm_malloc(sizeof(struct session));
[3652]389  if ( ses == NULL )
390   return NULL;
391
392  memset(ses, 0, sizeof(struct session));
393 }
394
395 if ( ses->refc == 0 ) {
[3138]396
397  if ( name == NULL )
[3500]398   name = getenv("ROAR_OSS_CLIENT_NAME");
399
400  if ( name == NULL )
[3138]401   name = "libroaross client";
402
[3652]403  if ( roar_simple_connect(&(ses->con), server, name) == -1 ) {
404   if ( new_session )
[3850]405    roar_mm_free(ses);
[3652]406
[3138]407   return NULL;
[3652]408  }
[3157]409
[3652]410  _find_volume_sid(ses);
[3184]411
[3652]412  if ( !new_session ) {
413   if ( getenv("ROAR_OSS_KEEP_SESSION") != NULL )
414    ses->refc++;
415  }
[3143]416 }
[3138]417
[3652]418 ses->refc++;
[3183]419
[3652]420 ROAR_DBG("_open_session(server='%s', name='%s') = %p", server, name, ses);
421 return ses;
[3138]422}
423
424static void _close_session(struct session * session) {
425 if ( session == NULL )
426  return;
427
428 session->refc--;
429
[3144]430 ROAR_DBG("_close_session(session=%p): session->refc=%i", session, session->refc);
431
[3138]432 if ( session->refc == 0 ) {
433  roar_disconnect(&(session->con));
434 }
[3652]435
436 if ( session != &_session )
[3850]437  roar_mm_free(session);
[3138]438}
439
[3140]440static struct handle * _open_handle(struct session * session) {
441 struct handle * handle;
442
[3183]443 ROAR_DBG("_open_handle(session=%p) = ?", session);
444
[3140]445 if ( (handle = roar_mm_malloc(sizeof(struct handle))) == NULL )
446  return NULL;
447
448 memset(handle, 0, sizeof(struct handle));
449
450 handle->refc = 1;
451 handle->session = session;
[3666]452
453 if ( session != NULL )
454  session->refc++; // TODO: better warp this
455
[3140]456 handle->type = HT_NONE;
[3144]457 handle->stream_dir = ROAR_DIR_PLAY;
458 roar_stream_new(&(handle->stream), ROAR_RATE_DEFAULT, ROAR_CHANNELS_DEFAULT, ROAR_BITS_DEFAULT, ROAR_CODEC_DEFAULT);
[3140]459
[3183]460 ROAR_DBG("_open_handle(session=%p) = %p", session, handle);
[3140]461 return handle;
462}
463
464static void _close_handle(struct handle * handle) {
[3664]465 int need_close = 0;
466
[3140]467 if (handle == NULL)
468  return;
469
470 handle->refc--;
471
[3144]472 ROAR_DBG("_close_handle(handle=%p): handle->refc=%i", handle, handle->refc);
473
[3140]474 if ( handle->refc == 0 ) {
[3664]475  switch (handle->type) {
476   case HT_VIO:
477     need_close = 1;
478    break;
479   case HT_STREAM:
480     if ( handle->stream_opened )
481      need_close = 1;
482    break;
483  }
484
485  if ( need_close )
[3140]486   roar_vio_close(&(handle->stream_vio));
487
[3664]488  if ( handle->session != NULL ) {
489   handle->session->refc--;
[3144]490
[3664]491   _close_session(handle->session);
492  }
[3144]493
[3140]494  roar_mm_free(handle);
495 }
496}
497
[4078]498static struct pointer * _get_pointer_by_fh_or_new (int fh) {
[3140]499 int i;
500
501 for (i = 0; i < _MAX_POINTER; i++) {
502  if ( _ptr[i].fh == fh )
503   return &(_ptr[i]);
504 }
505
506 return NULL;
507}
508
[4078]509static struct pointer * _get_pointer_by_fh (int fh) {
510 if ( fh == -1 )
[3140]511  return NULL;
512
[4078]513 return _get_pointer_by_fh_or_new(fh);
514}
515
516static struct pointer * _open_pointer(struct handle * handle) {
517 struct pointer * ret = _get_pointer_by_fh_or_new(-1);
518
519 ROAR_DBG("_open_pointer(handle=%p) = ?", handle);
520
521 if ( ret == NULL ) {
522  ROAR_DBG("_open_pointer(handle=%p) = NULL", handle);
[3140]523  return NULL;
[4078]524 }
525
526 if ( (ret->fh = _open_dummy()) == -1 ) {
527  ROAR_DBG("_open_pointer(handle=%p) = NULL", handle);
528  return NULL;
529 }
[3140]530
531 ret->handle = handle;
532
[4078]533 ROAR_DBG("_open_pointer(handle=%p) = %p", handle, ret);
534
[3140]535 return ret;
536}
537
[3657]538static struct pointer * _attach_pointer(struct handle * handle, int fh) {
[4078]539 struct pointer * ret = _get_pointer_by_fh_or_new(-1);
[3657]540
541 if ( ret == NULL )
542  return NULL;
543
544 if ( (ret->fh = fh) == -1 )
545  return NULL;
546
547 ret->handle = handle;
548
549 handle->refc++;
550
551 return ret;
552}
553
[3140]554static void _close_pointer(struct pointer * pointer) {
555 if ( pointer == NULL )
556  return;
557
558 _os.close(pointer->fh);
559
560 pointer->fh = -1;
561
562 _close_handle(pointer->handle);
563}
[3138]564
565// -------------------------------------
[3870]566// central function to find device:
567// -------------------------------------
568
569static struct devices * _get_device (const char * pathname) {
[4008]570 size_t len, pathlen;
[3870]571 int i;
[4008]572 int qm_match;
[3870]573
[4007]574 ROAR_DBG("_get_device(pathname='%s') = ?", pathname);
575
[4008]576 pathlen = strlen(pathname);
577
[3870]578 for (i = 0; _device_list[i].prefix != NULL; i++) {
579  len = strlen(_device_list[i].prefix);
580
[4008]581  qm_match = 0;
582
[3870]583  if ( _device_list[i].prefix[len-1] == '*' ) {
584   len--;
[4008]585  } else if ( _device_list[i].prefix[len-1] == '?' ) {
586   qm_match = 1;
587   len--;
[3870]588  } else {
589   len++;
590  }
[4008]591
[3870]592  if ( !strncmp(pathname, _device_list[i].prefix, len) ) {
[4008]593   if ( !qm_match || pathlen == (len + 1) )
594    return &(_device_list[i]);
[3870]595  }
596 }
597
[4007]598 ROAR_DBG("_get_device(pathname='%s') = NULL", pathname);
[3870]599 return NULL;
600}
601
602// -------------------------------------
[3142]603// central open function:
604// -------------------------------------
605
606static int _open_file (const char *pathname, int flags) {
[3143]607 struct session * session;
608 struct handle  * handle;
609 struct pointer * pointer;
[3662]610 struct devices * ptr = NULL;
[3143]611
[3665]612 ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = ?", pathname, flags);
613
[3777]614/*
615 * Flags we ignore:
616 * O_DIRECT, O_APPEND, O_LARGEFILE, O_NOATIME, O_NOCTTY, O_TRUNC
617 */
618
[4081]619 if ( (ptr = _get_device(pathname)) == NULL ) {
620  ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -2", pathname, flags);
621  return -2;
622 }
623
624 ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = ?", pathname, flags);
625
626
[3951]627#ifdef O_ASYNC
[3777]628 if ( flags & O_ASYNC ) {
629  ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1 // not supported O_ASYNC", pathname, flags);
630  errno = ENOSYS;
631  return -1;
632 }
[3951]633#endif
[3777]634
635 if ( (flags & O_DIRECTORY) || (flags & O_EXCL) ) {
636  ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1 // invalid flags (O_DIRECTORY or O_EXCL)", pathname, flags);
637  errno = EINVAL;
638  return -1;
639 }
640
[4007]641 ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = ?", pathname, flags);
642
[3666]643 if ( ptr->type == HT_STATIC || ptr->type == HT_VIO ) { // non-session handles
644  session = NULL;
645 } else {
646  if ( (session = _open_session(NULL, NULL)) == NULL ) {
647   ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1", pathname, flags);
648   return -1;
649  }
[3143]650 }
651
[3870]652 if ( ptr->open != NULL ) {
653  // TODO: Add support to pass mode (perms) to open.
654  if ( (handle = ptr->open(pathname, flags, 0000, ptr)) == NULL ) {
655   _close_session(session);
656   ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1", pathname, flags);
657   return -1;
658  }
659 } else {
660  if ( (handle = _open_handle(session)) == NULL ) {
661   _close_session(session);
662   ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1", pathname, flags);
663   return -1;
664  }
665
666  handle->type        = ptr->type;
667  handle->sysio_flags = flags;
668  handle->stream_dir  = -1;
[3143]669 }
670
[3868]671 switch (flags & _O_PARA_DIR) {
[3145]672  case O_RDONLY:
[3244]673    switch (ptr->type) {
674     case HT_WAVEFORM:
675       handle->stream_dir = ROAR_DIR_MONITOR;
676      break;
677     case HT_MIDI:
678       handle->stream_dir = ROAR_DIR_MIDI_OUT;
679      break;
[3246]680     case HT_DMX:
681       handle->stream_dir = ROAR_DIR_LIGHT_OUT;
682      break;
[3665]683     case HT_MIXER:
[3666]684     case HT_STATIC:
[3665]685      break;
[3248]686     default:
[3665]687       ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1", pathname, flags);
[3248]688       return -1;
[3244]689    }
[3145]690   break;
691  case O_WRONLY:
[3244]692    switch (ptr->type) {
693     case HT_WAVEFORM:
694       handle->stream_dir = ROAR_DIR_PLAY;
695      break;
696     case HT_MIDI:
697       handle->stream_dir = ROAR_DIR_MIDI_IN;
698      break;
[3246]699     case HT_DMX:
700       handle->stream_dir = ROAR_DIR_LIGHT_IN;
701      break;
[3666]702     case HT_MIXER:
703     case HT_STATIC:
704      break;
[3248]705     default:
[3665]706       ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1", pathname, flags);
[3248]707       return -1;
[3244]708    }
[3145]709   break;
710  case O_RDWR:
[3244]711    switch (ptr->type) {
712     case HT_WAVEFORM:
713       handle->stream_dir = ROAR_DIR_BIDIR;
714      break;
[3666]715     case HT_MIXER:
716     case HT_STATIC:
717      break;
[3248]718     default:
[3665]719       ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1", pathname, flags);
[3248]720       return -1;
[3244]721    }
722   break;
723 }
724
725 switch (handle->type) {
726  case HT_WAVEFORM:
727    handle->type = HT_STREAM;
728   break;
729  case HT_MIDI:
730    handle->type = HT_STREAM;
731    handle->stream.info.rate     = 0;
732    handle->stream.info.bits     = ROAR_MIDI_BITS;
733    handle->stream.info.channels = ROAR_MIDI_CHANNELS_DEFAULT;
734    handle->stream.info.codec    = ROAR_CODEC_MIDI;
[3145]735   break;
[3261]736  case HT_DMX:
737    handle->stream.info.rate     = 0;
738    handle->stream.info.bits     = ROAR_LIGHT_BITS;
739    handle->stream.info.channels = 512;
740    handle->stream.info.codec    = ROAR_CODEC_ROARDMX;
741   break;
[3666]742  case HT_STATIC:
743    handle->userdata.sf.len      = ptr->len;
744    handle->userdata.sf.data     = ptr->userdata;
745   break;
[3145]746 }
747
[4078]748 ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = ?", pathname, flags);
749
[3143]750 if ( (pointer = _open_pointer(handle)) == NULL ) {
751  _close_handle(handle);
[3665]752  ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = -1", pathname, flags);
[3143]753  return -1;
754 }
755
[3665]756 ROAR_DBG("_open_file(pathname='%s', flags=0x%x) = %i", pathname, flags, pointer->fh);
757
[3143]758 return pointer->fh;
[3142]759}
760
761// -------------------------------------
[3952]762// VIO open function:
763// -------------------------------------
764
765int libroaross_open_vio(struct handle ** handleret, struct roar_vio_calls ** vio, int flags) {
766 struct handle  * handle;
767 struct pointer * pointer;
768
769 _init();
770
771 if ( vio == NULL )
772  return -1;
773
774 if ( (handle = _open_handle(NULL)) == NULL ) {
775  return -1;
776 }
777
778 handle->type        = HT_VIO;
779 handle->sysio_flags = flags;
780
[3953]781 if ( roar_vio_init_calls(&(handle->stream_vio)) == -1 ) {
782  _close_handle(handle);
783  return -1;
784 }
785
[3952]786 *vio = &(handle->stream_vio);
787
788 if ( handleret != NULL )
789  *handleret = handle;
790
791 if ( (pointer = _open_pointer(handle)) == NULL ) {
792  _close_handle(handle);
793  return -1;
794 }
795
796 return pointer->fh;
797}
798
799// -------------------------------------
[3144]800// open function for streams:
801// -------------------------------------
802
803static int _open_stream (struct handle * handle) {
804  // FIXME: this should be re-written much more cleanly:
805
806 if ( handle == NULL )
807  return -1;
808
809 if ( roar_vio_simple_new_stream_obj(&(handle->stream_vio),
810                                     &(handle->session->con), &(handle->stream),
811                                     handle->stream.info.rate,
812                                     handle->stream.info.channels,
813                                     handle->stream.info.bits,
814                                     handle->stream.info.codec,
815                                     handle->stream_dir
816                                    ) == -1 )
817  return -1;
818
819 handle->stream_opened++;
820
[3150]821 _mix_settings.sid.pcm = roar_stream_get_id(&(handle->stream));
822
[3849]823 _update_nonblock(handle);
824
825 return 0;
826}
827
828// -------------------------------------
829// function to update O_NONBLOCK:
830// -------------------------------------
831
832static int _update_nonblock (struct handle * handle) {
833 int opened = 0;
834 int state  = handle->sysio_flags & O_NONBLOCK ? ROAR_SOCKET_NONBLOCK : ROAR_SOCKET_BLOCK;
835
836 switch (handle->type) {
837  case HT_NONE:
838  case HT_STATIC:
839  case HT_MIXER:
840    // we can ignore setting of nonblock flag here.
841    return 0;
842   break;
843  case HT_VIO:
844    opened = 1;
845   break;
846  case HT_STREAM:
847  case HT_WAVEFORM:
848  case HT_MIDI:
849  case HT_DMX:
850    opened = handle->stream_opened;
851   break;
852 }
853
854 if ( opened ) {
855  return roar_vio_nonblock(&(handle->stream_vio), state);
856 }
857
[3144]858 return 0;
859}
860
861// -------------------------------------
[3147]862// function to parse format:
863// -------------------------------------
864
865static int _ioctl_stream_format (struct handle * handle, int format) {
866 struct roar_audio_info * info = &(handle->stream.info);
867
868 switch (format) {
869  case AFMT_S8:
870    info->bits  = 8;
871    info->codec = ROAR_CODEC_PCM_S_LE;
872   break;
873  case AFMT_U8:
874    info->bits  = 8;
875    info->codec = ROAR_CODEC_PCM_U_LE;
876   break;
877  case AFMT_S16_BE:
878    info->bits  = 16;
879    info->codec = ROAR_CODEC_PCM_S_BE;
880   break;
881  case AFMT_S16_LE:
882    info->bits  = 16;
883    info->codec = ROAR_CODEC_PCM_S_LE;
884   break;
885  case AFMT_U16_BE:
886    info->bits  = 16;
887    info->codec = ROAR_CODEC_PCM_U_BE;
888   break;
889  case AFMT_U16_LE:
890    info->bits  = 16;
891    info->codec = ROAR_CODEC_PCM_U_LE;
892   break;
893#ifdef AFMT_S32_BE
894  case AFMT_S32_BE:
895    info->bits  = 32;
896    info->codec = ROAR_CODEC_PCM_S_BE;
897   break;
898#endif
899#ifdef AFMT_S32_LE
900  case AFMT_S32_LE:
901    info->bits  = 32;
902    info->codec = ROAR_CODEC_PCM_S_LE;
903   break;
904#endif
905  case AFMT_A_LAW:
906    info->bits  = 8;
907    info->codec = ROAR_CODEC_ALAW;
908   break;
909  case AFMT_MU_LAW:
910    info->bits  = 8;
911    info->codec = ROAR_CODEC_MULAW;
912   break;
913#ifdef AFMT_VORBIS
914  case AFMT_VORBIS:
915    info->codec = ROAR_CODEC_OGG_VORBIS;
916   break;
917#endif
[3148]918  default:
[3229]919    ROAR_DBG("_ioctl_stream_format(*): unsupported format");
[3148]920    errno = ENOSYS;
921    return -1;
922   break;
[3147]923 }
924
[3148]925 return 0;
[3147]926}
927
[3149]928static inline int _ioctl_stream_format_list (void) {
929 int format = 0;
930
931 format |= AFMT_S8;
932 format |= AFMT_U8;
933
934 format |= AFMT_S16_BE;
935 format |= AFMT_S16_LE;
936
937 format |= AFMT_U16_BE;
938 format |= AFMT_U16_LE;
939
940#ifdef AFMT_S32_BE
941 format |= AFMT_S32_BE;
942#endif
943#ifdef AFMT_S32_LE
944 format |= AFMT_S32_LE;
945#endif
946
947 format |= AFMT_A_LAW;
948 format |= AFMT_MU_LAW;
949
950#ifdef AFMT_VORBIS
951 format |= AFMT_VORBIS;
952#endif
953
954 return format;
955}
956
[3147]957// -------------------------------------
[3150]958// mixer ioctls:
959// -------------------------------------
960
[3158]961static int _ioctl_mixer (struct handle * handle, long unsigned int req, void * vp) {
[3159]962 mixer_info * info;
[3150]963 int channels;
964 struct roar_mixer_settings mixer;
[3155]965 int o_w    =  0;
[3150]966 int o_sid  = -1;
[3158]967 int * ip   = vp;
[3165]968#if defined(DEBUG) && defined(DEBUG_IOCTL_NAMES)
969 char * name = NULL;
970#endif
[3150]971
[3165]972#if defined(DEBUG) && defined(DEBUG_IOCTL_NAMES)
[3150]973 switch (req) {
974#if 0
975  case SNDCTL_MIX_DESCRIPTION: name = "SNDCTL_MIX_DESCRIPTION"; break;
976  case SNDCTL_MIX_ENUMINFO:    name = "SNDCTL_MIX_ENUMINFO";    break;
977  case SNDCTL_MIX_EXTINFO:     name = "SNDCTL_MIX_EXTINFO";     break;
978  case SNDCTL_MIX_NREXT:       name = "SNDCTL_MIX_NREXT";       break;
979  case SNDCTL_MIX_NRMIX:       name = "SNDCTL_MIX_NRMIX";       break;
980  case SNDCTL_MIX_READ:        name = "SNDCTL_MIX_READ";        break;
981  case SNDCTL_MIX_WRITE:       name = "SNDCTL_MIX_WRITE";       break;
982#endif
[3159]983//  case SOUND_MIXER_INFO:             name = "SOUND_MIXER_INFO";             break;
[3152]984  case SOUND_OLD_MIXER_INFO:         name = "SOUND_OLD_MIXER_INFO";         break;
985  case SOUND_MIXER_ACCESS:           name = "SOUND_MIXER_ACCESS";           break;
986  case SOUND_MIXER_AGC:              name = "SOUND_MIXER_AGC";              break;
987  case SOUND_MIXER_3DSE:             name = "SOUND_MIXER_3DSE";             break;
[3156]988  case SOUND_MIXER_GETLEVELS:        name = "SOUND_MIXER_GETLEVELS";        break;
989  case SOUND_MIXER_SETLEVELS:        name = "SOUND_MIXER_SETLEVELS";        break;
[3152]990  case SOUND_MIXER_PRIVATE1:         name = "SOUND_MIXER_PRIVATE1";         break;
991  case SOUND_MIXER_PRIVATE2:         name = "SOUND_MIXER_PRIVATE2";         break;
992  case SOUND_MIXER_PRIVATE3:         name = "SOUND_MIXER_PRIVATE3";         break;
993  case SOUND_MIXER_PRIVATE4:         name = "SOUND_MIXER_PRIVATE4";         break;
994  case SOUND_MIXER_PRIVATE5:         name = "SOUND_MIXER_PRIVATE5";         break;
995  case OSS_GETVERSION:               name = "OSS_GETVERSION";               break;
[3156]996//  case SOUND_MIXER_READ_CAPS:        name = "SOUND_MIXER_READ_CAPS";        break;
997  case SOUND_MIXER_READ_MUTE:        name = "SOUND_MIXER_READ_MUTE";        break;
[3152]998/*
999  case :     name = "";     break;
[3156]1000  case :     name = "";     break;
[3152]1001*/
[3150]1002 }
1003 if ( name != NULL ) {
[3656]1004  ROAR_DBG("_ioctl_mixer(handle=%p, req=0x%lX, ip=%p): unspported mixer command %s", handle, req, ip, name);
1005  ROAR_DBG("_ioctl_mixer(handle=%p, req=0x%lX, ip=%p) = -1 // errno = ENOSYS", handle, req, ip);
[3150]1006  errno = ENOSYS;
1007  return -1;
1008 }
[3165]1009#endif
[3150]1010
1011 switch (req) {
1012  case SOUND_MIXER_READ_VOLUME:    o_w = 0; o_sid = _mix_settings.sid.volume;   break;
1013  case SOUND_MIXER_READ_LINE:      o_w = 0; o_sid = _mix_settings.sid.line;     break;
1014  case SOUND_MIXER_READ_LINE1:     o_w = 0; o_sid = _mix_settings.sid.line1;    break;
1015  case SOUND_MIXER_READ_LINE2:     o_w = 0; o_sid = _mix_settings.sid.line2;    break;
1016  case SOUND_MIXER_READ_LINE3:     o_w = 0; o_sid = _mix_settings.sid.line3;    break;
1017#if 0
1018  case SOUND_MIXER_READ_DIGITAL1:  o_w = 0; o_sid = _mix_settings.sid.digital1; break;
1019  case SOUND_MIXER_READ_DIGITAL2:  o_w = 0; o_sid = _mix_settings.sid.digital2; break;
1020  case SOUND_MIXER_READ_DIGITAL3:  o_w = 0; o_sid = _mix_settings.sid.digital3; break;
1021#endif
1022  case SOUND_MIXER_WRITE_VOLUME:   o_w = 1; o_sid = _mix_settings.sid.volume;   break;
1023  case SOUND_MIXER_WRITE_LINE:     o_w = 1; o_sid = _mix_settings.sid.line;     break;
1024  case SOUND_MIXER_WRITE_LINE1:    o_w = 1; o_sid = _mix_settings.sid.line1;    break;
1025  case SOUND_MIXER_WRITE_LINE2:    o_w = 1; o_sid = _mix_settings.sid.line2;    break;
1026  case SOUND_MIXER_WRITE_LINE3:    o_w = 1; o_sid = _mix_settings.sid.line3;    break;
1027#if 0
1028  case SOUND_MIXER_WRITE_DIGITAL1: o_w = 1; o_sid = _mix_settings.sid.digital1; break;
1029  case SOUND_MIXER_WRITE_DIGITAL2: o_w = 1; o_sid = _mix_settings.sid.digital2; break;
1030  case SOUND_MIXER_WRITE_DIGITAL3: o_w = 1; o_sid = _mix_settings.sid.digital3; break;
1031#endif
[3177]1032  // we handle PCM seperatly as we want to be abled to abled to handle it on a stream (not mixer), too:
1033  case SOUND_MIXER_READ_PCM:
1034    o_w = 0;
1035    if ( handle->type == HT_STREAM ) {
1036     o_sid = roar_stream_get_id(&(handle->stream));
1037    } else {
1038     o_sid = _mix_settings.sid.pcm;
1039    }
1040   break;
1041  case SOUND_MIXER_WRITE_PCM:
1042    o_w = 1;
1043    if ( handle->type == HT_STREAM ) {
1044     o_sid = roar_stream_get_id(&(handle->stream));
1045    } else {
1046     o_sid = _mix_settings.sid.pcm;
1047    }
1048   break;
[3150]1049 }
1050 if ( o_sid != -1 ) {
1051  // set/get volume
1052  if ( o_w ) {
[3536]1053   mixer.scale    = OSS_VOLUME_SCALE;
1054   mixer.mixer[0] = ( *ip       & 0xFF);
1055   mixer.mixer[1] = ((*ip >> 8) & 0xFF);
[3150]1056   if ( roar_set_vol(&(handle->session->con), o_sid, &mixer, 2) == -1 ) {
[3156]1057    errno = EIO;
[3150]1058    return -1;
1059   }
1060   return 0;
1061  } else {
1062   if ( roar_get_vol(&(handle->session->con), o_sid, &mixer, &channels) == -1 ) {
[3156]1063    errno = EIO;
[3150]1064    return -1;
1065   }
[3153]1066   *ip = ((OSS_VOLUME_SCALE*mixer.mixer[0])/mixer.scale) | (((OSS_VOLUME_SCALE*mixer.mixer[0])/mixer.scale)<<8);
[3150]1067   return 0;
1068  }
1069 }
1070
1071 switch (req) {
[3155]1072  case SOUND_MIXER_READ_STEREODEVS: /* FIXME: check the streams for channel config */
[3150]1073  case SOUND_MIXER_READ_DEVMASK:
1074    *ip = 0;
1075
1076    if ( _mix_settings.sid.volume != -1 )
1077     *ip |= SOUND_MASK_VOLUME;
1078    if ( _mix_settings.sid.pcm != -1 )
1079     *ip |= SOUND_MASK_PCM;
1080    if ( _mix_settings.sid.line != -1 )
1081     *ip |= SOUND_MASK_LINE;
1082    if ( _mix_settings.sid.line1 != -1 )
1083     *ip |= SOUND_MASK_LINE1;
1084    if ( _mix_settings.sid.line2 != -1 )
1085     *ip |= SOUND_MASK_LINE2;
1086    if ( _mix_settings.sid.line3 != -1 )
1087     *ip |= SOUND_MASK_LINE3;
1088    if ( _mix_settings.sid.digital1 != -1 )
[3156]1089#if 0
[3150]1090     *ip |= SOUND_MASK_DIGITAL1;
1091    if ( _mix_settings.sid.digital2 != -1 )
1092     *ip |= SOUND_MASK_DIGITAL2;
1093    if ( _mix_settings.sid.digital3 != -1 )
1094     *ip |= SOUND_MASK_DIGITAL3;
[3156]1095#endif
[3150]1096
1097    return 0;
1098   break;
[3153]1099  case SOUND_MIXER_READ_RECMASK:
[3154]1100  case SOUND_MIXER_READ_RECSRC:
[3153]1101    *ip = SOUND_MASK_VOLUME; // we can currently only read from mixer
1102    return 0;
1103   break;
[3154]1104  case SOUND_MIXER_WRITE_RECSRC:
1105    if ( *ip == SOUND_MASK_VOLUME ) {
1106     return  0;
1107    } else {
1108     errno = ENOTSUP;
1109     return -1;
1110    }
1111   break;
[3156]1112  case SOUND_MIXER_READ_CAPS:
1113    *ip = 0;
1114    return 0;
1115   break;
[3159]1116  case SOUND_MIXER_INFO:
1117    info = vp;
1118    memset(info, 0, sizeof(*info));
1119    strcpy(info->id, "RoarAudio");
1120    strcpy(info->name, "RoarAudio");
1121    return 0;
1122   break;
[3150]1123 }
1124
[3656]1125 ROAR_DBG("_ioctl_mixer(handle=%p, req=0x%lX, ip=%p): unknown mixer CTL", handle, req, ip);
[3156]1126// _os.ioctl(-1, req, ip);
[3656]1127 ROAR_DBG("_ioctl_mixer(handle=%p, req=0x%lX, ip=%p) = -1 // errno = ENOSYS", handle, req, ip);
[3150]1128 errno = ENOSYS;
1129 return -1;
1130}
1131
1132// -------------------------------------
[3178]1133// buffer size calculation:
1134// -------------------------------------
1135
1136static size_t _get_stream_buffersize (struct handle * handle) {
1137 if ( handle->stream_buffersize )
1138  return handle->stream_buffersize;
1139
1140 return handle->stream_buffersize = handle->stream.info.rate     *
1141                                    handle->stream.info.channels *
1142                                    handle->stream.info.bits     / 800;
1143}
1144
1145// -------------------------------------
[3138]1146// emulated functions follow:
1147// -------------------------------------
1148
1149int     open(const char *pathname, int flags, ...) {
[3142]1150 int     ret;
1151 mode_t  mode = 0;
[3138]1152 va_list args;
1153
1154 _init();
1155
[3261]1156 if ( pathname == NULL ) {
1157  errno = EFAULT;
1158  return -1;
1159 }
1160
1161 ROAR_DBG("open(pathname='%s', flags=%x, ...) = ?\n", pathname, flags);
[3142]1162 ret = _open_file(pathname, flags);
1163
1164 switch (ret) {
1165  case -2:       // continue as normal, use _op.open()
[4081]1166    ROAR_DBG("open(pathname='%s', flags=%x, ...): is not handled by us, pass to kernel\n", pathname, flags);
[3142]1167   break;
1168  case -1:       // pass error to caller
1169    return -1;
1170   break;
1171  default:       // return successfully opened pointer to caller
1172    return ret;
1173   break;
1174 }
1175
[3138]1176 if (flags & O_CREAT) {
1177  va_start(args, flags);
[3891]1178  mode = va_arg(args, _VA_ARGS_MODE_T);
[3138]1179  va_end(args);
1180 }
1181
1182 return _os.open(pathname, flags, mode);
1183}
1184
[3866]1185int    open64(const char *__file, int __oflag, ...) {
1186 int     ret;
1187 mode_t  mode = 0;
1188 va_list args;
1189
1190 _init();
1191
1192 if ( __file == NULL ) {
1193  errno = EFAULT;
1194  return -1;
1195 }
1196
[4081]1197 ROAR_DBG("open64(__file='%s', __oflags=%x, ...) = ?", __file, __oflag);
[3866]1198 ret = _open_file(__file, __oflag);
1199
1200 switch (ret) {
1201  case -2:       // continue as normal, use _op.open()
[4081]1202    ROAR_DBG("open64(__file='%s', __oflags=%x, ...): not for us, passing to kernel", __file, __oflag);
[3866]1203   break;
1204  case -1:       // pass error to caller
1205    return -1;
1206   break;
1207  default:       // return successfully opened pointer to caller
[4081]1208    ROAR_DBG("open64(__file='%s', __oflags=%x, ...) = %i", __file, __oflag, ret);
[3866]1209    return ret;
1210   break;
1211 }
1212
1213 if (__oflag & O_CREAT) {
1214  va_start(args, __oflag);
[3891]1215  mode = va_arg(args, _VA_ARGS_MODE_T);
[3866]1216  va_end(args);
1217 }
1218
1219 if ( _os.open64 != NULL ) {
1220  return _os.open64(__file, __oflag, mode);
1221 } else {
1222#ifdef O_LARGEFILE
1223  return _os.open(__file, __oflag | O_LARGEFILE, mode);
1224#else
1225  return _os.open(__file, __oflag, mode);
1226#endif
1227 }
1228}
1229
[3138]1230int     close(int fd) {
[3140]1231 struct pointer * pointer;
[3138]1232 _init();
1233
[3140]1234 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
1235  _close_pointer(pointer);
1236  return 0;
1237 }
1238
[3138]1239 return _os.close(fd);
1240}
1241
1242ssize_t write(int fd, const void *buf, size_t count) {
[3261]1243 struct roar_roardmx_message roardmxmsg;
[3140]1244 struct pointer * pointer;
[3178]1245 ssize_t ret;
[3639]1246 size_t i;
[3140]1247
[3138]1248 _init();
1249
[3140]1250 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
[3655]1251  ROAR_DBG("write(fd=%i, buf=%p, count=%lu) = ? // pointer write", fd, buf, (long unsigned int) count);
[3261]1252  switch (pointer->handle->type) {
[3664]1253   case HT_STREAM: // handle stream specific stuff
[3261]1254     if ( pointer->handle->stream_opened == 0 ) {
1255      if ( _open_stream(pointer->handle) == -1 ) {
1256       errno = EIO;
1257       return -1;
1258      }
1259     }
[3664]1260   case HT_VIO: // from here we only look at the VIO object of streams, or handle simple VIOs
[3261]1261     ret = roar_vio_write(&(pointer->handle->stream_vio), (char*)buf, count);
1262     if ( ret > 0 )
1263      pointer->handle->writec += ret;
1264     return ret;
1265    break;
[3664]1266   case HT_DMX: // DMX need specal handling as we need to convert the protocol
[3261]1267     if ( pointer->handle->stream_opened == 0 ) {
1268      if ( _open_stream(pointer->handle) == -1 ) {
1269       errno = EIO;
1270       return -1;
1271      }
1272     }
1273     if ( count > 0 ) {
1274      if ( roar_roardmx_message_new_sset(&roardmxmsg) == -1 ) {
1275       errno = EIO;
1276       return -1;
1277      }
1278      for (i = 0; i < count; i++) {
1279       if ( roar_roardmx_message_add_chanval(&roardmxmsg, pointer->handle->pos + i, ((unsigned char*)buf)[i]) == -1 ) {
1280#ifdef EMSGSIZE
1281        errno = EMSGSIZE;
1282#else
1283        errno = EIO;
1284#endif
1285        return -1;
1286       }
1287      }
1288      if ( roar_roardmx_message_send(&roardmxmsg, &(pointer->handle->stream_vio)) == -1 ) {
1289       errno = EIO;
1290       return -1;
1291      }
1292     }
1293     pointer->handle->pos += count;
1294     return count;
1295    break;
[3664]1296   default: // we don't know what to do with other types
[3261]1297     errno = EINVAL;
[3140]1298     return -1;
[3261]1299    break;
[3140]1300  }
1301 }
1302
[3138]1303 return _os.write(fd, buf, count);
1304}
1305
1306ssize_t read(int fd, void *buf, size_t count) {
[3140]1307 struct pointer * pointer;
[3178]1308 ssize_t ret;
[3140]1309
[3138]1310 _init();
1311
[3140]1312 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
[3666]1313  ROAR_DBG("read(fd=%i, buf=%p, count=%lu) = ? // pointer read", fd, buf, (long unsigned int)count);
1314
[3664]1315  switch (pointer->handle->type) {
1316   case HT_STREAM:
1317     if ( pointer->handle->stream_opened == 0 ) {
1318      if ( _open_stream(pointer->handle) == -1 ) {
1319       errno = EIO;
1320       return -1;
1321      }
1322     }
1323   case HT_VIO:
1324     ret = roar_vio_read(&(pointer->handle->stream_vio), buf, count);
1325     if ( ret > 0 )
1326      pointer->handle->readc += ret;
1327     return ret;
1328    break;
[3666]1329   case HT_STATIC:
1330     ROAR_DBG("read(fd=%i, buf=%p, count=%lu) = ? // type=HT_STATIC", fd, buf, (long unsigned int)count);
1331     ret = pointer->handle->pos + count; // calc the end of the read
1332
1333     if ( ret > (ssize_t)pointer->handle->userdata.sf.len ) {
1334      count = pointer->handle->userdata.sf.len - pointer->handle->pos;
1335     }
1336
1337     memcpy(buf, pointer->handle->userdata.sf.data + pointer->handle->pos, count);
1338     pointer->handle->pos += count;
1339     return count;
1340    break;
[3664]1341   default:
1342     errno = EINVAL;
[3140]1343     return -1;
[3664]1344    break;
[3140]1345  }
1346 }
1347
[3138]1348 return _os.read(fd, buf, count);
1349}
1350
[3246]1351off_t lseek(int fildes, off_t offset, int whence) {
1352 struct pointer * pointer;
[3666]1353 ssize_t tmp;
[3246]1354
1355 _init();
1356
1357 if ( (pointer = _get_pointer_by_fh(fildes)) != NULL ) {
[3664]1358  switch (pointer->handle->type) {
1359   case HT_DMX:
1360     switch (whence) {
1361      case SEEK_SET:
1362        pointer->handle->pos  = offset;
1363       break;
1364      case SEEK_CUR:
1365        pointer->handle->pos += offset;
1366       break;
1367      case SEEK_END:
1368      default:
1369        errno = EINVAL;
1370        return -1;
1371       break;
1372     }
1373     return pointer->handle->pos;
1374    break;
1375   case HT_VIO:
1376     return roar_vio_lseek(&(pointer->handle->stream_vio), offset, whence);
1377    break;
[3666]1378   case HT_STATIC:
1379     switch (whence) {
1380      case SEEK_SET:
1381        if ( offset < 0 || offset > (ssize_t)pointer->handle->userdata.sf.len ) {
1382         errno = EINVAL;
1383         return -1;
1384        }
1385        pointer->handle->pos  = offset;
1386       break;
1387      case SEEK_CUR:
1388        tmp = pointer->handle->pos + offset;
1389        if ( tmp < 0 || tmp > (ssize_t)pointer->handle->userdata.sf.len ) {
1390         errno = EINVAL;
1391         return -1;
1392        }
1393        pointer->handle->pos = tmp;
1394       break;
1395      case SEEK_END:
1396        tmp = pointer->handle->userdata.sf.len + offset;
1397        if ( tmp < 0 || tmp > (ssize_t)pointer->handle->userdata.sf.len ) {
1398         errno = EINVAL;
1399         return -1;
1400        }
1401        pointer->handle->pos = tmp;
1402       break;
1403      default:
1404        errno = EINVAL;
1405        return -1;
1406       break;
1407     }
1408    break;
[3664]1409   default:
1410     errno = EINVAL;
1411     return -1;
1412    break;
[3246]1413  }
1414 }
1415
1416 return _os.lseek(fildes, offset, whence);
1417}
1418
[3169]1419IOCTL() {
1420 map_args;
[3147]1421 struct pointer * pointer;
1422 struct handle  * handle;
[3169]1423 int * ip = NULL;
[3655]1424 size_t tmp;
[3176]1425 audio_buf_info * bi;
[3178]1426 count_info     * ci;
[3229]1427#ifdef __FIXME__
1428 char * nosys_reqname = NULL;
1429#endif
[3169]1430#ifdef va_argp
[3146]1431 va_list args;
[3169]1432#endif
[3146]1433
1434 _init();
1435
[4079]1436 ROAR_DBG("ioctl(__fd=%i, __request=0x%lX) = ?", __fd, (long unsigned int) __request);
[3148]1437
[3169]1438#ifdef va_argp
[3180]1439 va_start (args, ioctl_lastarg);
[3146]1440 argp = va_arg (args, void *);
1441 va_end (args);
[3169]1442#endif
[3146]1443
[4079]1444// ROAR_DBG("ioctl(fh=%i, request=%i, ...) = ?", __fd, __request);
[4077]1445
[4079]1446 ROAR_DBG("ioctl(__fd=%i, __request=0x%lX): argp=%p", __fd, (long unsigned int) __request, argp);
[3148]1447
[3147]1448 if ( (pointer = _get_pointer_by_fh(__fd)) != NULL ) {
[3148]1449  ip = argp;
[3656]1450//  ROAR_DBG("ioctl(__fd=%i, __request=0x%lx): ip=%p", __fd, (long unsigned int) __request, ip);
[3229]1451#ifdef __FIXME__
[4079]1452  switch (__request) {
[3792]1453   case SOUND_PCM_READ_RATE: nosys_reqname     = "SOUND_PCM_READ_RATE";     break;
[3229]1454   case SOUND_PCM_READ_CHANNELS: nosys_reqname = "SOUND_PCM_READ_CHANNELS"; break;
[3792]1455   case SOUND_PCM_READ_BITS: nosys_reqname     = "SOUND_PCM_READ_BITS";     break;
1456   case SOUND_PCM_READ_FILTER: nosys_reqname   = "SOUND_PCM_READ_FILTER";   break;
1457   case SNDCTL_COPR_RESET: nosys_reqname       = "SNDCTL_COPR_RESET";       break;
1458   case SNDCTL_COPR_LOAD: nosys_reqname        = "SNDCTL_COPR_LOAD";        break;
1459   case SNDCTL_COPR_HALT: nosys_reqname        = "SNDCTL_COPR_HALT";        break;
1460   case SNDCTL_COPR_RDATA: nosys_reqname       = "SNDCTL_COPR_RDATA";       break;
1461   case SNDCTL_COPR_RCODE: nosys_reqname       = "SNDCTL_COPR_RCODE";       break;
1462   case SNDCTL_COPR_WDATA: nosys_reqname       = "SNDCTL_COPR_WDATA";       break;
1463   case SNDCTL_COPR_WCODE: nosys_reqname       = "SNDCTL_COPR_WCODE";       break;
1464   case SNDCTL_COPR_RUN: nosys_reqname         = "SNDCTL_COPR_RUN";         break;
1465   case SNDCTL_COPR_SENDMSG: nosys_reqname     = "SNDCTL_COPR_SENDMSG";     break;
1466   case SNDCTL_COPR_RCVMSG: nosys_reqname      = "SNDCTL_COPR_RCVMSG";      break;
1467   case SNDCTL_DSP_GETCAPS: nosys_reqname      = "SNDCTL_DSP_GETCAPS";      break;
[3654]1468   default: nosys_reqname = "<<<UNKNOWN>>>"; break;
[3229]1469/*
1470   case : nosys_reqname = ""; break;
1471   case : nosys_reqname = ""; break;
1472   case : nosys_reqname = ""; break;
1473*/
1474  }
1475#endif
[3147]1476  switch ((handle = pointer->handle)->type) {
1477   case HT_STREAM:
1478     switch (__request) {
1479      case SNDCTL_DSP_RESET:
1480      case SNDCTL_DSP_POST:
[3654]1481      case SNDCTL_DSP_SYNC: // ignore for the moment.
[3162]1482      case SNDCTL_DSP_SETFRAGMENT: // any fragments should be ok for us...
[3654]1483      case SNDCTL_DSP_SETTRIGGER: // we should implement this using PAUSE flag.
[3175]1484        return 0;
[3147]1485       break;
1486      case SNDCTL_DSP_SPEED:
1487        handle->stream.info.rate = *ip;
[3656]1488        ROAR_DBG("ioctl(__fd=%i, __request=0x%lX): rate=%i", __fd, (long unsigned int) __request, *ip);
[3147]1489        return 0;
1490       break;
1491      case SNDCTL_DSP_CHANNELS:
1492        handle->stream.info.channels = *ip;
[3656]1493        ROAR_DBG("ioctl(__fd=%i, __request=0x%lX): channels=%i", __fd, (long unsigned int) __request, *ip);
[3147]1494        return 0;
1495       break;
[3160]1496      case SNDCTL_DSP_STEREO:
1497        handle->stream.info.channels = *ip ? 2 : 1;
1498        return 0;
1499       break;
[3161]1500      case SNDCTL_DSP_GETBLKSIZE:
[3178]1501        *ip = _get_stream_buffersize(handle);
[3161]1502        return 0;
1503       break;
[3147]1504      case SNDCTL_DSP_SETFMT:
[3656]1505        ROAR_DBG("ioctl(__fd=%i, __request=0x%lX): fmt=0x%x", __fd, (long unsigned int) __request, *ip);
[3147]1506        return _ioctl_stream_format(handle, *ip);
1507       break;
[3148]1508      case SNDCTL_DSP_GETFMTS:
[3656]1509//        ROAR_DBG("ioctl(__fd=%i, __request=0x%lX): ip=%p", __fd, (long unsigned int) __request, ip);
[3149]1510        *ip = _ioctl_stream_format_list();
[3148]1511        return 0;
1512       break;
[3176]1513      case SNDCTL_DSP_GETOSPACE:
1514      case SNDCTL_DSP_GETISPACE:
1515        bi = argp;
1516        memset(bi, 0, sizeof(*bi));
[3178]1517        bi->bytes      = _get_stream_buffersize(handle);
[3176]1518        bi->fragments  = 1;
1519        bi->fragsize   = bi->bytes;
1520        bi->fragstotal = 1;
1521        return 0;
1522       break;
[3178]1523      case SNDCTL_DSP_GETOPTR:
[3655]1524        ROAR_DBG("ioctl(__fd=%i, __request=0x%lX): writec=%lu", __fd, (long unsigned int) __request, (long unsigned int) handle->writec);
[3178]1525        ci = argp;
1526        memset(ci, 0, sizeof(*ci));
1527        ci->bytes  = handle->writec;
[3655]1528        ci->blocks = ci->bytes / (tmp = _get_stream_buffersize(handle));
1529        ci->ptr    = ci->bytes % tmp;
[3178]1530        return 0;
1531       break;
1532      case SNDCTL_DSP_GETIPTR:
1533        ci = argp;
1534        memset(ci, 0, sizeof(*ci));
1535        ci->bytes  = handle->readc;
[3655]1536        ci->blocks = ci->bytes / (tmp = _get_stream_buffersize(handle));
1537        ci->ptr    = ci->bytes % tmp;
[3178]1538        return 0;
1539       break;
[3177]1540#ifdef SNDCTL_DSP_GETPLAYVOL
1541      case SNDCTL_DSP_GETPLAYVOL:
1542        return _ioctl_mixer(handle, SOUND_MIXER_READ_PCM, argp);
1543       break;
1544#endif
1545#ifdef SNDCTL_DSP_SETPLAYVOL
1546      case SNDCTL_DSP_SETPLAYVOL:
1547        return _ioctl_mixer(handle, SOUND_MIXER_WRITE_PCM, argp);
1548       break;
1549#endif
[3864]1550#ifdef SNDCTL_DSP_NONBLOCK
1551      case SNDCTL_DSP_NONBLOCK:
1552        return fcntl(__fd, F_SETFL, handle->sysio_flags|O_NONBLOCK);
1553       break;
1554#endif
[3147]1555      default:
[3229]1556#ifdef __FIXME__
[3656]1557        ROAR_DBG("ioctl(__fd=%i, __request=0x%lX (%s)) = -1 // errno = ENOSYS", __fd, (long unsigned int) __request, nosys_reqname);
[3229]1558#else
[3656]1559        ROAR_DBG("ioctl(__fd=%i, __request=0x%lX) = -1 // errno = ENOSYS", __fd, (long unsigned int) __request);
[3229]1560#endif
[3147]1561        errno = ENOSYS;
1562        return -1;
1563     }
1564    break;
1565   case HT_MIXER:
[3158]1566     return _ioctl_mixer(handle, __request, argp);
[3147]1567    break;
1568   default:
[3656]1569     ROAR_DBG("ioctl(__fd=%i, __request=0x%lX): unknown handle type: no ioctl()s supported", __fd, (long unsigned int) __request);
1570     ROAR_DBG("ioctl(__fd=%i, __request=0x%lX) = -1 // errno = ENOSYS", __fd, (long unsigned int) __request);
[3147]1571     errno = EINVAL;
1572     return -1;
1573    break;
1574  }
1575 }
1576
[3166]1577#ifdef IOCTL_IS_ALIAS
1578 errno = ENOSYS;
1579 return -1;
1580#else
[4081]1581 ROAR_DBG("ioctl(__fd=%i, __request=0x%lX, argp=%p): not for us, passing to kernel", __fd, (long unsigned int) __request, argp);
[3146]1582 return _os.ioctl(__fd, __request, argp);
[3166]1583#endif
[3146]1584}
1585
[3657]1586int dup(int oldfd) {
1587 struct pointer * pointer;
1588 int ret;
1589
1590 _init();
1591
1592 ret = _os.dup(oldfd);
1593
1594 if (ret == -1)
1595  return -1;
1596
1597 if ( (pointer = _get_pointer_by_fh(oldfd)) != NULL ) {
1598  if ( _attach_pointer(pointer->handle, ret) == NULL ) {
1599   _os.close(ret);
1600   return -1;
1601  }
1602 }
1603
1604 return ret;
1605}
1606
1607int dup2(int oldfd, int newfd) {
1608 struct pointer * pointer;
1609 int ret;
1610
1611 _init();
1612
1613 ret = _os.dup2(oldfd, newfd);
1614
1615 if (ret == -1)
1616  return -1;
1617
1618 if ( (pointer = _get_pointer_by_fh(oldfd)) != NULL ) {
1619  if ( _attach_pointer(pointer->handle, ret) == NULL ) {
1620   _os.close(ret);
1621   return -1;
1622  }
1623 }
1624
1625 return ret;
1626}
[3264]1627
[3771]1628int select(int nfds, fd_set *readfds, fd_set *writefds,
1629           fd_set *exceptfds, struct timeval *timeout) {
1630 struct roar_vio_selecttv rtv;
1631 struct roar_vio_select * sv  = NULL;
[3774]1632 struct pointer * pointer;
1633 struct handle  * handle;
[3771]1634 ssize_t ret;
1635 size_t num = 0;
[3773]1636 size_t idx;
[3771]1637 int i;
1638 int i_r, i_w, i_e;
1639 int max_index = -1;
[3773]1640 static volatile int is_critical = 0;
[3771]1641
1642 _init();
1643
1644 if ( is_critical )
1645  return _os.select(nfds, readfds, writefds, exceptfds, timeout);
1646
1647 ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = ?", nfds, readfds, writefds, exceptfds, timeout);
1648
1649 if ( nfds == 0 ) {
1650  ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = 0", nfds, readfds, writefds, exceptfds, timeout);
1651  return 0;
1652 }
1653
1654 if ( readfds == NULL && writefds == NULL && exceptfds == NULL ) {
1655  ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = 0", nfds, readfds, writefds, exceptfds, timeout);
1656  return 0;
1657 }
1658
1659 if ( timeout != NULL ) {
1660  rtv.sec = timeout->tv_sec;
1661  rtv.nsec = timeout->tv_usec*1000;
1662 }
1663
1664 // count number of handles:
1665 for (i = 0; i < nfds; i++) {
1666  ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p): i=%i, EXISTS", nfds, readfds, writefds, exceptfds, timeout, i);
1667  if ( (readfds   != NULL && FD_ISSET(i, readfds  )) ||
1668       (writefds  != NULL && FD_ISSET(i, writefds )) ||
1669       (exceptfds != NULL && FD_ISSET(i, exceptfds))
1670     ) {
1671   ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p): i=%i, EXISTS", nfds, readfds, writefds, exceptfds, timeout, i);
1672   num++;
1673   max_index = i;
1674  }
1675 }
1676
1677 if ( num == 0 ) {
1678  ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = 0", nfds, readfds, writefds, exceptfds, timeout);
1679  return 0;
1680 }
1681
1682 nfds = max_index + 1;
1683
1684 // create sv;
1685 sv = roar_mm_malloc(sizeof(struct roar_vio_select)*num);
1686 if ( sv == NULL ) {
1687  ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = -1", nfds, readfds, writefds, exceptfds, timeout);
1688  return -1;
1689 }
1690
1691 memset(sv, 0, sizeof(struct roar_vio_select)*num);
1692
1693 for (i = 0, idx = 0; i < nfds; i++) {
1694  if ( idx >= num ) {
1695   roar_mm_free(sv);
1696   errno = EFAULT;
1697   ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = -1 // i=%i, idx=%i, num=%i", nfds, readfds, writefds, exceptfds, timeout, i, (int)idx, (int)num);
1698   return -1;
1699  }
1700  i_r = readfds   != NULL && FD_ISSET(i, readfds);
1701  i_w = writefds  != NULL && FD_ISSET(i, writefds);
1702  i_e = exceptfds != NULL && FD_ISSET(i, exceptfds);
1703
1704  ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p): i=%i, i_r=%i, i_w=%i, i_e=%i", nfds, readfds, writefds, exceptfds, timeout, i, i_r, i_w, i_e);
1705
1706  if ( i_r || i_w || i_e ) {
1707   // TODO: use VIO for pointers...
[3774]1708   if ( (pointer = _get_pointer_by_fh(i)) != NULL ) {
1709    handle = pointer->handle;
1710    sv[idx].vio     = NULL;
1711    sv[idx].fh      = -1;
1712    switch (handle->type) {
1713     case HT_DMX:
1714     case HT_STREAM:
1715       if ( ! handle->stream_opened ) {
1716        // implement this as statichly return OK
1717        errno = ENOSYS;
1718        return -1;
1719       }
1720     case HT_VIO:
1721       sv[idx].vio = &(handle->stream_vio);
1722      break;
1723     default: /* non supported type */
1724       errno = EINVAL;
1725       return -1;
1726      break;
1727    }
1728   } else {
1729    sv[idx].vio     = NULL;
1730    sv[idx].fh      = i;
1731   }
[3771]1732
1733   sv[idx].ud.si   = i;
1734   sv[idx].eventsq = (i_r ? ROAR_VIO_SELECT_READ   : 0) |
1735                     (i_w ? ROAR_VIO_SELECT_WRITE  : 0) |
1736                     (i_e ? ROAR_VIO_SELECT_EXCEPT : 0);
1737   idx++;
1738  }
1739 }
1740
1741 is_critical++;
1742 ret = roar_vio_select(sv, num, timeout == NULL ? NULL : &rtv, NULL);
1743 is_critical--;
1744
1745 if ( ret < 1 ) {
1746  roar_mm_free(sv);
1747  ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = %i", nfds, readfds, writefds, exceptfds, timeout, (int)ret);
[4226]1748
1749  if ( ret == 0 ) {
1750   if ( readfds != NULL ) {
1751    FD_ZERO(readfds);
1752   }
1753   if ( writefds != NULL ) {
1754    FD_ZERO(writefds);
1755   }
[4227]1756   if ( exceptfds != NULL ) {
[4226]1757    FD_ZERO(exceptfds);
1758   }
1759  }
1760
[3771]1761  return ret;
1762 }
1763
1764 // update readfds, writefds, exceptfds:
1765 if ( readfds != NULL )
1766  FD_ZERO(readfds);
1767
1768 if ( writefds != NULL )
1769  FD_ZERO(writefds);
1770
1771 if ( exceptfds != NULL )
1772  FD_ZERO(exceptfds);
1773
1774 for (idx = 0; idx < num; idx++) {
1775  if ( sv[idx].eventsa == 0 )
1776   continue;
1777
1778  if ( sv[idx].eventsa & ROAR_VIO_SELECT_READ )
1779   if ( readfds != NULL )
1780    FD_SET(sv[idx].ud.si, readfds);
1781
1782  if ( sv[idx].eventsa & ROAR_VIO_SELECT_WRITE )
1783   if ( writefds != NULL )
1784    FD_SET(sv[idx].ud.si, writefds);
1785
1786  if ( sv[idx].eventsa & ROAR_VIO_SELECT_EXCEPT )
1787   if ( exceptfds != NULL )
1788    FD_SET(sv[idx].ud.si, exceptfds);
1789 }
1790
1791 roar_mm_free(sv);
1792
1793 ROAR_DBG("select(nfds=%i, readfds=%p, writefds=%p, exceptfds=%p, timeout=%p) = %i", nfds, readfds, writefds, exceptfds, timeout, (int)ret);
1794 return ret;
1795}
1796
[3778]1797int fcntl(int fd, int cmd, ...) {
1798 enum { NONE, UNKNOWN, LONG, POINTER } type = NONE;
1799 struct pointer * pointer;
1800 va_list ap;
1801 long argl = -1;
1802 void * vp = NULL;
[3780]1803 int ret   = -1;
1804 int diff;
[3778]1805
[3779]1806 _init();
1807
[3781]1808 ROAR_DBG("fcntl(fd=%i, cmd=%i, ...) = ?", fd, cmd);
1809
[3778]1810 switch (cmd) {
1811  case F_DUPFD:
1812  case F_SETFD:
1813  case F_SETFL:
1814  case F_SETOWN:
[3872]1815#ifdef F_SETSIG
[3778]1816  case F_SETSIG:
[3872]1817#endif
1818#ifdef F_SETLEASE
[3778]1819  case F_SETLEASE:
[3872]1820#endif
1821#ifdef F_NOTIFY
[3778]1822  case F_NOTIFY:
[3872]1823#endif
[3778]1824    type = LONG;
1825   break;
1826  case F_GETFD:
1827  case F_GETFL:
1828  case F_GETOWN:
[3872]1829#ifdef F_GETSIG
[3778]1830  case F_GETSIG:
[3872]1831#endif
1832#ifdef F_GETLEASE
[3778]1833  case F_GETLEASE:
[3872]1834#endif
[3778]1835    type = NONE;
1836   break;
1837  case F_GETLK:
1838  case F_SETLK:
1839  case F_SETLKW:
[4081]1840#ifdef F_GETLK64
[4121]1841#if F_GETLK64 != F_GETLK
[4081]1842  case F_GETLK64:
1843#endif
[4121]1844#endif
[4081]1845#ifdef F_SETLK64
[4121]1846#if F_SETLK64 != F_SETLK
[4081]1847  case F_SETLK64:
1848#endif
[4121]1849#endif
[4081]1850#ifdef F_SETLKW64
[4121]1851#if F_SETLKW64 != F_SETLKW
[4081]1852  case F_SETLKW64:
1853#endif
[4121]1854#endif
[3778]1855    type = POINTER;
1856   break;
1857/*
1858  case F_EXLCK:
1859  case F_GETLK64:
1860  case F_SETLK64:
1861  case F_SETLKW64:
1862  case F_SHLCK:
1863  case F_LINUX_SPECIFIC_BASE:
1864  case F_INPROGRESS:
1865*/
1866  default:
1867    type = UNKNOWN;
1868 }
1869
1870 if ( type == UNKNOWN ) {
[4081]1871  ROAR_DBG("fcntl(fd=%i, cmd=%i, ...): unknown data type!", fd, cmd);
1872  ROAR_DBG("fcntl(fd=%i, cmd=%i, ...) = -1 // errno = EINVAL", fd, cmd);
[3778]1873  errno = EINVAL;
1874  return -1;
1875 }
1876
1877 if ( type != NONE ) {
1878  va_start(ap, cmd);
1879  switch (type) {
1880   case LONG:
1881     argl = va_arg(ap, long);
1882    break;
1883   case POINTER:
1884     vp = va_arg(ap, void*);
1885    break;
1886   default: /* make compiler happy */
1887    break;
1888  }
1889  va_end(ap);
1890 }
1891
1892 if ( (pointer = _get_pointer_by_fh(fd)) == NULL ) {
1893  switch (type) {
1894   case NONE:
[3781]1895     ROAR_DBG("fcntl(fd=%i, cmd=%i): fd is true sysio, pass call to kernel", fd, cmd);
[3778]1896     return _os.fcntl(fd, cmd);
1897    break;
1898   case LONG:
[3781]1899     ROAR_DBG("fcntl(fd=%i, cmd=%i, arg=%li): fd is true sysio, pass call to kernel", fd, cmd, argl);
[3778]1900     return _os.fcntl(fd, cmd, argl);
1901    break;
1902   case POINTER:
[3781]1903     ROAR_DBG("fcntl(fd=%i, cmd=%i, lock=%p): fd is true sysio, pass call to kernel", fd, cmd, vp);
[3778]1904     return _os.fcntl(fd, cmd, vp);
1905    break;
1906   default: /* make compiler happy */
1907    break;
1908  }
1909 }
1910
[3781]1911 ROAR_DBG("fcntl(fd=%i, cmd=%i, ...): fd is true pointer, handle internaly", fd, cmd);
1912
[3780]1913 switch (cmd) {
1914  case F_DUPFD:
1915    ret = _os.fcntl(fd, F_DUPFD, argl);
1916
1917    if ( ret != -1 ) {
1918     if ( _attach_pointer(pointer->handle, ret) == NULL ) {
1919      _os.close(ret);
1920      ret = -1;
1921     }
1922    }
1923   break;
1924  case F_SETFD:
1925    if ( argl == 0 ) {
1926     ret = 0;
1927    } else {
1928     errno = ENOSYS;
1929     ret = -1;
1930    }
1931   break;
1932  case F_GETFD:
1933    ret = 0;
1934   break;
1935  case F_GETFL:
1936    ret = pointer->handle->sysio_flags;
1937   break;
1938  case F_SETFL:
1939    diff  = (int)argl ^ pointer->handle->sysio_flags;
[3868]1940    diff &= (int)~(int)_O_PARA_DIR;
1941    diff &= (int)~(int)_O_PARA_IGN;
[3849]1942
1943    if ( diff & O_NONBLOCK ) {
1944     diff -= O_NONBLOCK;
1945     pointer->handle->sysio_flags ^= O_NONBLOCK;
1946     if ( _update_nonblock(pointer->handle) == -1 ) {
1947      pointer->handle->sysio_flags ^= O_NONBLOCK;
1948      return -1;
1949     }
1950    }
1951
[3780]1952    if ( diff == 0 ) { // only flags changed we ignore anyway.
[3849]1953     pointer->handle->sysio_flags  = (int)argl;
[3780]1954     ret = 0;
1955    } else {
1956     errno = EINVAL;
1957     ret = -1;
1958    }
1959   break;
1960/* TODO: add support for those types:
1961  case F_SETFD:
1962  case F_SETOWN:
1963  case F_SETSIG:
1964  case F_SETLEASE:
1965  case F_NOTIFY:
1966  case F_GETOWN:
1967  case F_GETSIG:
1968  case F_GETLEASE:
1969  case F_GETLK:
1970  case F_SETLK:
1971  case F_SETLKW:
1972*/
1973  default:
1974    errno = ENOSYS;
1975    ret = -1;
1976   break;
1977 }
1978
1979 return ret;
[3778]1980}
1981
[3782]1982int access(const char *pathname, int mode) {
[3783]1983 struct devices * ptr = NULL;
[3782]1984
1985 _init();
1986
[3870]1987 if ( (ptr = _get_device(pathname)) != NULL ) {
[3783]1988  // the only flag we do not support is +x, which means
1989  // we need to reject all requets with X_OK.
1990  if ( mode & X_OK ) {
1991   errno = EACCES;
1992   return -1;
1993  }
1994
1995  // in addition HT_STATIC files do not support write (+w)
1996  // so we need to reject W_OK.
1997  if ( ptr->type == HT_STATIC && (mode & W_OK) ) {
1998   errno = EACCES;
1999   return -1;
2000  }
2001
2002  // Else the access is granted:
2003  return 0;
2004 }
2005
[3782]2006 return _os.access(pathname, mode);
2007}
2008
[3890]2009int creat(const char *_CREAT_ARG_PATHNAME, mode_t mode) {
[3871]2010 _init();
2011
[3890]2012 if ( _get_device(_CREAT_ARG_PATHNAME) != NULL ) {
[3871]2013  errno = EEXIST;
2014  return -1;
2015 }
2016
[3890]2017 return _os.creat(_CREAT_ARG_PATHNAME, mode);
[3871]2018}
2019
[3264]2020// -------------------------------------
[3880]2021// emulated *stat*() functions follow:
2022// -------------------------------------
2023
2024int stat(const char *path, struct stat *buf) {
2025 struct devices * ptr;
2026
2027 _init();
2028
2029 if ( (ptr = _get_device(path)) != NULL ) {
2030  errno = ENOSYS;
2031  return -1;
2032 }
2033
2034 return _os.stat(path, buf);
2035}
2036
2037int fstat(int filedes, struct stat *buf) {
2038 struct pointer * pointer;
2039
2040 _init();
2041
2042 if ( (pointer = _get_pointer_by_fh(filedes)) == NULL ) {
2043  return _os.fstat(filedes, buf);
2044 }
2045
2046 errno = ENOSYS;
2047 return -1;
2048}
2049
2050int lstat(const char *path, struct stat *buf) {
2051 _init();
2052
2053 if ( _get_device(path) != NULL ) {
2054  return stat(path, buf);
2055 }
2056
2057 return _os.lstat(path, buf);
2058}
2059
2060// -------------------------------------
[3264]2061// emulated stdio functions follow:
2062// -------------------------------------
2063
2064//roar_vio_to_stdio
2065
[3667]2066static int _vio_close    (struct roar_vio_calls * vio) {
2067 int ret = 0;
2068
2069 if ( roar_vio_get_fh(vio) != -1 )
2070  ret = close(roar_vio_get_fh(vio));
2071
2072 roar_mm_free(vio);
2073
2074 return ret;
2075}
2076
[3264]2077FILE *fopen(const char *path, const char *mode) {
[3667]2078 struct roar_vio_calls * vio;
[3264]2079 FILE  * fr;
2080 int     ret;
2081 int     r = 0, w = 0;
2082 int     flags = 0;
2083 int     i;
2084 register char c;
2085
2086 _init();
2087
2088 if ( path == NULL || mode == NULL ) {
2089  errno = EFAULT;
2090  return NULL;
2091 }
2092
[3265]2093 ROAR_DBG("open(path='%s', mode='%s') = ?\n", path, mode);
[3264]2094
2095 for (i = 0; (c = mode[i]) != 0; i++) {
2096  switch (c) {
2097   case 'r': r = 1; break;
2098   case 'w': w = 1; break;
2099   case 'a': w = 1; break;
2100   case '+':
2101     r = 1;
2102     w = 1;
2103    break;
2104  }
2105 }
2106
2107 if ( r && w ) {
2108  flags = O_RDWR;
2109 } else if ( r ) {
2110  flags = O_RDONLY;
2111 } else if ( w ) {
2112  flags = O_WRONLY;
2113 } else {
2114  errno = EINVAL;
2115  return NULL;
2116 }
2117
2118 ret = _open_file(path, flags);
2119
2120 switch (ret) {
2121  case -2:       // continue as normal, use _op.open()
[4081]2122    ROAR_DBG("fopen(path='%s', mode='%s'): not for us, passing to libc", path, mode);
[3264]2123   break;
2124  case -1:       // pass error to caller
2125    return NULL;
2126   break;
2127  default:       // return successfully opened pointer to caller
[4080]2128#ifdef __USE_FDOPEN__
2129    ROAR_DBG("fopen(path='%s', mode='%s') = fdopen(%i, '%s')", path, mode, ret, mode);
2130    return fdopen(ret, r ? (w ? "rw" : "r") : "w");
2131#else
[3667]2132    if ( (vio = roar_mm_malloc(sizeof(struct roar_vio_calls))) == NULL ) {
2133     return NULL; // errno should be set correctly by roar_mm_malloc().
2134    }
2135
2136    roar_vio_init_calls(vio);  // TODO: add error handling.
2137    roar_vio_set_fh(vio, ret); // TODO: add error handling.
2138    vio->close = _vio_close;
2139    if ( (fr = roar_vio_to_stdio(vio, flags)) == NULL ) {
2140     _vio_close(vio);
2141     errno = EIO;
2142     return NULL;
2143    } else {
2144     return fr;
2145    }
[4080]2146#endif
[3264]2147   break;
2148 }
2149
2150 return _os.fopen(path, mode);
2151}
2152
[3879]2153// -------------------------------------
2154// RoarAudio plugin functions follow:
2155// -------------------------------------
2156
2157ROAR_DL_PLUGIN_START(libroaross) {
2158 (void)para;
2159 _init();
2160} ROAR_DL_PLUGIN_END
2161
[3138]2162#endif
2163
2164//ll
Note: See TracBrowser for help on using the repository browser.