source: roaraudio/libroar/cdrom.c @ 5895:2bcffab4cd73

Last change on this file since 5895:2bcffab4cd73 was 5895:2bcffab4cd73, checked in by phi, 11 years ago

Moved away from roar_libroar_get_path_static()

File size: 6.7 KB
Line 
1//cdrom.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2013
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, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38#define ROAR_CDROM_ERROR_NORETURN(format, args...) ROAR_ERR(format, ## args); ROAR_U_EXIT(3)
39
40#if BYTE_ORDER == BIG_ENDIAN
41#define ROAR_CDROM_CDPARANOIA_OUTPUTFORMAT "--output-raw-big-endian"
42#elif BYTE_ORDER == LITTLE_ENDIAN
43#define ROAR_CDROM_CDPARANOIA_OUTPUTFORMAT "--output-raw-little-endian"
44#endif
45
46#ifdef ROAR_TARGET_WIN32
47#undef ROAR_HAVE_BIN_CDPARANOIA
48#endif
49
50pid_t roar_cdrom_run_cdparanoia (int cdrom, int data, int track, char * pos) {
51#if defined(ROAR_HAVE_BIN_CDPARANOIA) && defined(ROAR_CDROM_CDPARANOIA_OUTPUTFORMAT) && defined(ROAR_HAVE_CDROM)
52 char my_pos[32] = {0};
53 pid_t pid;
54 int fh[2];
55 char * bin_cdparanoia = NULL, * dev_stdin = NULL;
56 int err;
57
58 ROAR_DBG("roar_cdrom_run_cdparanoia(cdrom=%i, data=%i, track=%i, pos='%s') = ?", cdrom, data, track, pos);
59
60 if ( cdrom == -1 || data == -1 || (track == -1 && pos == NULL) || (track != -1 && pos != NULL) )
61  return -1;
62
63 if ( track != -1 ) {
64  pos = my_pos;
65  snprintf(pos, 32, "%i", track);
66 }
67
68 if ( (pid = roar_fork(NULL)) == (pid_t)-1 ) {
69  return -1;
70 }
71
72 if ( pid )
73  return pid;
74
75 fh[0] = dup(cdrom);
76 fh[1] = dup(data);
77
78 if ( fh[0] == -1 || fh[1] == -1 ) {
79  ROAR_CDROM_ERROR_NORETURN("Can not dup(): %s", strerror(errno));
80 }
81
82 close(ROAR_STDIN);
83 close(ROAR_STDOUT);
84
85 // TODO: should I close some other handles?
86
87 if ( dup2(fh[0], ROAR_STDIN) == -1 || dup2(fh[1], ROAR_STDOUT) == -1 ) {
88  ROAR_CDROM_ERROR_NORETURN("Can not dup2(): %s", strerror(errno));
89 }
90
91 // now close our backups:
92 close(fh[0]);
93 close(fh[1]);
94
95 bin_cdparanoia = roar_libroar_get_path("bin-cdparanoia", 0, NULL, NULL);
96 if ( bin_cdparanoia == NULL )
97  return -1;
98 dev_stdin = roar_libroar_get_path("dev-stdin", 0, NULL, NULL);
99 if ( dev_stdin == NULL ) {
100  err = roar_error;
101  roar_mm_free(bin_cdparanoia);
102  roar_error = err;
103  return -1;
104 }
105 execl(bin_cdparanoia, bin_cdparanoia, "--force-cdrom-device", dev_stdin, "-q",
106                ROAR_CDROM_CDPARANOIA_OUTPUTFORMAT, pos, "-", NULL);
107
108 roar_mm_free(bin_cdparanoia);
109 roar_mm_free(dev_stdin);
110
111 ROAR_CDROM_ERROR_NORETURN("We are still alive after exec()!, very bad!, error was: %s", strerror(errno));
112 return -1;
113#else
114#ifndef ROAR_HAVE_BIN_CDPARANOIA
115 ROAR_ERR("roar_cdrom_run_cdparanoia(*): ROAR_HAVE_BIN_CDPARANOIA not defined!");
116#endif
117#ifndef ROAR_CDROM_CDPARANOIA_OUTPUTFORMAT
118 ROAR_ERR("roar_cdrom_run_cdparanoia(*): ROAR_CDROM_CDPARANOIA_OUTPUTFORMAT not defined!");
119#endif
120 ROAR_ERR("roar_cdrom_run_cdparanoia(cdrom=%i, data=%i, track=%i, pos='%s') = -1 // no cdparanoia support compiled in",
121             cdrom, data, track, pos);
122 return -1;
123#endif
124}
125
126int roar_cdrom_open (struct roar_connection * con, struct roar_cdrom * cdrom, const char * device, int mixer) {
127#ifdef ROAR_HAVE_CDROM
128 int flags;
129
130 if ( cdrom == NULL )
131  return -1;
132
133 memset((void*)cdrom, 0, sizeof(struct roar_cdrom));
134
135 if ( device == NULL )
136  device = roar_cdromdevice();
137
138 if ( device == NULL )
139  return -1;
140
141 strncpy(cdrom->device, device, ROAR_CDROM_MAX_DEVLEN);
142
143 cdrom->con        = con; // we do not care here if it is set or not as we can operate in local only mode
144 cdrom->mixer      = mixer;
145
146 cdrom->stream     = -1;
147 cdrom->play_local =  1;
148 cdrom->player     = -1;
149
150 if ( (cdrom->fh = open(cdrom->device, O_RDONLY, 0644)) == -1 )
151  return -1;
152
153#ifndef ROAR_TARGET_WIN32
154 if ( (flags = fcntl(cdrom->fh, F_GETFL, 0)) == -1 ) {
155  close(cdrom->fh);
156  cdrom->fh  = -1;
157  return -1;
158 }
159
160 flags |= FD_CLOEXEC;
161
162 if ( fcntl(cdrom->fh, F_SETFL, flags) == -1 ) {
163  close(cdrom->fh);
164  cdrom->fh = -1;
165  return -1;
166 }
167#endif
168
169 return 0;
170#else
171 return -1;
172#endif
173}
174
175int roar_cdrom_close(struct roar_cdrom * cdrom) {
176#ifdef ROAR_HAVE_CDROM
177 if ( cdrom == NULL )
178  return -1;
179
180 roar_cdrom_stop(cdrom); // stop on close
181
182 if ( cdrom->fh != -1 )
183  close(cdrom->fh);
184
185 memset((void*)cdrom, 0, sizeof(struct roar_cdrom));
186
187 return 0;
188#else
189 return -1;
190#endif
191}
192
193int roar_cdrom_stop (struct roar_cdrom * cdrom) {
194#ifdef ROAR_HAVE_CDROM
195 int ret;
196
197 if ( cdrom == NULL )
198  return -1;
199
200 if ( cdrom->con == NULL )
201  return -1;
202
203 if ( cdrom->stream == -1 )
204  return -1;
205
206 if ( (ret = roar_kick(cdrom->con, ROAR_OT_STREAM, cdrom->stream)) == -1 ) {
207  return -1;
208 }
209
210#ifndef ROAR_TARGET_WIN32
211 if ( cdrom->player != -1 )
212  kill(cdrom->player, SIGINT);
213#else
214 if ( cdrom->player != -1 ) {
215  ROAR_ERR("roar_cdrom_stop(*): Can not kill player with pid %i, not supported on win32", cdrom->player);
216 }
217#endif
218
219 cdrom->player = -1;
220 cdrom->stream = -1;
221
222 return ret;
223#else
224 return -1;
225#endif
226}
227
228int roar_cdrom_play (struct roar_cdrom * cdrom, int track) {
229#ifdef ROAR_HAVE_CDROM
230 struct roar_vio_calls vio;
231 struct roar_stream stream[1];
232 int stream_fh;
233
234 if ( cdrom == NULL )
235  return -1;
236
237 if ( cdrom->con == NULL )
238  return -1;
239
240 if ( cdrom->stream != -1 ) {
241  if ( roar_cdrom_stop(cdrom) == -1 )
242   return -1;
243 }
244
245 if ( cdrom->play_local ) {
246
247  if ( roar_vio_simple_new_stream_obj(&vio, cdrom->con, stream, ROAR_CDROM_STREAMINFO, ROAR_DIR_PLAY, cdrom->mixer) == -1 ) {
248   return -1;
249  }
250
251  if ( roar_vio_ctl(&vio, ROAR_VIO_CTL_GET_WRITE_FH, &stream_fh) == -1 ) {
252   roar_vio_close(&vio);
253   return -1;
254  }
255
256  if ( (cdrom->player = roar_cdrom_run_cdparanoia(cdrom->fh, stream_fh, track, NULL)) != -1 ) {
257   cdrom->stream = stream->id;
258   return 0;
259  }
260
261  roar_vio_close(&vio);
262
263  return -1;
264 } else {
265  // no support for remote playback yet
266  return -1;
267 }
268#else
269 return -1;
270#endif
271}
272
273//ll
Note: See TracBrowser for help on using the repository browser.