source: roaraudio/roard/driver_portaudio.c @ 4708:c9d40761088a

Last change on this file since 4708:c9d40761088a was 4708:c9d40761088a, checked in by phi, 13 years ago

updated copyright statements

File size: 5.4 KB
Line 
1//driver_portaudio.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2011
5 *
6 *  This file is part of roard 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 *  RoarAudio 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, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "roard.h"
27
28#ifdef _DRIVER_PORTAUDIO_CAN_OPERATE
29
30int driver_portaudio_open(struct roar_vio_calls * inst, char * device, struct roar_audio_info * info, int fh, struct roar_stream_server * sstream) {
31 struct driver_portaudio * self;
32 PaSampleFormat fmt;
33#ifdef ROAR_HAVE_LIBPABLIO
34 long flags = PABLIO_WRITE;
35#elif defined(ROAR_HAVE_LIBPORTAUDIO_V0_19)
36 PaError err;
37 PaStreamParameters params;
38#endif
39
40 switch (info->bits) {
41  case 8:
42    switch (info->codec) {
43     case ROAR_CODEC_PCM_S_LE:
44     case ROAR_CODEC_PCM_S_BE:
45     case ROAR_CODEC_PCM_S_PDP:
46       fmt = paInt8;
47      break;
48     case ROAR_CODEC_PCM_U_LE:
49     case ROAR_CODEC_PCM_U_BE:
50     case ROAR_CODEC_PCM_U_PDP:
51       fmt = paUInt8;
52      break;
53     default:
54       return -1;
55      break;
56    }
57   break;
58  case 16:
59    if ( info->codec != ROAR_CODEC_DEFAULT )
60     return -1;
61    fmt = paInt16;
62   break;
63  case 24:
64    if ( info->codec != ROAR_CODEC_DEFAULT )
65     return -1;
66    fmt = paPackedInt24;
67   break;
68  case 32:
69    if ( info->codec != ROAR_CODEC_DEFAULT )
70     return -1;
71    fmt = paInt32;
72   break;
73  default:
74    return -1;
75 }
76
77 if ( (self = roar_mm_malloc(sizeof(struct driver_portaudio))) == NULL )
78  return -1;
79
80 memset(self, 0, sizeof(struct driver_portaudio));
81
82 memset(inst, 0, sizeof(struct roar_vio_calls));
83
84 inst->inst  = self;
85 inst->close = driver_portaudio_close;
86 inst->write = driver_portaudio_write;
87
88 Pa_Initialize();
89
90#ifdef ROAR_HAVE_LIBPABLIO
91 switch (info->channels) {
92  case 1: flags |= PABLIO_MONO;   break;
93  case 2: flags |= PABLIO_STEREO; break;
94  default:
95    roar_mm_free(self);
96    Pa_Terminate();
97    return -1;
98 }
99
100 if ( OpenAudioStream(&(self->ostream), info->rate, fmt, flags) != paNoError ) {
101  roar_mm_free(self);
102  Pa_Terminate();
103  return -1;
104 }
105
106 return 0;
107#elif defined(ROAR_HAVE_LIBPORTAUDIO_V0_19)
108 params.device                    = Pa_GetDefaultOutputDevice();
109 params.channelCount              = info->channels;
110 params.sampleFormat              = fmt;
111 params.suggestedLatency          = Pa_GetDeviceInfo(params.device)->defaultLowOutputLatency;
112 params.hostApiSpecificStreamInfo = NULL;
113
114 // TODO: FIXME: use libroar for this.
115 self->framesize = info->bits * info->channels / 8;
116
117 // Sets up blocking I/O stream.
118#if 0
119 err = Pa_OpenStream(&(self->stream),
120                     NULL,
121                     &params,
122                     info->rate,
123                     128 /*FIXME:frames*/,
124                     paClipOff,
125                     NULL,
126                     NULL
127                    );
128#endif
129
130 if ( err != paNoError ) {
131  ROAR_ERR("driver_portaudio_open(*): Could not open PortAudio device: \"%s\".", Pa_GetErrorText(err));
132  roar_mm_free(self);
133  return -1;
134 }
135
136 err = Pa_StartStream(self->stream);
137
138 if ( err != paNoError ) {
139  ROAR_ERR("driver_portaudio_open(*): Could not start stream: \"%s\".", Pa_GetErrorText(err));
140  roar_mm_free(self);
141  return -1;
142 }
143
144 return 0;
145#else
146 return -1;
147#endif
148}
149
150int     driver_portaudio_close        (struct roar_vio_calls * vio) {
151 struct driver_portaudio * self = vio->inst;
152
153 // TODO: cleanup common code.
154
155#ifdef ROAR_HAVE_LIBPABLIO
156 CloseAudioStream(self->ostream);
157
158 Pa_Terminate();
159
160 roar_mm_free(self);
161
162 return 0;
163#elif defined(ROAR_HAVE_LIBPORTAUDIO_V0_19)
164 if ( (self != NULL) && (self->stream != NULL) ) {
165  Pa_StopStream(self->stream);
166  Pa_CloseStream(self->stream);
167 }
168
169 roar_mm_free(self);
170
171 Pa_Terminate();
172
173 return 0;
174#else
175 return -1;
176#endif
177}
178
179ssize_t driver_portaudio_write        (struct roar_vio_calls * vio, void *buf, size_t count) {
180 struct driver_portaudio * self = vio->inst;
181
182 ROAR_DBG("driver_portaudio_write(vio=%p, buf=%p, count=%llu) = ?", vio, buf, (long long unsigned int)count);
183
184#ifdef ROAR_HAVE_LIBPABLIO
185 count /= self->ostream->bytesPerFrame; // TODO: FIXME: do not access private members
186 ROAR_DBG("driver_portaudio_write(vio=%p, buf=%p, count=%llu) = ? // PABLIO mode", vio, buf, (long long unsigned int)count);
187 return WriteAudioStream(self->ostream, buf, count) * self->ostream->bytesPerFrame;
188#elif defined(ROAR_HAVE_LIBPORTAUDIO_V0_19)
189 size_t write_frames = count / self->framesize;
190 PaError err;
191
192 ROAR_DBG("driver_portaudio_write(vio=%p, buf=%p, size=%llu) = ?", vio, buf, (long long unsigned int)size);
193
194 // I'm not 100% sure if you could write arbitrary number of frames to Pa_WriteStream(), but it seems to be backend dependent.
195 err = Pa_WriteStream(self->stream, buf, write_frames);
196
197 if ( err < 0 && err != paOutputUnderflowed )
198  return -1;
199
200 // PA always seems to write requested size, or it will error out.
201 return count;
202#else
203 return -1;
204#endif
205}
206
207#endif
208
209//ll
Note: See TracBrowser for help on using the repository browser.