source: roaraudio/libroaross/libroaross.c @ 4006:b5b7f0b40322

Last change on this file since 4006:b5b7f0b40322 was 3953:191e7d8fe7fc, checked in by phi, 14 years ago

init with save defaults

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