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
);
72 static void context_drain_complete(struct pa_context
*c
, void *userdata
) {
73 pa_context_disconnect(c
);
76 static void drain(void) {
77 struct pa_operation
*o
;
78 if (!(o
= pa_context_drain(context
, context_drain_complete
, NULL
)))
79 pa_context_disconnect(context
);
81 pa_operation_unref(o
);
84 static void stat_callback(struct pa_context
*c
, const struct pa_stat_info
*i
, void *userdata
) {
86 fprintf(stderr
, "Failed to get statistics: %s\n", pa_strerror(pa_context_errno(c
)));
91 fprintf(stderr
, "Currently in use: %u blocks containing %u bytes total.\n"
92 "Allocated during whole lifetime: %u blocks containing %u bytes total.\n",
93 i
->memblock_total
, i
->memblock_total_size
, i
->memblock_allocated
, i
->memblock_allocated_size
);
97 static void play_sample_callback(struct pa_context
*c
, int success
, void *userdata
) {
99 fprintf(stderr
, "Failed to play sample: %s\n", pa_strerror(pa_context_errno(c
)));
107 static void remove_sample_callback(struct pa_context
*c
, int success
, void *userdata
) {
109 fprintf(stderr
, "Failed to remove sample: %s\n", pa_strerror(pa_context_errno(c
)));
117 static void stream_state_callback(struct pa_stream
*s
, void *userdata
) {
120 switch (pa_stream_get_state(s
)) {
121 case PA_STREAM_CREATING
:
122 case PA_STREAM_READY
:
125 case PA_STREAM_TERMINATED
:
129 case PA_STREAM_FAILED
:
131 fprintf(stderr
, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s
))));
136 static void stream_write_callback(struct pa_stream
*s
, size_t length
, void *userdata
) {
139 assert(s
&& length
&& sndfile
);
144 assert(sample_length
>= length
);
145 l
= length
/pa_frame_size(&sample_spec
);
147 if ((sf_readf_float(sndfile
, d
, l
)) != l
) {
149 fprintf(stderr
, "Premature end of file\n");
153 pa_stream_write(s
, d
, length
, free
, 0);
155 sample_length
-= length
;
157 if (sample_length
<= 0) {
158 pa_stream_set_write_callback(sample_stream
, NULL
, NULL
);
159 pa_stream_finish_upload(sample_stream
);
163 static void context_state_callback(struct pa_context
*c
, void *userdata
) {
165 switch (pa_context_get_state(c
)) {
166 case PA_CONTEXT_CONNECTING
:
167 case PA_CONTEXT_AUTHORIZING
:
168 case PA_CONTEXT_SETTING_NAME
:
171 case PA_CONTEXT_READY
:
173 pa_operation_unref(pa_context_stat(c
, stat_callback
, NULL
));
174 else if (action
== PLAY_SAMPLE
)
175 pa_operation_unref(pa_context_play_sample(c
, process_argv
[2], NULL
, 0x100, play_sample_callback
, NULL
));
176 else if (action
== REMOVE_SAMPLE
)
177 pa_operation_unref(pa_context_remove_sample(c
, process_argv
[2], remove_sample_callback
, NULL
));
178 else if (action
== UPLOAD_SAMPLE
) {
180 sample_stream
= pa_stream_new(c
, sample_name
, &sample_spec
);
181 assert(sample_stream
);
183 pa_stream_set_state_callback(sample_stream
, stream_state_callback
, NULL
);
184 pa_stream_set_write_callback(sample_stream
, stream_write_callback
, NULL
);
185 pa_stream_connect_upload(sample_stream
, sample_length
);
187 assert(action
== EXIT
);
188 pa_context_exit_daemon(c
);
193 case PA_CONTEXT_TERMINATED
:
197 case PA_CONTEXT_FAILED
:
199 fprintf(stderr
, "Connection failure: %s\n", pa_strerror(pa_context_errno(c
)));
204 static void exit_signal_callback(struct pa_mainloop_api
*m
, struct pa_signal_event
*e
, int sig
, void *userdata
) {
205 fprintf(stderr
, "Got SIGINT, exiting.\n");
209 int main(int argc
, char *argv
[]) {
210 struct pa_mainloop
* m
= NULL
;
216 if (!strcmp(argv
[1], "stat"))
218 else if (!strcmp(argv
[1], "exit"))
220 else if (!strcmp(argv
[1], "scache_upload")) {
221 struct SF_INFO sfinfo
;
222 action
= UPLOAD_SAMPLE
;
225 fprintf(stderr
, "Please specify a sample file to load\n");
230 sample_name
= argv
[3];
232 char *f
= strrchr(argv
[2], '/');
240 strncpy(sample_name
= tmp
, f
, n
);
244 memset(&sfinfo
, 0, sizeof(sfinfo
));
245 if (!(sndfile
= sf_open(argv
[2], SFM_READ
, &sfinfo
))) {
246 fprintf(stderr
, "Failed to open sound file.\n");
250 sample_spec
.format
= PA_SAMPLE_FLOAT32
;
251 sample_spec
.rate
= sfinfo
.samplerate
;
252 sample_spec
.channels
= sfinfo
.channels
;
254 sample_length
= sfinfo
.frames
*pa_frame_size(&sample_spec
);
255 } else if (!strcmp(argv
[1], "scache_play")) {
256 action
= PLAY_SAMPLE
;
258 fprintf(stderr
, "You have to specify a sample name to play\n");
261 } else if (!strcmp(argv
[1], "scache_remove")) {
262 action
= REMOVE_SAMPLE
;
264 fprintf(stderr
, "You have to specify a sample name to remove\n");
270 if (action
== NONE
) {
271 fprintf(stderr
, "No valid action specified. Use one of: stat, exit, scache_upload, scache_play, scache_remove\n");
277 if (!(m
= pa_mainloop_new())) {
278 fprintf(stderr
, "pa_mainloop_new() failed.\n");
282 mainloop_api
= pa_mainloop_get_api(m
);
284 r
= pa_signal_init(mainloop_api
);
286 pa_signal_new(SIGINT
, exit_signal_callback
, NULL
);
287 signal(SIGPIPE
, SIG_IGN
);
289 if (!(context
= pa_context_new(mainloop_api
, argv
[0]))) {
290 fprintf(stderr
, "pa_context_new() failed.\n");
294 pa_context_set_state_callback(context
, context_state_callback
, NULL
);
295 pa_context_connect(context
, NULL
);
297 if (pa_mainloop_run(m
, &ret
) < 0) {
298 fprintf(stderr
, "pa_mainloop_run() failed.\n");
304 pa_stream_unref(sample_stream
);
307 pa_context_unref(context
);