hythmbox-2.98/backends/gstreamer/rb-player-gst-xfade.c

No issues found

   1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
   2  *
   3  *  Copyright (C) 2006,2010   Jonathan Matthew  <jonathan@d14n.org>
   4  *
   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.
   9  *
  10  *  The Rhythmbox authors hereby grant permission for non-GPL compatible
  11  *  GStreamer plugins to be used and distributed together with GStreamer
  12  *  and Rhythmbox. This permission is above and beyond the permissions granted
  13  *  by the GPL license by which Rhythmbox is covered. If you modify this code
  14  *  you may extend this exception to your version of the code, but you are not
  15  *  obligated to do so. If you do not wish to do so, delete this exception
  16  *  statement from your version.
  17  *
  18  *  This program is distributed in the hope that it will be useful,
  19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21  *  GNU General Public License for more details.
  22  *
  23  *  You should have received a copy of the GNU General Public License
  24  *  along with this program; if not, write to the Free Software
  25  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
  26  *
  27  */
  28 
  29 /*
  30  * GStreamer player backend with crossfading and gaplessness and trees and
  31  * flowers and bunnies.
  32  */
  33 
  34 /*
  35  * basic design:
  36  *
  37  * we have a single output bin, beginning with an adder.
  38  * connected to this are a number of stream bins, consisting of a
  39  * source, decodebin2, audio convert/resample, and a volume element used
  40  * for fading in and out.  (might be interesting to replace those with
  41  * high/low pass filter elements?)
  42  *
  43  * stream bins only stay connected to the adder while actually playing.
  44  * when not playing (prerolling or paused), the stream bin's source pad
  45  * is blocked so no data can flow.
  46  *
  47  * streams go through a number of states:
  48  *
  49  * when a stream is created (in rb_player_open()), it starts in PREROLLING
  50  * state.  from there:
  51  *
  52  * - rb_player_play():  -> PREROLL_PLAY
  53  * - preroll finishes:  -> WAITING
  54  *
  55  * from WAITING:
  56  *
  57  * - rb_player_play(), _AFTER_EOS, other stream playing:  -> WAITING_EOS
  58  * - rb_player_play(), _CROSSFADE, other stream playing:   -> FADING IN, link to adder, unblock
  59  *      + fade out existing stream
  60  * - rb_player_play(), _REPLACE, other stream playing:   -> PLAYING, link to adder, unblock
  61  *      + stop existing stream
  62  * - rb_player_play(), existing stream paused:  -> PLAYING, link to adder, unblock
  63  *      + stop existing stream
  64  * - rb_player_play(), nothing already playing:  -> PLAYING, link to adder, unblock
  65  *
  66  * from PREROLL_PLAY:
  67  *
  68  * - preroll finishes, _AFTER_EOS, other stream playing:  -> WAITING_EOS
  69  * - preroll finishes, _CROSSFADE, other stream playing:  -> FADING_IN, link to adder, unblock
  70  *   	+ fade out existing stream
  71  * - preroll finishes, _REPLACE, other stream playing:  -> PLAYING, link to adder, unblock
  72  *      + stop existing stream
  73  * - preroll finishes, existing stream paused:  -> PLAYING, link to adder, unblock
  74  *      + stop existing stream
  75  * - preroll finishes, nothing already playing:  -> PLAYING, link to adder, unblock
  76  *
  77  * from WAITING_EOS:
  78  *
  79  * - EOS received for another stream:  -> PLAYING, link to adder, unblock
  80  *
  81  * from FADING_IN:
  82  *
  83  * - fade in completes:  -> PLAYING
  84  * - another stream starts fading in:  -> FADING_OUT
  85  * - rb_player_pause():  -> PAUSED, block, unlink from adder
  86  * - stopped for another stream:  -> PENDING_REMOVE
  87  * - rb_player_set_time():  -> SEEKING, block, unlink
  88  * - reused for another stream:  -> REUSING; block, unlink
  89  *
  90  * from PLAYING:
  91  *
  92  * - rb_player_pause(): -> FADING_OUT_PAUSE, fade out (short fade)
  93  * - EOS:  -> PENDING_REMOVE
  94  * - another stream starts fading in:  -> FADING_OUT
  95  * - stopped for another stream:  -> PENDING_REMOVE
  96  * - rb_player_set_time():  -> SEEKING, block, unlink
  97  * - reused for another stream:  -> REUSING; block, unlink
  98  *
  99  * from SEEKING:
 100  * - rb_player_pause():  -> SEEKING_PAUSED
 101  * - blocked:  perform seek, link, unblock -> PLAYING | FADING_IN
 102  *
 103  * from SEEKING_PAUSED:
 104  * - blocked:  perform seek, -> PAUSED
 105  * - rb_player_play():   -> SEEKING
 106  *
 107  * from PAUSED:
 108  *
 109  * - rb_player_play():    -> FADING IN, link to adder, unblock (short fade)
 110  * - stopped for another stream:  -> PENDING_REMOVE
 111  * - rb_player_set_time(): -> perform seek
 112  *
 113  * from FADING_OUT:
 114  *
 115  * - fade out finishes:  -> PENDING_REMOVE
 116  * - EOS:  -> PENDING_REMOVE
 117  * - reused for another stream:  -> REUSING; block, unlink
 118  *
 119  * from FADING_OUT_PAUSED:
 120  *
 121  * - fade out finishes: -> SEEKING_PAUSED, block, unlink
 122  * - EOS: -> PENDING_REMOVE
 123  * - reused for another stream: -> REUSING, block, unlink
 124  * - rb_player_set_time():  -> SEEKING_PAUSED, block, unlink
 125  *
 126  * from PENDING_REMOVE:
 127  * - rb_player_set_time():  -> block, seek, -> SEEKING_EOS
 128  * - reap_streams idle handler called:  -> unlink from adder, stream destroyed
 129  *
 130  * from SEEKING_EOS:
 131  * - block completes -> link, unblock, -> PLAYING
 132  * - rb_player_pause() -> SEEKING_PAUSED
 133  *
 134  * from REUSING:
 135  *  - EOS: emit reuse-stream, -> PLAYING
 136  *  - rb_player_play(): -> block, unlink
 137  *  - blocked:  emit reuse-stream, link -> PLAYING
 138  */
 139 
 140 #include "config.h"
 141 #include <math.h>
 142 
 143 #include <glib/gi18n.h>
 144 #include <gst/gst.h>
 145 #include <gst/controller/gstcontroller.h>
 146 #include <gst/base/gstbasetransform.h>
 147 #include <gst/interfaces/streamvolume.h>
 148 #include <gst/pbutils/pbutils.h>
 149 
 150 #include "rb-player.h"
 151 #include "rb-player-gst-xfade.h"
 152 #include "rb-debug.h"
 153 #include "rb-file-helpers.h"
 154 #include "rb-util.h"
 155 #include "rb-marshal.h"
 156 #include "rb-player-gst-tee.h"
 157 #include "rb-player-gst-filter.h"
 158 #include "rb-player-gst-helper.h"
 159 
 160 static void rb_player_init (RBPlayerIface *iface);
 161 static void rb_player_gst_tee_init (RBPlayerGstTeeIface *iface);
 162 static void rb_player_gst_filter_init (RBPlayerGstFilterIface *iface);
 163 static void rb_player_gst_xfade_dispose (GObject *object);
 164 static void rb_player_gst_xfade_finalize (GObject *object);
 165 
 166 static gboolean rb_player_gst_xfade_open (RBPlayer *player,
 167 					  const char *uri,
 168 					  gpointer stream_data,
 169 					  GDestroyNotify stream_data_destroy,
 170 					  GError **error);
 171 static gboolean rb_player_gst_xfade_opened (RBPlayer *player);
 172 static gboolean rb_player_gst_xfade_close (RBPlayer *player, const char *uri, GError **error);
 173 static gboolean rb_player_gst_xfade_play (RBPlayer *player, RBPlayerPlayType play_type, gint64 crossfade, GError **error);
 174 static void rb_player_gst_xfade_pause (RBPlayer *player);
 175 static gboolean rb_player_gst_xfade_playing (RBPlayer *player);
 176 static gboolean rb_player_gst_xfade_seekable (RBPlayer *player);
 177 static void rb_player_gst_xfade_set_time (RBPlayer *player, gint64 time);
 178 static gint64 rb_player_gst_xfade_get_time (RBPlayer *player);
 179 static void rb_player_gst_xfade_set_volume (RBPlayer *player, float volume);
 180 static float rb_player_gst_xfade_get_volume (RBPlayer *player);
 181 static gboolean rb_player_gst_xfade_add_tee (RBPlayerGstTee *player, GstElement *element);
 182 static gboolean rb_player_gst_xfade_add_filter (RBPlayerGstFilter *player, GstElement *element);
 183 static gboolean rb_player_gst_xfade_remove_tee (RBPlayerGstTee *player, GstElement *element);
 184 static gboolean rb_player_gst_xfade_remove_filter (RBPlayerGstFilter *player, GstElement *element);
 185 
 186 static gboolean create_sink (RBPlayerGstXFade *player, GError **error);
 187 static gboolean start_sink (RBPlayerGstXFade *player, GError **error);
 188 static gboolean stop_sink (RBPlayerGstXFade *player);
 189 static void maybe_stop_sink (RBPlayerGstXFade *player);
 190 
 191 GType rb_xfade_stream_get_type (void);
 192 GType rb_xfade_stream_bin_get_type (void);
 193 
 194 G_DEFINE_TYPE_WITH_CODE(RBPlayerGstXFade, rb_player_gst_xfade, G_TYPE_OBJECT,
 195 			G_IMPLEMENT_INTERFACE(RB_TYPE_PLAYER,
 196 					      rb_player_init)
 197 			G_IMPLEMENT_INTERFACE(RB_TYPE_PLAYER_GST_TEE,
 198 					      rb_player_gst_tee_init)
 199 			G_IMPLEMENT_INTERFACE(RB_TYPE_PLAYER_GST_FILTER,
 200 					      rb_player_gst_filter_init))
 201 
 202 #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_PLAYER_GST_XFADE, RBPlayerGstXFadePrivate))
 203 
 204 #define RB_PLAYER_GST_XFADE_TICK_HZ 5
 205 
 206 #define EPSILON			(0.001)
 207 #define STREAM_PLAYING_MESSAGE	"rb-stream-playing"
 208 #define FADE_OUT_DONE_MESSAGE	"rb-fade-out-done"
 209 #define FADE_IN_DONE_MESSAGE	"rb-fade-in-done"
 210 #define STREAM_EOS_MESSAGE	"rb-stream-eos"
 211 
 212 #define PAUSE_FADE_LENGTH	(GST_SECOND / 2)
 213 
 214 enum
 215 {
 216 	PROP_0,
 217 	PROP_BUS
 218 };
 219 
 220 enum
 221 {
 222 	PREPARE_SOURCE,
 223 	CAN_REUSE_STREAM,
 224 	REUSE_STREAM,
 225 	MISSING_PLUGINS,
 226 	GET_STREAM_FILTERS,
 227 	LAST_SIGNAL
 228 };
 229 
 230 /* copied from gsturidecodebin.c:stream_uris */
 231 static const char *stream_schemes[] = {
 232 	"http", "https", "mms", "mmsh", "mmsu", "mmst", "ssh", "ftp", "sftp"
 233 };
 234 
 235 static guint signals[LAST_SIGNAL] = { 0 };
 236 
 237 struct _RBPlayerGstXFadePrivate
 238 {
 239 	/* probably don't need to store pointers to these either */
 240 	GstElement *pipeline;
 241 	GstElement *outputbin;
 242 	GstElement *silencebin;
 243 	GstElement *adder;
 244 	GstElement *capsfilter;
 245 	GstElement *volume;
 246 	GstElement *sink;
 247 	GstElement *tee;
 248 	GstElement *filterbin;
 249 	GstElement *filteridentity;
 250 	GstElement *filterconvert;
 251 	GstElement *volume_handler;
 252 	enum {
 253 		SINK_NULL,
 254 		SINK_STOPPED,
 255 		SINK_PLAYING
 256 	} sink_state;
 257 	GRecMutex sink_lock;
 258 
 259 	GList *waiting_tees;
 260 	GList *waiting_filters;
 261 
 262 	GRecMutex stream_list_lock;
 263 	GList *streams;
 264 	gint linked_streams;
 265 
 266 	int volume_changed;
 267 	int volume_applied;
 268 	float cur_volume;
 269 
 270 	guint tick_timeout_id;
 271 
 272 	guint stream_reap_id;
 273 	guint stop_sink_id;
 274 	guint bus_watch_id;
 275 };
 276 
 277 
 278 /* these aren't actually used to construct bitmasks,
 279  * but we search the list that way.
 280  */
 281 typedef enum
 282 {
 283 	/* stable states */
 284 	WAITING = 1,
 285 	PLAYING = 2,
 286 	PAUSED = 4,
 287 
 288 	/* transition states */
 289 	REUSING = 8,
 290 	PREROLLING = 16,
 291 	PREROLL_PLAY = 32,
 292 	FADING_IN = 64,
 293 	SEEKING = 128,
 294 	SEEKING_PAUSED = 256,
 295 	SEEKING_EOS = 512, 
 296 	WAITING_EOS = 1024,
 297 	FADING_OUT = 2048,
 298 	FADING_OUT_PAUSED = 4096,
 299 	PENDING_REMOVE = 8192
 300 } StreamState;
 301 
 302 typedef struct {
 303 	GstBinClass bin_class;
 304 } RBXFadeStreamClass;
 305 
 306 
 307 typedef struct
 308 {
 309 	GstBin parent;
 310 	RBPlayerGstXFade *player;
 311 
 312 	GMutex lock;
 313 
 314 	char *uri;
 315 	gpointer stream_data;
 316 	GDestroyNotify stream_data_destroy;
 317 
 318 	/* stream reuse data */
 319 	char *new_uri;
 320 	gpointer new_stream_data;
 321 	GDestroyNotify new_stream_data_destroy;
 322 
 323 	/* probably don't need to store pointers to all of these.. */
 324 	GstElement *decoder;
 325 	GstElement *volume;
 326 	GstElement *audioconvert;
 327 	GstElement *audioresample;
 328 	GstElement *capsfilter;
 329 	GstElement *preroll;
 330 	GstElement *identity;
 331 	gboolean decoder_linked;
 332 	gboolean emitted_playing;
 333 	gboolean emitted_fake_playing;
 334 
 335 	GstPad *decoder_pad;
 336 	GstPad *src_pad;
 337 	GstPad *ghost_pad;
 338 	GstPad *adder_pad;
 339 	gboolean src_blocked;
 340 	gboolean needs_unlink;
 341 	GstClockTime base_time;
 342 
 343 	gint64 seek_target;
 344 
 345 	GstInterpolationControlSource *fader;
 346 	StreamState state;
 347 	RBPlayerPlayType play_type;
 348 	gint64 crossfade;
 349 	gboolean fading;
 350 	gboolean starting_eos;
 351 	gboolean use_buffering;
 352 
 353 	gulong adjust_probe_id;
 354 
 355 	double fade_end;
 356 
 357 	gboolean emitted_error;
 358 	gulong error_idle_id;
 359 	GError *error;
 360 
 361 	GSList *missing_plugins;
 362 	gulong  emit_missing_plugins_id;
 363 
 364 	GList *tags;
 365 } RBXFadeStream;
 366 
 367 #define RB_TYPE_XFADE_STREAM 	(rb_xfade_stream_get_type ())
 368 #define RB_XFADE_STREAM(obj)	(G_TYPE_CHECK_INSTANCE_CAST ((obj), RB_TYPE_XFADE_STREAM, RBXFadeStream))
 369 #define RB_IS_XFADE_STREAM(obj)	(G_TYPE_CHECK_INSTANCE_TYPE ((obj), RB_TYPE_XFADE_STREAM))
 370 
 371 static void adjust_stream_base_time (RBXFadeStream *stream);
 372 static gboolean actually_start_stream (RBXFadeStream *stream, GError **error);
 373 
 374 static void rb_xfade_stream_class_init (RBXFadeStreamClass *klass);
 375 
 376 G_DEFINE_TYPE(RBXFadeStream, rb_xfade_stream, GST_TYPE_BIN)
 377 
 378 static gboolean
 379 rb_xfade_stream_send_event (GstElement *element, GstEvent *event)
 380 {
 381 	GstPad *pad;
 382 	GstPad *ghost_pad;
 383 	gboolean ret;
 384 
 385 	/* just send the event to the element that provides the src pad */
 386 	ghost_pad = gst_element_get_pad (element, "src");
 387 	pad = gst_ghost_pad_get_target (GST_GHOST_PAD (ghost_pad));
 388 
 389 	ret = gst_element_send_event (GST_PAD_PARENT (pad), event);
 390 
 391 	gst_object_unref (pad);
 392 	gst_object_unref (ghost_pad);
 393 
 394 	return ret;
 395 }
 396 
 397 static void
 398 rb_xfade_stream_init (RBXFadeStream *stream)
 399 {
 400 	g_mutex_init (&stream->lock);
 401 }
 402 
 403 static void
 404 rb_xfade_stream_dispose_stream_data (RBXFadeStream *stream)
 405 {
 406 	if (stream->stream_data && stream->stream_data_destroy) {
 407 		stream->stream_data_destroy (stream->stream_data);
 408 	}
 409 	stream->stream_data = NULL;
 410 	stream->stream_data_destroy = NULL;
 411 }
 412 
 413 static void
 414 rb_xfade_stream_dispose (GObject *object)
 415 {
 416 	RBXFadeStream *sd = RB_XFADE_STREAM (object);
 417 
 418 	rb_debug ("disposing stream %s", sd->uri);
 419 
 420 	if (sd->decoder != NULL) {
 421 		gst_object_unref (sd->decoder);
 422 		sd->decoder = NULL;
 423 	}
 424 
 425 	if (sd->volume != NULL) {
 426 		gst_object_unref (sd->volume);
 427 		sd->volume = NULL;
 428 	}
 429 
 430 	if (sd->fader != NULL) {
 431 		gst_object_unref (sd->fader);
 432 		sd->fader = NULL;
 433 	}
 434 
 435 	if (sd->audioconvert != NULL) {
 436 		gst_object_unref (sd->audioconvert);
 437 		sd->audioconvert = NULL;
 438 	}
 439 
 440 	if (sd->audioresample != NULL) {
 441 		gst_object_unref (sd->audioresample);
 442 		sd->audioresample = NULL;
 443 	}
 444 
 445 	if (sd->player != NULL) {
 446 		g_object_unref (sd->player);
 447 		sd->player = NULL;
 448 	}
 449 
 450 	if (sd->tags != NULL) {
 451 		rb_list_destroy_free (sd->tags, (GDestroyNotify) gst_tag_list_free);
 452 		sd->tags = NULL;
 453 	}
 454 
 455 	rb_xfade_stream_dispose_stream_data (sd);
 456 
 457 	G_OBJECT_CLASS (rb_xfade_stream_parent_class)->dispose (object);
 458 }
 459 
 460 static void
 461 rb_xfade_stream_finalize (GObject *object)
 462 {
 463 	RBXFadeStream *sd = RB_XFADE_STREAM (object);
 464 	
 465 	g_free (sd->uri);
 466 
 467 	if (sd->error != NULL) {
 468 		g_error_free (sd->error);
 469 	}
 470 
 471 	G_OBJECT_CLASS (rb_xfade_stream_parent_class)->finalize (object);
 472 }
 473 
 474 static void
 475 rb_xfade_stream_class_init (RBXFadeStreamClass *klass)
 476 {
 477 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 478 	GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 479 
 480 	object_class->dispose = rb_xfade_stream_dispose;
 481 	object_class->finalize = rb_xfade_stream_finalize;
 482 
 483 	element_class->send_event = rb_xfade_stream_send_event;
 484 }
 485 
 486 /* caller must hold stream list lock */
 487 static void
 488 dump_stream_list (RBPlayerGstXFade *player)
 489 {
 490 	GList *l;
 491 	if (player->priv->streams == NULL) {
 492 		rb_debug ("stream list is empty");
 493 	} else {
 494 		rb_debug ("current stream list:");
 495 		for (l = player->priv->streams; l != NULL; l = l->next) {
 496 			RBXFadeStream *stream = (RBXFadeStream *)l->data;
 497 			const char *statename = "<wtf>";
 498 			switch (stream->state) {
 499 			case WAITING:	 	statename = "waiting";		break;
 500 			case PLAYING:	 	statename = "playing";		break;
 501 			case PAUSED:	 	statename = "paused";		break;
 502 
 503 			case REUSING:		statename = "reusing";		break;
 504 			case PREROLLING: 	statename = "prerolling"; 	break;
 505 			case PREROLL_PLAY: 	statename = "preroll->play"; 	break;
 506 			case FADING_IN: 	statename = "fading in"; 	break;
 507 			case SEEKING:		statename = "seeking";		break;
 508 			case SEEKING_PAUSED:	statename = "seeking->paused";	break;
 509 			case SEEKING_EOS:	statename = "seeking post EOS"; break;
 510 			case WAITING_EOS: 	statename = "waiting for EOS"; 	break;
 511 			case FADING_OUT: 	statename = "fading out"; 	break;
 512 			case FADING_OUT_PAUSED: statename = "fading->paused";   break;
 513 
 514 			case PENDING_REMOVE:	statename = "pending remove";	break;
 515 			}
 516 
 517 			rb_debug ("[%s] %s", statename, stream->uri);
 518 		}
 519 	}
 520 }
 521 
 522 /* caller must hold stream list lock */
 523 static RBXFadeStream *
 524 find_stream_by_uri (RBPlayerGstXFade *player, const char *uri)
 525 {
 526 	GList *i;
 527 	if (uri == NULL)
 528 		return NULL;
 529 
 530 	for (i = player->priv->streams; i != NULL; i = i->next) {
 531 		RBXFadeStream *stream = (RBXFadeStream *)i->data;
 532 		if (strcmp (uri, stream->uri) == 0)
 533 			return g_object_ref (stream);
 534 	}
 535 	return NULL;
 536 }
 537 
 538 /* caller must hold stream list lock */
 539 static RBXFadeStream *
 540 find_stream_by_element (RBPlayerGstXFade *player, GstElement *element)
 541 {
 542 	GList *i;
 543 
 544 	for (i = player->priv->streams; i != NULL; i = i->next) {
 545 		RBXFadeStream *stream;
 546 		GstElement *e;
 547 
 548 		stream = (RBXFadeStream *)i->data;
 549 		e = element;
 550 		while (e != NULL) {
 551 			if (e == GST_ELEMENT (stream))
 552 				return g_object_ref (stream);
 553 
 554 			e = GST_ELEMENT_PARENT (e);
 555 		}
 556 	}
 557 
 558 	return NULL;
 559 }
 560 
 561 /* caller must hold stream list lock */
 562 static RBXFadeStream *
 563 find_stream_by_state (RBPlayerGstXFade *player, gint state_mask)
 564 {
 565 	GList *i;
 566 
 567 	for (i = player->priv->streams; i != NULL; i = i->next) {
 568 		RBXFadeStream *stream;
 569 
 570 		stream = (RBXFadeStream *)i->data;
 571 		if ((stream->state & state_mask) != 0) {
 572 			return g_object_ref (stream);
 573 		}
 574 	}
 575 
 576 	return NULL;
 577 }
 578 
 579 static void
 580 rb_player_gst_xfade_get_property (GObject *object,
 581 				  guint prop_id,
 582 				  GValue *value,
 583 				  GParamSpec *pspec)
 584 {
 585 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (object);
 586 
 587 	switch (prop_id) {
 588 	case PROP_BUS:
 589 		if (player->priv->pipeline) {
 590 			GstBus *bus;
 591 			bus = gst_element_get_bus (player->priv->pipeline);
 592 			g_value_set_object (value, bus);
 593 			gst_object_unref (bus);
 594 		}
 595 		break;
 596 	default:
 597 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 598 		break;
 599 	}
 600 }
 601 
 602 static void
 603 rb_player_gst_xfade_set_property (GObject *object,
 604 				  guint prop_id,
 605 				  const GValue *value,
 606 				  GParamSpec *pspec)
 607 {
 608 	/*RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (object);*/
 609 
 610 	switch (prop_id) {
 611 	default:
 612 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 613 		break;
 614 	}
 615 }
 616 
 617 static void
 618 rb_player_gst_xfade_class_init (RBPlayerGstXFadeClass *klass)
 619 {
 620 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 621 
 622 	object_class->dispose = rb_player_gst_xfade_dispose;
 623 	object_class->finalize = rb_player_gst_xfade_finalize;
 624 	object_class->set_property = rb_player_gst_xfade_set_property;
 625 	object_class->get_property = rb_player_gst_xfade_get_property;
 626 
 627 	g_object_class_install_property (object_class,
 628 					 PROP_BUS,
 629 					 g_param_spec_object ("bus",
 630 							      "bus",
 631 							      "GStreamer message bus",
 632 							      GST_TYPE_BUS,
 633 							      G_PARAM_READABLE));
 634 
 635 	signals[PREPARE_SOURCE] =
 636 		g_signal_new ("prepare-source",
 637 			      G_OBJECT_CLASS_TYPE (object_class),
 638 			      G_SIGNAL_RUN_LAST,
 639 			      G_STRUCT_OFFSET (RBPlayerGstXFadeClass, prepare_source),
 640 			      NULL, NULL,
 641 			      rb_marshal_VOID__STRING_OBJECT,
 642 			      G_TYPE_NONE,
 643 			      2,
 644 			      G_TYPE_STRING, GST_TYPE_ELEMENT);
 645 	signals[CAN_REUSE_STREAM] =
 646 		g_signal_new ("can-reuse-stream",
 647 			      G_OBJECT_CLASS_TYPE (object_class),
 648 			      G_SIGNAL_RUN_LAST,
 649 			      G_STRUCT_OFFSET (RBPlayerGstXFadeClass, can_reuse_stream),
 650 			      NULL, NULL,
 651 			      rb_marshal_BOOLEAN__STRING_STRING_OBJECT,
 652 			      G_TYPE_BOOLEAN,
 653 			      3,
 654 			      G_TYPE_STRING, G_TYPE_STRING, GST_TYPE_ELEMENT);
 655 	signals[REUSE_STREAM] =
 656 		g_signal_new ("reuse-stream",
 657 			      G_OBJECT_CLASS_TYPE (object_class),
 658 			      G_SIGNAL_RUN_LAST,
 659 			      G_STRUCT_OFFSET (RBPlayerGstXFadeClass, reuse_stream),
 660 			      NULL, NULL,
 661 			      rb_marshal_VOID__STRING_STRING_OBJECT,
 662 			      G_TYPE_NONE,
 663 			      3,
 664 			      G_TYPE_STRING, G_TYPE_STRING, GST_TYPE_ELEMENT);
 665 	signals[MISSING_PLUGINS] =
 666 		g_signal_new ("missing-plugins",
 667 			      G_OBJECT_CLASS_TYPE (object_class),
 668 			      G_SIGNAL_RUN_LAST,
 669 			      0,	/* no point handling this internally */
 670 			      NULL, NULL,
 671 			      rb_marshal_VOID__POINTER_POINTER_POINTER,
 672 			      G_TYPE_NONE,
 673 			      3,
 674 			      G_TYPE_POINTER, G_TYPE_STRV, G_TYPE_STRV);
 675 	signals[GET_STREAM_FILTERS] =
 676 		g_signal_new ("get-stream-filters",
 677 			      G_OBJECT_CLASS_TYPE (object_class),
 678 			      G_SIGNAL_RUN_LAST,
 679 			      0,
 680 			      rb_signal_accumulator_value_array, NULL,
 681 			      rb_marshal_BOXED__STRING,
 682 			      G_TYPE_ARRAY,
 683 			      1,
 684 			      G_TYPE_STRING);
 685 
 686 	g_type_class_add_private (klass, sizeof (RBPlayerGstXFadePrivate));
 687 }
 688 
 689 static void
 690 rb_player_init (RBPlayerIface *iface)
 691 {
 692 	iface->open = rb_player_gst_xfade_open;
 693 	iface->opened = rb_player_gst_xfade_opened;
 694 	iface->close = rb_player_gst_xfade_close;
 695 	iface->play = rb_player_gst_xfade_play;
 696 	iface->pause = rb_player_gst_xfade_pause;
 697 	iface->playing = rb_player_gst_xfade_playing;
 698 	iface->set_volume = rb_player_gst_xfade_set_volume;
 699 	iface->get_volume = rb_player_gst_xfade_get_volume;
 700 	iface->seekable = rb_player_gst_xfade_seekable;
 701 	iface->set_time = rb_player_gst_xfade_set_time;
 702 	iface->get_time = rb_player_gst_xfade_get_time;
 703 	iface->multiple_open = (RBPlayerFeatureFunc) rb_true_function;
 704 }
 705 
 706 static void
 707 rb_player_gst_tee_init (RBPlayerGstTeeIface *iface)
 708 {
 709 	iface->add_tee = rb_player_gst_xfade_add_tee;
 710 	iface->remove_tee = rb_player_gst_xfade_remove_tee;
 711 }
 712 
 713 static void
 714 rb_player_gst_filter_init (RBPlayerGstFilterIface *iface)
 715 {
 716 	iface->add_filter = rb_player_gst_xfade_add_filter;
 717 	iface->remove_filter = rb_player_gst_xfade_remove_filter;
 718 }
 719 
 720 
 721 static void
 722 rb_player_gst_xfade_init (RBPlayerGstXFade *player)
 723 {
 724 	player->priv = GET_PRIVATE (player);
 725 
 726 	g_rec_mutex_init (&player->priv->stream_list_lock);
 727 	g_rec_mutex_init (&player->priv->sink_lock);
 728 	player->priv->cur_volume = 1.0f;
 729 }
 730 
 731 static void
 732 rb_player_gst_xfade_dispose (GObject *object)
 733 {
 734 	RBPlayerGstXFade *player;
 735 	GList *l;
 736 
 737 	g_return_if_fail (RB_IS_PLAYER_GST_XFADE (object));
 738 	player = RB_PLAYER_GST_XFADE (object);
 739 
 740 	/* clean up streams */
 741 	g_rec_mutex_lock (&player->priv->stream_list_lock);
 742 	for (l = player->priv->streams; l != NULL; l = l->next) {
 743 		RBXFadeStream *stream = (RBXFadeStream *)l->data;
 744 
 745 		/* unlink instead? */
 746 		gst_element_set_state (GST_ELEMENT (stream), GST_STATE_NULL);
 747 
 748 		g_object_unref (stream);
 749 	}
 750 	g_list_free (player->priv->streams);
 751 	player->priv->streams = NULL;
 752 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
 753 
 754 	if (player->priv->volume_handler) {
 755 		g_object_unref (player->priv->volume_handler);
 756 		player->priv->volume_handler = NULL;
 757 	}
 758 
 759 	g_rec_mutex_lock (&player->priv->sink_lock);
 760 	stop_sink (player);
 761 	g_rec_mutex_unlock (&player->priv->sink_lock);
 762 
 763 	if (player->priv->pipeline != NULL) {
 764 		/* maybe we should keep references to the adder, sink, etc.? */
 765 		gst_element_set_state (player->priv->pipeline, GST_STATE_NULL);
 766 		g_object_unref (player->priv->pipeline);
 767 		player->priv->pipeline = NULL;
 768 	}
 769 
 770 	G_OBJECT_CLASS (rb_player_gst_xfade_parent_class)->dispose (object);
 771 }
 772 
 773 static void
 774 rb_player_gst_xfade_finalize (GObject *object)
 775 {
 776 	RBPlayerGstXFade *player;
 777 
 778 	player = RB_PLAYER_GST_XFADE (object);
 779 
 780 	if (player->priv->waiting_tees) {
 781 		g_list_foreach (player->priv->waiting_tees, (GFunc)gst_object_sink, NULL);
 782 	}
 783 	g_list_free (player->priv->waiting_tees);
 784 
 785 	if (player->priv->waiting_filters) {
 786 		g_list_foreach (player->priv->waiting_filters, (GFunc)gst_object_sink, NULL);
 787 	}
 788 	g_list_free (player->priv->waiting_filters);
 789 
 790 	G_OBJECT_CLASS (rb_player_gst_xfade_parent_class)->finalize (object);
 791 }
 792 
 793 RBPlayer *
 794 rb_player_gst_xfade_new (GError **error)
 795 {
 796 	RBPlayer *mp;
 797 
 798 	mp = RB_PLAYER (g_object_new (RB_TYPE_PLAYER_GST_XFADE, NULL, NULL));
 799 
 800 	return mp;
 801 }
 802 
 803 static gboolean
 804 emit_stream_error_cb (RBXFadeStream *stream)
 805 {
 806 	stream->error_idle_id = 0;
 807 	_rb_player_emit_error (RB_PLAYER (stream->player),
 808 			       stream->stream_data,
 809 			       stream->error);
 810 	g_error_free (stream->error);
 811 	stream->error = NULL;
 812 
 813 	return FALSE;
 814 }
 815 
 816 static void
 817 emit_stream_error (RBXFadeStream *stream, GError *error)
 818 {
 819 	if (stream->error_idle_id != 0) {
 820 		g_error_free (error);
 821 	} else {
 822 		stream->error = error;
 823 		stream->error_idle_id = g_idle_add ((GSourceFunc) emit_stream_error_cb,
 824 						    stream);
 825 	}
 826 }
 827 
 828 static void
 829 post_stream_playing_message (RBXFadeStream *stream, gboolean fake)
 830 {
 831 	GstMessage *msg;
 832 	GstStructure *s;
 833 
 834 	if (stream->emitted_playing) {
 835 		return;
 836 	}
 837 
 838 	rb_debug ("posting " STREAM_PLAYING_MESSAGE " message for stream %s", stream->uri);
 839 	s = gst_structure_new (STREAM_PLAYING_MESSAGE, NULL);
 840 	msg = gst_message_new_application (GST_OBJECT (stream), s);
 841 	gst_element_post_message (GST_ELEMENT (stream), msg);
 842 
 843 	if (fake == FALSE) {
 844 		stream->emitted_playing = TRUE;
 845 	} else {
 846 		stream->emitted_fake_playing = TRUE;
 847 	}
 848 }
 849 
 850 static gboolean
 851 adjust_base_time_probe_cb (GstPad *pad, GstBuffer *data, RBXFadeStream *stream)
 852 {
 853 	rb_debug ("attempting to adjust base time for stream %s", stream->uri);
 854 	adjust_stream_base_time (stream);
 855 	return TRUE;
 856 }
 857 
 858 /* updates a stream's base time so its position is reported correctly */
 859 static void
 860 adjust_stream_base_time (RBXFadeStream *stream)
 861 {
 862 	GstFormat format;
 863 	gint64 output_pos = -1;
 864 	gint64 stream_pos = -1;
 865 
 866 	g_mutex_lock (&stream->lock);
 867 
 868 	if (stream->adder_pad == NULL) {
 869 		rb_debug ("stream isn't linked, can't adjust base time");
 870 		g_mutex_unlock (&stream->lock);
 871 		return;
 872 	}
 873 
 874 	format = GST_FORMAT_TIME;
 875 	gst_element_query_position (GST_PAD_PARENT (stream->adder_pad), &format, &output_pos);
 876 	if (output_pos != -1) {
 877 		stream->base_time = output_pos;
 878 	}
 879 
 880 	/* offset the base position to account for the current stream position */
 881 	format = GST_FORMAT_TIME;
 882 	gst_element_query_position (stream->volume, &format, &stream_pos);
 883 	if (stream_pos != -1) {
 884 		rb_debug ("adjusting base time: %" G_GINT64_FORMAT
 885 		    " - %" G_GINT64_FORMAT " => %" G_GINT64_FORMAT,
 886 		    stream->base_time, stream_pos,
 887 		    stream->base_time - stream_pos);
 888 		stream->base_time -= stream_pos;
 889 
 890 		/* once we've successfully adjusted the base time, we don't need the data probe */
 891 		if (stream->adjust_probe_id != 0) {
 892 			gst_pad_remove_buffer_probe (stream->ghost_pad,
 893 						     stream->adjust_probe_id);
 894 			stream->adjust_probe_id = 0;
 895 		}
 896 	} else {
 897 		rb_debug ("unable to adjust base time as position query failed");
 898 
 899 		/* add a pad probe to attempt to adjust when the next buffer goes out */
 900 		if (stream->adjust_probe_id == 0) {
 901 			stream->adjust_probe_id =
 902 				gst_pad_add_buffer_probe (stream->ghost_pad,
 903 							  G_CALLBACK (adjust_base_time_probe_cb),
 904 							  stream);
 905 		}
 906 	}
 907 		
 908 	g_mutex_unlock (&stream->lock);
 909 }
 910 
 911 /* called on a streaming thread when the volume level for a stream changes. */
 912 static void
 913 volume_changed_cb (GObject *object, GParamSpec *pspec, RBPlayerGstXFade *player)
 914 {
 915 	RBXFadeStream *stream;
 916 	gdouble vol;
 917 	char *message = NULL;
 918 
 919 	/* post app messages on the bus when fades complete.
 920 	 * our bus callback will handle them on the main thread.
 921 	 */
 922 
 923 	g_rec_mutex_lock (&player->priv->stream_list_lock);
 924 	stream = find_stream_by_element (player, GST_ELEMENT (object));
 925 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
 926 
 927 	if (stream == NULL) {
 928 		rb_debug ("got volume change for unknown stream");
 929 		return;
 930 	}
 931 
 932 	g_mutex_lock (&stream->lock);
 933 
 934 	/* check if the fade is complete */
 935 	g_object_get (stream->volume, "volume", &vol, NULL);
 936 	switch (stream->state) {
 937 	case FADING_IN:
 938 		if (vol > (stream->fade_end - EPSILON) && stream->fading) {
 939 			rb_debug ("stream %s fully faded in (at %f) -> PLAYING state", stream->uri, vol);
 940 			/*message = FADE_IN_DONE_MESSAGE;*/		/* not actually used */
 941 			stream->fading = FALSE;
 942 			stream->state = PLAYING;
 943 			
 944 		/*} else {
 945 			rb_debug ("fading %s in: %f", stream->uri, (float)vol);*/
 946 		}
 947 		break;
 948 	case FADING_OUT:
 949 	case FADING_OUT_PAUSED:
 950 		if (vol < (stream->fade_end + EPSILON)) {
 951 			rb_debug ("stream %s fully faded out (at %f)", stream->uri, vol);
 952 			if (stream->fading) {
 953 				message = FADE_OUT_DONE_MESSAGE;
 954 				stream->fading = FALSE;
 955 			}
 956 		} else {
 957 			/*rb_debug ("fading %s out: %f", stream->uri, (float)vol);*/
 958 			/* force the volume element out of passthrough mode so it
 959 			 * continues to update the controller (otherwise, if the
 960 			 * fade out starts at 1.0, it never gets anywhere)
 961 			 */
 962 			gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (stream->volume), FALSE);
 963 		}
 964 		break;
 965 	default:
 966 		/*rb_debug ("unexpectedly got a volume change for stream %s to %f (not fading)", stream->uri, (float)vol);*/
 967 		break;
 968 	}
 969 	
 970 	g_mutex_unlock (&stream->lock);
 971 
 972 	if (message != NULL) {
 973 		GstMessage *msg;
 974 		GstStructure *s;
 975 
 976 		rb_debug ("posting %s message for stream %s", message, stream->uri);
 977 		s = gst_structure_new (message, NULL);
 978 		msg = gst_message_new_application (GST_OBJECT (object), s);
 979 		gst_element_post_message (GST_ELEMENT (object), msg);
 980 	}
 981 
 982 	g_object_unref (stream);
 983 }
 984 
 985 /* starts a volume slide on a stream.
 986  * volume_changed_cb watches the volume change
 987  * and posts a message on the bus when the slide
 988  * is done.
 989  */
 990 static void
 991 start_stream_fade (RBXFadeStream *stream, double start, double end, gint64 time)
 992 {
 993 	GValue v = {0,};
 994 	gint64 pos = -1;
 995 	GstFormat format = GST_FORMAT_TIME;
 996 
 997 	/* hmm, can we take the stream lock safely here?  probably should.. */
 998 
 999 	gst_element_query_position (stream->volume, &format, &pos);
1000 	if (pos < 0) {
1001 		/* probably means we haven't actually started the stream yet.
1002 		 * we also get (weird) negative results with some decoders
1003 		 * (mad but not flump3dec, for instance) immediately after prerolling.
1004 		 * the controller doesn't seem to work if we give it a 0 timestamp
1005 		 * here, but something unnoticeably later does work.
1006 		 */
1007 		pos = 100000;
1008 	}
1009 	if (format != GST_FORMAT_TIME) {
1010 		rb_debug ("got position query results in some other format: %s", gst_format_get_name (format));
1011 		pos = 0;
1012 	}
1013 
1014 	rb_debug ("fading stream %s: [%f, %" G_GINT64_FORMAT "] to [%f, %" G_GINT64_FORMAT "]",
1015 		  stream->uri,
1016 		  (float)start, pos,
1017 		  (float)end, pos + time);
1018 
1019 	g_signal_handlers_block_by_func (stream->volume, volume_changed_cb, stream->player);
1020 
1021 	/* apparently we need to set the starting volume, otherwise fading in doesn't work. */
1022 	stream->fade_end = end;
1023 	g_object_set (stream->volume, "volume", start, NULL);
1024 
1025 	gst_interpolation_control_source_unset_all (stream->fader);
1026 
1027 	g_value_init (&v, G_TYPE_DOUBLE);
1028 	g_value_set_double (&v, start);
1029 	if (gst_interpolation_control_source_set (stream->fader, pos, &v) == FALSE) {
1030 		rb_debug ("controller didn't like our start point");
1031 	}
1032 	if (gst_interpolation_control_source_set (stream->fader, 0, &v) == FALSE) {
1033 		rb_debug ("controller didn't like our 0 start point");
1034 	}
1035 	g_value_unset (&v);
1036 
1037 	g_value_init (&v, G_TYPE_DOUBLE);
1038 	g_value_set_double (&v, end);
1039 	if (gst_interpolation_control_source_set (stream->fader, pos + time, &v) == FALSE) {
1040 		rb_debug ("controller didn't like our end point");
1041 	}
1042 	g_value_unset (&v);
1043 
1044 	g_signal_handlers_unblock_by_func (stream->volume, volume_changed_cb, stream->player);
1045 
1046 	stream->fading = TRUE;
1047 
1048 	/* tiny hack:  if the controlled element is in passthrough mode, the
1049 	 * controller won't get updated.
1050 	 */
1051 	gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (stream->volume), FALSE);
1052 }
1053 
1054 
1055 static void
1056 link_unblocked_cb (GstPad *pad, gboolean blocked, RBXFadeStream *stream)
1057 {
1058 	GstStateChangeReturn state_ret;
1059 	g_mutex_lock (&stream->lock);
1060 
1061 	/* sometimes we seem to get called twice */
1062 	if (stream->state == FADING_IN || stream->state == PLAYING) {
1063 		rb_debug ("stream %s already unblocked", stream->uri);
1064 		g_mutex_unlock (&stream->lock);
1065 		return;
1066 	}
1067 
1068 	rb_debug ("stream %s is unblocked -> FADING_IN | PLAYING", stream->uri);
1069 	stream->src_blocked = FALSE;
1070 	if (stream->fading)
1071 		stream->state = FADING_IN;
1072 	else
1073 		stream->state = PLAYING;
1074 	
1075 	g_mutex_unlock (&stream->lock);
1076 
1077 	adjust_stream_base_time (stream);
1078 
1079 	/* should handle state change failures here.. */
1080 	state_ret = gst_element_set_state (GST_ELEMENT (stream), GST_STATE_PLAYING);
1081 	rb_debug ("stream %s state change returned: %s", stream->uri,
1082 		  gst_element_state_change_return_get_name (state_ret));
1083 
1084 	post_stream_playing_message (stream, FALSE);
1085 	g_object_unref (stream);
1086 }
1087 
1088 /* links a stream bin to the adder
1089  * - adds the bin to the pipeline
1090  * - links to a new adder pad
1091  * - unblocks the stream if it's blocked
1092  */
1093 static gboolean
1094 link_and_unblock_stream (RBXFadeStream *stream, GError **error)
1095 {
1096 	GstPadLinkReturn plr;
1097 	GstStateChangeReturn scr;
1098 	RBPlayerGstXFade *player = stream->player;
1099 	
1100 	if (start_sink (player, error) == FALSE) {
1101 		rb_debug ("sink didn't start, so we're not going to link the stream");
1102 		return FALSE;
1103 	}
1104 
1105 	if (stream->adder_pad != NULL) {
1106 		rb_debug ("stream %s is already linked", stream->uri);
1107 		return TRUE;
1108 	}
1109 	stream->needs_unlink = FALSE;
1110 
1111 	rb_debug ("linking stream %s", stream->uri);
1112 	if (GST_ELEMENT_PARENT (GST_ELEMENT (stream)) == NULL)
1113 		gst_bin_add (GST_BIN (player->priv->pipeline), GST_ELEMENT (stream));
1114 
1115 	stream->adder_pad = gst_element_get_request_pad (player->priv->adder, "sink%d");
1116 	if (stream->adder_pad == NULL) {
1117 		/* this error message kind of sucks */
1118 		rb_debug ("couldn't get adder pad to link in new stream");
1119 		g_set_error (error,
1120 			     RB_PLAYER_ERROR,
1121 			     RB_PLAYER_ERROR_GENERAL,
1122 			     _("Failed to link new stream into GStreamer pipeline"));
1123 		return FALSE;
1124 	}
1125 
1126 	plr = gst_pad_link (stream->ghost_pad, stream->adder_pad);
1127 	if (GST_PAD_LINK_FAILED (plr)) {
1128 		gst_element_release_request_pad (player->priv->adder, stream->adder_pad);
1129 		stream->adder_pad = NULL;
1130 
1131 		/* this error message kind of sucks */
1132 		rb_debug ("linking stream pad to adder pad failed: %d", plr);
1133 		g_set_error (error,
1134 			     RB_PLAYER_ERROR,
1135 			     RB_PLAYER_ERROR_GENERAL,
1136 			     _("Failed to link new stream into GStreamer pipeline"));
1137 		return FALSE;
1138 	}
1139 
1140 
1141 	g_atomic_int_inc (&player->priv->linked_streams);
1142 	rb_debug ("now have %d linked streams", player->priv->linked_streams);
1143 
1144 	if (stream->src_blocked) {
1145 		g_object_ref (stream);
1146 		gst_pad_set_blocked_async (stream->src_pad,
1147 					   FALSE,
1148 					   (GstPadBlockCallback) link_unblocked_cb,
1149 					   stream);
1150 		return TRUE;
1151 	} else {
1152 		rb_debug ("??? stream %s is already unblocked -> PLAYING", stream->uri);
1153 		stream->state = PLAYING;
1154 		adjust_stream_base_time (stream);
1155 
1156 		scr = gst_element_set_state (GST_ELEMENT (stream), GST_STATE_PLAYING);
1157 
1158 		post_stream_playing_message (stream, FALSE);
1159 
1160 		if (scr == GST_STATE_CHANGE_FAILURE) {
1161 			g_set_error (error,
1162 				     RB_PLAYER_ERROR,
1163 				     RB_PLAYER_ERROR_GENERAL,
1164 				     _("Failed to start new stream"));
1165 			return FALSE;
1166 		}
1167 		return TRUE;
1168 	}
1169 }
1170 
1171 /*
1172  * reuses a stream.  the stream reuse signal is handled by some
1173  * external code somewhere.
1174  */
1175 static void
1176 reuse_stream (RBXFadeStream *stream)
1177 {
1178 	g_signal_emit (stream->player,
1179 		       signals[REUSE_STREAM], 0,
1180 		       stream->new_uri, stream->uri, GST_ELEMENT (stream));
1181 
1182 	/* replace URI and stream data */
1183 	g_free (stream->uri);
1184 	stream->uri = stream->new_uri;
1185 
1186 	rb_xfade_stream_dispose_stream_data (stream);
1187 	stream->stream_data = stream->new_stream_data;
1188 	stream->stream_data_destroy = stream->new_stream_data_destroy;
1189 
1190 	stream->new_uri = NULL;
1191 	stream->new_stream_data = NULL;
1192 	stream->new_stream_data_destroy = NULL;
1193 
1194 	stream->emitted_playing = FALSE;
1195 }
1196 
1197 
1198 /*
1199  * performs a seek on an unlinked and blocked stream.
1200  * if the stream is still in FADING_IN or PLAYING state,
1201  * relinks and unblocks the stream.
1202  */
1203 static void
1204 perform_seek (RBXFadeStream *stream)
1205 {
1206 	GstEvent *event;
1207 
1208 	rb_debug ("sending seek event..");
1209 	event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
1210 				    GST_SEEK_FLAG_FLUSH,
1211 				    GST_SEEK_TYPE_SET, stream->seek_target,
1212 				    GST_SEEK_TYPE_NONE, -1);
1213 	gst_pad_send_event (stream->src_pad, event);
1214 
1215 	switch (stream->state) {
1216 	case SEEKING:
1217 		stream->state = PLAYING;
1218 		break;
1219 	case SEEKING_PAUSED:
1220 		rb_debug ("leaving paused stream %s unlinked", stream->uri);
1221 		stream->state = PAUSED;
1222 		break;
1223 	case SEEKING_EOS:
1224 		rb_debug ("waiting for pad block to complete for %s before unlinking", stream->uri);
1225 		break;
1226 	default:
1227 		break;
1228 	}
1229 }
1230 
1231 static gboolean
1232 perform_seek_idle (RBXFadeStream *stream)
1233 {
1234 	perform_seek (stream);
1235 	g_object_unref (stream);
1236 	return FALSE;
1237 }
1238 
1239 /*
1240  * called when a stream doing a post-EOS seek is blocked.  this indicates
1241  * that the seek has completed (that's the only way data can flow out of
1242  * the stream bin), so the stream can be linked and unblocked.
1243  */
1244 static void
1245 post_eos_seek_blocked_cb (GstPad *pad, gboolean blocked, RBXFadeStream *stream)
1246 {
1247 	GError *error = NULL;
1248 
1249 	g_mutex_lock (&stream->lock);
1250 
1251 	rb_debug ("stream %s is blocked; linking and unblocking", stream->uri);
1252 	stream->src_blocked = TRUE;
1253 	if (link_and_unblock_stream (stream, &error) == FALSE) {
1254 		emit_stream_error (stream, error);
1255 	}
1256 
1257 	g_mutex_unlock (&stream->lock);
1258 }
1259 
1260 /*
1261  * called when a src pad for a stream is blocked during reuse.
1262  * we don't need to do anything here.
1263  */
1264 static void
1265 unlink_reuse_blocked_cb (GstPad *pad, gboolean blocked, RBXFadeStream *stream)
1266 {
1267 	rb_debug ("stream %s pad blocked during reuse", stream->uri);
1268 }
1269 
1270 static void
1271 unlink_reuse_relink (RBPlayerGstXFade *player, RBXFadeStream *stream)
1272 {
1273 	GError *error = NULL;
1274 
1275 	g_mutex_lock (&stream->lock);
1276 
1277 	if (stream->adder_pad == NULL) {
1278 		rb_debug ("stream %s doesn't need to be unlinked.. weird.", stream->uri);
1279 	} else {
1280 		rb_debug ("unlinking stream %s for reuse", stream->uri);
1281 
1282 		if (gst_pad_unlink (stream->ghost_pad, stream->adder_pad) == FALSE) {
1283 			g_warning ("Couldn't unlink stream %s: this is going to suck.", stream->uri);
1284 		}
1285 
1286 		gst_element_release_request_pad (player->priv->adder, stream->adder_pad);
1287 		stream->adder_pad = NULL;
1288 
1289 		(void) g_atomic_int_dec_and_test (&player->priv->linked_streams);
1290 		rb_debug ("%d linked streams left", player->priv->linked_streams);
1291 	}
1292 
1293 	stream->needs_unlink = FALSE;
1294 	stream->emitted_playing = FALSE;
1295 
1296 	g_mutex_unlock (&stream->lock);
1297 
1298 	/* block the src pad so we don't get not-linked errors if it pushes a buffer
1299 	 * before we get around to relinking
1300 	 */
1301 	gst_pad_set_blocked_async (stream->src_pad,
1302 				   TRUE,
1303 				   (GstPadBlockCallback) unlink_reuse_blocked_cb,
1304 				   stream);
1305 	stream->src_blocked = TRUE;
1306 
1307 	reuse_stream (stream);
1308 	if (link_and_unblock_stream (stream, &error) == FALSE) {
1309 		emit_stream_error (stream, error);
1310 	}
1311 }
1312 
1313 /* called when a stream's source pad is blocked, so it can be unlinked
1314  * from the pipeline.
1315  */
1316 static void
1317 unlink_blocked_cb (GstPad *pad, gboolean blocked, RBXFadeStream *stream)
1318 {
1319 	int stream_state;
1320 	gboolean last;
1321 	RBPlayerGstXFade *player;
1322 	GError *error = NULL;
1323 
1324 	g_mutex_lock (&stream->lock);
1325 
1326 	if (stream->needs_unlink == FALSE || stream->adder_pad == NULL) {
1327 		rb_debug ("stream %s doesn't need to be unlinked", stream->uri);
1328 		g_mutex_unlock (&stream->lock);
1329 		return;
1330 	}
1331 
1332 	rb_debug ("stream %s is blocked; unlinking", stream->uri);
1333 
1334 	if (gst_pad_unlink (stream->ghost_pad, stream->adder_pad) == FALSE) {
1335 		g_warning ("Couldn't unlink stream %s: things will probably go quite badly from here on", stream->uri);
1336 	}
1337 	stream->needs_unlink = FALSE;
1338 
1339 	gst_element_release_request_pad (GST_PAD_PARENT (stream->adder_pad), stream->adder_pad);
1340 	stream->adder_pad = NULL;
1341 
1342 	stream->src_blocked = TRUE;
1343 	stream->emitted_playing = FALSE;
1344 
1345 	stream_state = stream->state;
1346 	player = stream->player;
1347 
1348 	g_mutex_unlock (&stream->lock);
1349 
1350 	/* might want a stream-paused signal here? */
1351 
1352 	last = g_atomic_int_dec_and_test (&player->priv->linked_streams);
1353 	rb_debug ("%d linked streams left", player->priv->linked_streams);
1354 
1355 	/* handle unlinks for seeking and stream reuse */
1356 	switch (stream_state) {
1357 	case REUSING:
1358 		reuse_stream (stream);
1359 		if (link_and_unblock_stream (stream, &error) == FALSE) {
1360 			emit_stream_error (stream, error);
1361 		}
1362 		break;
1363 
1364 	case SEEKING_PAUSED:
1365 		g_idle_add ((GSourceFunc) perform_seek_idle, g_object_ref (stream));
1366 		/* fall through.  this only happens when pausing, so it's OK
1367 		 * to stop the sink here.
1368 		 */
1369 	default:
1370 		/* consider pausing the sink if this is the linked last stream */
1371 		if (last) {
1372 			maybe_stop_sink (player);
1373 		}
1374 
1375 		break;
1376 	}
1377 }
1378 
1379 /*
1380  * blocks and unlinks a stream.  this is the only way we can pause a stream -
1381  * if the stream is linked to the adder and the audio sink is in PLAYING, the
1382  * stream will play.
1383  */
1384 static void
1385 unlink_and_block_stream (RBXFadeStream *stream)
1386 {
1387 	if (stream->adder_pad == NULL) {
1388 		rb_debug ("stream %s is not linked", stream->uri);
1389 		return;
1390 	}
1391 
1392 	stream->needs_unlink = TRUE;
1393 	if (stream->src_blocked) {
1394 		/* probably shouldn't happen, but we'll handle it anyway */
1395 		unlink_blocked_cb (stream->src_pad, TRUE, stream);
1396 	} else {
1397 		gst_pad_set_blocked_async (stream->src_pad,
1398 					   TRUE,
1399 					   (GstPadBlockCallback) unlink_blocked_cb,
1400 					   stream);
1401 	}
1402 }
1403 
1404 /*
1405  * sets a stream to NULL state, unlinks it from the adder,
1406  * removes it from the pipeline, removes it from the
1407  * stream list, and frees it (hopefully).
1408  *
1409  * must not be called on a streaming thread.
1410  */
1411 static void
1412 unlink_and_dispose_stream (RBPlayerGstXFade *player, RBXFadeStream *stream)
1413 {
1414 	GstStateChangeReturn sr;
1415 	gboolean was_linked = FALSE;
1416 	gboolean was_in_pipeline = FALSE;
1417 
1418 	/* seems to be too much locking in here.. */
1419 
1420 
1421 	rb_debug ("stopping stream %s", stream->uri);
1422 	sr = gst_element_set_state (GST_ELEMENT (stream), GST_STATE_NULL);
1423 	if (sr == GST_STATE_CHANGE_ASYNC) {
1424 		/* downward state transitions aren't supposed to return ASYNC.. */
1425 		rb_debug ("!!! stream %s isn't cooperating", stream->uri);
1426 		gst_element_get_state (GST_ELEMENT (stream), NULL, NULL, GST_CLOCK_TIME_NONE);
1427 	}
1428 	
1429 	g_mutex_lock (&stream->lock);
1430 
1431 	if (stream->adder_pad != NULL) {
1432 		rb_debug ("unlinking stream %s", stream->uri);
1433 		if (gst_pad_unlink (stream->ghost_pad, stream->adder_pad) == FALSE) {
1434 			g_warning ("Couldn't unlink stream %s: things will probably go quite badly from here on", stream->uri);
1435 		}
1436 
1437 		gst_element_release_request_pad (GST_PAD_PARENT (stream->adder_pad), stream->adder_pad);
1438 		stream->adder_pad = NULL;
1439 
1440 		was_linked = TRUE;
1441 	}
1442 
1443 	was_in_pipeline = (GST_ELEMENT_PARENT (GST_ELEMENT (stream)) == player->priv->pipeline);
1444 	
1445 	g_mutex_unlock (&stream->lock);
1446 
1447 	if (was_in_pipeline)
1448 		gst_bin_remove (GST_BIN (player->priv->pipeline), GST_ELEMENT (stream));
1449 
1450 	if (was_linked) {
1451 		gboolean last;
1452 
1453 		last = g_atomic_int_dec_and_test (&player->priv->linked_streams);
1454 		rb_debug ("now have %d linked streams", player->priv->linked_streams);
1455 
1456 		if (last) {
1457 			maybe_stop_sink (player);
1458 		}
1459 	}
1460 
1461 	g_rec_mutex_lock (&player->priv->stream_list_lock);
1462 	player->priv->streams = g_list_remove (player->priv->streams, stream);
1463 	dump_stream_list (player);
1464 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
1465 
1466 	g_object_unref (stream);
1467 }
1468 
1469 /* idle handler used to clean up finished streams */
1470 static gboolean
1471 reap_streams (RBPlayerGstXFade *player)
1472 {
1473 	GList *t;
1474 	GList *reap = NULL;
1475 
1476 	g_rec_mutex_lock (&player->priv->stream_list_lock);
1477 	player->priv->stream_reap_id = 0;
1478 	dump_stream_list (player);
1479 	for (t = player->priv->streams; t != NULL; t = t->next) {
1480 		RBXFadeStream *stream = (RBXFadeStream *)t->data;
1481 
1482 		if (stream->state == PENDING_REMOVE) {
1483 			reap = g_list_prepend (reap, stream);
1484 		}
1485 	}
1486 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
1487 
1488 	for (t = reap; t != NULL; t = t->next) {
1489 		RBXFadeStream *stream = (RBXFadeStream *)t->data;
1490 		rb_debug ("reaping stream %s", stream->uri);
1491 		unlink_and_dispose_stream (player, stream);
1492 	}
1493 	g_list_free (reap);
1494 
1495 	return FALSE;
1496 }
1497 
1498 /* schedules a call to reap_streams */
1499 static void
1500 schedule_stream_reap (RBPlayerGstXFade *player)
1501 {
1502 	g_rec_mutex_lock (&player->priv->stream_list_lock);
1503 
1504 	if (player->priv->stream_reap_id == 0) {
1505 		dump_stream_list (player);
1506 		player->priv->stream_reap_id = g_idle_add ((GSourceFunc) reap_streams, player);
1507 	}
1508 	
1509 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
1510 }
1511 
1512 /* emits a tag signal from the player, maybe */
1513 static void
1514 process_tag (const GstTagList *list, const gchar *tag, RBXFadeStream *stream)
1515 {
1516 	RBMetaDataField field;
1517 	GValue value = {0,};
1518 
1519 	/* process embedded images */
1520 	if (!g_strcmp0 (tag, GST_TAG_IMAGE) || !g_strcmp0 (tag, GST_TAG_PREVIEW_IMAGE)) {
1521 		GdkPixbuf *pixbuf;
1522 		pixbuf = rb_gst_process_embedded_image (list, tag);
1523 		if (pixbuf != NULL) {
1524 			_rb_player_emit_image (RB_PLAYER (stream->player),
1525 					       stream->stream_data,
1526 					       pixbuf);
1527 			g_object_unref (pixbuf);
1528 		}
1529 	} else if (rb_gst_process_tag_string (list, tag, &field, &value)) {
1530 		rb_debug ("emitting info field %d", field);
1531 		_rb_player_emit_info (RB_PLAYER (stream->player),
1532 				      stream->stream_data,
1533 				      field,
1534 				      &value);
1535 		g_value_unset (&value);
1536 	}
1537 }
1538 
1539 
1540 static gboolean
1541 emit_missing_plugins (RBXFadeStream *stream)
1542 {
1543 	char **details;
1544 	char **descriptions;
1545 	int count;
1546 	GSList *t;
1547 	int i;
1548 
1549 	stream->emit_missing_plugins_id = 0;
1550 	count = g_slist_length (stream->missing_plugins);
1551 
1552 	details = g_new0 (char *, count + 1);
1553 	descriptions = g_new0 (char *, count + 1);
1554 	i = 0;
1555 	for (t = stream->missing_plugins; t != NULL; t = t->next) {
1556 		GstMessage *msg = GST_MESSAGE (t->data);
1557 		char *detail;
1558 		char *description;
1559 
1560 		detail = gst_missing_plugin_message_get_installer_detail (msg);
1561 		description = gst_missing_plugin_message_get_description (msg);
1562 		details[i] = g_strdup (detail);
1563 		descriptions[i] = g_strdup (description);
1564 		i++;
1565 
1566 		gst_message_unref (msg);
1567 	}
1568 
1569 	g_signal_emit (stream->player, signals[MISSING_PLUGINS], 0, stream->stream_data, details, descriptions);
1570 	g_strfreev (details);
1571 	g_strfreev (descriptions);
1572 
1573 	g_slist_free (stream->missing_plugins);
1574 	stream->missing_plugins = NULL;
1575 
1576 	return FALSE;
1577 }
1578 
1579 
1580 static void
1581 rb_player_gst_xfade_handle_missing_plugin_message (RBPlayerGstXFade *player, RBXFadeStream *stream, GstMessage *message)
1582 {
1583 	if (stream == NULL) {
1584 		rb_debug ("got missing-plugin message from unknown stream");
1585 		return;
1586 	}
1587 
1588 	rb_debug ("got missing-plugin message from %s: %s",
1589 		  stream->uri,
1590 		  gst_missing_plugin_message_get_installer_detail (message));
1591 
1592 	/* can only handle missing-plugins while prerolling */
1593 	switch (stream->state) {
1594 	case PREROLLING:
1595 	case PREROLL_PLAY:
1596 		stream->missing_plugins = g_slist_prepend (stream->missing_plugins,
1597 							   gst_message_ref (message));
1598 		if (stream->emit_missing_plugins_id == 0) {
1599 			stream->emit_missing_plugins_id =
1600 				g_idle_add ((GSourceFunc) emit_missing_plugins,
1601 					    g_object_ref (stream));
1602 		}
1603 
1604 		/* what do we do now?  if we're missing the decoder
1605 		 * or something, it'll never preroll..
1606 		 */
1607 		break;
1608 
1609 	default:
1610 		rb_debug ("can't process missing-plugin messages for this stream now");
1611 		break;
1612 	}
1613 }
1614 
1615 static void
1616 start_waiting_eos_streams (RBPlayerGstXFade *player)
1617 {
1618 	GList *l;
1619 	GList *to_start = NULL;
1620 
1621 	g_rec_mutex_lock (&player->priv->stream_list_lock);
1622 	for (l = player->priv->streams; l != NULL; l = l->next) {
1623 		RBXFadeStream *pstream = l->data;
1624 		if (pstream->state == WAITING_EOS && pstream->starting_eos == FALSE) {
1625 			pstream->starting_eos = TRUE;
1626 			to_start = g_list_prepend (to_start, g_object_ref (pstream));
1627 		}
1628 	}
1629 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
1630 
1631 	for (l = to_start; l != NULL; l = l->next) {
1632 		RBXFadeStream *pstream = l->data;
1633 		GError *error = NULL;
1634 
1635 		rb_debug ("starting stream %s on EOS from previous", pstream->uri);
1636 		if (link_and_unblock_stream (pstream, &error) == FALSE) {
1637 			emit_stream_error (pstream, error);
1638 		}
1639 
1640 		g_object_unref (pstream);
1641 	}
1642 	g_list_free (to_start);
1643 }
1644 
1645 /* gstreamer message bus callback */
1646 static gboolean
1647 rb_player_gst_xfade_bus_cb (GstBus *bus, GstMessage *message, RBPlayerGstXFade *player)
1648 {
1649 	RBXFadeStream *stream;
1650 	GstObject *message_src;
1651 
1652 	g_return_val_if_fail (player != NULL, FALSE);
1653 
1654 	g_rec_mutex_lock (&player->priv->stream_list_lock);
1655 
1656 	message_src = GST_MESSAGE_SRC (message);
1657 	if (GST_IS_PAD (message_src)) {
1658 		message_src = GST_OBJECT_PARENT (message_src);
1659 	}
1660 	stream = find_stream_by_element (player, GST_ELEMENT (message_src));
1661 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
1662 
1663 	switch (GST_MESSAGE_TYPE (message)) {
1664 	case GST_MESSAGE_ERROR:
1665 	{
1666 		char *debug;
1667 		GError *error, *sig_error;
1668 		int code;
1669 		gboolean emit = TRUE;
1670 
1671 		gst_message_parse_error (message, &error, &debug);
1672 
1673 		if (stream == NULL) {
1674 			rb_debug ("Couldn't find stream for error \"%s\": %s", error->message, debug);
1675 			g_error_free (error);
1676 			g_free (debug);
1677 			break;
1678 		}
1679 
1680 		/* If we've already got an error, ignore 'internal data flow error'
1681 		 * type messages, as they're too generic to be helpful.
1682 		 */
1683 		if (stream->emitted_error &&
1684 		    error->domain == GST_STREAM_ERROR &&
1685 		    error->code == GST_STREAM_ERROR_FAILED) {
1686 			rb_debug ("Ignoring generic error \"%s\"", error->message);
1687 			emit = FALSE;
1688 		}
1689 
1690 		code = rb_gst_error_get_error_code (error);
1691 
1692 		if (emit) {
1693 			rb_debug ("emitting error %s for stream %s", error->message, stream->uri);
1694 			sig_error = g_error_new_literal (RB_PLAYER_ERROR,
1695 							 code,
1696 							 error->message);
1697 			stream->emitted_error = TRUE;
1698 			if (stream->emitted_playing == FALSE) {
1699 				_rb_player_emit_playing_stream (RB_PLAYER (player), stream->stream_data);
1700 			}
1701 			_rb_player_emit_error (RB_PLAYER (player), stream->stream_data, sig_error);
1702 		}
1703 
1704 		g_error_free (error);
1705 		g_free (debug);
1706 		break;
1707 	}
1708 	case GST_MESSAGE_TAG:
1709 		if (stream == NULL) {
1710 			rb_debug ("got tag message for unknown stream");
1711 		} else {
1712 			GstTagList *tags;
1713 			gst_message_parse_tag (message, &tags);
1714 
1715 			g_mutex_lock (&stream->lock);
1716 			if (stream->emitted_playing) {
1717 				gst_tag_list_foreach (tags, (GstTagForeachFunc) process_tag, stream);
1718 				gst_tag_list_free (tags);
1719 			} else {
1720 				stream->tags = g_list_append (stream->tags, tags);
1721 			}
1722 			g_mutex_unlock (&stream->lock);
1723 		}
1724 		break;
1725 
1726 	case GST_MESSAGE_DURATION:
1727 		if (stream == NULL) {
1728 			rb_debug ("got duration message for unknown stream");
1729 		} else {
1730 			gint64 duration;
1731 			GstFormat format;
1732 			gst_message_parse_duration (message, &format, &duration);
1733 			rb_debug ("got duration %" G_GINT64_FORMAT
1734 			    " for stream %s", duration, stream->uri);
1735 		}
1736 		break;
1737 
1738 	case GST_MESSAGE_APPLICATION:
1739 	{
1740 		/* process fade messages and emit signals for
1741 		 * other stuff.
1742 		 */
1743 		const GstStructure *structure;
1744 		const char *name;
1745 
1746 		structure = gst_message_get_structure (message);
1747 		name = gst_structure_get_name (structure);
1748 		if (stream == NULL) {
1749 			rb_debug ("got application message %s for unknown stream", name);
1750 		} else if (strcmp (name, STREAM_PLAYING_MESSAGE) == 0) {
1751 			GList *l;
1752 			GList *t;
1753 
1754 			rb_debug ("got stream playing message for %s", stream->uri);
1755 			_rb_player_emit_playing_stream (RB_PLAYER (player), stream->stream_data);
1756 
1757 			/* process any buffered tag lists we received while prerolling the stream */
1758 			g_mutex_lock (&stream->lock);
1759 			l = stream->tags;
1760 			stream->tags = NULL;
1761 			g_mutex_unlock (&stream->lock);
1762 
1763 			for (t = l; t != NULL; t = t->next) {
1764 				GstTagList *tags;
1765 
1766 				tags = (GstTagList *)t->data;
1767 				rb_debug ("processing buffered taglist");
1768 				gst_tag_list_foreach (tags, (GstTagForeachFunc) process_tag, stream);
1769 				gst_tag_list_free (tags);
1770 			}
1771 			g_list_free (l);
1772 
1773 		} else if (strcmp (name, FADE_IN_DONE_MESSAGE) == 0) {
1774 			/* do something? */
1775 		} else if (strcmp (name, FADE_OUT_DONE_MESSAGE) == 0) {
1776 			switch (stream->state) {
1777 			case FADING_OUT:
1778 				/* stop the stream and dispose of it */
1779 				rb_debug ("got fade-out-done for stream %s -> PENDING_REMOVE", stream->uri);
1780 				g_mutex_lock (&stream->lock);
1781 				stream->state = PENDING_REMOVE;
1782 				g_mutex_unlock (&stream->lock);
1783 				schedule_stream_reap (player);
1784 				break;
1785 
1786 			case FADING_OUT_PAUSED:
1787 				{
1788 					/* try to seek back a bit to account for the fade */
1789 					GstFormat format = GST_FORMAT_TIME;
1790 					gint64 pos = -1;
1791 
1792 					g_mutex_lock (&stream->lock);
1793 					gst_element_query_position (stream->volume, &format, &pos);
1794 					if (pos != -1) {
1795 						stream->seek_target = pos > PAUSE_FADE_LENGTH ? pos - PAUSE_FADE_LENGTH : 0;
1796 						stream->state = SEEKING_PAUSED;
1797 						rb_debug ("got fade-out-done for stream %s -> SEEKING_PAUSED [%" G_GINT64_FORMAT "]",
1798 							  stream->uri, stream->seek_target);
1799 					} else {
1800 						stream->state = PAUSED;
1801 						rb_debug ("got fade-out-done for stream %s -> PAUSED (position query failed)",
1802 							  stream->uri);
1803 					}
1804 					g_mutex_unlock (&stream->lock);
1805 				}
1806 				unlink_and_block_stream (stream);
1807 				break;
1808 
1809 			default:
1810 				g_assert_not_reached ();
1811 			}
1812 		} else if (strcmp (name, STREAM_EOS_MESSAGE) == 0) {
1813 			/* emit EOS (if we aren't already reusing the stream), then unlink it.
1814 			 * the stream stay around so we can seek back in it.
1815 			 */
1816 			stream->needs_unlink = TRUE;
1817 			if (stream->state != REUSING) {
1818 				rb_debug ("got EOS message for stream %s -> PENDING_REMOVE", stream->uri);
1819 				_rb_player_emit_eos (RB_PLAYER (player), stream->stream_data, FALSE);
1820 				stream->state = PENDING_REMOVE;
1821 
1822 				unlink_blocked_cb (stream->src_pad, TRUE, stream);
1823 
1824 				/* start playing any streams that were waiting on an EOS
1825 				 * if they finished preroll between when we posted the EOS
1826 				 * message on the stream thread and now.
1827 				 */
1828 				start_waiting_eos_streams (player);
1829 			} else {
1830 				/* no need to emit EOS here, we already know what to do next */
1831 				rb_debug ("got EOS message for stream %s in REUSING state", stream->uri);
1832 
1833 				unlink_reuse_relink (player, stream);
1834 			}
1835 
1836 		} else {
1837 			_rb_player_emit_event (RB_PLAYER (player), stream->stream_data, name, NULL);
1838 		}
1839 
1840 		break;
1841 	}
1842 	case GST_MESSAGE_BUFFERING:
1843 	{
1844 		const GstStructure *s;
1845 		gint progress;
1846 
1847 		s = gst_message_get_structure (message);
1848 		if (!gst_structure_get_int (s, "buffer-percent", &progress)) {
1849 			g_warning ("Could not get value from BUFFERING message");
1850 			break;
1851 		}
1852 		if (stream == NULL) {
1853 			rb_debug ("got buffering message for unknown stream (%d)", progress);
1854 			break;
1855 		}
1856 
1857 		g_mutex_lock (&stream->lock);
1858 		if (progress >= 100) {
1859 			GError *error = NULL;
1860 			switch (stream->state) {
1861 			case PREROLLING:
1862 				rb_debug ("stream %s is buffered, now waiting", stream->uri);
1863 				stream->state = WAITING;
1864 				break;
1865 
1866 			case WAITING_EOS:
1867 				/* hmm, not sure */
1868 				break;
1869 
1870 			case PREROLL_PLAY:
1871 				rb_debug ("stream %s is buffered, now playing", stream->uri);
1872 				if (actually_start_stream (stream, &error) == FALSE) {
1873 					emit_stream_error (stream, error);
1874 				}
1875 				break;
1876 
1877 			default:
1878 				rb_debug ("stream %s is buffered, resuming", stream->uri);
1879 				link_and_unblock_stream (stream, &error);
1880 				if (error) {
1881 					g_warning ("couldn't restart newly buffered stream: %s", error->message);
1882 					g_clear_error (&error);
1883 				}
1884 				break;
1885 			}
1886 		} else {
1887 			switch (stream->state) {
1888 			case PREROLLING:
1889 			case WAITING:
1890 				rb_debug ("still buffering, %d", progress);
1891 				stream->state = PREROLLING;
1892 				break;
1893 
1894 			case WAITING_EOS:
1895 				/* not sure */
1896 				break;
1897 
1898 			default:
1899 				if (stream->adder_pad != NULL) {
1900 					rb_debug ("stream buffering, stopping playback");
1901 					unlink_and_block_stream (stream);
1902 				}
1903 				break;
1904 			}
1905 		}
1906 		g_mutex_unlock (&stream->lock);
1907 		_rb_player_emit_buffering (RB_PLAYER (player), stream->stream_data, progress);
1908 		break;
1909 	}
1910 	case GST_MESSAGE_ELEMENT:
1911 	{
1912 		const GstStructure *s;
1913 		const char *name;
1914 
1915 		if (gst_is_missing_plugin_message (message)) {
1916 			rb_player_gst_xfade_handle_missing_plugin_message (player, stream, message);
1917 			break;
1918 		}
1919 
1920 		s = gst_message_get_structure (message);
1921 		name = gst_structure_get_name (s);
1922 		if ((strcmp (name, "imperfect-timestamp") == 0) ||
1923 		    (strcmp (name, "imperfect-offset") == 0)) {
1924 			char *details;
1925 			const char *uri = "unknown-stream";
1926 
1927 			if (stream != NULL) {
1928 				uri = stream->uri;
1929 			}
1930 
1931 			details = gst_structure_to_string (s);
1932 			rb_debug_realf ("check-imperfect", __FILE__, __LINE__, TRUE, "%s: %s", uri, details);
1933 			g_free (details);
1934 		} else if (strcmp (name, "redirect") == 0) {
1935 			const char *uri = gst_structure_get_string (s, "new-location");
1936 			if (stream != NULL) {
1937 				_rb_player_emit_redirect (RB_PLAYER (player), stream->stream_data, uri);
1938 			} else {
1939 				rb_debug ("got redirect to %s, but no active stream found", uri);
1940 			}
1941 		}
1942 		break;
1943 	}
1944 	default:
1945 		break;
1946 	}
1947 
1948 	if (stream != NULL)
1949 		g_object_unref (stream);
1950 
1951 	/* emit message signals too, so plugins can process bus messages */
1952 	gst_bus_async_signal_func (bus, message, NULL);
1953 
1954 	return TRUE;
1955 }
1956 
1957 static void
1958 stream_notify_source_cb (GstElement *decoder, GParamSpec *pspec, RBXFadeStream *stream)
1959 {
1960 	GstElement *source;
1961 	rb_debug ("got source notification for stream %s", stream->uri);
1962 	g_object_get (decoder, "source", &source, NULL);
1963 	g_signal_emit (stream->player, signals[PREPARE_SOURCE], 0, stream->uri, source);
1964 	g_object_unref (source);
1965 }
1966 
1967 /* links uridecodebin src pads to the rest of the output pipeline */
1968 static void
1969 stream_pad_added_cb (GstElement *decoder, GstPad *pad, RBXFadeStream *stream)
1970 {
1971 	GstCaps *caps;
1972 	GstStructure *structure;
1973 	const char *mediatype;
1974 	GstPad *vpad;
1975 
1976 	/* make sure this is an audio pad */
1977 	caps = gst_pad_get_caps (pad);
1978 	if (gst_caps_is_empty (caps) || gst_caps_is_any (caps)) {
1979 		rb_debug ("got empty/any decoded caps.  hmm?");
1980 		gst_caps_unref (caps);
1981 		return;
1982 	}
1983 
1984 	structure = gst_caps_get_structure (caps, 0);
1985 	mediatype = gst_structure_get_name (structure);
1986 	if (g_str_has_prefix (mediatype, "audio/x-raw") == FALSE) {
1987 		rb_debug ("got non-audio decoded caps: %s", mediatype);
1988 	} else if (stream->decoder_linked) {
1989 		/* probably should never happen */
1990 		rb_debug ("hmm, decoder is already linked");
1991 	} else {
1992 		rb_debug ("got decoded audio pad for stream %s", stream->uri);
1993 		vpad = gst_element_get_static_pad (stream->identity, "sink");
1994 		gst_pad_link (pad, vpad);
1995 		gst_object_unref (vpad);
1996 		stream->decoder_linked = TRUE;
1997 
1998 		stream->decoder_pad = gst_object_ref (pad);
1999 	}
2000 	
2001 	gst_caps_unref (caps);
2002 }
2003 
2004 static void
2005 stream_pad_removed_cb (GstElement *decoder, GstPad *pad, RBXFadeStream *stream)
2006 {
2007 	if (pad == stream->decoder_pad) {
2008 		rb_debug ("active output pad for stream %s removed", stream->uri);
2009 		stream->decoder_linked = FALSE;
2010 
2011 		gst_object_unref (stream->decoder_pad);
2012 		stream->decoder_pad = NULL;
2013 	}
2014 }
2015 
2016 /* handles EOS events on stream bins.  since the pipeline as a whole
2017  * never goes EOS, we don't get an EOS bus message, so we have to handle
2018  * it here.
2019  *
2020  * when an EOS event is received, a bus message is posted, and any streams
2021  * in the WAITING_EOS state are started.
2022  *
2023  * when a new segment event is received, the stream base time is updated
2024  * (mostly for seeking)
2025  *
2026  * flush events are dropped, as they're only relevant inside the stream bin.
2027  * flushing the adder or the output bin mostly just breaks everything.
2028  */
2029 static gboolean
2030 stream_src_event_cb (GstPad *pad, GstEvent *event, RBXFadeStream *stream)
2031 {
2032 	GstMessage *msg;
2033 	GstStructure *s;
2034 
2035 	switch (GST_EVENT_TYPE (event)) {
2036 	case GST_EVENT_EOS:
2037 		rb_debug ("posting EOS message for stream %s", stream->uri);
2038 		s = gst_structure_new (STREAM_EOS_MESSAGE, NULL);
2039 		msg = gst_message_new_application (GST_OBJECT (stream), s);
2040 		gst_element_post_message (GST_ELEMENT (stream), msg);
2041 
2042 		/* start playing any streams that were waiting on an EOS
2043 		 * (are we really allowed to do this on a stream thread?)
2044 		 */
2045 		start_waiting_eos_streams (stream->player);
2046 		break;
2047 
2048 	case GST_EVENT_NEWSEGMENT:
2049 		rb_debug ("got new segment for stream %s", stream->uri);
2050 		adjust_stream_base_time (stream);
2051 		break;
2052 
2053 	case GST_EVENT_FLUSH_STOP:
2054 	case GST_EVENT_FLUSH_START:
2055 		rb_debug ("dropping %s event for stream %s", GST_EVENT_TYPE_NAME (event), stream->uri);
2056 		return FALSE;
2057 
2058 	default:
2059 		rb_debug ("got %s event for stream %s", GST_EVENT_TYPE_NAME (event), stream->uri);
2060 		break;
2061 	}
2062 
2063 	return TRUE;
2064 }
2065 
2066 /*
2067  * stream playback bin:
2068  *
2069  * src [ ! queue ] ! decodebin2 ! audioconvert ! audioresample ! caps ! queue ! volume
2070  *
2071  * the first queue is only added for non-local streams.  the thresholds
2072  * and such are probably going to be configurable at some point,
2073  * since people seem to get all whiny if they don't have a buffer
2074  * size slider to play with.
2075  *
2076  * the volume element is used for crossfading.
2077  */
2078 static RBXFadeStream *
2079 create_stream (RBPlayerGstXFade *player, const char *uri, gpointer stream_data, GDestroyNotify stream_data_destroy)
2080 {
2081 	RBXFadeStream *stream;
2082 	GstCaps *caps;
2083 	GArray *stream_filters = NULL;
2084 	GstElement *tail;
2085 	GstController *controller;
2086 	int i;
2087 
2088 	rb_debug ("creating new stream for %s (stream data %p)", uri, stream_data);
2089 	stream = g_object_new (RB_TYPE_XFADE_STREAM, NULL, NULL);
2090 	stream->player = g_object_ref (player);
2091 	stream->stream_data = stream_data;
2092 	stream->stream_data_destroy = stream_data_destroy;
2093 	stream->uri = g_strdup (uri);
2094 	stream->state = WAITING;
2095 
2096 	stream->use_buffering = FALSE;
2097 	for (i = 0; i < G_N_ELEMENTS (stream_schemes); i++) {
2098 		if (gst_uri_has_protocol (uri, stream_schemes[i])) {
2099 			stream->use_buffering = TRUE;
2100 			break;
2101 		}
2102 	}
2103 
2104 	/* kill the floating reference */
2105 	g_object_ref (stream);
2106 	gst_object_sink (stream);
2107 	gst_element_set_locked_state (GST_ELEMENT (stream), TRUE);
2108 	stream->decoder = gst_element_factory_make ("uridecodebin", NULL);
2109 	if (stream->decoder == NULL) {
2110 		rb_debug ("unable to create uridecodebin");
2111 		g_object_unref (stream);
2112 		return NULL;
2113 	}
2114 	gst_object_ref (stream->decoder);
2115 	g_object_set (stream->decoder, "uri", uri, NULL);
2116 
2117 	/* connect uridecodebin to audioconvert when it creates its output pad */
2118 	g_signal_connect_object (stream->decoder,
2119 				 "notify::source",
2120 				 G_CALLBACK (stream_notify_source_cb),
2121 				 stream,
2122 				 0);
2123 	g_signal_connect_object (stream->decoder,
2124 				 "pad-added",
2125 				 G_CALLBACK (stream_pad_added_cb),
2126 				 stream,
2127 				 0);
2128 	g_signal_connect_object (stream->decoder,
2129 				 "pad-removed",
2130 				 G_CALLBACK (stream_pad_removed_cb),
2131 				 stream,
2132 				 0);
2133 
2134 	stream->identity = gst_element_factory_make ("identity", NULL);
2135 	if (stream->identity == NULL) {
2136 		rb_debug ("unable to create identity");
2137 		g_object_unref (stream);
2138 		return NULL;
2139 	}
2140 
2141 	stream->audioconvert = gst_element_factory_make ("audioconvert", NULL);
2142 	if (stream->audioconvert == NULL) {
2143 		rb_debug ("unable to create audio converter");
2144 		g_object_unref (stream);
2145 		return NULL;
2146 	}
2147 	gst_object_ref (stream->audioconvert);
2148 
2149 	stream->audioresample = gst_element_factory_make ("audioresample", NULL);
2150 	if (stream->audioresample == NULL) {
2151 		rb_debug ("unable to create audio resample");
2152 		g_object_unref (stream);
2153 		return NULL;
2154 	}
2155 	gst_object_ref (stream->audioresample);
2156 
2157 	stream->capsfilter = gst_element_factory_make ("capsfilter", NULL);
2158 	if (stream->capsfilter == NULL) {
2159 		rb_debug ("unable to create capsfilter");
2160 		g_object_unref (stream);
2161 		return NULL;
2162 	}
2163 	gst_object_ref (stream->capsfilter);
2164 
2165 	caps = gst_caps_new_simple ("audio/x-raw-int",
2166 				    "channels", G_TYPE_INT, 2,
2167 				    "rate",	G_TYPE_INT, 44100,
2168 				    "width",	G_TYPE_INT, 16,
2169 				    "depth",	G_TYPE_INT, 16,
2170 				    NULL);
2171 	g_object_set (stream->capsfilter, "caps", caps, NULL);
2172 	gst_caps_unref (caps);
2173 
2174 	stream->volume = gst_element_factory_make ("volume", NULL);
2175 	if (stream->volume == NULL) {
2176 		rb_debug ("unable to create volume control");
2177 		g_object_unref (stream);
2178 		return NULL;
2179 	}
2180 	gst_object_ref (stream->volume);
2181 
2182 	g_signal_connect_object (stream->volume,
2183 				 "notify::volume",
2184 				 G_CALLBACK (volume_changed_cb),
2185 				 player, 0);
2186 
2187 	controller = gst_object_control_properties (G_OBJECT (stream->volume), "volume", NULL);
2188 	if (controller == NULL) {
2189 		rb_debug ("unable to create volume controller");
2190 		g_object_unref (stream);
2191 		return NULL;
2192 	}
2193 
2194 	stream->fader = gst_interpolation_control_source_new ();
2195 	gst_interpolation_control_source_set_interpolation_mode (stream->fader, GST_INTERPOLATE_LINEAR);
2196 	gst_controller_set_control_source (controller, "volume", GST_CONTROL_SOURCE (stream->fader));
2197 
2198 	stream->preroll = gst_element_factory_make ("queue", NULL);
2199 	if (stream->preroll == NULL) {
2200 		rb_debug ("unable to create preroll queue");
2201 		g_object_unref (stream);
2202 		return NULL;
2203 	}
2204 	/* decode at least a second during prerolling, to hopefully avoid underruns.
2205 	 * we clear this when prerolling is finished.  bump the max buffer count up
2206 	 * a bit (from 200) as with some formats it often takes more buffers to
2207 	 * make up a whole second.  don't really want to remove it altogether, though.
2208 	 */
2209 	g_object_set (stream->preroll,
2210 		      "min-threshold-time", GST_SECOND,
2211 		      "max-size-buffers", 1000,
2212 		      NULL);
2213 
2214 	gst_bin_add_many (GST_BIN (stream),
2215 			  stream->decoder,
2216 			  stream->identity,
2217 			  stream->audioconvert,
2218 			  stream->audioresample,
2219 			  stream->capsfilter,
2220 			  stream->preroll,
2221 			  stream->volume,
2222 			  NULL);
2223 	gst_element_link_many (stream->audioconvert,
2224 			       stream->audioresample,
2225 			       stream->capsfilter,
2226 			       stream->preroll,
2227 			       stream->volume,
2228 			       NULL);
2229 
2230 	if (rb_debug_matches ("check-imperfect", __FILE__)) {
2231 
2232 		if (rb_debug_matches ("check-imperfect-timestamp", __FILE__)) {
2233 			g_object_set (stream->identity, "check-imperfect-timestamp", TRUE, NULL);
2234 		}
2235 		if (rb_debug_matches ("check-imperfect-offset", __FILE__)) {
2236 			g_object_set (stream->identity, "check-imperfect-offset", TRUE, NULL);
2237 		}
2238 	}
2239 	stream->src_pad = gst_element_get_static_pad (stream->volume, "src");
2240 
2241 	/* link in any per-stream filters after the identity element, with an
2242 	 * audioconvert before each.
2243 	 */
2244 	tail = stream->identity;
2245 	g_signal_emit (player, signals[GET_STREAM_FILTERS], 0, uri, &stream_filters);
2246 	if (stream_filters != NULL) {
2247 		int i;
2248 		for (i = 0; i < stream_filters->len; i++) {
2249 			GValue *v = &g_array_index (stream_filters, GValue, i);
2250 			GstElement *filter;
2251 			GstElement *audioconvert;
2252 
2253 			audioconvert = gst_element_factory_make ("audioconvert", NULL);
2254 			filter = GST_ELEMENT (g_value_get_object (v));
2255 
2256 			gst_bin_add_many (GST_BIN (stream), audioconvert, filter, NULL);
2257 			gst_element_link_many (tail, audioconvert, filter, NULL);
2258 			tail = filter;
2259 		}
2260 
2261 		g_array_unref (stream_filters);
2262 	}
2263 	gst_element_link (tail, stream->audioconvert);
2264 
2265 	/* ghost the stream src pad up to the bin */
2266 	stream->ghost_pad = gst_ghost_pad_new ("src", stream->src_pad);
2267 	gst_element_add_pad (GST_ELEMENT (stream), stream->ghost_pad);
2268 
2269 	/* watch for EOS events using a pad probe */
2270 	gst_pad_add_event_probe (stream->src_pad, (GCallback) stream_src_event_cb, stream);
2271 
2272 	/* use the pipeline bus even when not inside the pipeline (?) */
2273 	gst_element_set_bus (GST_ELEMENT (stream), gst_element_get_bus (player->priv->pipeline));
2274 
2275 	return stream;
2276 }
2277 
2278 /* starts playback for a stream.
2279  * - links to adder and unblocks
2280  * - if play_type is CROSSFADE:
2281  *   - starts the fade in of the new stream
2282  *   - starts the fade out of the old stream
2283  *   - sets the stream to PLAYING state
2284  * - if play_type is WAIT_EOS:
2285  *   - if something is playing, set the stream to wait-eos state
2286  *   - otherwise, starts it
2287  * - if play_type is REPLACE:
2288  *   - stops any existing stream
2289  *   - starts the new stream
2290  */
2291 static gboolean
2292 actually_start_stream (RBXFadeStream *stream, GError **error)
2293 {
2294 	RBPlayerGstXFade *player = stream->player;
2295 	gboolean ret = TRUE;
2296 	gboolean need_reap = FALSE;
2297 	gboolean playing;
2298 	GList *l;
2299 	GList *to_fade;
2300 
2301 	rb_debug ("going to start playback for stream %s (play type %d, crossfade %" G_GINT64_FORMAT ") -> FADING_IN | PLAYING", stream->uri, stream->play_type, stream->crossfade);
2302 	switch (stream->play_type) {
2303 	case RB_PLAYER_PLAY_CROSSFADE:
2304 
2305 		to_fade = NULL;
2306 		g_rec_mutex_lock (&player->priv->stream_list_lock);
2307 		for (l = player->priv->streams; l != NULL; l = l->next) {
2308 			RBXFadeStream *pstream = (RBXFadeStream *)l->data;
2309 
2310 			if (pstream == stream)
2311 				continue;
2312 
2313 			switch (pstream->state) {
2314 			case FADING_IN:
2315 			case PLAYING:
2316 				rb_debug ("stream %s is playing; crossfading -> FADING_OUT", pstream->uri);
2317 				to_fade = g_list_prepend (to_fade, g_object_ref (pstream));
2318 				break;
2319 
2320 			case PAUSED:
2321 			case WAITING_EOS:
2322 			case SEEKING:
2323 			case SEEKING_PAUSED:
2324 			case PREROLLING:
2325 			case PREROLL_PLAY:
2326 				rb_debug ("stream %s is paused; replacing it", pstream->uri);
2327 				pstream->state = PENDING_REMOVE;
2328 				/* fall through */
2329 			case PENDING_REMOVE:
2330 				need_reap = TRUE;
2331 				break;
2332 
2333 			default:
2334 				break;
2335 			}
2336 		}
2337 
2338 		g_rec_mutex_unlock (&player->priv->stream_list_lock);
2339 
2340 		for (l = to_fade; l != NULL; l = l->next) {
2341 			RBXFadeStream *pstream = (RBXFadeStream *)l->data;
2342 			double fade_out_start = 1.0f;
2343 			gint64 fade_out_time = stream->crossfade;
2344 
2345 			switch (pstream->state) {
2346 			case FADING_IN:
2347 				/* fade out from where the fade in got up to */
2348 				g_object_get (pstream->volume, "volume", &fade_out_start, NULL);
2349 				fade_out_time = (gint64)(((double) stream->crossfade) * fade_out_start);
2350 				/* fall through */
2351 
2352 			case PLAYING:
2353 				start_stream_fade (pstream, fade_out_start, 0.0f, fade_out_time);
2354 				pstream->state = FADING_OUT;
2355 
2356 				start_stream_fade (stream, 0.0f, 1.0f, stream->crossfade);
2357 				break;
2358 
2359 			default:
2360 				/* shouldn't happen, but ignore it if it does */
2361 				break;
2362 			}
2363 
2364 			g_object_unref (pstream);
2365 		}
2366 		g_list_free (to_fade);
2367 
2368 		if (stream->fading == FALSE) {
2369 			GValue v = {0,};
2370 
2371 			rb_debug ("stream isn't fading; setting volume to 1.0");
2372 			g_value_init (&v, G_TYPE_DOUBLE);
2373 			g_value_set_double (&v, 1.0);
2374 			if (gst_interpolation_control_source_set (stream->fader, 0, &v) == FALSE) {
2375 				rb_debug ("controller didn't like our start point");
2376 			}
2377 			g_value_unset (&v);
2378 		}
2379 
2380 		ret = link_and_unblock_stream (stream, error);
2381 		break;
2382 
2383 	case RB_PLAYER_PLAY_AFTER_EOS:
2384 
2385 		g_rec_mutex_lock (&player->priv->stream_list_lock);
2386 
2387 		playing = FALSE;
2388 		for (l = player->priv->streams; l != NULL; l = l->next) {
2389 			RBXFadeStream *pstream = (RBXFadeStream *)l->data;
2390 			if (pstream == stream)
2391 				continue;
2392 
2393 			switch (pstream->state) {
2394 			case PLAYING:
2395 			case FADING_IN:
2396 			case FADING_OUT:
2397 				rb_debug ("stream %s is already playing", pstream->uri);
2398 				playing = TRUE;
2399 				break;
2400 			case PAUSED:
2401 				rb_debug ("stream %s is paused; replacing it", pstream->uri);
2402 				pstream->state = PENDING_REMOVE;
2403 			case PENDING_REMOVE:
2404 				need_reap = TRUE;
2405 				break;
2406 			default:
2407 				break;
2408 			}
2409 		}
2410 
2411 		g_rec_mutex_unlock (&player->priv->stream_list_lock);
2412 	
2413 		if (playing) {
2414 			/* wait for current stream's EOS */
2415 			rb_debug ("existing playing stream found; waiting for its EOS -> WAITING_EOS");
2416 			stream->state = WAITING_EOS;
2417 			stream->starting_eos = FALSE;
2418 		} else {
2419 			rb_debug ("no playing stream found, so starting immediately");
2420 			ret = link_and_unblock_stream (stream, error);
2421 		}
2422 		break;
2423 
2424 	case RB_PLAYER_PLAY_REPLACE:
2425 		/* replace any existing playing stream */
2426 		g_rec_mutex_lock (&player->priv->stream_list_lock);
2427 
2428 		for (l = player->priv->streams; l != NULL; l = l->next) {
2429 			RBXFadeStream *pstream = (RBXFadeStream *)l->data;
2430 			if (pstream == stream)
2431 				continue;
2432 
2433 			switch (pstream->state) {
2434 			case PLAYING:
2435 			case PAUSED:
2436 			case FADING_IN:
2437 			case PENDING_REMOVE:
2438 				/* kill this one */
2439 				rb_debug ("stopping stream %s (replaced by new stream)", pstream->uri);
2440 				need_reap = TRUE;
2441 				pstream->state = PENDING_REMOVE;
2442 				break;
2443 
2444 			default:
2445 				/* let it go */
2446 				break;
2447 			}
2448 		}
2449 
2450 		g_rec_mutex_unlock (&player->priv->stream_list_lock);
2451 
2452 		ret = link_and_unblock_stream (stream, error);
2453 		break;
2454 
2455 	default:
2456 		g_assert_not_reached ();
2457 	}
2458 
2459 	if (need_reap) {
2460 		schedule_stream_reap (player);
2461 	}
2462 
2463 	return ret;
2464 }
2465 
2466 /* called on a streaming thread when the stream src pad is blocked
2467  * (that is, when prerolling is complete).  in some situations we
2468  * start playback immediately, otherwise we wait for something else
2469  * to happen.
2470  */
2471 static void
2472 stream_src_blocked_cb (GstPad *pad, gboolean blocked, RBXFadeStream *stream)
2473 {
2474 	GError *error = NULL;
2475 	gboolean start_stream = FALSE;
2476 
2477 	g_mutex_lock (&stream->lock);
2478 	if (stream->src_blocked) {
2479 		rb_debug ("stream %s already blocked", stream->uri);
2480 		g_mutex_unlock (&stream->lock);
2481 		return;
2482 	}
2483 	stream->src_blocked = TRUE;
2484 
2485 	g_object_set (stream->preroll,
2486 		      "min-threshold-time", G_GINT64_CONSTANT (0),
2487 		      "max-size-buffers", 200,		/* back to normal value */
2488 		      NULL);
2489 
2490 	if (stream->use_buffering) {
2491 		rb_debug ("stream %s requires buffering", stream->uri);
2492 		switch (stream->state) {
2493 		case PREROLL_PLAY:
2494 			post_stream_playing_message (stream, TRUE);
2495 			break;
2496 		default:
2497 			break;
2498 		}
2499 		g_mutex_unlock (&stream->lock);
2500 		return;
2501 	}
2502 
2503 	/* update stream state */
2504 	switch (stream->state) {
2505 	case PREROLLING:
2506 		rb_debug ("stream %s is prerolled, not starting yet -> WAITING", stream->uri);
2507 		stream->state = WAITING;
2508 		break;
2509 	case PREROLL_PLAY:
2510 		rb_debug ("stream %s is prerolled, need to start it", stream->uri);
2511 		start_stream = TRUE;
2512 		break;
2513 	default:
2514 		rb_debug ("didn't expect to get preroll completion callback in this state (%d)", stream->state);
2515 		break;
2516 	}
2517 	
2518 	g_mutex_unlock (&stream->lock);
2519 	
2520 	if (start_stream == TRUE) {	
2521 		/* not sure this is actually an acceptable thing to do on a streaming thread.. */
2522 		if (actually_start_stream (stream, &error) == FALSE) {
2523 			emit_stream_error (stream, error);
2524 		}
2525 	}
2526 }
2527 
2528 /*
2529  * starts prerolling for a stream.
2530  * since the stream isn't linked to anything yet, we
2531  * block the src pad.  when the pad block callback
2532  * is called, prerolling is complete and the stream
2533  * can be linked and played immediately if required.
2534  *
2535  * must be called *without* the stream list lock?
2536  */
2537 static void
2538 preroll_stream (RBPlayerGstXFade *player, RBXFadeStream *stream)
2539 {
2540 	GstStateChangeReturn state;
2541 	gboolean unblock = FALSE;
2542 	GstMessage *message;
2543 	GstBus *bus;
2544 
2545 	gst_pad_set_blocked_async (stream->src_pad,
2546 				   TRUE,
2547 				   (GstPadBlockCallback) stream_src_blocked_cb,
2548 				   stream);
2549 
2550 	stream->emitted_playing = FALSE;
2551 	stream->state = PREROLLING;
2552 	state = gst_element_set_state (GST_ELEMENT (stream), GST_STATE_PAUSED);
2553 	switch (state) {
2554 	case GST_STATE_CHANGE_FAILURE:
2555 		rb_debug ("preroll for stream %s failed (state change failed)", stream->uri);
2556 		/* attempting to unblock here causes deadlock */
2557 
2558 		/* process bus messages in case we got a redirect for this stream */
2559 		bus = gst_element_get_bus (GST_ELEMENT (player->priv->pipeline));
2560 		message = gst_bus_pop (bus);
2561 		while (message != NULL) {
2562 			rb_player_gst_xfade_bus_cb (bus, message, player);
2563 			gst_message_unref (message);
2564 			message = gst_bus_pop (bus);
2565 		}
2566 		g_object_unref (bus);
2567 		break;
2568 
2569 	case GST_STATE_CHANGE_NO_PREROLL:
2570 		rb_debug ("no preroll for stream %s, setting to PLAYING instead?", stream->uri);
2571 		gst_element_set_state (GST_ELEMENT (stream), GST_STATE_PLAYING);
2572 		break;
2573 	case GST_STATE_CHANGE_SUCCESS:
2574 	case GST_STATE_CHANGE_ASYNC:
2575 		/* uridecodebin returns SUCCESS from state changes when streaming, so we can't
2576 		 * use that to figure out what to do next.  instead, we wait for pads to be added
2577 		 * and for our pad block callbacks to be called.
2578 		 */
2579 		break;
2580 	default:
2581 		g_assert_not_reached();
2582 	}
2583 
2584 	if (unblock) {
2585 		rb_debug ("unblocking stream source pad");
2586 		gst_pad_set_blocked_async (stream->src_pad,
2587 					   FALSE,
2588 					   NULL,
2589 					   NULL);
2590 	}
2591 }
2592 
2593 /*
2594  * returns the RBXFadeStream, playback position, and duration of the current
2595  * playing stream.
2596  */
2597 static gboolean
2598 get_times_and_stream (RBPlayerGstXFade *player, RBXFadeStream **pstream, gint64 *pos, gint64 *duration)
2599 {
2600 	gboolean got_time = FALSE;
2601 	gboolean buffering = FALSE;
2602 	RBXFadeStream *stream;
2603 
2604 	if (player->priv->pipeline == NULL)
2605 		return FALSE;
2606 
2607 	g_rec_mutex_lock (&player->priv->stream_list_lock);
2608 	
2609 	/* first look for a network stream that is buffering during preroll */
2610 	stream = find_stream_by_state (player, PREROLLING | PREROLL_PLAY);
2611 	if (stream != NULL) {
2612 		if (stream->emitted_fake_playing == FALSE) {
2613 			g_object_unref (stream);
2614 			stream = NULL;
2615 		} else {
2616 			rb_debug ("found buffering stream %s as current", stream->uri);
2617 			buffering = TRUE;
2618 		}
2619 	}
2620 
2621 	/* otherwise, the stream that is playing */
2622 	if (stream == NULL) {
2623 		stream = find_stream_by_state (player, FADING_IN | PLAYING | FADING_OUT_PAUSED | PAUSED | PENDING_REMOVE | REUSING);
2624 	}
2625 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
2626 
2627 	if (stream != NULL) {
2628 		if (pstream != NULL) {
2629 			*pstream = stream;
2630 		}
2631 
2632 		if (pos != NULL) {
2633 			if (buffering) {
2634 				*pos = 0;
2635 			} else if (stream->state == PAUSED) {
2636 				GstFormat format = GST_FORMAT_TIME;
2637 				*pos = -1;
2638 
2639 				gst_element_query_position (stream->volume, &format, pos);
2640 			} else {
2641 				/* for playing streams, we subtract the current output position
2642 				 * (a running counter generated by the adder) from the position
2643 				 * at which we started playback.
2644 				 */
2645 				GstFormat format = GST_FORMAT_TIME;
2646 				*pos = -1;
2647 				gst_element_query_position (player->priv->pipeline, &format, pos);
2648 				if (*pos != -1) {
2649 					*pos -= stream->base_time;
2650 				} else {
2651 					rb_debug ("position query failed");
2652 				}
2653 			}
2654 		}
2655 
2656 		if (duration != NULL) {
2657 			GstFormat format = GST_FORMAT_TIME;
2658 			*duration = -1;
2659 			/* queries are supposed to go to sinks, but the closest thing we
2660 			 * have in the stream bin is the volume element, which is the last
2661 			 * linked element.
2662 			 */
2663 			gst_element_query_duration (stream->volume, &format, duration);
2664 		}
2665 		got_time = TRUE;
2666 		if (pstream == NULL) {
2667 			g_object_unref (stream);
2668 		}
2669 	} else {
2670 		rb_debug ("not playing");
2671 	}
2672 
2673 	return got_time;
2674 }
2675 
2676 static gboolean
2677 tick_timeout (RBPlayerGstXFade *player)
2678 {
2679 	gint64 pos = -1;
2680 	gint64 duration = -1;
2681 	RBXFadeStream *stream = NULL;
2682 
2683 	if (get_times_and_stream (player, &stream, &pos, &duration)) {
2684 		_rb_player_emit_tick (RB_PLAYER (player), stream->stream_data, pos, duration);
2685 		g_object_unref (stream);
2686 	}
2687 
2688 	return TRUE;
2689 }
2690 
2691 static gboolean
2692 emit_volume_changed_idle (RBPlayerGstXFade *player)
2693 {
2694 	double vol;
2695 
2696 	if (gst_element_implements_interface (player->priv->volume_handler, GST_TYPE_STREAM_VOLUME)) {
2697 		vol = gst_stream_volume_get_volume (GST_STREAM_VOLUME (player->priv->volume_handler),
2698 						    GST_STREAM_VOLUME_FORMAT_CUBIC);
2699 	} else {
2700 		vol = player->priv->cur_volume;
2701 	}
2702 
2703 	_rb_player_emit_volume_changed (RB_PLAYER (player), vol);
2704 	return FALSE;
2705 }
2706 
2707 static void
2708 stream_volume_changed (GObject *element, GParamSpec *pspec, RBPlayerGstXFade *player)
2709 {
2710 	double v;
2711 
2712 	g_object_get (element, "volume", &v, NULL);
2713 	player->priv->cur_volume = v;
2714 
2715 	g_idle_add ((GSourceFunc) emit_volume_changed_idle, player);
2716 }
2717 
2718 /*
2719  * output sink + adder pipeline:
2720  *
2721  * outputcaps = audio/x-raw-int,channels=2,rate=44100,width=16,depth=16
2722  * outputbin = outputcaps ! volume ! filterbin ! audioconvert ! audioresample ! tee ! queue ! audiosink
2723  * silencebin = audiotestsrc wave=silence ! outputcaps
2724  *
2725  * pipeline = silencebin ! adder ! outputbin
2726  *
2727  * the tee in output bin has branches attached to it using the
2728  * RBPlayerGstTee interface.  filterbin contains elements inserted
2729  * using the RBPlayerGstFilter interface.
2730  *
2731  * silencebin is there for two reasons:
2732  * - lets us start the sink without having any streams playing
2733  * - probably helps keep things from falling over between streams
2734  */
2735 
2736 static void
2737 add_bus_watch (RBPlayerGstXFade *player)
2738 {
2739 	GstBus *bus;
2740 
2741 	bus = gst_element_get_bus (GST_ELEMENT (player->priv->pipeline));
2742 	player->priv->bus_watch_id = gst_bus_add_watch (bus, (GstBusFunc) rb_player_gst_xfade_bus_cb, player);
2743 	gst_object_unref (bus);
2744 }
2745 
2746 static gboolean
2747 start_sink_locked (RBPlayerGstXFade *player, GList **messages, GError **error)
2748 {
2749 	GstStateChangeReturn sr;
2750 	gboolean waiting;
2751 	GError *generic_error = NULL;
2752 	GstBus *bus;
2753 
2754 	g_set_error (&generic_error,
2755 		     RB_PLAYER_ERROR,
2756 		     RB_PLAYER_ERROR_INTERNAL,		/* ? */
2757 		     _("Failed to open output device"));
2758 
2759 	rb_debug ("starting sink");
2760 
2761 	/* first, start the output bin.
2762 	 * this won't preroll until we start the silence bin.
2763 	 */
2764 	sr = gst_element_set_state (player->priv->outputbin, GST_STATE_PAUSED);
2765 	if (sr == GST_STATE_CHANGE_FAILURE) {
2766 		rb_debug ("output bin state change failed");
2767 		g_propagate_error (error, generic_error);
2768 		return FALSE;
2769 	}
2770 
2771 	/* then the adder */
2772 	sr = gst_element_set_state (player->priv->adder, GST_STATE_PAUSED);
2773 	if (sr == GST_STATE_CHANGE_FAILURE) {
2774 		rb_debug ("adder state change failed");
2775 		g_propagate_error (error, generic_error);
2776 		return FALSE;
2777 	}
2778 
2779 	/* then the silence bin */
2780 	sr = gst_element_set_state (player->priv->silencebin, GST_STATE_PAUSED);
2781 	if (sr == GST_STATE_CHANGE_FAILURE) {
2782 		rb_debug ("silence bin state change failed");
2783 		g_propagate_error (error, generic_error);
2784 		return FALSE;
2785 	}
2786 
2787 	/* now wait for everything to finish */
2788 	waiting = TRUE;
2789 	bus = gst_element_get_bus (GST_ELEMENT (player->priv->pipeline));
2790 	while (waiting) {
2791 		GstMessage *message;
2792 		GstState oldstate;
2793 		GstState newstate;
2794 		GstState pending;
2795 
2796 		message = gst_bus_timed_pop (bus, GST_SECOND * 5);
2797 		if (message == NULL) {
2798 			rb_debug ("sink is taking too long to start..");
2799 			g_propagate_error (error, generic_error);
2800 			gst_object_unref (bus);
2801 			return FALSE;
2802 		}
2803 
2804 		switch (GST_MESSAGE_TYPE (message)) {
2805 		case GST_MESSAGE_ERROR:
2806 			{
2807 				char *debug;
2808 				GError *gst_error = NULL;
2809 				GstObject *message_src;
2810 				RBXFadeStream *stream;
2811 
2812 				/* we only want to process errors from the sink here.
2813 				 * errors from streams should go to the normal message handler.
2814 				 */
2815 				message_src = GST_MESSAGE_SRC (message);
2816 				stream = find_stream_by_element (player, GST_ELEMENT (message_src));
2817 				if (stream != NULL) {
2818 					rb_debug ("got an error from a stream; passing it to the bus handler");
2819 					*messages = g_list_append (*messages, gst_message_ref (message));
2820 					g_object_unref (stream);
2821 				} else {
2822 					gst_message_parse_error (message, &gst_error, &debug);
2823 					rb_debug ("got error message: %s (%s)", gst_error->message, debug);
2824 					gst_message_unref (message);
2825 					g_free (debug);
2826 
2827 					if (error != NULL && *error == NULL) {
2828 						/* Translators: the parameter here is an error message */
2829 						g_set_error (error,
2830 							     RB_PLAYER_ERROR,
2831 							     RB_PLAYER_ERROR_INTERNAL,		/* ? */
2832 							     _("Failed to open output device: %s"),
2833 							     gst_error->message);
2834 					}
2835 					g_error_free (gst_error);
2836 					g_error_free (generic_error);
2837 
2838 					gst_element_set_state (player->priv->outputbin, GST_STATE_NULL);
2839 					gst_element_set_state (player->priv->adder, GST_STATE_NULL);
2840 					gst_element_set_state (player->priv->silencebin, GST_STATE_NULL);
2841 					gst_object_unref (bus);
2842 					return FALSE;
2843 				}
2844 			}
2845 			break;
2846 
2847 		case GST_MESSAGE_STATE_CHANGED:
2848 			{
2849 				gst_message_parse_state_changed (message, &oldstate, &newstate, &pending);
2850 				if (newstate == GST_STATE_PAUSED && pending == GST_STATE_VOID_PENDING) {
2851 					if (GST_MESSAGE_SRC (message) == GST_OBJECT (player->priv->outputbin)) {
2852 						rb_debug ("outputbin is now PAUSED");
2853 						waiting = FALSE;
2854 					} else if (GST_MESSAGE_SRC (message) == GST_OBJECT (player->priv->adder)) {
2855 						rb_debug ("adder is now PAUSED");
2856 					} else if (GST_MESSAGE_SRC (message) == GST_OBJECT (player->priv->silencebin)) {
2857 						rb_debug ("silencebin is now PAUSED");
2858 					}
2859 				}
2860 			}
2861 			break;
2862 
2863 		default:
2864 			/* save the message to pass to the bus callback once we've dropped
2865 			 * the sink lock.
2866 			 */
2867 			*messages = g_list_append (*messages, gst_message_ref (message));
2868 			break;
2869 		}
2870 
2871 		gst_message_unref (message);
2872 	}
2873 	gst_object_unref (bus);
2874 
2875 	/* if the sink provides a 'volume' property, use that to control output volume */
2876 	player->priv->volume_handler = rb_player_gst_find_element_with_property (player->priv->sink, "volume");
2877 	if (player->priv->volume_handler == NULL) {
2878 		rb_debug ("sink doesn't provide volume control, using volume element");
2879 		player->priv->volume_handler = g_object_ref (player->priv->volume);
2880 	} else if (player->priv->volume_applied == 0) {
2881 		/* ignore the initial volume setting, allowing the
2882 		 * sink to restore its own volume.
2883 		 */
2884 		player->priv->volume_applied = 1;
2885 	}
2886 
2887 	/* if there has been a volume change that we haven't applied, apply it now */
2888 	if (player->priv->volume_applied < player->priv->volume_changed) {
2889 		g_object_set (player->priv->volume_handler, "volume", player->priv->cur_volume, NULL);
2890 		player->priv->volume_applied = player->priv->volume_changed;
2891 	}
2892 
2893 	g_signal_connect_object (player->priv->volume_handler,
2894 				 "notify::volume",
2895 				 G_CALLBACK (stream_volume_changed),
2896 				 player, 0);
2897 
2898 
2899 	sr = gst_element_set_state (player->priv->silencebin, GST_STATE_PLAYING);
2900 	if (sr == GST_STATE_CHANGE_FAILURE) {
2901 		rb_debug ("silence bin state change failed");
2902 		g_propagate_error (error, generic_error);
2903 		return FALSE;
2904 	}
2905 
2906 	sr = gst_element_set_state (player->priv->adder, GST_STATE_PLAYING);
2907 	if (sr == GST_STATE_CHANGE_FAILURE) {
2908 		rb_debug ("adder state change failed");
2909 		g_propagate_error (error, generic_error);
2910 		return FALSE;
2911 	}
2912 
2913 	sr = gst_element_set_state (player->priv->outputbin, GST_STATE_PLAYING);
2914 	if (sr == GST_STATE_CHANGE_FAILURE) {
2915 		rb_debug ("output bin state change failed");
2916 		g_propagate_error (error, generic_error);
2917 		return FALSE;
2918 	}
2919 
2920 	rb_debug ("sink playing");
2921 	player->priv->sink_state = SINK_PLAYING;
2922 
2923 	/* set the pipeline to PLAYING so it selects a clock */
2924 	gst_element_set_state (player->priv->pipeline, GST_STATE_PLAYING);
2925 
2926 	/* now that the sink is running, start polling for playing position.
2927 	 * might want to replace this with a complicated set of pad probes
2928 	 * to avoid polling, but duration queries on the sink are better
2929 	 * as they account for internal buffering etc.  maybe there's a way
2930 	 * to account for that in a pad probe callback on the sink's sink pad?
2931 	 */
2932 	if (player->priv->tick_timeout_id == 0) {
2933 		gint ms_period = 1000 / RB_PLAYER_GST_XFADE_TICK_HZ;
2934 		player->priv->tick_timeout_id =
2935 			g_timeout_add (ms_period,
2936 				      (GSourceFunc) tick_timeout,
2937 				      player);
2938 	}
2939 	return TRUE;
2940 }
2941 
2942 static gboolean
2943 start_sink (RBPlayerGstXFade *player, GError **error)
2944 {
2945 	GList *messages = NULL;
2946 	GList *t;
2947 	GstBus *bus;
2948 	gboolean ret;
2949 
2950 	g_rec_mutex_lock (&player->priv->sink_lock);
2951 	switch (player->priv->sink_state) {
2952 	case SINK_NULL:
2953 		g_assert_not_reached ();
2954 		break;
2955 
2956 	case SINK_STOPPED:
2957 		/* prevent messages from being processed by the main thread while we're starting the sink */
2958 		g_source_remove (player->priv->bus_watch_id);
2959 		ret = start_sink_locked (player, &messages, error);
2960 		add_bus_watch (player);
2961 		break;
2962 
2963 	case SINK_PLAYING:
2964 		ret = TRUE;
2965 		break;
2966 
2967 	default:
2968 		g_assert_not_reached ();
2969 	}
2970 	g_rec_mutex_unlock (&player->priv->sink_lock);
2971 
2972 	bus = gst_element_get_bus (GST_ELEMENT (player->priv->pipeline));
2973 	for (t = messages; t != NULL; t = t->next) {
2974 		rb_player_gst_xfade_bus_cb (bus, t->data, player);
2975 	}
2976 	gst_object_unref (bus);
2977 
2978 	rb_list_destroy_free (messages, (GDestroyNotify) gst_mini_object_unref);
2979 	return ret;
2980 }
2981 
2982 static gboolean
2983 stop_sink (RBPlayerGstXFade *player)
2984 {
2985 	GstStateChangeReturn sr;
2986 
2987 	switch (player->priv->sink_state) {
2988 	case SINK_PLAYING:
2989 		rb_debug ("stopping sink");
2990 
2991 		if (player->priv->tick_timeout_id != 0) {
2992 			g_source_remove (player->priv->tick_timeout_id);
2993 			player->priv->tick_timeout_id = 0;
2994 		}
2995 
2996 		sr = gst_element_set_state (player->priv->outputbin, GST_STATE_READY);
2997 		if (sr == GST_STATE_CHANGE_FAILURE) {
2998 			rb_debug ("couldn't stop output bin");
2999 			return FALSE;
3000 		}
3001 
3002 		sr = gst_element_set_state (player->priv->adder, GST_STATE_READY);
3003 		if (sr == GST_STATE_CHANGE_FAILURE) {
3004 			rb_debug ("couldn't stop adder");
3005 			return FALSE;
3006 		}
3007 
3008 		sr = gst_element_set_state (player->priv->silencebin, GST_STATE_READY);
3009 		if (sr == GST_STATE_CHANGE_FAILURE) {
3010 			rb_debug ("couldn't stop silence bin");
3011 			return FALSE;
3012 		}
3013 
3014 		/* try stopping the sink, but don't worry if we can't */
3015 		sr = gst_element_set_state (player->priv->sink, GST_STATE_NULL);
3016 		if (sr == GST_STATE_CHANGE_FAILURE) {
3017 			rb_debug ("couldn't set audio sink to NULL state");
3018 		}
3019 
3020 		if (player->priv->volume_handler) {
3021 			g_object_unref (player->priv->volume_handler);
3022 			player->priv->volume_handler = NULL;
3023 		}
3024 
3025 		/* set the pipeline to READY so we can make it select a clock when we
3026 		 * start the sink again.  everything inside the pipeline has its state
3027 		 * locked, so this doesn't affect anything else.
3028 		 */
3029 		gst_element_set_state (player->priv->pipeline, GST_STATE_READY);
3030 
3031 		player->priv->sink_state = SINK_STOPPED;
3032 		break;
3033 
3034 	case SINK_STOPPED:
3035 	case SINK_NULL:
3036 		break;
3037 	}
3038 
3039 	return TRUE;
3040 }
3041 
3042 
3043 static gboolean
3044 create_sink (RBPlayerGstXFade *player, GError **error)
3045 {
3046 	const char *try_sinks[] = { "gsettingsaudiosink", "gconfaudiosink", "autoaudiosink" };
3047 	GstElement *audiotestsrc;
3048 	GstElement *audioconvert;
3049 	GstElement *audioresample;
3050 	GstElement *capsfilter;
3051 	GstElement *queue;
3052 	GstCaps *caps;
3053 	GstPad *filterpad;
3054 	GstPad *outputghostpad;
3055 	GstPad *ghostpad;
3056 	GstPad *reqpad;
3057 	GstPad *addersrcpad;
3058 	GstPadLinkReturn plr;
3059 	GList *l;
3060 	int i;
3061 
3062 	if (player->priv->sink_state != SINK_NULL)
3063 		return TRUE;
3064 
3065 	/* set filter caps.
3066 	 * 44100Hz is about the most reasonable thing to use;
3067 	 * we have audioconvert+audioresample afterwards in
3068 	 * case the output device doesn't actually support
3069 	 * that rate.
3070 	 */
3071 	caps = gst_caps_new_simple ("audio/x-raw-int",
3072 				    "channels", G_TYPE_INT, 2,
3073 				    "rate",	G_TYPE_INT, 44100,
3074 				    "width",	G_TYPE_INT, 16,
3075 				    "depth",	G_TYPE_INT, 16,
3076 				    NULL);
3077 
3078 	player->priv->pipeline = gst_pipeline_new ("rbplayer");
3079 	add_bus_watch (player);
3080 	g_object_notify (G_OBJECT (player), "bus");
3081 
3082 	player->priv->outputbin = gst_bin_new ("outputbin");
3083 	gst_element_set_locked_state (player->priv->outputbin, TRUE);
3084 	player->priv->adder = gst_element_factory_make ("adder", "outputadder");
3085 	player->priv->capsfilter = gst_element_factory_make ("capsfilter", "outputcapsfilter");
3086 	audioconvert = gst_element_factory_make ("audioconvert", "outputconvert");
3087 	audioresample = gst_element_factory_make ("audioresample", "outputresample");
3088 	player->priv->tee = gst_element_factory_make ("tee", "outputtee");
3089 	queue = gst_element_factory_make ("queue", NULL);
3090 	player->priv->volume = gst_element_factory_make ("volume", "outputvolume");
3091 	player->priv->filterbin = rb_gst_create_filter_bin ();
3092 	capsfilter = gst_element_factory_make ("capsfilter", NULL);
3093 	if (player->priv->pipeline == NULL ||
3094 	    player->priv->adder == NULL ||
3095 	    player->priv->capsfilter == NULL ||
3096 	    audioconvert == NULL ||
3097 	    audioresample == NULL ||
3098 	    player->priv->tee == NULL ||
3099 	    queue == NULL ||
3100 	    player->priv->volume == NULL ||
3101 	    player->priv->filterbin == NULL ||
3102 	    capsfilter == NULL) {
3103 		/* we could include the element name in the error message,
3104 		 * but these are all fundamental elements that are always
3105 		 * available.
3106 		 */
3107 		g_set_error (error,
3108 			     RB_PLAYER_ERROR,
3109 			     RB_PLAYER_ERROR_GENERAL,
3110 			     _("Failed to create GStreamer element; check your installation"));
3111 		return FALSE;
3112 	}
3113 
3114 	for (i = 0; i < G_N_ELEMENTS (try_sinks); i++) {
3115 		player->priv->sink = rb_player_gst_try_audio_sink (try_sinks[i], NULL);
3116 		if (player->priv->sink != NULL) {
3117 			break;
3118 		}
3119 	}
3120 	if (player->priv->sink == NULL) {
3121 		g_set_error (error,
3122 			     RB_PLAYER_ERROR,
3123 			     RB_PLAYER_ERROR_GENERAL,
3124 			     _("Failed to create audio output element; check your installation"));
3125 		return FALSE;
3126 	}
3127 
3128 	g_object_set (player->priv->capsfilter, "caps", caps, NULL);
3129 	g_object_set (capsfilter, "caps", caps, NULL);
3130 
3131 	g_object_set (queue, "max-size-buffers", 10, NULL);
3132 
3133 	gst_bin_add_many (GST_BIN (player->priv->outputbin),
3134 			  player->priv->capsfilter,
3135 			  player->priv->volume,
3136 			  player->priv->filterbin,
3137 			  audioconvert,
3138 			  audioresample,
3139 			  capsfilter,
3140 			  player->priv->tee,
3141 			  queue,
3142 			  player->priv->sink,
3143 			  NULL);
3144 	if (gst_element_link_many (player->priv->capsfilter,
3145 			       player->priv->volume,
3146 			       player->priv->filterbin,
3147 			       audioconvert,
3148 			       audioresample,
3149 			       capsfilter,
3150 			       player->priv->tee,
3151 			       queue,
3152 			       player->priv->sink,
3153 			       NULL) == FALSE) {
3154 		g_set_error (error,
3155 			     RB_PLAYER_ERROR,
3156 			     RB_PLAYER_ERROR_GENERAL,
3157 			     _("Failed to link GStreamer pipeline; check your installation"));
3158 		return FALSE;
3159 	}
3160 
3161 	filterpad = gst_element_get_static_pad (player->priv->capsfilter, "sink");
3162 	outputghostpad = gst_ghost_pad_new ("sink", filterpad);
3163 	gst_element_add_pad (player->priv->outputbin, outputghostpad);
3164 	gst_object_unref (filterpad);
3165 
3166 	/* create silence bin */
3167 	player->priv->silencebin = gst_bin_new ("silencebin");
3168 	audiotestsrc = gst_element_factory_make ("audiotestsrc", "silence");
3169 	g_object_set (audiotestsrc, "wave", 4, NULL);
3170 
3171 	audioconvert = gst_element_factory_make ("audioconvert", "silenceconvert");
3172 
3173 	capsfilter = gst_element_factory_make ("capsfilter", "silencecapsfilter");
3174 	g_object_set (capsfilter, "caps", caps, NULL);
3175 	gst_caps_unref (caps);
3176 
3177 	if (audiotestsrc == NULL ||
3178 	    audioconvert == NULL ||
3179 	    capsfilter == NULL) {
3180 		g_set_error (error,
3181 			     RB_PLAYER_ERROR,
3182 			     RB_PLAYER_ERROR_GENERAL,
3183 			     _("Failed to create GStreamer element; check your installation"));
3184 		return FALSE;
3185 	}
3186 
3187 	gst_bin_add_many (GST_BIN (player->priv->silencebin),
3188 			  audiotestsrc,
3189 			  audioconvert,
3190 			  capsfilter,
3191 			  NULL);
3192 	if (gst_element_link_many (audiotestsrc,
3193 				   audioconvert,
3194 				   capsfilter,
3195 				   NULL) == FALSE) {
3196 		g_set_error (error,
3197 			     RB_PLAYER_ERROR,
3198 			     RB_PLAYER_ERROR_GENERAL,
3199 			     _("Failed to link GStreamer pipeline; check your installation"));
3200 		return FALSE;
3201 	}
3202 
3203 	filterpad = gst_element_get_static_pad (capsfilter, "src");
3204 	ghostpad = gst_ghost_pad_new (NULL, filterpad);
3205 	gst_element_add_pad (player->priv->silencebin, ghostpad);
3206 	gst_object_unref (filterpad);
3207 
3208 	/* assemble stuff:
3209 	 * - add everything to the pipeline
3210 	 * - link adder to output bin
3211 	 * - link silence bin to adder
3212 	 */
3213 	gst_bin_add_many (GST_BIN (player->priv->pipeline),
3214 			  player->priv->adder,
3215 			  player->priv->outputbin,
3216 			  player->priv->silencebin,
3217 			  NULL);
3218 
3219 	addersrcpad = gst_element_get_static_pad (player->priv->adder, "src");
3220 	plr = gst_pad_link (addersrcpad, outputghostpad);
3221 	if (plr != GST_PAD_LINK_OK) {
3222 		g_set_error (error,
3223 			     RB_PLAYER_ERROR,
3224 			     RB_PLAYER_ERROR_GENERAL,
3225 			     _("Failed to link GStreamer pipeline; check your installation"));
3226 		return FALSE;
3227 	}
3228 
3229 	reqpad = gst_element_get_request_pad (player->priv->adder, "sink%d");
3230 	if (reqpad == NULL) {
3231 		g_set_error (error,
3232 			     RB_PLAYER_ERROR,
3233 			     RB_PLAYER_ERROR_GENERAL,
3234 			     _("Failed to link GStreamer pipeline; check your installation"));
3235 		return FALSE;
3236 	}
3237 
3238 	plr = gst_pad_link (ghostpad, reqpad);
3239 	if (plr != GST_PAD_LINK_OK) {
3240 		g_set_error (error,
3241 			     RB_PLAYER_ERROR,
3242 			     RB_PLAYER_ERROR_GENERAL,
3243 			     _("Failed to link GStreamer pipeline; check your installation"));
3244 		return FALSE;
3245 	}
3246 
3247 	/* add any tees and filters that were waiting for us */
3248 	for (l = player->priv->waiting_tees; l != NULL; l = g_list_next (l)) {
3249 		rb_player_gst_tee_add_tee (RB_PLAYER_GST_TEE (player), GST_ELEMENT (l->data));
3250 	}
3251 	g_list_free (player->priv->waiting_tees);
3252 	player->priv->waiting_tees = NULL;
3253 
3254 	for (l = player->priv->waiting_filters; l != NULL; l = g_list_next (l)) {
3255 		rb_player_gst_filter_add_filter (RB_PLAYER_GST_FILTER (player), GST_ELEMENT (l->data));
3256 	}
3257 	g_list_free (player->priv->waiting_filters);
3258 	player->priv->waiting_filters = NULL;
3259 
3260 	player->priv->sink_state = SINK_STOPPED;
3261 	return TRUE;
3262 }
3263 
3264 
3265 
3266 static gboolean
3267 rb_player_gst_xfade_open (RBPlayer *iplayer,
3268 			  const char *uri,
3269 			  gpointer stream_data,
3270 			  GDestroyNotify stream_data_destroy,
3271 			  GError **error)
3272 {
3273 	RBXFadeStream *stream;
3274 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3275 	gboolean reused = FALSE;
3276 	GList *t;
3277 
3278 	/* create sink if we don't already have one */
3279 	if (create_sink (player, error) == FALSE)
3280 		return FALSE;
3281 
3282 	/* see if anyone wants us to reuse an existing stream */
3283 	g_rec_mutex_lock (&player->priv->stream_list_lock);
3284 	for (t = player->priv->streams; t != NULL; t = t->next) {
3285 		RBXFadeStream *stream = (RBXFadeStream *)t->data;
3286 
3287 		switch (stream->state) {
3288 		case WAITING:
3289 		case PENDING_REMOVE:
3290 		case REUSING:
3291 		case SEEKING:
3292 		case SEEKING_PAUSED:
3293 		case SEEKING_EOS:
3294 		case PREROLLING:
3295 		case PREROLL_PLAY:
3296 			break;
3297 
3298 		case PLAYING:
3299 		case FADING_IN:
3300 		case FADING_OUT:
3301 		case FADING_OUT_PAUSED:
3302 		case WAITING_EOS:
3303 		case PAUSED:
3304 			g_signal_emit (player,
3305 				       signals[CAN_REUSE_STREAM], 0,
3306 				       uri, stream->uri, GST_ELEMENT (stream),
3307 				       &reused);
3308 			break;
3309 		}
3310 
3311 		if (reused) {
3312 			rb_debug ("reusing stream %s for new stream %s", stream->uri, uri);
3313 			stream->state = REUSING;
3314 			stream->new_uri = g_strdup (uri);
3315 			stream->new_stream_data = stream_data;
3316 			stream->new_stream_data_destroy = stream_data_destroy;
3317 
3318 			/* move the stream to the front of the list so it'll be started when
3319 			 * _play is called (it's probably already there, but just in case..)
3320 			 */
3321 			player->priv->streams = g_list_remove (player->priv->streams, stream);
3322 			player->priv->streams = g_list_prepend (player->priv->streams, stream);
3323 			break;
3324 		}
3325 	}
3326 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
3327 	if (reused) {
3328 		return TRUE;
3329 	}
3330 
3331 	/* construct new stream */
3332 	stream = create_stream (player, uri, stream_data, stream_data_destroy);
3333 	if (stream == NULL) {
3334 		rb_debug ("unable to create pipeline to play %s", uri);
3335 		g_set_error (error,
3336 			     RB_PLAYER_ERROR,
3337 			     RB_PLAYER_ERROR_GENERAL,
3338 			     _("Failed to create GStreamer pipeline to play %s"),
3339 			     uri);
3340 		return FALSE;
3341 	}
3342 
3343 	g_rec_mutex_lock (&player->priv->stream_list_lock);
3344 	player->priv->streams = g_list_prepend (player->priv->streams, stream);
3345 	dump_stream_list (player);
3346 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
3347 
3348 	/* start prerolling it */
3349 	preroll_stream (player, stream);
3350 
3351 	return TRUE;
3352 }
3353 
3354 static gboolean
3355 stop_sink_later (RBPlayerGstXFade *player)
3356 {
3357 	g_rec_mutex_lock (&player->priv->sink_lock);
3358 	player->priv->stop_sink_id = 0;
3359 	if (g_atomic_int_get (&player->priv->linked_streams) == 0) {
3360 		stop_sink (player);
3361 	}
3362 	g_rec_mutex_unlock (&player->priv->sink_lock);
3363 
3364 	return FALSE;
3365 }
3366 
3367 static void
3368 maybe_stop_sink (RBPlayerGstXFade *player)
3369 {
3370 	g_rec_mutex_lock (&player->priv->sink_lock);
3371 	if (player->priv->stop_sink_id == 0) {
3372 		player->priv->stop_sink_id =
3373 			g_timeout_add (1000,
3374 				       (GSourceFunc) stop_sink_later,
3375 				       player);
3376 	}
3377 	g_rec_mutex_unlock (&player->priv->sink_lock);
3378 }
3379 
3380 static gboolean
3381 rb_player_gst_xfade_close (RBPlayer *iplayer, const char *uri, GError **error)
3382 {
3383 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3384 	gboolean ret = TRUE;
3385 
3386 	if (uri == NULL) {
3387 		GList *list;
3388 		GList *l;
3389 
3390 		/* need to copy the list as unlink_and_dispose_stream modifies it */
3391 		g_rec_mutex_lock (&player->priv->stream_list_lock);
3392 		list = g_list_copy (player->priv->streams);
3393 		for (l = list; l != NULL; l = l->next) {
3394 			RBXFadeStream *stream = (RBXFadeStream *)l->data;
3395 			g_object_ref (stream);
3396 		}
3397 		g_rec_mutex_unlock (&player->priv->stream_list_lock);
3398 
3399 		for (l = list; l != NULL; l = l->next) {
3400 			RBXFadeStream *stream = (RBXFadeStream *)l->data;
3401 			unlink_and_dispose_stream (player, stream);
3402 			g_object_unref (stream);
3403 		}
3404 		g_list_free (list);
3405 	} else {
3406 		/* just stop and close the stream for the specified uri */
3407 		RBXFadeStream *stream;
3408 
3409 		g_rec_mutex_lock (&player->priv->stream_list_lock);
3410 		stream = find_stream_by_uri (player, uri);
3411 		g_rec_mutex_unlock (&player->priv->stream_list_lock);
3412 
3413 		if (stream != NULL) {
3414 			unlink_and_dispose_stream (player, stream);
3415 			g_object_unref (stream);
3416 		} else {
3417 			rb_debug ("can't find stream for %s", uri);
3418 			/* XXX set error ?*/
3419 			ret = FALSE;
3420 		}
3421 	}
3422 
3423 	return ret;
3424 }
3425 
3426 
3427 static gboolean
3428 rb_player_gst_xfade_opened (RBPlayer *iplayer)
3429 {
3430 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3431 	RBXFadeStream *stream;
3432 	gboolean opened = FALSE;
3433 
3434 	/* maybe replace this with just a flag somewhere? */
3435 
3436 	g_rec_mutex_lock (&player->priv->stream_list_lock);
3437 
3438 	stream = find_stream_by_state (player, PREROLLING | PREROLL_PLAY | WAITING_EOS | WAITING | FADING_IN | PLAYING | PAUSED);
3439 	if (stream != NULL) {
3440 		opened = TRUE;
3441 		g_object_unref (stream);
3442 	}
3443 
3444 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
3445 
3446 	return opened;
3447 }
3448 
3449 static gboolean
3450 rb_player_gst_xfade_play (RBPlayer *iplayer,
3451 			  RBPlayerPlayType play_type,
3452 			  gint64 crossfade,
3453 			  GError **error)
3454 {
3455 	RBXFadeStream *stream;
3456 	int stream_state;
3457 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3458 	gboolean ret = TRUE;
3459 
3460 	g_rec_mutex_lock (&player->priv->stream_list_lock);
3461 
3462 	/* is there anything to play? */
3463 	if (player->priv->streams == NULL) {
3464 		g_set_error (error,
3465 			     RB_PLAYER_ERROR,
3466 			     RB_PLAYER_ERROR_GENERAL,
3467 			     "Nothing to play");		/* should never happen */
3468 
3469 		g_rec_mutex_unlock (&player->priv->stream_list_lock);
3470 		return FALSE;
3471 	}
3472 	
3473 	stream = g_list_first (player->priv->streams)->data;
3474 	g_object_ref (stream);
3475 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
3476 
3477 	/* make sure the sink is playing */
3478 	if (start_sink (player, error) == FALSE) {
3479 		g_object_unref (stream);
3480 		return FALSE;
3481 	}
3482 
3483 	g_mutex_lock (&stream->lock);
3484 
3485 	rb_debug ("playing stream %s, play type %d, crossfade %" G_GINT64_FORMAT, stream->uri, play_type, crossfade);
3486 
3487 	/* handle transitional states while holding the lock, and handle states that
3488 	 * require action outside it (lock precedence, mostly)
3489 	 */
3490 	switch (stream->state) {
3491 	case PREROLLING:
3492 	case PREROLL_PLAY:
3493 		rb_debug ("stream %s is prerolling; will start playback once prerolling is complete -> PREROLL_PLAY", stream->uri);
3494 		stream->play_type = play_type;
3495 		stream->crossfade = crossfade;
3496 		stream->state = PREROLL_PLAY;
3497 		break;
3498 	
3499 	case SEEKING_PAUSED:
3500 		rb_debug ("unpausing seeking stream %s", stream->uri);
3501 		stream->state = SEEKING;
3502 		break;
3503 
3504 	case PENDING_REMOVE:
3505 		rb_debug ("hmm, can't play streams in PENDING_REMOVE state..");
3506 		break;
3507 
3508 	default:
3509 		break;
3510 	}
3511 
3512 	stream_state = stream->state;
3513 	g_mutex_unlock (&stream->lock);
3514 
3515 	/* is the head stream already playing? */
3516 	switch (stream_state) {
3517 	case FADING_IN:
3518 	case FADING_OUT:
3519 	case FADING_OUT_PAUSED:
3520 	case PLAYING:
3521 	case SEEKING:
3522 	case SEEKING_EOS:
3523 		rb_debug ("stream %s is already playing", stream->uri);
3524 		_rb_player_emit_playing_stream (RB_PLAYER (player), stream->stream_data);
3525 		break;
3526 
3527 	case PAUSED:
3528 		rb_debug ("unpausing stream %s", stream->uri);
3529 		start_stream_fade (stream, 0.0f, 1.0f, PAUSE_FADE_LENGTH);
3530 		ret = link_and_unblock_stream (stream, error);
3531 		break;
3532 
3533 	case WAITING_EOS:
3534 	case WAITING:
3535 		stream->play_type = play_type;
3536 		stream->crossfade = crossfade;
3537 		ret = actually_start_stream (stream, error);
3538 		break;
3539 
3540 	case REUSING:
3541 		switch (play_type) {
3542 		case RB_PLAYER_PLAY_REPLACE:
3543 		case RB_PLAYER_PLAY_CROSSFADE:
3544 			/* probably should split this into two states.. */
3545 			if (stream->src_blocked) {
3546 				rb_debug ("reusing and restarting paused stream %s", stream->uri);
3547 				reuse_stream (stream);
3548 				ret = link_and_unblock_stream (stream, error);
3549 			} else {
3550 				rb_debug ("unlinking stream %s for reuse", stream->uri);
3551 				unlink_and_block_stream (stream);
3552 			}
3553 			break;
3554 		case RB_PLAYER_PLAY_AFTER_EOS:
3555 			rb_debug ("waiting for EOS before reusing stream %s", stream->uri);
3556 			break;
3557 		}
3558 		break;
3559 
3560 	default:
3561 		break;
3562 	}
3563 
3564 	g_object_unref (stream);
3565 
3566 	return ret;
3567 }
3568 
3569 static void
3570 rb_player_gst_xfade_pause (RBPlayer *iplayer)
3571 {
3572 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3573 	GList *l;
3574 	GList *to_fade = NULL;
3575 	gboolean done = FALSE;
3576 	double fade_out_start = 1.0f;
3577 	gint64 fade_out_time = PAUSE_FADE_LENGTH;
3578 
3579 	g_rec_mutex_lock (&player->priv->stream_list_lock);
3580 
3581 	for (l = player->priv->streams; l != NULL; l = l->next) {
3582 		RBXFadeStream *stream;
3583 		stream = (RBXFadeStream *)l->data;
3584 		switch (stream->state) {
3585 		case WAITING:
3586 		case WAITING_EOS:
3587 			rb_debug ("stream %s is not yet playing, can't pause", stream->uri);
3588 			break;
3589 
3590 		case PREROLLING:
3591 		case PREROLL_PLAY:
3592 			rb_debug ("stream %s is prerolling, can't pause", stream->uri);
3593 			break;
3594 
3595 		case REUSING:
3596 			rb_debug ("stream %s is being reused, can't pause", stream->uri);
3597 			break;
3598 
3599 		case PAUSED:
3600 		case SEEKING_PAUSED:
3601 		case FADING_OUT_PAUSED:
3602 			rb_debug ("stream %s is already paused", stream->uri);
3603 			done = TRUE;
3604 			break;
3605 
3606 		case FADING_IN:
3607 		case PLAYING:
3608 			rb_debug ("pausing stream %s -> FADING_OUT_PAUSED", stream->uri);
3609 			to_fade = g_list_prepend (to_fade, g_object_ref (stream));
3610 			done = TRUE;
3611 			break;
3612 
3613 		case SEEKING:
3614 			rb_debug ("pausing seeking stream %s -> SEEKING_PAUSED", stream->uri);
3615 			stream->state = SEEKING_PAUSED;
3616 			done = TRUE;
3617 			break;
3618 		case SEEKING_EOS:
3619 			rb_debug ("stream %s is seeking after EOS -> SEEKING_PAUSED", stream->uri);
3620 			stream->state = SEEKING_PAUSED;
3621 			done = TRUE;
3622 			break;
3623 
3624 		case FADING_OUT:
3625 			rb_debug ("stream %s is fading out, can't be bothered pausing it", stream->uri);
3626 			break;
3627 
3628 		case PENDING_REMOVE:
3629 			rb_debug ("stream %s is done, can't pause", stream->uri);
3630 			break;
3631 		}
3632 
3633 		if (done)
3634 			break;
3635 	}
3636 
3637 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
3638 
3639 	for (l = to_fade; l != NULL; l = l->next) {
3640 		RBXFadeStream *stream = (RBXFadeStream *)l->data;
3641 
3642 		switch (stream->state) {
3643 		case FADING_IN:
3644 			g_object_get (stream->volume, "volume", &fade_out_start, NULL);
3645 			fade_out_time = (gint64)(((double) PAUSE_FADE_LENGTH) * fade_out_start);
3646 
3647 		case PLAYING:
3648 			stream->state = FADING_OUT_PAUSED;
3649 			start_stream_fade (stream, fade_out_start, 0.0f, fade_out_time);
3650 
3651 		default:
3652 			/* shouldn't happen, but ignore it if it does */
3653 			break;
3654 		}
3655 
3656 		g_object_unref (stream);
3657 	}
3658 	g_list_free (to_fade);
3659 	
3660 	if (done == FALSE)
3661 		rb_debug ("couldn't find a stream to pause");
3662 }
3663 
3664 static gboolean
3665 rb_player_gst_xfade_playing (RBPlayer *iplayer)
3666 {
3667 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3668 	gboolean playing = FALSE;
3669 	RBXFadeStream *stream;
3670 
3671 	if (player->priv->sink_state != SINK_PLAYING)
3672 		return FALSE;
3673 
3674 	/* XXX maybe replace with just a flag? */
3675 
3676 	g_rec_mutex_lock (&player->priv->stream_list_lock);
3677 
3678 	stream = find_stream_by_state (player, PLAYING | FADING_IN);
3679 	if (stream != NULL) {
3680 		playing = TRUE;
3681 		g_object_unref (stream);
3682 	}
3683 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
3684 	return playing;
3685 }
3686 
3687 
3688 static void
3689 rb_player_gst_xfade_set_volume (RBPlayer *iplayer, float volume)
3690 {
3691 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3692 
3693 	player->priv->volume_changed++;
3694 	if (player->priv->volume_handler != NULL) {
3695 		gdouble v = (gdouble)volume;
3696 
3697 		/* maybe use a controller here for smoother changes? */
3698 		if (gst_element_implements_interface (player->priv->volume_handler,
3699 						      GST_TYPE_STREAM_VOLUME)) {
3700 			gst_stream_volume_set_volume (GST_STREAM_VOLUME (player->priv->volume_handler),
3701 						      GST_STREAM_VOLUME_FORMAT_CUBIC, v);
3702 		} else {
3703 			g_object_set (player->priv->volume_handler, "volume", v, NULL);
3704 		}
3705 		player->priv->volume_applied = player->priv->volume_changed;
3706 	}
3707 	player->priv->cur_volume = volume;
3708 }
3709 
3710 
3711 static float
3712 rb_player_gst_xfade_get_volume (RBPlayer *iplayer)
3713 {
3714 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3715 
3716 	if (gst_element_implements_interface (player->priv->volume_handler, GST_TYPE_STREAM_VOLUME))
3717 		return gst_stream_volume_get_volume (GST_STREAM_VOLUME (player->priv->volume_handler),
3718 						     GST_STREAM_VOLUME_FORMAT_CUBIC);
3719 
3720 	return player->priv->cur_volume;
3721 }
3722 
3723 static gboolean
3724 rb_player_gst_xfade_seekable (RBPlayer *iplayer)
3725 {
3726 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3727 	gboolean can_seek = TRUE;
3728 	RBXFadeStream *stream;
3729 
3730 	/* is this supposed to query the most recently opened stream,
3731 	 * or the current playing stream?  I really don't know.
3732 	 */
3733 	g_rec_mutex_lock (&player->priv->stream_list_lock);
3734 	stream = find_stream_by_state (player, FADING_IN | PAUSED | PLAYING);
3735 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
3736 
3737 	if (stream) {
3738 		GstQuery *query = NULL;
3739 		query = gst_query_new_seeking (GST_FORMAT_TIME);
3740 		if (gst_element_query (stream->volume, query)) {
3741 			gst_query_parse_seeking (query, NULL, &can_seek, NULL, NULL);
3742 		} else {
3743 			gst_query_unref (query);
3744 
3745 			query = gst_query_new_duration (GST_FORMAT_TIME);
3746 			can_seek = gst_element_query (stream->volume, query);
3747 		}
3748 		gst_query_unref (query);
3749 		g_object_unref (stream);
3750 	}
3751 
3752 	return can_seek;
3753 }
3754 
3755 static void
3756 rb_player_gst_xfade_set_time (RBPlayer *iplayer, gint64 time)
3757 {
3758 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3759 	RBXFadeStream *stream;
3760 
3761 	g_rec_mutex_lock (&player->priv->stream_list_lock);
3762 	stream = find_stream_by_state (player, FADING_IN | PLAYING | PAUSED | FADING_OUT_PAUSED | PENDING_REMOVE);
3763 	g_rec_mutex_unlock (&player->priv->stream_list_lock);
3764 
3765 	if (stream == NULL) {
3766 		rb_debug ("got seek while no playing streams exist");
3767 		return;
3768 	}
3769 
3770 	stream->seek_target = time;
3771 	switch (stream->state) {
3772 	case PAUSED:
3773 		rb_debug ("seeking in paused stream %s; target %" 
3774 		    G_GINT64_FORMAT, stream->uri, stream->seek_target);
3775 		perform_seek (stream);
3776 		break;
3777 
3778 	case FADING_OUT_PAUSED:
3779 		/* don't unblock and relink when the seek is done */
3780 		stream->state = SEEKING_PAUSED;
3781 		rb_debug ("seeking in pausing stream %s; target %"
3782 			  G_GINT64_FORMAT, stream->uri, stream->seek_target);
3783 		unlink_and_block_stream (stream);
3784 		break;
3785 
3786 	case FADING_IN:
3787 	case PLAYING:
3788 		stream->state = SEEKING;
3789 		rb_debug ("seeking in playing stream %s; target %"
3790 			  G_GINT64_FORMAT, stream->uri, stream->seek_target);
3791 		perform_seek (stream);
3792 		break;
3793 
3794 	case PENDING_REMOVE:
3795 		/* this should only happen when the stream has ended,
3796 		 * which means we can't wait for the src pad to be blocked
3797 		 * before we seek.  we unlink the stream when it reaches EOS,
3798 		 * so now we just perform the seek and relink.
3799 		 */
3800 		rb_debug ("seeking in EOS stream %s; target %"
3801 			  G_GINT64_FORMAT, stream->uri, stream->seek_target);
3802 		stream->state = SEEKING_EOS;
3803 		gst_pad_set_blocked_async (stream->src_pad,
3804 					   TRUE,
3805 					   (GstPadBlockCallback) post_eos_seek_blocked_cb,
3806 					   stream);
3807 		perform_seek (stream);
3808 		break;
3809 	default:
3810 		g_assert_not_reached ();
3811 	}
3812 
3813 	g_object_unref (stream);
3814 }
3815 
3816 static gint64
3817 rb_player_gst_xfade_get_time (RBPlayer *iplayer)
3818 {
3819 	gint64 pos = -1;
3820 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3821 
3822 	get_times_and_stream (player, NULL, &pos, NULL);
3823 	return pos;
3824 }
3825 
3826 static gboolean
3827 need_pad_block (RBPlayerGstXFade *player)
3828 {
3829 	return (player->priv->sink_state == SINK_PLAYING);
3830 }
3831 
3832 static gboolean
3833 rb_player_gst_xfade_add_tee (RBPlayerGstTee *iplayer, GstElement *element)
3834 {
3835 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3836 	if (player->priv->tee == NULL) {
3837 		player->priv->waiting_tees = g_list_prepend (player->priv->waiting_tees, element);
3838 		return TRUE;
3839 	}
3840 
3841 	return rb_gst_add_tee (RB_PLAYER (player), player->priv->tee, element, need_pad_block (player));
3842 }
3843 
3844 static gboolean
3845 rb_player_gst_xfade_remove_tee (RBPlayerGstTee *iplayer, GstElement *element)
3846 {
3847 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3848 	if (player->priv->tee == NULL) {
3849 		gst_object_sink (element);
3850 		player->priv->waiting_tees = g_list_remove (player->priv->waiting_tees, element);
3851 		return TRUE;
3852 	}
3853 
3854 	return rb_gst_remove_tee (RB_PLAYER (player), player->priv->tee, element, need_pad_block (player));
3855 }
3856 
3857 
3858 static gboolean
3859 rb_player_gst_xfade_add_filter (RBPlayerGstFilter *iplayer, GstElement *element)
3860 {
3861 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3862 	if (player->priv->filterbin == NULL) {
3863 		player->priv->waiting_filters = g_list_prepend (player->priv->waiting_filters, element);
3864 		return TRUE;
3865 	}
3866 
3867 	return rb_gst_add_filter (RB_PLAYER (player), player->priv->filterbin, element, need_pad_block (player));
3868 }
3869 
3870 
3871 static gboolean
3872 rb_player_gst_xfade_remove_filter (RBPlayerGstFilter *iplayer, GstElement *element)
3873 {
3874 	RBPlayerGstXFade *player = RB_PLAYER_GST_XFADE (iplayer);
3875 	if (player->priv->filterbin == NULL) {
3876 		gst_object_sink (element);
3877 		player->priv->waiting_filters = g_list_remove (player->priv->waiting_filters, element);
3878 		return TRUE;
3879 	}
3880 
3881 	return rb_gst_remove_filter (RB_PLAYER (player), player->priv->filterbin, element, need_pad_block (player));
3882 }