source: roaraudio/libroaross/libroaross.c @ 3152:9758b6a09e24

Last change on this file since 3152:9758b6a09e24 was 3152:9758b6a09e24, checked in by phi, 14 years ago

added names of a lot unsupported mixer CTLs

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