source: roaraudio/libroaross/libroaross.c @ 4079:869ec5347fb5

Last change on this file since 4079:869ec5347fb5 was 4079:869ec5347fb5, checked in by phi, 14 years ago

fixed some small bugs

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