mixer.c 7.67 KB
Newer Older
Wim Taymans's avatar
Wim Taymans committed
1 2
#include <stdlib.h>
#include <gst/gst.h>
3 4
#include "mixer.h"

5
//#define DEBUG
6 7 8

/* function prototypes */

9 10
input_channel_t*	create_input_channel (int id, char* location);
void				destroy_input_channel (input_channel_t *pipe);
11

Wim Taymans's avatar
Wim Taymans committed
12 13 14 15

gboolean playing;

/* example based on helloworld by thomas@apestaart.org
16 17
   demonstrates the adder plugin and the volume envelope plugin 
   work in progress but do try it out */
Wim Taymans's avatar
Wim Taymans committed
18 19 20 21 22 23 24 25 26

/* eos will be called when the src element has an end of stream */
void eos(GstElement *element) 
{
  g_print("have eos, quitting\n");

  playing = FALSE;
}

27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
static void
gst_play_have_type (GstElement *sink, GstElement *sink2, gpointer data)
{
  GST_DEBUG (0,"GstPipeline: play have type %p\n", (gboolean *)data);
 
  *(gboolean *)data = TRUE;
}

static GstCaps*
gst_play_typefind (GstBin *bin, GstElement *element)
{
  gboolean found = FALSE;
  GstElement *typefind;
  GstCaps *caps = NULL;

  GST_DEBUG (0,"GstPipeline: typefind for element \"%s\" %p\n",
             GST_ELEMENT_NAME(element), &found);
 
  typefind = gst_elementfactory_make ("typefind", "typefind");
  g_return_val_if_fail (typefind != NULL, FALSE);

  gtk_signal_connect (GTK_OBJECT (typefind), "have_type",  
                      GTK_SIGNAL_FUNC (gst_play_have_type), &found);
 
  gst_pad_connect (gst_element_get_pad (element, "src"),
                   gst_element_get_pad (typefind, "sink"));
  gst_bin_add (bin, typefind);
  
  gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
  
  // push a buffer... the have_type signal handler will set the found flag
  gst_bin_iterate (bin);
  
  gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);

  caps = gst_pad_get_caps (gst_element_get_pad (element, "src"));

  gst_pad_disconnect (gst_element_get_pad (element, "src"),
                      gst_element_get_pad (typefind, "sink"));
  gst_bin_remove (bin, typefind);
  gst_object_unref (GST_OBJECT (typefind));
                   
  return caps;
}

Wim Taymans's avatar
Wim Taymans committed
72 73
int main(int argc,char *argv[]) 
{
74 75
  input_channel_t *channel_in1;
  input_channel_t *channel_in2;
76 77
  
  GstElement *main_bin;
Wim Taymans's avatar
Wim Taymans committed
78 79 80 81 82 83 84 85 86 87 88 89
  GstElement *adder;
  GstElement *audiosink;

  GstPad *pad; /* to request pads for the adder */

  gst_init(&argc,&argv);

  if (argc != 3) {
    g_print("usage: %s <filename1> <filename2>\n", argv[0]);
    exit(-1);
  }

90
  /* create input channels */
Wim Taymans's avatar
Wim Taymans committed
91

92 93
  channel_in1 = create_input_channel (1, argv[1]);
  channel_in2 = create_input_channel (2, argv[2]);
Wim Taymans's avatar
Wim Taymans committed
94 95 96 97 98 99 100 101 102 103 104


  /* create adder */
  adder = gst_elementfactory_make("adder", "adderel");

  /* create an audio sink */
  audiosink = gst_elementfactory_make("esdsink", "play_audio");

  /* now create main bin */
  main_bin = gst_bin_new("bin");

105 106
  gst_bin_add(GST_BIN(main_bin), channel_in1->pipe);
  gst_bin_add(GST_BIN(main_bin), channel_in2->pipe);
Wim Taymans's avatar
Wim Taymans committed
107 108 109 110 111 112 113
  gst_bin_add(GST_BIN(main_bin), adder);
  gst_bin_add(GST_BIN(main_bin), audiosink);

  /* request pads and connect to adder */

  pad = gst_element_request_pad_by_name (adder, "sink%d");
  g_print ("new pad %s\n", gst_pad_get_name (pad));
114
  gst_pad_connect (gst_element_get_pad (channel_in1->pipe, "channel1"), pad);
Wim Taymans's avatar
Wim Taymans committed
115 116
  pad = gst_element_request_pad_by_name (adder, "sink%d");
  g_print ("new pad %s\n", gst_pad_get_name (pad));
117
  gst_pad_connect (gst_element_get_pad (channel_in2->pipe, "channel2"), pad);
Wim Taymans's avatar
Wim Taymans committed
118 119 120 121 122 123 124 125

  /* connect adder and audiosink */

  gst_pad_connect(gst_element_get_pad(adder,"src"),
                  gst_element_get_pad(audiosink,"sink"));

  /* register the volume envelope */

126 127 128 129 130
  gtk_object_set(GTK_OBJECT(channel_in1->volenv), "controlpoint", "0:0.000001", NULL);
  gtk_object_set(GTK_OBJECT(channel_in1->volenv), "controlpoint", "5:0.000001", NULL);
  gtk_object_set(GTK_OBJECT(channel_in1->volenv), "controlpoint", "10:1", NULL);
  gtk_object_set(GTK_OBJECT(channel_in1->volenv), "controlpoint", "15:1", NULL);
  gtk_object_set(GTK_OBJECT(channel_in1->volenv), "controlpoint", "20:0.000001", NULL);
131

132 133 134 135 136
  gtk_object_set(GTK_OBJECT(channel_in2->volenv), "controlpoint", "0:1", NULL);
  gtk_object_set(GTK_OBJECT(channel_in2->volenv), "controlpoint", "5:1", NULL);
  gtk_object_set(GTK_OBJECT(channel_in2->volenv), "controlpoint", "10:0.000001", NULL);
  gtk_object_set(GTK_OBJECT(channel_in2->volenv), "controlpoint", "15:0.000001", NULL);
  gtk_object_set(GTK_OBJECT(channel_in2->volenv), "controlpoint", "20:1", NULL);
Wim Taymans's avatar
Wim Taymans committed
137 138 139 140 141 142 143 144 145 146 147 148 149

  /* start playing */
  gst_element_set_state(main_bin, GST_STATE_PLAYING);

  playing = TRUE;

  while (playing) {
    gst_bin_iterate(GST_BIN(main_bin));
  }

  /* stop the bin */
  gst_element_set_state(main_bin, GST_STATE_NULL);

150 151
  destroy_input_channel (channel_in1);
  destroy_input_channel (channel_in2);
152
  
Wim Taymans's avatar
Wim Taymans committed
153 154 155 156 157 158 159
  gst_object_destroy(GST_OBJECT(audiosink));

  gst_object_destroy(GST_OBJECT(main_bin));

  exit(0);
}

160 161
input_channel_t*
create_input_channel (int id, char* location)
162
{
163 164
  /* create an input channel, reading from location
   * return a pointer to the channel
165 166 167
   * return NULL if failed
   */

168 169
  input_channel_t *channel;
  
170 171
  char buffer[20]; 		/* hold the names */

172 173 174
  GstAutoplug *autoplug;
  GstCaps *srccaps;
  GstElement *new_element;  
175 176

#ifdef DEBUG
177
  printf ("DEBUG : c_i_p : creating channel with id %d for file %s\n",
178 179 180
  		  id, location);
#endif
  
181
  /* allocate channel */
182

183 184
  channel = (input_channel_t *) malloc (sizeof (input_channel_t));
  if (channel == NULL)
185
  {
186
    printf ("create_input_channel : could not allocate memory for channel !\n");
187 188 189
    return NULL;
  }

190 191 192 193 194
  /* create channel */

#ifdef DEBUG
  printf ("DEBUG : c_i_p : creating pipeline\n");
#endif
195

196 197 198
  channel->pipe = gst_bin_new ("pipeline");
  g_assert(channel->pipe != NULL);    
    
199 200
  /* create elements */

201 202 203 204
#ifdef DEBUG
  printf ("DEBUG : c_i_p : creating disksrc\n");
#endif

205
  sprintf (buffer, "disksrc%d", id);
206 207 208 209 210 211 212 213
  channel->disksrc = gst_elementfactory_make ("disksrc", buffer);
  g_assert(channel->disksrc != NULL);    
  
  gtk_object_set(GTK_OBJECT(channel->disksrc),"location", location, NULL);

  /* add disksrc to the bin before autoplug */
  gst_bin_add(GST_BIN(channel->pipe), channel->disksrc);

214 215 216 217
/*  gtk_signal_connect(GTK_OBJECT(disksrc1),"eos",
                     GTK_SIGNAL_FUNC(eos),NULL);
*/

218 219 220 221 222 223 224 225 226 227 228 229 230
#ifdef DEBUG
  printf ("DEBUG : c_i_p : creating volume envelope\n");
#endif

  sprintf (buffer, "volenv%d", id);
  channel->volenv = gst_elementfactory_make ("volenv", buffer);
  g_assert(channel->volenv != NULL);    

  /* autoplug the pipe */

#ifdef DEBUG
  printf ("DEBUG : c_i_p : getting srccaps\n");
#endif
231

232 233 234 235 236 237 238 239 240 241
  srccaps = gst_play_typefind (GST_BIN (channel->pipe), channel->disksrc);

  if (!srccaps) {
    g_print ("could not autoplug, unknown media type...\n");
    exit (-1);
  }

#ifdef DEBUG
  printf ("DEBUG : c_i_p : creating autoplug\n");
#endif
242

243 244
  autoplug = gst_autoplugfactory_make ("static");
  g_assert (autoplug != NULL);
245

246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
#ifdef DEBUG
  printf ("DEBUG : c_i_p : autoplugging\n");
#endif
 
  new_element = gst_autoplug_to_caps (autoplug, srccaps, 
  					gst_caps_new ("audio", "audio/raw", NULL), NULL);
 
  if (!new_element) {
    g_print ("could not autoplug, no suitable codecs found...\n");
    exit (-1);
  }
  
  gst_bin_add(GST_BIN(channel->pipe), channel->volenv);
  gst_bin_add (GST_BIN (channel->pipe), new_element);
  
  gst_element_connect (channel->disksrc, "src", new_element, "sink");
  gst_element_connect (new_element, "src_00", channel->volenv, "sink");
  
264 265
  /* add a ghost pad */
  sprintf (buffer, "channel%d", id);
266 267
  gst_element_add_ghost_pad (channel->pipe,
                             gst_element_get_pad (channel->volenv, "src"), buffer);
268

269
   
270 271 272 273
#ifdef DEBUG
  printf ("DEBUG : c_i_p : end function\n");
#endif

274
  return channel;
275 276 277
}

void
278
destroy_input_channel (input_channel_t *channel)
279 280
{
  /* 
281
   * destroy an input channel
282 283 284 285 286 287
   */
   
#ifdef DEBUG
  printf ("DEBUG : d_i_p : start\n");
#endif

288
  /* destroy elements */
289

290
  gst_object_destroy (GST_OBJECT (channel->pipe));
291

292
  free (channel);
293 294 295 296 297
}