source: roaraudio/libroaross/libroaross.c @ 3156:e07625a1a2e7

Last change on this file since 3156:e07625a1a2e7 was 3156:e07625a1a2e7, checked in by phi, 12 years ago

got it to work with gnome mixer!

File size: 19.1 KB
Line 
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>
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
65
66#define OSS_VOLUME_SCALE 100
67
68#define _MAX_POINTER  8
69
70// handle type:
71#define HT_NONE       0
72#define HT_STREAM     1
73#define HT_MIXER      2
74
75struct session {
76 int refc;
77 struct roar_connection con;
78};
79
80static struct session _session = {.refc = 0};
81
82struct handle {
83 int refc; // refrence counter
84 struct session * session;
85 int type;
86 struct roar_stream    stream;
87 struct roar_vio_calls stream_vio;
88 int                   stream_dir;
89 int                   stream_opened;
90};
91
92static struct {
93 int     (*open)(const char *pathname, int flags, mode_t mode);
94 int     (*close)(int fd);
95 ssize_t (*write)(int fd, const void *buf, size_t count);
96 ssize_t (*read)(int fd, void *buf, size_t count);
97 int     (*ioctl)(int d, int request, ...);
98} _os;
99
100static struct {
101 struct {
102  int volume;
103  int pcm;
104  int line;
105  int line1;
106  int line2;
107  int line3;
108  int digital1;
109  int digital2;
110  int digital3;
111 } sid;
112} _mix_settings = {
113                   .sid = {
114                           .volume   = -1,
115                           .pcm      = -1,
116                           .line     =  0,
117                           .line1    =  1,
118                           .line2    =  2,
119                           .line3    =  3,
120                           .digital1 =  1,
121                           .digital2 =  2,
122                           .digital3 =  3
123                          }
124                  };
125
126static struct pointer {
127 int fh;
128 struct handle * handle;
129} _ptr[_MAX_POINTER];
130
131static void _init_os (void) {
132 memset(&_os, 0, sizeof(_os));
133
134 _os.open  = dlsym(REAL_LIBC, "open");
135 _os.close = dlsym(REAL_LIBC, "close");
136 _os.write = dlsym(REAL_LIBC, "write");
137 _os.read  = dlsym(REAL_LIBC, "read");
138 _os.ioctl = dlsym(REAL_LIBC, "ioctl");
139}
140
141static void _init_ptr (void) {
142 int i;
143
144 for (i = 0; i < _MAX_POINTER; i++) {
145  _ptr[i].fh = -1;
146 }
147}
148
149static void _init (void) {
150 static int inited = 0;
151
152 if ( !inited ) {
153  _init_os();
154  _init_ptr();
155  inited++;
156 }
157}
158
159static int _open_dummy (void) {
160 int p[2];
161
162 if ( pipe(p) == -1 )
163  return -1;
164
165 close(p[1]);
166
167 return p[0];
168}
169
170static struct session * _open_session (char * server, char * name) {
171 if ( _session.refc == 0 ) {
172
173  if ( name == NULL )
174   name = "libroaross client";
175
176  if ( roar_simple_connect(&(_session.con), server, name) == -1 )
177   return NULL;
178 }
179
180 _session.refc++;
181 return &_session;
182}
183
184static void _close_session(struct session * session) {
185 if ( session == NULL )
186  return;
187
188 session->refc--;
189
190 ROAR_DBG("_close_session(session=%p): session->refc=%i", session, session->refc);
191
192 if ( session->refc == 0 ) {
193  roar_disconnect(&(session->con));
194 }
195}
196
197static struct handle * _open_handle(struct session * session) {
198 struct handle * handle;
199
200 if ( (handle = roar_mm_malloc(sizeof(struct handle))) == NULL )
201  return NULL;
202
203 memset(handle, 0, sizeof(struct handle));
204
205 handle->refc = 1;
206 handle->session = session;
207 session->refc++; // TODO: better warp this
208 handle->type = HT_NONE;
209 handle->stream_dir = ROAR_DIR_PLAY;
210 roar_stream_new(&(handle->stream), ROAR_RATE_DEFAULT, ROAR_CHANNELS_DEFAULT, ROAR_BITS_DEFAULT, ROAR_CODEC_DEFAULT);
211
212 return handle;
213}
214
215static void _close_handle(struct handle * handle) {
216 if (handle == NULL)
217  return;
218
219 handle->refc--;
220
221 ROAR_DBG("_close_handle(handle=%p): handle->refc=%i", handle, handle->refc);
222
223 if ( handle->refc == 0 ) {
224  if ( handle->stream_opened )
225   roar_vio_close(&(handle->stream_vio));
226
227  handle->session->refc--;
228
229  _close_session(handle->session);
230
231  roar_mm_free(handle);
232 }
233}
234
235static struct pointer * _get_pointer_by_fh (int fh) {
236 int i;
237
238 for (i = 0; i < _MAX_POINTER; i++) {
239  if ( _ptr[i].fh == fh )
240   return &(_ptr[i]);
241 }
242
243 return NULL;
244}
245
246static struct pointer * _open_pointer(struct handle * handle) {
247 struct pointer * ret = _get_pointer_by_fh(-1);
248
249 if ( ret == NULL )
250  return NULL;
251
252 if ( (ret->fh = _open_dummy()) == -1 )
253  return NULL;
254
255 ret->handle = handle;
256
257 return ret;
258}
259
260static void _close_pointer(struct pointer * pointer) {
261 if ( pointer == NULL )
262  return;
263
264 _os.close(pointer->fh);
265
266 pointer->fh = -1;
267
268 _close_handle(pointer->handle);
269}
270
271// -------------------------------------
272// central open function:
273// -------------------------------------
274
275static int _open_file (const char *pathname, int flags) {
276 struct session * session;
277 struct handle  * handle;
278 struct pointer * pointer;
279 struct {
280  char * prefix;
281  int type;
282 } * ptr = NULL, p[] = {
283  {"/dev/dsp",   HT_STREAM},
284  {"/dev/mixer", HT_MIXER},
285  {NULL, HT_NONE},
286 };
287 int i;
288
289 for (i = 0; p[i].prefix != NULL; i++) {
290  if ( !strcmp(pathname, p[i].prefix) ) {
291   ptr = &(p[i]);
292  }
293 }
294
295 if ( ptr == NULL )
296  return -2;
297
298 if ( (session = _open_session(NULL, NULL)) == NULL ) {
299  return -1;
300 }
301
302 if ( (handle = _open_handle(session)) == NULL ) {
303  _close_session(session);
304  return -1;
305 }
306
307 handle->type = ptr->type;
308
309 switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) {
310  case O_RDONLY:
311    handle->stream_dir = ROAR_DIR_MONITOR;
312   break;
313  case O_WRONLY:
314    handle->stream_dir = ROAR_DIR_PLAY;
315   break;
316  case O_RDWR:
317    handle->stream_dir = ROAR_DIR_BIDIR;
318   break;
319 }
320
321 if ( (pointer = _open_pointer(handle)) == NULL ) {
322  _close_handle(handle);
323  return -1;
324 }
325
326 return pointer->fh;
327}
328
329// -------------------------------------
330// open function for streams:
331// -------------------------------------
332
333static int _open_stream (struct handle * handle) {
334  // FIXME: this should be re-written much more cleanly:
335
336 if ( handle == NULL )
337  return -1;
338
339 if ( roar_vio_simple_new_stream_obj(&(handle->stream_vio),
340                                     &(handle->session->con), &(handle->stream),
341                                     handle->stream.info.rate,
342                                     handle->stream.info.channels,
343                                     handle->stream.info.bits,
344                                     handle->stream.info.codec,
345                                     handle->stream_dir
346                                    ) == -1 )
347  return -1;
348
349 handle->stream_opened++;
350
351 _mix_settings.sid.pcm = roar_stream_get_id(&(handle->stream));
352
353 return 0;
354}
355
356// -------------------------------------
357// function to parse format:
358// -------------------------------------
359
360static int _ioctl_stream_format (struct handle * handle, int format) {
361 struct roar_audio_info * info = &(handle->stream.info);
362
363 switch (format) {
364  case AFMT_S8:
365    info->bits  = 8;
366    info->codec = ROAR_CODEC_PCM_S_LE;
367   break;
368  case AFMT_U8:
369    info->bits  = 8;
370    info->codec = ROAR_CODEC_PCM_U_LE;
371   break;
372  case AFMT_S16_BE:
373    info->bits  = 16;
374    info->codec = ROAR_CODEC_PCM_S_BE;
375   break;
376  case AFMT_S16_LE:
377    info->bits  = 16;
378    info->codec = ROAR_CODEC_PCM_S_LE;
379   break;
380  case AFMT_U16_BE:
381    info->bits  = 16;
382    info->codec = ROAR_CODEC_PCM_U_BE;
383   break;
384  case AFMT_U16_LE:
385    info->bits  = 16;
386    info->codec = ROAR_CODEC_PCM_U_LE;
387   break;
388#ifdef AFMT_S32_BE
389  case AFMT_S32_BE:
390    info->bits  = 32;
391    info->codec = ROAR_CODEC_PCM_S_BE;
392   break;
393#endif
394#ifdef AFMT_S32_LE
395  case AFMT_S32_LE:
396    info->bits  = 32;
397    info->codec = ROAR_CODEC_PCM_S_LE;
398   break;
399#endif
400  case AFMT_A_LAW:
401    info->bits  = 8;
402    info->codec = ROAR_CODEC_ALAW;
403   break;
404  case AFMT_MU_LAW:
405    info->bits  = 8;
406    info->codec = ROAR_CODEC_MULAW;
407   break;
408#ifdef AFMT_VORBIS
409  case AFMT_VORBIS:
410    info->codec = ROAR_CODEC_OGG_VORBIS;
411   break;
412#endif
413  default:
414    errno = ENOSYS;
415    return -1;
416   break;
417 }
418
419 return 0;
420}
421
422static inline int _ioctl_stream_format_list (void) {
423 int format = 0;
424
425 format |= AFMT_S8;
426 format |= AFMT_U8;
427
428 format |= AFMT_S16_BE;
429 format |= AFMT_S16_LE;
430
431 format |= AFMT_U16_BE;
432 format |= AFMT_U16_LE;
433
434#ifdef AFMT_S32_BE
435 format |= AFMT_S32_BE;
436#endif
437#ifdef AFMT_S32_LE
438 format |= AFMT_S32_LE;
439#endif
440
441 format |= AFMT_A_LAW;
442 format |= AFMT_MU_LAW;
443
444#ifdef AFMT_VORBIS
445 format |= AFMT_VORBIS;
446#endif
447
448 return format;
449}
450
451// -------------------------------------
452// mixer ioctls:
453// -------------------------------------
454
455static int _ioctl_mixer (struct handle * handle, long unsigned int req, int * ip) {
456 int channels;
457 struct roar_mixer_settings mixer;
458 char * name = NULL;
459 int o_w    =  0;
460 int o_sid  = -1;
461
462 switch (req) {
463#if 0
464  case SNDCTL_MIX_DESCRIPTION: name = "SNDCTL_MIX_DESCRIPTION"; break;
465  case SNDCTL_MIX_ENUMINFO:    name = "SNDCTL_MIX_ENUMINFO";    break;
466  case SNDCTL_MIX_EXTINFO:     name = "SNDCTL_MIX_EXTINFO";     break;
467  case SNDCTL_MIX_NREXT:       name = "SNDCTL_MIX_NREXT";       break;
468  case SNDCTL_MIX_NRMIX:       name = "SNDCTL_MIX_NRMIX";       break;
469  case SNDCTL_MIX_READ:        name = "SNDCTL_MIX_READ";        break;
470  case SNDCTL_MIX_WRITE:       name = "SNDCTL_MIX_WRITE";       break;
471#endif
472  case SOUND_MIXER_INFO:             name = "SOUND_MIXER_INFO";             break;
473  case SOUND_OLD_MIXER_INFO:         name = "SOUND_OLD_MIXER_INFO";         break;
474  case SOUND_MIXER_ACCESS:           name = "SOUND_MIXER_ACCESS";           break;
475  case SOUND_MIXER_AGC:              name = "SOUND_MIXER_AGC";              break;
476  case SOUND_MIXER_3DSE:             name = "SOUND_MIXER_3DSE";             break;
477  case SOUND_MIXER_GETLEVELS:        name = "SOUND_MIXER_GETLEVELS";        break;
478  case SOUND_MIXER_SETLEVELS:        name = "SOUND_MIXER_SETLEVELS";        break;
479  case SOUND_MIXER_PRIVATE1:         name = "SOUND_MIXER_PRIVATE1";         break;
480  case SOUND_MIXER_PRIVATE2:         name = "SOUND_MIXER_PRIVATE2";         break;
481  case SOUND_MIXER_PRIVATE3:         name = "SOUND_MIXER_PRIVATE3";         break;
482  case SOUND_MIXER_PRIVATE4:         name = "SOUND_MIXER_PRIVATE4";         break;
483  case SOUND_MIXER_PRIVATE5:         name = "SOUND_MIXER_PRIVATE5";         break;
484  case OSS_GETVERSION:               name = "OSS_GETVERSION";               break;
485//  case SOUND_MIXER_READ_CAPS:        name = "SOUND_MIXER_READ_CAPS";        break;
486  case SOUND_MIXER_READ_MUTE:        name = "SOUND_MIXER_READ_MUTE";        break;
487/*
488  case :     name = "";     break;
489  case :     name = "";     break;
490*/
491 }
492 if ( name != NULL ) {
493  ROAR_DBG("_ioctl_mixer(handle=%p, req=%lu, ip=%p): unspported mixer command %s", handle, req, ip, name);
494  ROAR_DBG("_ioctl_mixer(handle=%p, req=%lu, ip=%p) = -1 // errno = ENOSYS", handle, req, ip);
495  errno = ENOSYS;
496  return -1;
497 }
498
499 switch (req) {
500  case SOUND_MIXER_READ_VOLUME:    o_w = 0; o_sid = _mix_settings.sid.volume;   break;
501  case SOUND_MIXER_READ_PCM:       o_w = 0; o_sid = _mix_settings.sid.pcm;      break;
502  case SOUND_MIXER_READ_LINE:      o_w = 0; o_sid = _mix_settings.sid.line;     break;
503  case SOUND_MIXER_READ_LINE1:     o_w = 0; o_sid = _mix_settings.sid.line1;    break;
504  case SOUND_MIXER_READ_LINE2:     o_w = 0; o_sid = _mix_settings.sid.line2;    break;
505  case SOUND_MIXER_READ_LINE3:     o_w = 0; o_sid = _mix_settings.sid.line3;    break;
506#if 0
507  case SOUND_MIXER_READ_DIGITAL1:  o_w = 0; o_sid = _mix_settings.sid.digital1; break;
508  case SOUND_MIXER_READ_DIGITAL2:  o_w = 0; o_sid = _mix_settings.sid.digital2; break;
509  case SOUND_MIXER_READ_DIGITAL3:  o_w = 0; o_sid = _mix_settings.sid.digital3; break;
510#endif
511  case SOUND_MIXER_WRITE_VOLUME:   o_w = 1; o_sid = _mix_settings.sid.volume;   break;
512  case SOUND_MIXER_WRITE_PCM:      o_w = 1; o_sid = _mix_settings.sid.pcm;      break;
513  case SOUND_MIXER_WRITE_LINE:     o_w = 1; o_sid = _mix_settings.sid.line;     break;
514  case SOUND_MIXER_WRITE_LINE1:    o_w = 1; o_sid = _mix_settings.sid.line1;    break;
515  case SOUND_MIXER_WRITE_LINE2:    o_w = 1; o_sid = _mix_settings.sid.line2;    break;
516  case SOUND_MIXER_WRITE_LINE3:    o_w = 1; o_sid = _mix_settings.sid.line3;    break;
517#if 0
518  case SOUND_MIXER_WRITE_DIGITAL1: o_w = 1; o_sid = _mix_settings.sid.digital1; break;
519  case SOUND_MIXER_WRITE_DIGITAL2: o_w = 1; o_sid = _mix_settings.sid.digital2; break;
520  case SOUND_MIXER_WRITE_DIGITAL3: o_w = 1; o_sid = _mix_settings.sid.digital3; break;
521#endif
522 }
523 if ( o_sid != -1 ) {
524  // set/get volume
525  if ( o_w ) {
526   mixer.scale    = 65535;
527   mixer.mixer[0] = ( *ip       & 0xFF)*65535/OSS_VOLUME_SCALE;
528   mixer.mixer[1] = ((*ip >> 8) & 0xFF)*65535/OSS_VOLUME_SCALE;
529   if ( roar_set_vol(&(handle->session->con), o_sid, &mixer, 2) == -1 ) {
530    errno = EIO;
531    return -1;
532   }
533   return 0;
534  } else {
535   if ( roar_get_vol(&(handle->session->con), o_sid, &mixer, &channels) == -1 ) {
536    errno = EIO;
537    return -1;
538   }
539   *ip = ((OSS_VOLUME_SCALE*mixer.mixer[0])/mixer.scale) | (((OSS_VOLUME_SCALE*mixer.mixer[0])/mixer.scale)<<8);
540   return 0;
541  }
542 }
543
544 switch (req) {
545  case SOUND_MIXER_READ_STEREODEVS: /* FIXME: check the streams for channel config */
546  case SOUND_MIXER_READ_DEVMASK:
547    *ip = 0;
548
549    if ( _mix_settings.sid.volume != -1 )
550     *ip |= SOUND_MASK_VOLUME;
551    if ( _mix_settings.sid.pcm != -1 )
552     *ip |= SOUND_MASK_PCM;
553    if ( _mix_settings.sid.line != -1 )
554     *ip |= SOUND_MASK_LINE;
555    if ( _mix_settings.sid.line1 != -1 )
556     *ip |= SOUND_MASK_LINE1;
557    if ( _mix_settings.sid.line2 != -1 )
558     *ip |= SOUND_MASK_LINE2;
559    if ( _mix_settings.sid.line3 != -1 )
560     *ip |= SOUND_MASK_LINE3;
561    if ( _mix_settings.sid.digital1 != -1 )
562#if 0
563     *ip |= SOUND_MASK_DIGITAL1;
564    if ( _mix_settings.sid.digital2 != -1 )
565     *ip |= SOUND_MASK_DIGITAL2;
566    if ( _mix_settings.sid.digital3 != -1 )
567     *ip |= SOUND_MASK_DIGITAL3;
568#endif
569
570    return 0;
571   break;
572  case SOUND_MIXER_READ_RECMASK:
573  case SOUND_MIXER_READ_RECSRC:
574    *ip = SOUND_MASK_VOLUME; // we can currently only read from mixer
575    return 0;
576   break;
577  case SOUND_MIXER_WRITE_RECSRC:
578    if ( *ip == SOUND_MASK_VOLUME ) {
579     return  0;
580    } else {
581     errno = ENOTSUP;
582     return -1;
583    }
584   break;
585  case SOUND_MIXER_READ_CAPS:
586    *ip = 0;
587    return 0;
588   break;
589 }
590
591 ROAR_DBG("_ioctl_mixer(handle=%p, req=%lu, ip=%p): unknown mixer CTL", handle, req, ip);
592// _os.ioctl(-1, req, ip);
593 ROAR_DBG("_ioctl_mixer(handle=%p, req=%lu, ip=%p) = -1 // errno = ENOSYS", handle, req, ip);
594 errno = ENOSYS;
595 return -1;
596}
597
598// -------------------------------------
599// emulated functions follow:
600// -------------------------------------
601
602int     open(const char *pathname, int flags, ...) {
603 int     ret;
604 mode_t  mode = 0;
605 va_list args;
606
607 _init();
608
609 ret = _open_file(pathname, flags);
610
611 switch (ret) {
612  case -2:       // continue as normal, use _op.open()
613   break;
614  case -1:       // pass error to caller
615    return -1;
616   break;
617  default:       // return successfully opened pointer to caller
618    return ret;
619   break;
620 }
621
622 if (flags & O_CREAT) {
623  va_start(args, flags);
624  mode = va_arg(args, mode_t);
625  va_end(args);
626 }
627
628 return _os.open(pathname, flags, mode);
629}
630
631int     close(int fd) {
632 struct pointer * pointer;
633 _init();
634
635 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
636  _close_pointer(pointer);
637  return 0;
638 }
639
640 return _os.close(fd);
641}
642
643ssize_t write(int fd, const void *buf, size_t count) {
644 struct pointer * pointer;
645
646 _init();
647
648 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
649  if ( pointer->handle->type == HT_STREAM ) {
650   if ( pointer->handle->stream_opened == 0 ) {
651    if ( _open_stream(pointer->handle) == -1 ) {
652     errno = EIO;
653     return -1;
654    }
655   }
656   return roar_vio_write(&(pointer->handle->stream_vio), (char*)buf, count);
657  } else {
658   errno = EINVAL;
659   return -1;
660  }
661 }
662
663 return _os.write(fd, buf, count);
664}
665
666ssize_t read(int fd, void *buf, size_t count) {
667 struct pointer * pointer;
668
669 _init();
670
671 if ( (pointer = _get_pointer_by_fh(fd)) != NULL ) {
672  if ( pointer->handle->type == HT_STREAM ) {
673   if ( pointer->handle->stream_opened == 0 ) {
674    if ( _open_stream(pointer->handle) == -1 ) {
675     errno = EIO;
676     return -1;
677    }
678   }
679   return roar_vio_read(&(pointer->handle->stream_vio), buf, count);
680  } else {
681   errno = EINVAL;
682   return -1;
683  }
684 }
685
686 return _os.read(fd, buf, count);
687}
688
689extern int ioctl (int __fd, unsigned long int __request, ...) {
690 struct pointer * pointer;
691 struct handle  * handle;
692 va_list args;
693 void *argp;
694 int * ip = NULL;
695
696 _init();
697
698// ROAR_DBG("ioctl(__fd=%i, __request=%lu) = ?", __fd, (long unsigned int) __request);
699
700 va_start (args, __request);
701 argp = va_arg (args, void *);
702 va_end (args);
703
704// ROAR_DBG("ioctl(__fd=%i, __request=%lu): argp=%p", __fd, (long unsigned int) __request, argp);
705
706 if ( (pointer = _get_pointer_by_fh(__fd)) != NULL ) {
707  ip = argp;
708//  ROAR_DBG("ioctl(__fd=%i, __request=%lu): ip=%p", __fd, (long unsigned int) __request, ip);
709  switch ((handle = pointer->handle)->type) {
710   case HT_STREAM:
711     switch (__request) {
712      case SNDCTL_DSP_RESET:
713      case SNDCTL_DSP_POST:
714       break;
715      case SNDCTL_DSP_SPEED:
716        handle->stream.info.rate = *ip;
717        return 0;
718       break;
719      case SNDCTL_DSP_CHANNELS:
720        handle->stream.info.channels = *ip;
721        return 0;
722       break;
723      case SNDCTL_DSP_SETFMT:
724        return _ioctl_stream_format(handle, *ip);
725       break;
726      case SNDCTL_DSP_GETFMTS:
727//        ROAR_DBG("ioctl(__fd=%i, __request=%lu): ip=%p", __fd, (long unsigned int) __request, ip);
728        *ip = _ioctl_stream_format_list();
729        return 0;
730       break;
731      default:
732        ROAR_DBG("ioctl(__fd=%i, __request=%lu) = -1 // errno = ENOSYS", __fd, (long unsigned int) __request);
733        errno = ENOSYS;
734        return -1;
735     }
736    break;
737   case HT_MIXER:
738     return _ioctl_mixer(handle, __request, ip);
739    break;
740   default:
741     ROAR_DBG("ioctl(__fd=%i, __request=%lu): unknown handle type: no ioctl()s supported", __fd, (long unsigned int) __request);
742     ROAR_DBG("ioctl(__fd=%i, __request=%lu) = -1 // errno = ENOSYS", __fd, (long unsigned int) __request);
743     errno = EINVAL;
744     return -1;
745    break;
746  }
747 }
748
749 return _os.ioctl(__fd, __request, argp);
750}
751
752#endif
753
754//ll
Note: See TracBrowser for help on using the repository browser.