4 This file is part of polypaudio.
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
37 #include <polyp/polyplib.h>
38 #include <polyp/polyplib-error.h>
39 #include <polyp/mainloop.h>
40 #include <polyp/mainloop-signal.h>
41 #include <polyp/sample.h>
45 static struct pa_context
*context
= NULL
;
46 static struct pa_mainloop_api
*mainloop_api
= NULL
;
48 static char **process_argv
= NULL
;
50 static SNDFILE
*sndfile
= NULL
;
51 static struct pa_stream
*sample_stream
= NULL
;
52 static struct pa_sample_spec sample_spec
;
53 static size_t sample_length
= 0;
55 static char *sample_name
= NULL
;
66 static void quit(int ret
) {
68 mainloop_api
->quit(mainloop_api
, ret
);
71 static void context_die_callback(struct pa_context
*c
, void *userdata
) {
73 fprintf(stderr
, "Connection to server shut down, exiting.\n");
77 static void context_drain_complete(struct pa_context
*c
, void *userdata
) {
79 fprintf(stderr
, "Connection to server shut down, exiting.\n");
83 static void drain(void) {
84 if (pa_context_drain(context
, context_drain_complete
, NULL
) < 0)
88 static void stat_callback(struct pa_context
*c
, uint32_t blocks
, uint32_t total
, void *userdata
) {
89 if (blocks
== (uint32_t) -1) {
90 fprintf(stderr
, "Failed to get statistics: %s\n", pa_strerror(pa_context_errno(c
)));
95 fprintf(stderr
, "Currently in use: %u blocks containing %u bytes total.\n", blocks
, total
);
99 static void play_sample_callback(struct pa_context
*c
, int success
, void *userdata
) {
101 fprintf(stderr
, "Failed to play sample: %s\n", pa_strerror(pa_context_errno(c
)));
109 static void remove_sample_callback(struct pa_context
*c
, int success
, void *userdata
) {
111 fprintf(stderr
, "Failed to remove sample: %s\n", pa_strerror(pa_context_errno(c
)));
119 static void stream_die_callback(struct pa_stream
*s
, void *userdata
) {
121 fprintf(stderr
, "Stream deleted, exiting.\n");
125 static void finish_sample_callback(struct pa_stream
*s
, int success
, void *userdata
) {
129 fprintf(stderr
, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(context
)));
137 static void stream_write_callback(struct pa_stream
*s
, size_t length
, void *userdata
) {
140 assert(s
&& length
&& sndfile
);
145 assert(sample_length
>= length
);
146 l
= length
/pa_frame_size(&sample_spec
);
148 if ((sf_readf_float(sndfile
, d
, l
)) != l
) {
150 fprintf(stderr
, "Premature end of file\n");
154 pa_stream_write(s
, d
, length
);
157 sample_length
-= length
;
159 if (sample_length
<= 0) {
160 pa_stream_set_write_callback(sample_stream
, NULL
, NULL
);
161 pa_stream_finish_sample(sample_stream
, finish_sample_callback
, NULL
);
165 static void upload_callback(struct pa_stream
*s
, int success
, void *userdata
) {
167 fprintf(stderr
, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(context
)));
172 static void context_complete_callback(struct pa_context
*c
, int success
, void *userdata
) {
176 fprintf(stderr
, "Connection failed: %s\n", pa_strerror(pa_context_errno(c
)));
180 fprintf(stderr
, "Connection established.\n");
183 pa_context_stat(c
, stat_callback
, NULL
);
184 else if (action
== PLAY_SAMPLE
)
185 pa_context_play_sample(c
, process_argv
[2], NULL
, 0x100, play_sample_callback
, NULL
);
186 else if (action
== REMOVE_SAMPLE
)
187 pa_context_remove_sample(c
, process_argv
[2], remove_sample_callback
, NULL
);
188 else if (action
== UPLOAD_SAMPLE
) {
189 if (!(sample_stream
= pa_context_upload_sample(c
, sample_name
, &sample_spec
, sample_length
, upload_callback
, NULL
))) {
190 fprintf(stderr
, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(c
)));
194 pa_stream_set_die_callback(sample_stream
, stream_die_callback
, NULL
);
195 pa_stream_set_write_callback(sample_stream
, stream_write_callback
, NULL
);
197 assert(action
== EXIT
);
208 static void exit_signal_callback(void *id
, int sig
, void *userdata
) {
209 fprintf(stderr
, "Got SIGINT, exiting.\n");
213 int main(int argc
, char *argv
[]) {
214 struct pa_mainloop
* m
= NULL
;
220 if (!strcmp(argv
[1], "stat"))
222 else if (!strcmp(argv
[1], "exit"))
224 else if (!strcmp(argv
[1], "scache_upload")) {
225 struct SF_INFO sfinfo
;
226 action
= UPLOAD_SAMPLE
;
229 fprintf(stderr
, "Please specify a sample file to load\n");
234 sample_name
= argv
[3];
236 char *f
= strrchr(argv
[2], '/');
242 strncpy(sample_name
= tmp
, f
, strcspn(f
, "."));
245 memset(&sfinfo
, 0, sizeof(sfinfo
));
246 if (!(sndfile
= sf_open(argv
[2], SFM_READ
, &sfinfo
))) {
247 fprintf(stderr
, "Failed to open sound file.\n");
251 sample_spec
.format
= PA_SAMPLE_FLOAT32
;
252 sample_spec
.rate
= sfinfo
.samplerate
;
253 sample_spec
.channels
= sfinfo
.channels
;
255 sample_length
= sfinfo
.frames
*pa_frame_size(&sample_spec
);
256 } else if (!strcmp(argv
[1], "scache_play")) {
257 action
= PLAY_SAMPLE
;
259 fprintf(stderr
, "You have to specify a sample name to play\n");
262 } else if (!strcmp(argv
[1], "scache_remove")) {
263 action
= REMOVE_SAMPLE
;
265 fprintf(stderr
, "You have to specify a sample name to remove\n");
271 if (action
== NONE
) {
272 fprintf(stderr
, "No valid action specified. Use one of: stat, exit, scache_upload, scache_play, scache_remove\n");
278 if (!(m
= pa_mainloop_new())) {
279 fprintf(stderr
, "pa_mainloop_new() failed.\n");
283 mainloop_api
= pa_mainloop_get_api(m
);
285 r
= pa_signal_init(mainloop_api
);
287 pa_signal_register(SIGINT
, exit_signal_callback
, NULL
);
288 signal(SIGPIPE
, SIG_IGN
);
290 if (!(context
= pa_context_new(mainloop_api
, argv
[0]))) {
291 fprintf(stderr
, "pa_context_new() failed.\n");
295 if (pa_context_connect(context
, NULL
, context_complete_callback
, NULL
) < 0) {
296 fprintf(stderr
, "pa_context_connext() failed.\n");
300 pa_context_set_die_callback(context
, context_die_callback
, NULL
);
302 if (pa_mainloop_run(m
, &ret
) < 0) {
303 fprintf(stderr
, "pa_mainloop_run() failed.\n");
309 pa_context_free(context
);