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 }