2 * Copyright (C) 2003-2010 The Music Player Daemon Project
3 * http://www.musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "output_plugin.h"
22 #include "output_internal.h"
23 #include "output_control.h"
25 #include "audio_parser.h"
26 #include "filter_registry.h"
27 #include "pcm_convert.h"
28 #include "event_pipe.h"
38 idle_add(G_GNUC_UNUSED
unsigned flags
)
43 event_pipe_emit(G_GNUC_UNUSED
enum pipe_event event
)
47 void pcm_convert_init(G_GNUC_UNUSED
struct pcm_convert_state
*state
)
51 void pcm_convert_deinit(G_GNUC_UNUSED
struct pcm_convert_state
*state
)
56 pcm_convert(G_GNUC_UNUSED
struct pcm_convert_state
*state
,
57 G_GNUC_UNUSED
const struct audio_format
*src_format
,
58 G_GNUC_UNUSED
const void *src
, G_GNUC_UNUSED
size_t src_size
,
59 G_GNUC_UNUSED
const struct audio_format
*dest_format
,
60 G_GNUC_UNUSED
size_t *dest_size_r
,
63 g_set_error(error_r
, pcm_convert_quark(), 0,
68 const struct filter_plugin
*
69 filter_plugin_by_name(G_GNUC_UNUSED
const char *name
)
75 static const struct config_param
*
76 find_named_config_block(const char *block
, const char *name
)
78 const struct config_param
*param
= NULL
;
80 while ((param
= config_get_next_param(block
, param
)) != NULL
) {
81 const char *current_name
=
82 config_get_block_string(param
, "name", NULL
);
83 if (current_name
!= NULL
&& strcmp(current_name
, name
) == 0)
91 load_audio_output(struct audio_output
*ao
, const char *name
)
93 const struct config_param
*param
;
97 param
= find_named_config_block(CONF_AUDIO_OUTPUT
, name
);
99 g_printerr("No such configured audio output: %s\n", name
);
103 success
= audio_output_init(ao
, param
, &error
);
105 g_printerr("%s\n", error
->message
);
112 int main(int argc
, char **argv
)
114 struct audio_output ao
;
115 struct audio_format audio_format
;
116 struct audio_format_string af_string
;
118 GError
*error
= NULL
;
121 size_t frame_size
, length
= 0, play_length
, consumed
;
123 if (argc
< 3 || argc
> 4) {
124 g_printerr("Usage: run_output CONFIG NAME [FORMAT] <IN\n");
128 audio_format_init(&audio_format
, 44100, SAMPLE_FORMAT_S16
, 2);
132 /* read configuration file (mpd.conf) */
134 config_global_init();
135 success
= config_read_file(argv
[1], &error
);
137 g_printerr("%s:", error
->message
);
142 /* initialize the audio output */
144 if (!load_audio_output(&ao
, argv
[2]))
147 /* parse the audio format */
150 success
= audio_format_parse(&audio_format
, argv
[3],
153 g_printerr("Failed to parse audio format: %s\n",
160 /* open the audio output */
162 success
= ao_plugin_open(ao
.plugin
, ao
.data
, &audio_format
, &error
);
164 g_printerr("Failed to open audio output: %s\n",
170 g_printerr("audio_format=%s\n",
171 audio_format_to_string(&audio_format
, &af_string
));
173 frame_size
= audio_format_frame_size(&audio_format
);
178 if (length
< sizeof(buffer
)) {
179 nbytes
= read(0, buffer
+ length
, sizeof(buffer
) - length
);
183 length
+= (size_t)nbytes
;
186 play_length
= (length
/ frame_size
) * frame_size
;
187 if (play_length
> 0) {
188 consumed
= ao_plugin_play(ao
.plugin
, ao
.data
,
192 g_printerr("Failed to play: %s\n",
198 assert(consumed
<= length
);
199 assert(consumed
% frame_size
== 0);
202 memmove(buffer
, buffer
+ consumed
, length
);
206 /* cleanup and exit */
208 ao_plugin_close(ao
.plugin
, ao
.data
);
209 ao_plugin_finish(ao
.plugin
, ao
.data
);
210 g_mutex_free(ao
.mutex
);
212 config_global_finish();