implement filtered pipeline
[gst-scaletempo-demo-rj.git] / src / play.c
blob122c1cb6c299229a8f535fc77350a708429387f8
1 /* Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
3 * Permission is hereby granted, free of charge, to any person obtaining a
4 * copy of this software and associated documentation files (the "Software"),
5 * to deal in the Software without restriction, including without limitation
6 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 * and/or sell copies of the Software, and to permit persons to whom the
8 * Software is furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19 * DEALINGS IN THE SOFTWARE.
21 * Alternatively, the contents of this file may be used under the
22 * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
23 * which case the following provisions apply instead of the ones
24 * mentioned above:
26 * This library is free software; you can redistribute it and/or
27 * modify it under the terms of the GNU Library General Public
28 * License as published by the Free Software Foundation; either
29 * version 2 of the License, or (at your option) any later version.
31 * This library is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 * Library General Public License for more details.
36 * You should have received a copy of the GNU Library General Public
37 * License along with this library; if not, write to the
38 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
39 * Boston, MA 02111-1307, USA.
42 #include <string.h>
43 #include "play.h"
45 static GstElement *pipeline;
47 #define MAKE_ELEMENT(v,c,n) \
48 if ( ! (v = gst_element_factory_make (c, n) ) ) { \
49 g_print ("element could not be created: %s/%s\n", c, n); \
50 return; \
53 #define LINK_ELEMENTS(isdyn, src, sink) \
54 if (isdyn) { \
55 g_signal_connect (G_OBJECT (src), "pad-added", \
56 G_CALLBACK (dynamic_link), sink); \
57 } else { \
58 if (!gst_element_link (src, sink)) { \
59 g_warning ("Failed to link elements: %s -> %s", \
60 GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink) ); \
61 return; \
62 } \
65 #define ADD_AND_LINK(isdyn, pipe, src, sink) \
66 gst_bin_add(GST_BIN (pipe), sink); \
67 LINK_ELEMENTS(isdyn, src, sink);
69 static void
70 dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data) {
71 GstElement *bin = (GstElement *) data;
72 GstPad *sink = gst_element_get_pad (bin, "sink");
74 if (gst_pad_can_link (newpad, sink)) {
75 gst_bin_add (GST_BIN (pipeline), bin);
76 gst_pad_link (newpad, sink);
80 void
81 play_file (const gchar * filename, const play_file_args * args)
83 GstStateChangeReturn sret;
84 GstMessage *msg = NULL;
85 GstBus *bus;
87 g_print ("Trying to play %s ...\n", filename);
88 g_print (" silent: %s\n", (args->silent?"Yes":"No"));
89 g_print (" is raw file: %s\n", (args->israwfile?"Yes":"No"));
90 g_print (" filter: %s\n", args->filter_name);
91 g_print (" param_name: %s\n", args->param_name);
92 g_print (" scale: %3.2f\n", args->scale);
93 g_print (" temp: %3.2f\n", args->temp);
94 g_print (" # buffers: %i\n", args->num_buffers);
95 g_print (" audio: %s\n", (args->noaudio?"No":"Yes"));
96 g_print (" video: %s\n", (args->novideo?"No":"Yes"));
98 pipeline = gst_pipeline_new ("my-pipeline");
99 bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
100 gst_object_unref (bus);
102 GstElement *source, *decode;
103 MAKE_ELEMENT(source, "filesrc", "source");
104 g_object_set (G_OBJECT (source), "location", filename, NULL);
105 if (args->num_buffers > 0) {
106 g_object_set (G_OBJECT (source), "num_buffers", args->num_buffers, NULL);
108 gst_bin_add (GST_BIN(pipeline), source);
110 MAKE_ELEMENT(decode, "decodebin2", "decode");
111 ADD_AND_LINK(0, pipeline, source, decode);
113 if (!args->noaudio) {
114 GstElement *queue, *format1, *resample1, *filter, *format2, *resample2, *sink;
115 MAKE_ELEMENT(queue, "queue", "audio_queue");
116 MAKE_ELEMENT(format1, "audioconvert", "format1");
117 MAKE_ELEMENT(resample1, "audioresample", "resample1");
118 MAKE_ELEMENT(filter, args->filter_name, "filter");
119 MAKE_ELEMENT(format2, "audioconvert", "format2");
120 MAKE_ELEMENT(resample2, "audioresample", "resample2");
121 MAKE_ELEMENT(sink, "gconfaudiosink", "audio_sink");
123 if (args->param_name)
124 g_object_set (G_OBJECT (filter), args->param_name, args->scale, NULL);
126 GstElement *subline = gst_bin_new ("audioline");
128 gst_bin_add (GST_BIN(subline), queue);
129 ADD_AND_LINK(0, subline, queue, format1);
130 ADD_AND_LINK(0, subline, format1, resample1);
131 ADD_AND_LINK(0, subline, resample1, filter);
132 ADD_AND_LINK(0, subline, filter, format2);
133 ADD_AND_LINK(0, subline, format2, resample2);
134 ADD_AND_LINK(0, subline, resample2, sink);
136 GstPad *ghostpad = gst_element_get_pad (queue, "sink");
137 gst_element_add_pad (subline, gst_ghost_pad_new ("sink", ghostpad));
138 gst_object_unref (ghostpad);
140 gst_element_set_state (subline, GST_STATE_PAUSED);
142 LINK_ELEMENTS(1, decode, subline);
145 if (!args->novideo) {
146 GstElement *queue, *colorspace, *sink;
147 MAKE_ELEMENT(queue, "queue", "video_queue");
148 MAKE_ELEMENT(colorspace, "ffmpegcolorspace", "colorspace");
149 MAKE_ELEMENT(sink, "gconfvideosink", "video_sink");
151 GstElement *subline = gst_bin_new ("videoline");
153 gst_bin_add (GST_BIN(subline), queue);
154 ADD_AND_LINK(0, subline, queue, colorspace);
155 ADD_AND_LINK(0, subline, colorspace, sink);
157 GstPad *ghostpad = gst_element_get_pad (queue, "sink");
158 gst_element_add_pad (subline, gst_ghost_pad_new ("sink", ghostpad));
159 gst_object_unref (ghostpad);
161 gst_element_set_state (subline, GST_STATE_PLAYING);
163 LINK_ELEMENTS(1, decode, subline);
166 /* and GO GO GO! */
167 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
168 g_print ("Hi there1.\n");
169 /* wait (blocks!) until state change either completes or fails */
170 sret = gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL, -1);
171 g_print ("Hi there2.\n");
172 switch (sret) {
173 case GST_STATE_CHANGE_FAILURE:{
174 msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0);
175 goto got_error_message;
177 case GST_STATE_CHANGE_SUCCESS:{
178 GstMessage *msg;
180 g_print ("Playing ...\n");
182 while (1) {
183 GstFormat time_format;
184 gint64 dur, pos;
186 time_format = GST_FORMAT_TIME;
187 if (gst_element_query_duration (pipeline, &time_format, &dur) &&
188 gst_element_query_position (pipeline, &time_format, &pos)) {
189 g_print (" %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\n",
190 GST_TIME_ARGS (pos), GST_TIME_ARGS (dur));
193 /* check if we finished or if there was an error,
194 * but don't wait/block if neither is the case */
195 msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, 0);
197 if (msg && GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR)
198 goto got_error_message;
200 if (msg && GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) {
201 g_print ("Finished.\n");
202 break;
205 /* sleep for one second */
206 g_usleep (G_USEC_PER_SEC * 1);
208 break;
210 default:
211 g_assert_not_reached ();
214 /* shut down and free everything */
215 gst_element_set_state (pipeline, GST_STATE_NULL);
216 gst_object_unref (pipeline);
217 gst_object_unref (bus);
218 return;
220 /* ERRORS */
221 got_error_message:
223 if (msg) {
224 GError *err = NULL;
225 gchar *dbg_str = NULL;
227 gst_message_parse_error (msg, &err, &dbg_str);
228 g_printerr ("FAILED to play %s: %s\n%s\n", filename, err->message,
229 (dbg_str) ? dbg_str : "(no debugging information)");
230 g_error_free (err);
231 g_free (dbg_str);
232 gst_message_unref (msg);
233 } else {
234 g_printerr ("FAILED to play %s: unknown error\n", filename);
237 /* shut down and free everything */
238 gst_element_set_state (pipeline, GST_STATE_NULL);
239 gst_object_unref (pipeline);
240 gst_object_unref (bus);
241 return;