hythmbox-2.98/shell/rb-play-order-queue.c

No issues found

  1 /*
  2  *  Copyright (C) 2003 Jeffrey Yasskin <jyasskin@mail.utexas.edu>
  3  *
  4  *  This program is free software; you can redistribute it and/or modify
  5  *  it under the terms of the GNU General Public License as published by
  6  *  the Free Software Foundation; either version 2 of the License, or
  7  *  (at your option) any later version.
  8  *
  9  *  The Rhythmbox authors hereby grant permission for non-GPL compatible
 10  *  GStreamer plugins to be used and distributed together with GStreamer
 11  *  and Rhythmbox. This permission is above and beyond the permissions granted
 12  *  by the GPL license by which Rhythmbox is covered. If you modify this code
 13  *  you may extend this exception to your version of the code, but you are not
 14  *  obligated to do so. If you do not wish to do so, delete this exception
 15  *  statement from your version.
 16  *
 17  *  This program is distributed in the hope that it will be useful,
 18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20  *  GNU General Public License for more details.
 21  *
 22  *  You should have received a copy of the GNU General Public License
 23  *  along with this program; if not, write to the Free Software
 24  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
 25  *
 26  */
 27 
 28 #include "config.h"
 29 
 30 #include "rb-play-order-queue.h"
 31 
 32 #include "rb-debug.h"
 33 
 34 static void rb_queue_play_order_class_init (RBQueuePlayOrderClass *klass);
 35 
 36 static RhythmDBEntry* rb_queue_play_order_get_next (RBPlayOrder* method);
 37 static RhythmDBEntry* rb_queue_play_order_get_previous (RBPlayOrder* method);
 38 static void rb_queue_play_order_go_next (RBPlayOrder* method);
 39 
 40 static void rb_queue_play_order_playing_entry_changed (RBPlayOrder *porder,
 41 						       RhythmDBEntry *old_entry,
 42 						       RhythmDBEntry *new_entry);
 43 static void rb_queue_play_order_playing_entry_removed (RBPlayOrder *porder,
 44 						       RhythmDBEntry *entry);
 45 
 46 G_DEFINE_TYPE (RBQueuePlayOrder, rb_queue_play_order, RB_TYPE_PLAY_ORDER)
 47 #define RB_QUEUE_PLAY_ORDER_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), RB_TYPE_QUEUE_PLAY_ORDER, RBQueuePlayOrderPrivate))
 48 
 49 typedef struct _RBQueuePlayOrderPrivate RBQueuePlayOrderPrivate;
 50 
 51 struct _RBQueuePlayOrderPrivate
 52 {
 53 	gboolean playing_entry_removed;
 54 };
 55 
 56 RBPlayOrder *
 57 rb_queue_play_order_new (RBShellPlayer *player)
 58 {
 59 	RBQueuePlayOrder *lorder;
 60 
 61 	lorder = g_object_new (RB_TYPE_QUEUE_PLAY_ORDER,
 62 			       "player", player,
 63 			       NULL);
 64 
 65 	return RB_PLAY_ORDER (lorder);
 66 }
 67 
 68 static void
 69 rb_queue_play_order_class_init (RBQueuePlayOrderClass *klass)
 70 {
 71 	RBPlayOrderClass *porder = RB_PLAY_ORDER_CLASS (klass);
 72 	porder->get_next = rb_queue_play_order_get_next;
 73 	porder->go_next = rb_queue_play_order_go_next;
 74 	porder->get_previous = rb_queue_play_order_get_previous;
 75 	porder->playing_entry_changed = rb_queue_play_order_playing_entry_changed;
 76 	porder->playing_entry_removed = rb_queue_play_order_playing_entry_removed;
 77 
 78 	g_type_class_add_private (klass, sizeof (RBQueuePlayOrderPrivate));
 79 }
 80 
 81 static void
 82 rb_queue_play_order_init (RBQueuePlayOrder *porder)
 83 {
 84 }
 85 
 86 static RhythmDBEntry *
 87 rb_queue_play_order_get_next (RBPlayOrder* porder)
 88 {
 89 	RhythmDBQueryModel *model;
 90 	RhythmDBEntry *entry;
 91 	RhythmDBEntry *first;
 92 	GtkTreeIter iter;
 93 
 94 	g_return_val_if_fail (porder != NULL, NULL);
 95 	g_return_val_if_fail (RB_IS_QUEUE_PLAY_ORDER (porder), NULL);
 96 
 97 	model = rb_play_order_get_query_model (porder);
 98 	if (model == NULL)
 99 		return NULL;
100 
101 	/* the play queue should try to play the earliest entry in the
102 	 * query model that it can.  so there are three possible cases here:
103 	 *
104 	 * - we have no current playing entry, so return the first
105 	 * - the current playing entry is the first, so return the next
106 	 * - the current playing entry is not the first, so return the first
107 	 */
108 
109 	g_object_get (porder, "playing-entry", &entry, NULL);
110 
111 	if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter)) {
112 		first = NULL;
113 	} else {
114 		first = rhythmdb_query_model_iter_to_entry (model, &iter);
115 	}
116 
117 	if (entry == NULL) {
118 		return first;
119 	} else if (entry != first) {
120 		rhythmdb_entry_unref (entry);
121 		return first;
122 	} else {
123 		RhythmDBEntry *next;
124 
125 		next = rhythmdb_query_model_get_next_from_entry (model, entry);
126 		rhythmdb_entry_unref (entry);
127 		rhythmdb_entry_unref (first);
128 		return next;
129 	}
130 }
131 
132 static void
133 rb_queue_play_order_go_next (RBPlayOrder *porder)
134 {
135 	RhythmDBEntry *next;
136 	RhythmDBQueryModel *model;
137 
138 	model = rb_play_order_get_query_model (porder);
139 	if (model == NULL)
140 		return;
141 
142 	next = rb_queue_play_order_get_next (porder);
143 	rb_play_order_set_playing_entry (porder, next);
144 	if (next)
145 		rhythmdb_entry_unref (next);
146 }
147 
148 static RhythmDBEntry*
149 rb_queue_play_order_get_previous (RBPlayOrder *porder)
150 {
151 	RhythmDBQueryModel *model;
152 	RhythmDBEntry *entry, *prev;
153 
154 	g_return_val_if_fail (porder != NULL, NULL);
155 	g_return_val_if_fail (RB_IS_QUEUE_PLAY_ORDER (porder), NULL);
156 
157 	model = rb_play_order_get_query_model (porder);
158 	if (model == NULL)
159 		return NULL;
160 
161 	g_object_get (porder, "playing-entry", &entry, NULL);
162 	if (entry == NULL)
163 		return NULL;
164 	prev = rhythmdb_query_model_get_previous_from_entry (model, entry);
165 	return prev;
166 }
167 
168 static void
169 rb_queue_play_order_playing_entry_changed (RBPlayOrder *porder,
170 					   RhythmDBEntry *old_entry,
171 					   RhythmDBEntry *new_entry)
172 {
173 	RhythmDBQueryModel *model = rb_play_order_get_query_model (porder);
174 	RBQueuePlayOrderPrivate *priv = RB_QUEUE_PLAY_ORDER_GET_PRIVATE (porder);
175 	if (model == NULL)
176 		return;
177 
178 	if (old_entry && old_entry != new_entry && !priv->playing_entry_removed) {
179 		rhythmdb_query_model_remove_entry (model, old_entry);
180 	}
181 	priv->playing_entry_removed = FALSE;
182 }
183 
184 static void
185 rb_queue_play_order_playing_entry_removed (RBPlayOrder *porder,
186 					   RhythmDBEntry *entry)
187 {
188 	RBQueuePlayOrderPrivate *priv = RB_QUEUE_PLAY_ORDER_GET_PRIVATE (porder);
189 	priv->playing_entry_removed = TRUE;
190 
191 	RB_PLAY_ORDER_CLASS (rb_queue_play_order_parent_class)->playing_entry_removed (porder, entry);
192 }