2 * This file is a part of MAFW
4 * Copyright (C) 2007, 2008, 2009 Nokia Corporation, all rights reserved.
6 * Contact: Visa Smolander <visa.smolander@nokia.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; version 2.1 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 #include "mafw-playlist-iterator.h"
26 #include "mafw-gst-renderer-marshal.h"
29 #define G_LOG_DOMAIN "mafw-gst-renderer-playlist-iterator"
31 struct _MafwPlaylistIteratorPrivate {
32 MafwPlaylist *playlist;
34 gchar *current_objectid;
38 typedef gboolean (*movement_function) (MafwPlaylist *playlist,
48 static guint mafw_playlist_iterator_signals[LAST_SIGNAL];
50 G_DEFINE_TYPE(MafwPlaylistIterator, mafw_playlist_iterator, G_TYPE_OBJECT);
53 mafw_playlist_iterator_dispose(GObject *object)
55 MafwPlaylistIterator *iterator = (MafwPlaylistIterator *) object;
57 g_return_if_fail(MAFW_IS_PLAYLIST_ITERATOR(iterator));
59 mafw_playlist_iterator_invalidate(iterator);
61 G_OBJECT_CLASS(mafw_playlist_iterator_parent_class)->dispose(object);
65 mafw_playlist_iterator_class_init(MafwPlaylistIteratorClass *klass)
67 GObjectClass *gclass = NULL;
69 gclass = G_OBJECT_CLASS(klass);
70 g_return_if_fail(gclass != NULL);
72 g_type_class_add_private(klass, sizeof(MafwPlaylistIteratorPrivate));
74 gclass->dispose = mafw_playlist_iterator_dispose;
76 mafw_playlist_iterator_signals[PLAYLIST_CHANGED] =
77 g_signal_new("playlist-changed",
78 G_TYPE_FROM_CLASS(klass),
80 G_STRUCT_OFFSET(MafwPlaylistIteratorClass, playlist_changed),
83 mafw_gst_renderer_marshal_VOID__BOOLEAN_UINT_INT_STRING,
87 G_TYPE_UINT, G_TYPE_INT, G_TYPE_STRING);
91 mafw_playlist_iterator_init(MafwPlaylistIterator *self)
93 self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
94 MAFW_TYPE_PLAYLIST_ITERATOR,
95 MafwPlaylistIteratorPrivate);
99 mafw_playlist_iterator_set_data(MafwPlaylistIterator *iterator, gint index,
102 g_assert(mafw_playlist_iterator_is_valid(iterator));
104 g_free(iterator->priv->current_objectid);
105 iterator->priv->current_index = index;
106 iterator->priv->current_objectid = objectid;
109 static MafwPlaylistIteratorMovementResult
110 mafw_playlist_iterator_move_to_next_in_direction(MafwPlaylistIterator *iterator,
111 movement_function get_next_in_direction,
115 gchar *objectid = NULL;
116 GError *new_error = NULL;
117 gboolean playlist_movement_result = FALSE;
118 MafwPlaylistIteratorMovementResult iterator_movement_result =
119 MAFW_PLAYLIST_ITERATOR_MOVE_RESULT_OK;
121 g_return_val_if_fail(mafw_playlist_iterator_is_valid(iterator),
122 MAFW_PLAYLIST_ITERATOR_MOVE_RESULT_INVALID);
124 index = iterator->priv->current_index;
126 playlist_movement_result =
127 get_next_in_direction (iterator->priv->playlist,
129 &objectid, &new_error);
131 if (new_error != NULL) {
132 g_propagate_error(error, new_error);
133 iterator_movement_result =
134 MAFW_PLAYLIST_ITERATOR_MOVE_RESULT_ERROR;
135 } else if (playlist_movement_result) {
136 mafw_playlist_iterator_set_data(iterator, index, objectid);
138 iterator_movement_result =
139 MAFW_PLAYLIST_ITERATOR_MOVE_RESULT_LIMIT;
142 return iterator_movement_result;
146 mafw_playlist_iterator_playlist_contents_changed_handler(MafwPlaylist *playlist,
153 gboolean clip_changed = FALSE;
154 GError *error = NULL;
155 MafwPlaylistIterator *iterator = (MafwPlaylistIterator*) user_data;
157 g_return_if_fail(MAFW_IS_PLAYLIST(playlist));
158 g_return_if_fail(MAFW_IS_PLAYLIST_ITERATOR(iterator));
160 if (iterator->priv->playlist == NULL) {
161 g_critical("Got playlist:contents-changed but renderer has no" \
162 "playlist assigned!. Skipping...");
166 play_index = iterator->priv->current_index;
167 iterator->priv->size += nreplace;
170 /* Items have been removed from the playlist */
171 iterator->priv->size -= nremove;
172 if ((play_index >= from) &&
173 (play_index < from + nremove)) {
174 /* The current index has been removed */
176 mafw_playlist_iterator_get_size(iterator,
179 /* Is the current index invalid now? If not,
180 set current item to the last in the playlist,
181 otherwise the keep the index and update the
184 mafw_playlist_iterator_set_data(iterator, -1, NULL);
185 } else if (play_index >= pls_size) {
186 mafw_playlist_iterator_move_to_index(iterator,
190 mafw_playlist_iterator_update(iterator,
196 } else if (from < play_index) {
197 /* The current index has been moved towards
198 the head of the playlist */
199 play_index -= nremove;
200 if (play_index < 0) {
203 mafw_playlist_iterator_move_to_index(iterator,
207 } else if (nremove == 0) {
208 /* Items have been inserted in the playlist */
209 if (play_index == -1) {
210 /* First item has been added to an empty playlist */
211 mafw_playlist_iterator_reset(iterator,
214 } else if (play_index >= from) {
215 /* The current item has been moved towards the
216 tail of the playlist */
217 mafw_playlist_iterator_move_to_index(iterator,
218 play_index + nreplace,
224 g_critical("playlist::contents-changed handler failed "
225 "with \"%s\"", error->message);
226 g_signal_emit(iterator,
227 mafw_playlist_iterator_signals[PLAYLIST_CHANGED],
228 0, FALSE, error->domain, error->code, error->message);
229 g_error_free (error);
231 g_signal_emit(iterator,
232 mafw_playlist_iterator_signals[PLAYLIST_CHANGED],
233 0, clip_changed, 0, 0, NULL);
238 mafw_playlist_iterator_playlist_item_moved_handler(MafwPlaylist *playlist,
243 MafwPlaylistIterator *iterator = (MafwPlaylistIterator *) user_data;
245 GError *error = NULL;
247 g_return_if_fail(MAFW_IS_PLAYLIST(playlist));
248 g_return_if_fail(MAFW_IS_PLAYLIST_ITERATOR(iterator));
250 if (iterator->priv->playlist == NULL) {
251 g_critical("Got playlist:item-moved but renderer has not a " \
252 "playlist assigned! Skipping...");
256 play_index = iterator->priv->current_index;
258 if (play_index == from) {
259 /* So the current item has been moved, let's update the
260 the current index to the new location */
261 mafw_playlist_iterator_move_to_index(iterator, to, &error);
262 } else if (play_index > from && play_index <= to) {
263 /* So we current item has been pushed one position towards
264 the head, let's update the current index */
265 mafw_playlist_iterator_move_to_prev(iterator, &error);
266 } else if (play_index >= to && play_index < from) {
267 /* So we current item has been pushed one position towards
268 the head, let's update the current index */
269 mafw_playlist_iterator_move_to_next(iterator, &error);
273 g_critical("playlist::item-moved handler failed "
274 "with \"%s\"", error->message);
275 g_error_free (error);
279 MafwPlaylistIterator *
280 mafw_playlist_iterator_new(void)
282 MafwPlaylistIterator *iterator = (MafwPlaylistIterator *)
283 g_object_new(MAFW_TYPE_PLAYLIST_ITERATOR, NULL);
285 g_assert(iterator != NULL);
287 iterator->priv->playlist = NULL;
288 iterator->priv->current_index = -1;
289 iterator->priv->current_objectid = NULL;
290 iterator->priv->size = -1;
296 mafw_playlist_iterator_initialize(MafwPlaylistIterator *iterator,
297 MafwPlaylist *playlist, GError **error)
301 gchar *objectid = NULL;
302 GError *new_error = NULL;
304 g_return_if_fail(MAFW_IS_PLAYLIST_ITERATOR(iterator));
305 g_return_if_fail(iterator->priv->playlist == NULL);
307 iterator->priv->size = -1;
309 mafw_playlist_get_starting_index(playlist, (guint *) &index, &objectid,
312 if (new_error == NULL) {
313 size = mafw_playlist_get_size(playlist, &new_error);
316 if (new_error == NULL) {
317 iterator->priv->playlist = g_object_ref(playlist);
318 iterator->priv->current_index = index;
319 iterator->priv->current_objectid = objectid;
320 iterator->priv->size = size;
322 g_signal_connect(playlist,
324 G_CALLBACK(mafw_playlist_iterator_playlist_item_moved_handler),
326 g_signal_connect(playlist,
328 G_CALLBACK(mafw_playlist_iterator_playlist_contents_changed_handler),
332 g_propagate_error (error, new_error);
337 mafw_playlist_iterator_invalidate(MafwPlaylistIterator *iterator)
339 g_return_if_fail(MAFW_IS_PLAYLIST_ITERATOR(iterator));
341 if (iterator->priv->playlist != NULL) {
342 g_signal_handlers_disconnect_matched(iterator->priv->playlist,
343 (GSignalMatchType) G_SIGNAL_MATCH_FUNC,
345 mafw_playlist_iterator_playlist_item_moved_handler,
348 g_signal_handlers_disconnect_matched(iterator->priv->playlist,
349 (GSignalMatchType) G_SIGNAL_MATCH_FUNC,
351 mafw_playlist_iterator_playlist_contents_changed_handler,
354 g_object_unref(iterator->priv->playlist);
355 g_free(iterator->priv->current_objectid);
356 iterator->priv->playlist = NULL;
357 iterator->priv->current_index = -1;
358 iterator->priv->current_objectid = NULL;
359 iterator->priv->size = -1;
364 mafw_playlist_iterator_is_valid(MafwPlaylistIterator *iterator)
366 g_return_val_if_fail(MAFW_IS_PLAYLIST_ITERATOR(iterator), FALSE);
368 return iterator->priv->playlist != NULL;
372 mafw_playlist_iterator_reset(MafwPlaylistIterator *iterator, GError **error)
375 gchar *objectid = NULL;
376 GError *new_error = NULL;
378 g_return_if_fail(mafw_playlist_iterator_is_valid(iterator));
380 mafw_playlist_get_starting_index(iterator->priv->playlist,
382 &objectid, &new_error);
384 if (new_error == NULL) {
385 mafw_playlist_iterator_set_data(iterator, index, objectid);
388 g_propagate_error (error, new_error);
393 mafw_playlist_iterator_move_to_last(MafwPlaylistIterator *iterator,
396 GError *new_error = NULL;
398 gchar *objectid = NULL;
400 g_return_if_fail(mafw_playlist_iterator_is_valid(iterator));
402 mafw_playlist_get_last_index(iterator->priv->playlist,
404 &objectid, &new_error);
406 if (new_error == NULL) {
407 mafw_playlist_iterator_set_data(iterator, index, objectid);
410 g_propagate_error (error, new_error);
414 MafwPlaylistIteratorMovementResult
415 mafw_playlist_iterator_move_to_next(MafwPlaylistIterator *iterator,
418 return mafw_playlist_iterator_move_to_next_in_direction(iterator,
419 mafw_playlist_get_next,
423 MafwPlaylistIteratorMovementResult
424 mafw_playlist_iterator_move_to_prev(MafwPlaylistIterator *iterator,
427 return mafw_playlist_iterator_move_to_next_in_direction(iterator,
428 mafw_playlist_get_prev,
432 MafwPlaylistIteratorMovementResult
433 mafw_playlist_iterator_move_to_index(MafwPlaylistIterator *iterator,
437 GError *new_error = NULL;
438 MafwPlaylistIteratorMovementResult iterator_movement_result =
439 MAFW_PLAYLIST_ITERATOR_MOVE_RESULT_OK;
442 g_return_val_if_fail(mafw_playlist_iterator_is_valid(iterator),
443 MAFW_PLAYLIST_ITERATOR_MOVE_RESULT_INVALID);
445 playlist_size = mafw_playlist_iterator_get_size(iterator, &new_error);
447 if (new_error != NULL) {
448 g_propagate_error(error, new_error);
449 iterator_movement_result =
450 MAFW_PLAYLIST_ITERATOR_MOVE_RESULT_ERROR;
451 } else if ((index < 0) || (index >= playlist_size)) {
452 iterator_movement_result =
453 MAFW_PLAYLIST_ITERATOR_MOVE_RESULT_LIMIT;
456 mafw_playlist_get_item(iterator->priv->playlist,
460 if (new_error != NULL) {
461 g_propagate_error(error, new_error);
462 iterator_movement_result =
463 MAFW_PLAYLIST_ITERATOR_MOVE_RESULT_ERROR;
465 mafw_playlist_iterator_set_data(iterator, index, objectid);
469 return iterator_movement_result;
473 mafw_playlist_iterator_update(MafwPlaylistIterator *iterator, GError **error)
475 GError *new_error = NULL;
476 gchar *objectid = NULL;
479 mafw_playlist_get_item(iterator->priv->playlist,
480 iterator->priv->current_index,
483 if (new_error != NULL) {
484 g_propagate_error(error, new_error);
486 mafw_playlist_iterator_set_data(iterator,
487 iterator->priv->current_index,
493 mafw_playlist_iterator_get_current_objectid(MafwPlaylistIterator *iterator)
495 g_return_val_if_fail(mafw_playlist_iterator_is_valid(iterator), NULL);
497 return iterator->priv->current_objectid;
501 mafw_playlist_iterator_get_current_index(MafwPlaylistIterator *iterator)
503 g_return_val_if_fail(mafw_playlist_iterator_is_valid(iterator), 0);
505 return iterator->priv->current_index;
509 mafw_playlist_iterator_get_size(MafwPlaylistIterator *iterator,
512 g_return_val_if_fail(mafw_playlist_iterator_is_valid(iterator), -1);
514 if (iterator->priv->size == -1) {
515 iterator->priv->size =
516 mafw_playlist_get_size(iterator->priv->playlist,
520 return iterator->priv->size;