source: roaraudio/libroaross/libroaross.c @ 3167:3acda2883192

Last change on this file since 3167:3acda2883192 was 3167:3acda2883192, checked in by phi, 14 years ago

redefine mode_t for FreeBSD

File size: 20.9 KB
RevLine 
[3138]1//libroaross.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 *  NOTE for everyone want's to change something and send patches:
24 *  read README and HACKING! There a addition information on
25 *  the license of this document you need to read before you send
26 *  any patches.
27 *
28 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
29 *  or libpulse*:
30 *  The libs libroaresd, libroararts and libroarpulse link this lib
31 *  and are therefore GPL. Because of this it may be illigal to use
32 *  them with any software that uses libesd, libartsc or libpulse*.
33 */
34
35#include "roaraudio.h"
36
37#if defined(ROAR_HAVE_OSS_BSD) || defined(ROAR_HAVE_OSS)
38#if defined(__OpenBSD__) || defined(__NetBSD__)
39#include <soundcard.h>
40#else
41#include <sys/soundcard.h>
42#endif
43#include <sys/ioctl.h>
44
45#ifdef ROAR_HAVE_H_SYS_TYPES
46#include <sys/types.h>
47#endif
48
49#ifdef ROAR_HAVE_H_FCNTL
50#include <fcntl.h>
51#endif
52
53#ifdef ROAR_HAVE_H_UNISTD
54#include <unistd.h>
55#endif
56
57#include <sys/stat.h>
[3139]58#include <dlfcn.h>
59
60#if defined(RTLD_NEXT)
61#define REAL_LIBC RTLD_NEXT
62#else
63#define REAL_LIBC ((void *) -1L)
64#endif
[3138]65
[3164]66#ifndef ENOTSUP
67#define ENOTSUP ENOSYS
68#endif
69
[3166]70#if defined(ROAR_OS_NETBSD) && defined(ioctl)
71#define IOCTL_IS_ALIAS
72#endif
73
[3167]74#ifdef ROAR_OS_FREEBSD
75#define mode_t int
76#endif
77
[3153]78#define OSS_VOLUME_SCALE 100
79
[3138]80#define _MAX_POINTER  8
81
[3140]82// handle type:
83#define HT_NONE       0
84#define HT_STREAM     1
85#define HT_MIXER      2
86
[3138]87struct session {
88 int refc;
89 struct roar_connection con;
90};
91
92static struct session _session = {.refc = 0};
93
94struct handle {
95 int refc; // refrence counter
96 struct session * session;
[3140]97 int type;
98 struct roar_stream    stream;
99 struct roar_vio_calls stream_vio;
[3144]100 int                   stream_dir;
[3140]101 int                   stream_opened;
[3138]102};
103
104static struct {
105 int     (*open)(const char *pathname, int flags, mode_t mode);
106 int     (*close)(int fd);
107 ssize_t (*write)(int fd, const void *buf, size_t count);
108 ssize_t (*read)(int fd, void *buf, size_t count);
[3166]109#ifndef IOCTL_IS_ALIAS
[3146]110 int     (*ioctl)(int d, int request, ...);
[3166]111#endif
[3138]112} _os;
113
[3150]114static struct {
115 struct {
116  int volume;
117  int pcm;
118  int line;
119  int line1;
120  int line2;
121  int line3;
122  int digital1;
123  int digital2;
124  int digital3;
125 } sid;
126} _mix_settings = {
127                   .sid = {
128                           .volume   = -1,
129                           .pcm      = -1,
130                           .line     =  0,
131                           .line1    =  1,
132                           .line2    =  2,
133                           .line3    =  3,
134                           .digital1 =  1,
135                           .digital2 =  2,
136                           .digital3 =  3
137                          }
138                  };
139
[3140]140static struct pointer {
[3138]141 int fh;
142 struct handle * handle;
143} _ptr[_MAX_POINTER];
144
145static void _init_os (void) {
146 memset(&_os, 0, sizeof(_os));
[3139]147
148 _os.open  = dlsym(REAL_LIBC, "open");
149 _os.close = dlsym(REAL_LIBC, "close");
150 _os.write = dlsym(REAL_LIBC, "write");
151 _os.read  = dlsym(REAL_LIBC, "read");
[3166]152#ifndef IOCTL_IS_ALIAS
[3146]153 _os.ioctl = dlsym(REAL_LIBC, "ioctl");
[3166]154#endif
[3138]155}
156
157static void _init_ptr (void) {
158 int i;
159
160 for (i = 0; i < _MAX_POINTER; i++) {
161  _ptr[i].fh = -1;
162 }
163}
164
165static void _init (void) {
166 static int inited = 0;
167
168 if ( !inited ) {
169  _init_os();
170  _init_ptr();
171  inited++;
172 }
173}
174
[3157]175static void _find_volume_sid (struct session * session) {
176 int i;
177 int num;
178 int id[ROAR_STREAMS_MAX];
179 struct roar_stream s;
180 char name[1024];
181
182 ROAR_DBG("_find_volume_sid(session=%p) = ?", session);
183
184 if ( (num = roar_list_streams(&(session->con), id, ROAR_STREAMS_MAX)) == -1 ) {
185  return;
186 }
187
188 for (i = 0; i < num; i++) {
189  if ( roar_get_stream(&(session->con), &s, id[i]) == -1 )
190   continue;
191
192  if ( s.dir != ROAR_DIR_MIXING )
193   continue;
194
195  if ( roar_stream_get_name(&(session->con), &s, name, 1024) == -1 )
196   continue;
197
198  if ( !strcasecmp(name, "Waveform Mixer") ) {
199   _mix_settings.sid.volume = id[i];
200   ROAR_DBG("_find_volume_sid(session=%p): found waveform mixer at sid %i", session, id[i]);
201   ROAR_DBG("_find_volume_sid(session=%p) = (void)", session);
202   return;
203  }
204 }
205}
206
[3138]207static int _open_dummy (void) {
208 int p[2];
209
210 if ( pipe(p) == -1 )
211  return -1;
212
213 close(p[1]);
214
215 return p[0];
216}
217
218static struct session * _open_session (char * server, char * name) {
219 if ( _session.refc == 0 ) {
220
221  if ( name == NULL )
222   name = "libroaross client";
223
224  if ( roar_simple_connect(&(_session.con), server, name) == -1 )
225   return NULL;
[3157]226
227  _find_volume_sid(&_session);
[3143]228 }
[3138]229
[3143]230 _session.refc++;
231 return &_session;
[3138]232}
233
234static void _close_session(struct session * session) {
235 if ( session == NULL )
236  return;
237
238 session->refc--;
239
[3144]240 ROAR_DBG("_close_session(session=%p): session->refc=%i", session, session->refc);
241
[3138]242 if ( session->refc == 0 ) {
243  roar_disconnect(&(session->con));
244 }
245}
246
[3140]247static struct handle * _open_handle(struct session * session) {
248 struct handle * handle;
249
250 if ( (handle = roar_mm_malloc(sizeof(struct handle))) == NULL )
251  return NULL;
252
253 memset(handle, 0, sizeof(struct handle));
254
255 handle->refc = 1;
256 handle->session = session;
257 session->refc++; // TODO: better warp this
258 handle->type = HT_NONE;
[3144]259 handle->stream_dir = ROAR_DIR_PLAY;
260 roar_stream_new(&(handle->stream), ROAR_RATE_DEFAULT, ROAR_CHANNELS_DEFAULT, ROAR_BITS_DEFAULT, ROAR_CODEC_DEFAULT);
[3140]261
262 return handle;
263}
264
265static void _close_handle(struct handle * handle) {
266 if (handle == NULL)
267  return;
268
269 handle->refc--;
270
[3144]271 ROAR_DBG("_close_handle(handle=%p): handle->refc=%i", handle, handle->refc);
272
[3140]273 if ( handle->refc == 0 ) {
274  if ( handle->stream_opened )
275   roar_vio_close(&(handle->stream_vio));
276
[3144]277  handle->session->refc--;
278
279  _close_session(handle->session);
280
[3140]281  roar_mm_free(handle);
282 }
283}
284
285static struct pointer * _get_pointer_by_fh (int fh) {
286 int i;
287
288 for (i = 0; i < _MAX_POINTER; i++) {
289  if ( _ptr[i].fh == fh )
290   return &(_ptr[i]);
291 }
292
293 return NULL;
294}
295
296static struct pointer * _open_pointer(struct handle * handle) {
297 struct pointer * ret = _get_pointer_by_fh(-1);
298
299 if ( ret == NULL )
300  return NULL;
301
302 if ( (ret->fh = _open_dummy()) == -1 )
303  return NULL;
304
305 ret->handle = handle;
306
307 return ret;
308}
309
310static void _close_pointer(struct pointer * pointer) {
311 if ( pointer == NULL )
312  return;
313
314 _os.close(pointer->fh);
315
316 pointer->fh = -1;
317
318 _close_handle(pointer->handle);
319}
[3138]320
321// -------------------------------------
[3142]322// central open function:
323// -------------------------------------
324
325static int _open_file (const char *pathname, int flags) {
[3143]326 struct session * session;
327 struct handle  * handle;
328 struct pointer * pointer;
329 struct {
330  char * prefix;
331  int type;
332 } * ptr = NULL, p[] = {
[3150]333  {"/dev/dsp",   HT_STREAM},
334  {"/dev/mixer", HT_MIXER},
[3143]335  {NULL, HT_NONE},
336 };
337 int i;
338
339 for (i = 0; p[i].prefix != NULL; i++) {
340  if ( !strcmp(pathname, p[i].prefix) ) {
341   ptr = &(p[i]);
342  }
343 }
344
345 if ( ptr == NULL )
346  return -2;
347
348 if ( (session = _open_session(NULL, NULL)) == NULL ) {
349  return -1;
350 }
351
352 if ( (handle = _open_handle(session)) == NULL ) {
353  _close_session(session);
354  return -1;
355 }
356
357 handle->type = ptr->type;
358
[3145]359 switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) {
360  case O_RDONLY:
361    handle->stream_dir = ROAR_DIR_MONITOR;
362   break;
363  case O_WRONLY:
364    handle->stream_dir = ROAR_DIR_PLAY;
365   break;
366  case O_RDWR:
367    handle->stream_dir = ROAR_DIR_BIDIR;
368   break;
369 }
370
[3143]371 if ( (pointer = _open_pointer(handle)) == NULL ) {
372  _close_handle(handle);
373  return -1;
374 }
375
376 return pointer->fh;
[3142]377}
378
379// -------------------------------------
[3144]380// open function for streams:
381// -------------------------------------
382
383static int _open_stream (struct handle * handle) {
384  // FIXME: this should be re-written much more cleanly:
385
386 if ( handle == NULL )
387  return -1;
388
389 if ( roar_vio_simple_new_stream_obj(&(handle->stream_vio),
390                                     &(handle->session->con), &(handle->stream),
391                                     handle->stream.info.rate,
392                                     handle->stream.info.channels,
393                                     handle->stream.info.bits,
394                                     handle->stream.info.codec,
395                                     handle->stream_dir
396                                    ) == -1 )
397  return -1;
398
399 handle->stream_opened++;
400
[3150]401 _mix_settings.sid.pcm = roar_stream_get_id(&(handle->stream));
402
[3144]403 return 0;
404}
405
406// -------------------------------------
[3147]407// function to parse format:
408// -------------------------------------
409
410static int _ioctl_stream_format (struct handle * handle, int format) {
411 struct roar_audio_info * info = &(handle->stream.info);
412
413 switch (format) {
414  case AFMT_S8:
415    info->bits  = 8;
416    info->codec = ROAR_CODEC_PCM_S_LE;
417   break;
418  case AFMT_U8:
419    info->bits  = 8;
420    info->codec = ROAR_CODEC_PCM_U_LE;
421   break;
422  case AFMT_S16_BE:
423    info->bits  = 16;
424    info->codec = ROAR_CODEC_PCM_S_BE;
425   break;
426  case AFMT_S16_LE:
427    info->bits  = 16;
428    info->codec = ROAR_CODEC_PCM_S_LE;
429   break;
430  case AFMT_U16_BE:
431    info->bits  = 16;
432    info->codec = ROAR_CODEC_PCM_U_BE;
433   break;
434  case AFMT_U16_LE:
435    info->bits  = 16;
436    info->codec = ROAR_CODEC_PCM_U_LE;
437   break;
438#ifdef AFMT_S32_BE
439  case AFMT_S32_BE:
440    info->bits  = 32;
441    info->codec = ROAR_CODEC_PCM_S_BE;
442   break;
443#endif
444#ifdef AFMT_S32_LE
445  case AFMT_S32_LE:
446    info->bits  = 32;
447    info->codec = ROAR_CODEC_PCM_S_LE;
448   break;
449#endif
450  case AFMT_A_LAW:
451    info->bits  = 8;
452    info->codec = ROAR_CODEC_ALAW;
453   break;
454  case AFMT_MU_LAW:
455    info->bits  = 8;
456    info->codec = ROAR_CODEC_MULAW;
457   break;
458#ifdef AFMT_VORBIS
459  case AFMT_VORBIS:
460    info->codec = ROAR_CODEC_OGG_VORBIS;
461   break;
462#endif
[3148]463  default:
464    errno = ENOSYS;
465    return -1;
466   break;
[3147]467 }
468
[3148]469 return 0;
[3147]470}
471
[3149]472static inline int _ioctl_stream_format_list (void) {
473 int format = 0;
474
475 format |= AFMT_S8;
476 format |= AFMT_U8;
477
478 format |= AFMT_S16_BE;
479 format |= AFMT_S16_LE;
480
481 format |= AFMT_U16_BE;
482 format |= AFMT_U16_LE;
483
484#ifdef AFMT_S32_BE
485 format |= AFMT_S32_BE;
486#endif
487#ifdef AFMT_S32_LE
488 format |= AFMT_S32_LE;
489#endif
490
491 format |= AFMT_A_LAW;
492 format |= AFMT_MU_LAW;
493
494#ifdef AFMT_VORBIS
495 format |= AFMT_VORBIS;
496#endif
497
498 return format;
499}
500
[3147]501// -------------------------------------
[3150]502// mixer ioctls:
503// -------------------------------------
504
[3158]505static int _ioctl_mixer (struct handle * handle, long unsigned int req, void * vp) {
[3159]506 mixer_info * info;
[3150]507 int channels;
508 struct roar_mixer_settings mixer;
[3155]509 int o_w    =  0;
[3150]510 int o_sid  = -1;
[3158]511 int * ip   = vp;
[3165]512#if defined(DEBUG) && defined(DEBUG_IOCTL_NAMES)
513 char * name = NULL;
514#endif
[3150]515
[3165]516#if defined(DEBUG) && defined(DEBUG_IOCTL_NAMES)
[3150]517 switch (req) {
518#if 0
519  case SNDCTL_MIX_DESCRIPTION: name = "SNDCTL_MIX_DESCRIPTION"; break;
520  case SNDCTL_MIX_ENUMINFO:    name = "SNDCTL_MIX_ENUMINFO";    break;
521  case SNDCTL_MIX_EXTINFO:     name = "SNDCTL_MIX_EXTINFO";     break;
522  case SNDCTL_MIX_NREXT:       name = "SNDCTL_MIX_NREXT";       break;
523  case SNDCTL_MIX_NRMIX:       name = "SNDCTL_MIX_NRMIX";       break;
524  case SNDCTL_MIX_READ:        name = "SNDCTL_MIX_READ";        break;
525  case SNDCTL_MIX_WRITE:       name = "SNDCTL_MIX_WRITE";       break;
526#endif
[3159]527//  case SOUND_MIXER_INFO:             name = "SOUND_MIXER_INFO";             break;
[3152]528  case SOUND_OLD_MIXER_INFO:         name = "SOUND_OLD_MIXER_INFO";         break;
529  case SOUND_MIXER_ACCESS:           name = "SOUND_MIXER_ACCESS";           break;
530  case SOUND_MIXER_AGC:              name = "SOUND_MIXER_AGC";              break;
531  case SOUND_MIXER_3DSE:             name = "SOUND_MIXER_3DSE";             break;
[3156]532  case SOUND_MIXER_GETLEVELS:        name = "SOUND_MIXER_GETLEVELS";        break;
533  case SOUND_MIXER_SETLEVELS:        name = "SOUND_MIXER_SETLEVELS";        break;
[3152]534  case SOUND_MIXER_PRIVATE1:         name = "SOUND_MIXER_PRIVATE1";         break;
535  case SOUND_MIXER_PRIVATE2:         name = "SOUND_MIXER_PRIVATE2";         break;
536  case SOUND_MIXER_PRIVATE3:         name = "SOUND_MIXER_PRIVATE3";         break;
537  case SOUND_MIXER_PRIVATE4:         name = "SOUND_MIXER_PRIVATE4";         break;
538  case SOUND_MIXER_PRIVATE5:         name = "SOUND_MIXER_PRIVATE5";         break;
539  case OSS_GETVERSION:               name = "OSS_GETVERSION";               break;
[3156]540//  case SOUND_MIXER_READ_CAPS:        name = "SOUND_MIXER_READ_CAPS";        break;
541  case SOUND_MIXER_READ_MUTE:        name = "SOUND_MIXER_READ_MUTE";        break;
[3152]542/*
543  case :     name = "";     break;
[3156]544  case :     name = "";     break;
[3152]545*/
[3150]546 }
547 if ( name != NULL ) {
548  ROAR_DBG("_ioctl_mixer(handle=%p, req=%lu, ip=%p): unspported mixer command %s", handle, req, ip, name);
549  ROAR_DBG("_ioctl_mixer(handle=%p, req=%lu, ip=%p) = -1 // errno = ENOSYS", handle, req, ip);
550  errno = ENOSYS;
551  return -1;
552 }
[3165]553#endif
[3150]554
555 switch (req) {
556  case SOUND_MIXER_READ_VOLUME:    o_w = 0; o_sid = _mix_settings.sid.volume;   break;
557  case SOUND_MIXER_READ_PCM:       o_w = 0; o_sid = _mix_settings.sid.pcm;      break;
558  case SOUND_MIXER_READ_LINE:      o_w = 0; o_sid = _mix_settings.sid.line;     break;
559  case SOUND_MIXER_READ_LINE1:     o_w = 0; o_sid = _mix_settings.sid.line1;    break;
560  case SOUND_MIXER_READ_LINE2:     o_w = 0; o_sid = _mix_settings.sid.line2;    break;
561  case SOUND_MIXER_READ_LINE3:     o_w = 0; o_sid = _mix_settings.sid.line3;    break;
562#if 0
563  case SOUND_MIXER_READ_DIGITAL1:  o_w = 0; o_sid = _mix_settings.sid.digital1; break;
564  case SOUND_MIXER_READ_DIGITAL2:  o_w = 0; o_sid = _mix_settings.sid.digital2; break;
565  case SOUND_MIXER_READ_DIGITAL3:  o_w = 0; o_sid = _mix_settings.sid.digital3; break;
566#endif
567  case SOUND_MIXER_WRITE_VOLUME:   o_w = 1; o_sid = _mix_settings.sid.volume;   break;
568  case SOUND_MIXER_WRITE_PCM:      o_w = 1; o_sid = _mix_settings.sid.pcm;      break;
569  case SOUND_MIXER_WRITE_LINE:     o_w = 1; o_sid = _mix_settings.sid.line;     break;
570  case SOUND_MIXER_WRITE_LINE1:    o_w = 1; o_sid = _mix_settings.sid.line1;    break;
571  case SOUND_MIXER_WRITE_LINE2:    o_w = 1; o_sid = _mix_settings.sid.line2;    break;
572  case SOUND_MIXER_WRITE_LINE3:    o_w = 1; o_sid = _mix_settings.sid.line3;    break;
573#if 0
574  case SOUND_MIXER_WRITE_DIGITAL1: o_w = 1; o_sid = _mix_settings.sid.digital1; break;
575  case SOUND_MIXER_WRITE_DIGITAL2: o_w = 1; o_sid = _mix_settings.sid.digital2; break;
576  case SOUND_MIXER_WRITE_DIGITAL3: o_w = 1; o_sid = _mix_settings.sid.digital3; break;
577#endif
578 }
579 if ( o_sid != -1 ) {
580  // set/get volume
581  if ( o_w ) {
582   mixer.scale    = 65535;
[3153]583   mixer.mixer[0] = ( *ip       & 0xFF)*65535/OSS_VOLUME_SCALE;
584   mixer.mixer[1] = ((*ip >> 8) & 0xFF)*65535/OSS_VOLUME_SCALE;
[3150]585   if ( roar_set_vol(&(handle->session->con), o_sid, &mixer, 2) == -1 ) {
[3156]586    errno = EIO;
[3150]587    return -1;
588   }
589   return 0;
590  } else {
591   if ( roar_get_vol(&(handle->session->con), o_sid, &mixer, &channels) == -1 ) {
[3156]592    errno = EIO;
[3150]593    return -1;
594   }
[3153]595   *ip = ((OSS_VOLUME_SCALE*mixer.mixer[0])/mixer.scale) | (((OSS_VOLUME_SCALE*mixer.mixer[0])/mixer.scale)<<8);
[3150]596   return 0;
597  }
598 }
599
600 switch (req) {
[3155]601  case SOUND_MIXER_READ_STEREODEVS: /* FIXME: check the streams for channel config */
[3150]602  case SOUND_MIXER_READ_DEVMASK:
603    *ip = 0;
604
605    if ( _mix_settings.sid.volume != -1 )
606     *ip |= SOUND_MASK_VOLUME;
607    if ( _mix_settings.sid.pcm != -1 )
608     *ip |= SOUND_MASK_PCM;
609    if ( _mix_settings.sid.line != -1 )
610     *ip |= SOUND_MASK_LINE;
611    if ( _mix_settings.sid.line1 != -1 )
612     *ip |= SOUND_MASK_LINE1;
613    if ( _mix_settings.sid.line2 != -1 )
614     *ip |= SOUND_MASK_LINE2;
615    if ( _mix_settings.sid.line3 != -1 )
616     *ip |= SOUND_MASK_LINE3;
617    if ( _mix_settings.sid.digital1 != -1 )
[3156]618#if 0
[3150]619     *ip |= SOUND_MASK_DIGITAL1;
620    if ( _mix_settings.sid.digital2 != -1 )
621     *ip |= SOUND_MASK_DIGITAL2;
622    if ( _mix_settings.sid.digital3 != -1 )
623     *ip |= SOUND_MASK_DIGITAL3;
[3156]624#endif
[3150]625
626    return 0;
627   break;
[3153]628  case SOUND_MIXER_READ_RECMASK:
[3154]629  case SOUND_MIXER_READ_RECSRC:
[3153]630    *ip = SOUND_MASK_VOLUME; // we can currently only read from mixer
631    return 0;
632   break;
[3154]633  case SOUND_MIXER_WRITE_RECSRC:
634    if ( *ip == SOUND_MASK_VOLUME ) {
635     return  0;
636    } else {
637     errno = ENOTSUP;
638     return -1;
639    }
640   break;
[3156]641  case SOUND_MIXER_READ_CAPS:
642    *ip = 0;
643    return 0;
644   break;
[3159]645  case SOUND_MIXER_INFO:
646    info = vp;
647    memset(info, 0, sizeof(*info));
648    strcpy(info->id, "RoarAudio");
649    strcpy(info->name, "RoarAudio");
650    return 0;
651   break;
[3150]652 }
653
654 ROAR_DBG("_ioctl_mixer(handle=%p, req=%lu, ip=%p): unknown mixer CTL", handle, req, ip);
[3156]655// _os.ioctl(-1, req, ip);
[3150]656 ROAR_DBG("_ioctl_mixer(handle=%p, req=%lu, ip=%p) = -1 // errno = ENOSYS", handle, req, ip);
657 errno = ENOSYS;
658 return -1;
659}
660
661// -------------------------------------
[3138]662// emulated functions follow:
663// -------------------------------------
664
665int     open(const char *pathname, int flags, ...) {
[3142]666 int     ret;
667 mode_t  mode = 0;
[3138]668 va_list args;
669
670 _init();
671
[3142]672 ret = _open_file(pathname, flags);
673
674 switch (ret) {
675  case -2:       // continue as normal, use _op.open()
676   break;
677  case -1:       // pass error to caller
678    return -1;
679   break;
680  default:       // return successfully opened pointer to caller
681    return ret;
682   break;
683 }
684
[3138]685 if (flags & O_CREAT) {
686  va_start(args, flags);
687  mode = va_arg(args, mode_t);
688  va_end(args);
689 }
690
691 return _os.open(pathname, flags, mode);
692}
693
694int     close(int fd) {
[3140]695 struct pointer * pointer;
[3138]696 _init();
697
[3140]698 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
699  _close_pointer(pointer);
700  return 0;
701 }
702
[3138]703 return _os.close(fd);
704}
705
706ssize_t write(int fd, const void *buf, size_t count) {
[3140]707 struct pointer * pointer;
708
[3138]709 _init();
710
[3140]711 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
712  if ( pointer->handle->type == HT_STREAM ) {
713   if ( pointer->handle->stream_opened == 0 ) {
714    if ( _open_stream(pointer->handle) == -1 ) {
715     errno = EIO;
716     return -1;
717    }
718   }
[3141]719   return roar_vio_write(&(pointer->handle->stream_vio), (char*)buf, count);
[3140]720  } else {
721   errno = EINVAL;
722   return -1;
723  }
724 }
725
[3138]726 return _os.write(fd, buf, count);
727}
728
729ssize_t read(int fd, void *buf, size_t count) {
[3140]730 struct pointer * pointer;
731
[3138]732 _init();
733
[3140]734 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
735  if ( pointer->handle->type == HT_STREAM ) {
736   if ( pointer->handle->stream_opened == 0 ) {
737    if ( _open_stream(pointer->handle) == -1 ) {
738     errno = EIO;
739     return -1;
740    }
741   }
742   return roar_vio_read(&(pointer->handle->stream_vio), buf, count);
743  } else {
744   errno = EINVAL;
745   return -1;
746  }
747 }
748
[3138]749 return _os.read(fd, buf, count);
750}
751
[3146]752extern int ioctl (int __fd, unsigned long int __request, ...) {
[3147]753 struct pointer * pointer;
754 struct handle  * handle;
[3146]755 va_list args;
756 void *argp;
[3147]757 int * ip = NULL;
[3146]758
759 _init();
760
[3150]761// ROAR_DBG("ioctl(__fd=%i, __request=%lu) = ?", __fd, (long unsigned int) __request);
[3148]762
[3146]763 va_start (args, __request);
764 argp = va_arg (args, void *);
765 va_end (args);
766
[3150]767// ROAR_DBG("ioctl(__fd=%i, __request=%lu): argp=%p", __fd, (long unsigned int) __request, argp);
[3148]768
[3147]769 if ( (pointer = _get_pointer_by_fh(__fd)) != NULL ) {
[3148]770  ip = argp;
[3150]771//  ROAR_DBG("ioctl(__fd=%i, __request=%lu): ip=%p", __fd, (long unsigned int) __request, ip);
[3147]772  switch ((handle = pointer->handle)->type) {
773   case HT_STREAM:
774     switch (__request) {
775      case SNDCTL_DSP_RESET:
776      case SNDCTL_DSP_POST:
[3162]777      case SNDCTL_DSP_SETFRAGMENT: // any fragments should be ok for us...
[3147]778       break;
779      case SNDCTL_DSP_SPEED:
780        handle->stream.info.rate = *ip;
781        return 0;
782       break;
783      case SNDCTL_DSP_CHANNELS:
784        handle->stream.info.channels = *ip;
785        return 0;
786       break;
[3160]787      case SNDCTL_DSP_STEREO:
788        handle->stream.info.channels = *ip ? 2 : 1;
789        return 0;
790       break;
[3161]791      case SNDCTL_DSP_GETBLKSIZE:
792         *ip = handle->stream.info.rate * handle->stream.info.channels * handle->stream.info.bits / 800;
793        return 0;
794       break;
[3147]795      case SNDCTL_DSP_SETFMT:
796        return _ioctl_stream_format(handle, *ip);
797       break;
[3148]798      case SNDCTL_DSP_GETFMTS:
[3150]799//        ROAR_DBG("ioctl(__fd=%i, __request=%lu): ip=%p", __fd, (long unsigned int) __request, ip);
[3149]800        *ip = _ioctl_stream_format_list();
[3148]801        return 0;
802       break;
[3147]803      default:
[3148]804        ROAR_DBG("ioctl(__fd=%i, __request=%lu) = -1 // errno = ENOSYS", __fd, (long unsigned int) __request);
[3147]805        errno = ENOSYS;
806        return -1;
807     }
808    break;
809   case HT_MIXER:
[3158]810     return _ioctl_mixer(handle, __request, argp);
[3147]811    break;
812   default:
[3150]813     ROAR_DBG("ioctl(__fd=%i, __request=%lu): unknown handle type: no ioctl()s supported", __fd, (long unsigned int) __request);
814     ROAR_DBG("ioctl(__fd=%i, __request=%lu) = -1 // errno = ENOSYS", __fd, (long unsigned int) __request);
[3147]815     errno = EINVAL;
816     return -1;
817    break;
818  }
819 }
820
[3166]821#ifdef IOCTL_IS_ALIAS
822 errno = ENOSYS;
823 return -1;
824#else
[3146]825 return _os.ioctl(__fd, __request, argp);
[3166]826#endif
[3146]827}
828
[3138]829#endif
830
831//ll
Note: See TracBrowser for help on using the repository browser.