47
49
static void rb_random_play_order_go_previous (RBPlayOrder* porder);
49
51
static void rb_random_db_changed (RBPlayOrder *porder, RhythmDB *db);
50
static void rb_random_playing_entry_changed (RBPlayOrder *porder, RhythmDBEntry *entry);
51
static void rb_random_entry_view_changed (RBPlayOrder *porder);
52
static void rb_random_playing_entry_changed (RBPlayOrder *porder,
53
RhythmDBEntry *old_entry,
54
RhythmDBEntry *new_entry);
55
static void rb_random_query_model_changed (RBPlayOrder *porder);
52
56
static void rb_random_db_entry_deleted (RBPlayOrder *porder, RhythmDBEntry *entry);
54
static void rb_random_handle_entry_view_changed (RBRandomPlayOrder *rorder);
55
static void rb_random_filter_history (RBRandomPlayOrder *rorder, RBEntryView *entry_view);
58
static void rb_random_handle_query_model_changed (RBRandomPlayOrder *rorder);
59
static void rb_random_filter_history (RBRandomPlayOrder *rorder, RhythmDBQueryModel *model);
57
61
struct RBRandomPlayOrderPrivate
62
66
* over the real one when go_{next,previous} are called. */
63
67
RBHistory *tentative_history;
65
gboolean entry_view_changed;
69
gboolean query_model_changed;
68
static RBPlayOrderClass *parent_class = NULL;
71
rb_random_play_order_get_type (void)
73
static GType rb_random_play_order_type = 0;
75
if (rb_random_play_order_type == 0)
77
static const GTypeInfo our_info =
79
sizeof (RBRandomPlayOrderClass),
82
(GClassInitFunc) rb_random_play_order_class_init,
85
sizeof (RBRandomPlayOrder),
87
(GInstanceInitFunc) rb_random_play_order_init
90
rb_random_play_order_type = g_type_register_static (RB_TYPE_PLAY_ORDER,
95
return rb_random_play_order_type;
72
G_DEFINE_TYPE (RBRandomPlayOrder, rb_random_play_order, RB_TYPE_PLAY_ORDER)
73
#define RB_RANDOM_PLAY_ORDER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_RANDOM_PLAY_ORDER, RBRandomPlayOrderPrivate))
99
77
rb_random_play_order_class_init (RBRandomPlayOrderClass *klass)
101
79
GObjectClass *object_class = G_OBJECT_CLASS (klass);
102
80
RBPlayOrderClass *porder;
104
parent_class = g_type_class_peek_parent (klass);
106
82
object_class->finalize = rb_random_play_order_finalize;
109
84
porder = RB_PLAY_ORDER_CLASS (klass);
110
85
porder->db_changed = rb_random_db_changed;
111
86
porder->playing_entry_changed = rb_random_playing_entry_changed;
112
porder->entry_added = (void (*)(RBPlayOrder*,RhythmDBEntry*))rb_random_entry_view_changed;
113
porder->entry_removed = (void (*)(RBPlayOrder*,RhythmDBEntry*))rb_random_entry_view_changed;
114
porder->entries_replaced = rb_random_entry_view_changed;
87
porder->entry_added = (void (*)(RBPlayOrder*,RhythmDBEntry*))rb_random_query_model_changed;
88
porder->entry_removed = (void (*)(RBPlayOrder*,RhythmDBEntry*))rb_random_query_model_changed;
89
porder->query_model_changed = rb_random_query_model_changed;
115
90
porder->db_entry_deleted = rb_random_db_entry_deleted;
117
92
porder->get_next = rb_random_play_order_get_next;
118
93
porder->go_next = rb_random_play_order_go_next;
119
94
porder->get_previous = rb_random_play_order_get_previous;
120
95
porder->go_previous = rb_random_play_order_go_previous;
97
g_type_class_add_private (klass, sizeof (RBRandomPlayOrderPrivate));
124
101
rb_random_play_order_init (RBRandomPlayOrder *rorder)
126
rorder->priv = g_new0 (RBRandomPlayOrderPrivate, 1);
103
rorder->priv = RB_RANDOM_PLAY_ORDER_GET_PRIVATE (rorder);
128
105
rorder->priv->history = rb_history_new (TRUE,
129
106
(GFunc) rb_play_order_unref_entry_swapped,
130
107
rb_play_order_get_db (RB_PLAY_ORDER (rorder)));
131
108
rb_history_set_maximum_size (rorder->priv->history, 50);
133
rorder->priv->entry_view_changed = TRUE;
110
rorder->priv->query_model_changed = TRUE;
179
get_entry_view_contents (RBRandomPlayOrder *rorder, RBEntryView *entry_view)
155
get_query_model_contents (RBRandomPlayOrder *rorder, RhythmDBQueryModel *model)
181
157
guint num_entries;
161
double cumulative_weight = 0.0;
185
163
GArray *result = g_array_new (FALSE, FALSE, sizeof (EntryWeight));
187
if (entry_view == NULL)
190
num_entries = rb_entry_view_get_num_entries (entry_view);
168
num_entries = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), NULL);
191
169
if (num_entries == 0)
194
172
g_array_set_size (result, num_entries);
195
g_object_get (G_OBJECT (entry_view),
199
g_array_index (result, EntryWeight, 0).entry = rb_entry_view_get_first_entry (entry_view);
200
g_array_index (result, EntryWeight, 0).weight
201
= rb_random_play_order_get_entry_weight (rorder, db, g_array_index (result, EntryWeight, 0).entry);
202
for (i=1; i<num_entries; ++i) {
203
g_array_index (result, EntryWeight, i).entry
204
= rb_entry_view_get_next_from_entry (entry_view, g_array_index (result, EntryWeight, i-1).entry);
205
g_array_index (result, EntryWeight, i).weight
206
= rb_random_play_order_get_entry_weight (rorder, db, g_array_index (result, EntryWeight, i).entry);
211
for (i=0; i < num_entries; ++i) {
212
g_array_index (result, EntryWeight, i).cumulative_weight = total_weight;
213
total_weight += g_array_index (result, EntryWeight, i).weight;
173
db = rb_play_order_get_db (RB_PLAY_ORDER (rorder));
175
if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter))
180
RhythmDBEntry *entry = rhythmdb_query_model_iter_to_entry (model, &iter);
183
weight = rb_random_play_order_get_entry_weight (rorder, db, entry);
185
g_array_index (result, EntryWeight, i).entry = entry;
186
g_array_index (result, EntryWeight, i).weight = weight;
187
g_array_index (result, EntryWeight, i).cumulative_weight = cumulative_weight;
188
cumulative_weight += weight;
190
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter));
220
rb_random_handle_entry_view_changed (RBRandomPlayOrder *rorder)
196
rb_random_handle_query_model_changed (RBRandomPlayOrder *rorder)
222
if (rorder->priv->entry_view_changed) {
223
RBEntryView *entry_view;
224
entry_view = rb_play_order_get_entry_view (RB_PLAY_ORDER (rorder));
226
rb_random_filter_history (rorder, entry_view);
228
rorder->priv->entry_view_changed = FALSE;
198
RhythmDBQueryModel *model;
200
if (!rorder->priv->query_model_changed)
203
model = rb_play_order_get_query_model (RB_PLAY_ORDER (rorder));
204
rb_random_filter_history (rorder, model);
205
rorder->priv->query_model_changed = FALSE;
233
rb_random_filter_history (RBRandomPlayOrder *rorder, RBEntryView *entry_view)
209
rb_random_filter_history (RBRandomPlayOrder *rorder, RhythmDBQueryModel *model)
235
211
GPtrArray *history_contents;
242
218
history_contents = rb_history_dump (rorder->priv->history);
243
219
for (i=0; i < history_contents->len; ++i) {
244
if (!entry_view || !rb_entry_view_get_entry_contained (entry_view, g_ptr_array_index (history_contents, i))) {
220
gboolean remove = TRUE;
223
if (rhythmdb_query_model_entry_to_iter (model, g_ptr_array_index (history_contents, i), &iter))
245
228
if (!rorder->priv->tentative_history)
246
229
rorder->priv->tentative_history
247
230
= rb_history_clone (rorder->priv->history,
248
231
(GFunc) rb_play_order_ref_entry_swapped,
249
232
rb_play_order_get_db (RB_PLAY_ORDER (rorder)));
250
rb_history_remove_entry (rorder->priv->tentative_history, g_ptr_array_index (history_contents, i));
233
rb_history_remove_entry (rorder->priv->tentative_history,
234
g_ptr_array_index (history_contents, i));
331
315
RBRandomPlayOrder *rorder;
332
316
RhythmDBEntry *entry;
334
319
g_return_val_if_fail (porder != NULL, NULL);
335
320
g_return_val_if_fail (RB_IS_RANDOM_PLAY_ORDER (porder), NULL);
337
322
rorder = RB_RANDOM_PLAY_ORDER (porder);
339
rb_random_handle_entry_view_changed (rorder);
324
rb_random_handle_query_model_changed (rorder);
325
history = get_history (rorder);
341
if (rb_history_current (get_history (rorder)) == NULL
342
|| (rb_play_order_get_playing_entry (porder) == rb_history_current (get_history (rorder))
343
&& rb_history_current (get_history (rorder)) == rb_history_last (get_history (rorder)))) {
327
entry = rb_play_order_get_playing_entry (porder);
328
if (rb_history_current (history) == NULL
329
|| (entry == rb_history_current (history)
330
&& rb_history_current (history) == rb_history_last (history))) {
345
332
rb_debug ("choosing random entry");
346
333
entry = rb_random_play_order_pick_entry (rorder);
335
rhythmdb_entry_ref (rb_play_order_get_db (porder), entry);
336
rb_history_append (history, entry);
348
339
rb_debug ("choosing enqueued entry");
349
if (rb_play_order_get_playing_entry (porder) == rb_history_current (get_history (rorder)))
350
entry = rb_history_next (get_history (rorder));
340
if (entry == rb_history_current (history))
341
entry = rb_history_next (history);
352
entry = rb_history_current (get_history (rorder));
343
entry = rb_history_current (history);
359
350
rb_random_play_order_go_next (RBPlayOrder* porder)
361
352
RBRandomPlayOrder *rorder;
353
RhythmDBEntry *entry;
363
356
g_return_if_fail (porder != NULL);
364
357
g_return_if_fail (RB_IS_RANDOM_PLAY_ORDER (porder));
366
359
rorder = RB_RANDOM_PLAY_ORDER (porder);
368
if (rb_play_order_get_playing_entry (porder) == rb_history_current (get_history (rorder)))
369
rb_history_go_next (get_history (rorder));
371
/* Leave the current entry current */
360
history = get_history (rorder);
362
g_object_get (G_OBJECT (rorder), "playing-entry", &entry, NULL);
363
g_assert (entry == NULL || entry == rb_history_current (history));
364
if (entry == rb_history_current (history))
365
rb_history_go_next (history);
366
rb_play_order_set_playing_entry (porder, rb_history_current (history));
375
369
static RhythmDBEntry*
380
374
g_return_val_if_fail (porder != NULL, NULL);
381
375
g_return_val_if_fail (RB_IS_RANDOM_PLAY_ORDER (porder), NULL);
382
/* It doesn't make sense to call get_previous when the player is stopped */
383
g_return_val_if_fail (rb_play_order_player_is_playing (porder), NULL);
385
377
rorder = RB_RANDOM_PLAY_ORDER (porder);
387
rb_random_handle_entry_view_changed (rorder);
379
rb_random_handle_query_model_changed (rorder);
389
381
rb_debug ("choosing history entry");
390
382
return rb_history_previous (get_history (rorder));
394
386
rb_random_play_order_go_previous (RBPlayOrder* porder)
396
388
RBRandomPlayOrder *rorder;
398
391
g_return_if_fail (porder != NULL);
399
392
g_return_if_fail (RB_IS_RANDOM_PLAY_ORDER (porder));
400
/* It doesn't make sense to call get_previous when the player is stopped */
393
/* It doesn't make sense to call go_previous when the player is stopped */
401
394
g_return_if_fail (rb_play_order_player_is_playing (porder));
403
396
rorder = RB_RANDOM_PLAY_ORDER (porder);
397
history = get_history (rorder);
405
rb_history_go_previous (get_history (rorder));
399
rb_history_go_previous (history);
400
rb_play_order_set_playing_entry (porder, rb_history_current (history));
428
425
rb_random_commit_history (rorder);
431
if (entry == rb_history_current (get_history (rorder))) {
428
if (new_entry == rb_history_current (get_history (rorder))) {
434
rhythmdb_entry_ref (rb_play_order_get_db (porder), entry);
435
rb_history_set_playing (get_history (rorder), entry);
431
rhythmdb_entry_ref (rb_play_order_get_db (porder), new_entry);
432
rb_history_set_playing (get_history (rorder), new_entry);
441
rb_random_entry_view_changed (RBPlayOrder *porder)
438
rb_random_query_model_changed (RBPlayOrder *porder)
443
440
g_return_if_fail (RB_IS_RANDOM_PLAY_ORDER (porder));
444
RB_RANDOM_PLAY_ORDER (porder)->priv->entry_view_changed = TRUE;
441
RB_RANDOM_PLAY_ORDER (porder)->priv->query_model_changed = TRUE;