Ticket #76: ao_roar.c

File ao_roar.c, 5.8 KB (added by ph3-der-loewe, 13 years ago)

Output driver for RoarAudio

Line 
1//ao_roar.c:
2/*
3 * ao_roar - RoarAudio audio output driver for MPlayer
4 *
5 * copyright (c) 2002 Juergen Keil <jk@tools.de>
6 * copyright (c) 2008-2010 Philipp 'ph3-der-loewe' Schafft
7 * copyright (c) 2010 Hans-Kristian 'maister' Arntzen
8 *
9 * This file is part of MPlayer.
10 *
11 * MPlayer is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * MPlayer is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26
27#include "config.h"
28
29#include <stdlib.h>
30#include <string.h>
31
32#include "libavutil/common.h"
33#include "mpbswap.h"
34#include "subopt-helper.h"
35#include "libaf/af_format.h"
36#include "libaf/reorder_ch.h"
37#include "audio_out.h"
38#include "audio_out_internal.h"
39#include "mp_msg.h"
40#include "help_mp.h"
41
42#include <roaraudio.h>
43
44static const ao_info_t info =
45{
46   "RoarAudio audio output",
47   "roar",
48   "Philipp 'ph3-der-loewe' Schafft <lion@lion.leolix.org>, Hans-Kristian Arntzen",
49   ""
50};
51
52LIBAO_EXTERN(roar)
53
54static char *host = NULL;
55static char *role = NULL;
56static roar_vs_t * vss = NULL;
57static int err = ROAR_ERROR_NONE;
58
59static int format2codecbits (int format, int * codec_p, int * bits_p) {
60   int codec = -1;
61   int bits  = -1;
62
63   if ( (format & AF_FORMAT_POINT_MASK) != AF_FORMAT_I && (format & AF_FORMAT_POINT_MASK) != 0 )
64      return -1;
65
66   switch (format & (AF_FORMAT_BITS_MASK|AF_FORMAT_SPECIAL_MASK)) {
67    case AF_FORMAT_8BIT:
68    case AF_FORMAT_A_LAW:
69    case AF_FORMAT_MU_LAW:
70      bits = 8;
71     break;
72    case AF_FORMAT_16BIT: bits = 16; break;
73    case AF_FORMAT_24BIT: bits = 24; break;
74    case AF_FORMAT_32BIT: bits = 32; break;
75    case AF_FORMAT_40BIT: bits = 40; break;
76    case AF_FORMAT_48BIT: bits = 48; break;
77    default:
78      return -1;
79   }
80
81   switch (format & AF_FORMAT_SPECIAL_MASK) {
82    case 0:
83      codec = 0;
84     break;
85    case AF_FORMAT_A_LAW:
86      codec = ROAR_CODEC_ALAW;
87     break;
88    case AF_FORMAT_MU_LAW:
89      codec = ROAR_CODEC_MULAW;
90     break;
91    default:
92      return -1;
93   }
94
95   if ( codec == 0 ) {
96    codec = ROAR_CODEC_PCM;
97
98    switch (format & AF_FORMAT_END_MASK) {
99     case AF_FORMAT_BE: codec |= ROAR_CODEC_BE; break;
100     case AF_FORMAT_LE: codec |= ROAR_CODEC_LE; break;
101     default:
102       return -1;
103    }
104    switch (format & AF_FORMAT_SIGN_MASK) {
105     case AF_FORMAT_SI: codec |= 0 /* no specal const here */; break;
106     case AF_FORMAT_US: codec |= ROAR_CODEC_UNSIGNED; break;
107     default:
108       return -1;
109    }
110   }
111
112   if ( codec_p != NULL )
113      *codec_p = codec;
114   if ( bits_p != NULL )
115      *bits_p  = bits;
116
117   return 0;
118}
119
120static int control(int cmd, void *arg)
121{
122    ao_control_vol_t * vol;
123
124    switch (cmd) {
125    case AOCONTROL_QUERY_FORMAT:
126      if ( format2codecbits((int)arg, NULL, NULL) == 0 )
127        return CONTROL_TRUE;
128      return CONTROL_FALSE;
129    case AOCONTROL_GET_VOLUME:
130      vol = arg;
131      if ( roar_vs_volume_get(vss, &(vol->left), &(vol->right), &err) == -1 )
132         return CONTROL_ERROR;
133
134      vol->left  *= 100.;
135      vol->right *= 100.;
136
137      return CONTROL_OK;
138    case AOCONTROL_SET_VOLUME:
139      vol = arg;
140
141      if ( roar_vs_volume_stereo(vss, vol->left / 100., vol->right / 100., &err) == -1 )
142         return CONTROL_ERROR;
143      return CONTROL_OK;
144
145    default:
146      return CONTROL_UNKNOWN;
147    }
148}
149
150static int init(int rate, int channels, int format, int flags)
151{
152   int bufsize = (1 << 15);
153   int codec;
154   int bits;
155   int roleid = ROAR_ROLE_UNKNOWN;
156
157   if ( host != NULL )
158      free(host);
159
160   if ( role != NULL )
161      free(role);
162
163   // Parses commandline
164   const opt_t subopts[] = {
165      {"host", OPT_ARG_MSTRZ, &host, NULL},
166      {"role", OPT_ARG_MSTRZ, &role, NULL},
167      {NULL}
168   };
169
170   if (subopt_parse(ao_subdevice, subopts) != 0) {
171      return 0;
172   }
173
174
175   if ( role != NULL ) {
176      roleid = roar_str2role(role);
177      if ( roleid == ROAR_ROLE_UNKNOWN )
178         return 0;
179   }
180
181   ao_data.format = format;
182
183   if ( format2codecbits(format, &codec, &bits) == -1 ) {
184      ao_data.format = AF_FORMAT_S16_LE;
185      codec = ROAR_CODEC_PCM_S_LE;
186      bits  = 16;
187   }
188
189   vss = roar_vs_new_simple(host, "MPlayer", rate, channels, codec, bits, ROAR_DIR_PLAY, &err);
190
191   if ( vss == NULL )
192      return 0;
193
194   if ( roleid != ROAR_ROLE_UNKNOWN ) {
195      if ( roar_vs_role(vss, roleid, &err) == -1 ) {
196         roar_vs_close(vss, ROAR_VS_TRUE, NULL);
197         vss = NULL;
198         return 0;
199      }
200   }
201
202   if ( roar_vs_buffer(vss, bufsize, &err) == -1 ) {
203      roar_vs_close(vss, ROAR_VS_TRUE, NULL);
204      vss = NULL;
205      return 0;
206   }
207
208   ao_data.channels = channels;
209   ao_data.samplerate = rate;
210   ao_data.bps = (channels*rate*bits)/8;
211
212   ao_data.outburst = (1 << 10);
213   ao_data.buffersize = bufsize;
214   
215   return 1;
216}
217
218static void uninit(int n)
219{
220   roar_vs_close(vss, ROAR_VS_FALSE, &err);
221   vss = NULL;
222}
223
224static void reset(void)
225{
226 // XXX: ???
227}
228
229static void audio_pause(void)
230{
231   roar_vs_pause(vss, ROAR_VS_TRUE, &err);
232}
233
234static void audio_resume(void)
235{
236   roar_vs_pause(vss, ROAR_VS_FALSE, &err);
237}
238
239static int get_space(void)
240{
241   return roar_vs_get_avail_write(vss, &err);
242}
243
244static int play(void* data, int len, int flags)
245{
246   ssize_t ret = roar_vs_write(vss, data, len, &err);
247
248   // FIXME: what does we need to return?
249   return ret;
250}
251
252static float get_delay(void)
253{
254   // TODO: maister needs to fix this. He know how to handle this correcly with MPlayer.
255   return 0;
256}
257
258