68
68
static void xmms_playlist_update_queue (xmms_playlist_t *playlist, const gchar *plname, xmmsc_coll_t *coll);
69
69
static void xmms_playlist_update_partyshuffle (xmms_playlist_t *playlist, const gchar *plname, xmmsc_coll_t *coll);
71
static void xmms_playlist_current_pos_msg_send (xmms_playlist_t *playlist, GTree *dict);
72
static GTree * xmms_playlist_current_pos_msg_new (xmms_playlist_t *playlist, guint32 pos, const gchar *plname);
72
74
XMMS_CMD_DEFINE (load, xmms_playlist_load, xmms_playlist_t *, NONE, STRING, NONE);
73
75
XMMS_CMD_DEFINE3 (insert_url, xmms_playlist_insert_url, xmms_playlist_t *, NONE, STRING, UINT32, STRING);
78
80
XMMS_CMD_DEFINE3 (move, xmms_playlist_move, xmms_playlist_t *, NONE, STRING, UINT32, UINT32);
79
81
XMMS_CMD_DEFINE (add_url, xmms_playlist_add_url, xmms_playlist_t *, NONE, STRING, STRING);
80
82
XMMS_CMD_DEFINE (add_id, xmms_playlist_add_id, xmms_playlist_t *, NONE, STRING, UINT32);
83
XMMS_CMD_DEFINE (add_idlist, xmms_playlist_add_idlist, xmms_playlist_t *, NONE, STRING, COLL);
81
84
XMMS_CMD_DEFINE3 (add_coll, xmms_playlist_add_collection, xmms_playlist_t *, NONE, STRING, COLL, STRINGLIST);
82
85
XMMS_CMD_DEFINE (clear, xmms_playlist_clear, xmms_playlist_t *, NONE, STRING, NONE);
83
86
XMMS_CMD_DEFINE (sort, xmms_playlist_sort, xmms_playlist_t *, NONE, STRING, STRINGLIST);
84
87
XMMS_CMD_DEFINE (list_entries, xmms_playlist_list_entries, xmms_playlist_t *, LIST, STRING, NONE);
85
XMMS_CMD_DEFINE (current_pos, xmms_playlist_current_pos, xmms_playlist_t *, UINT32, STRING, NONE);
88
XMMS_CMD_DEFINE (current_pos, xmms_playlist_current_pos, xmms_playlist_t *, DICT, STRING, NONE);
86
89
XMMS_CMD_DEFINE (current_active, xmms_playlist_current_active, xmms_playlist_t *, STRING, NONE, NONE);
87
90
XMMS_CMD_DEFINE (set_pos, xmms_playlist_set_current_position, xmms_playlist_t *, UINT32, UINT32, NONE);
88
91
XMMS_CMD_DEFINE (set_pos_rel, xmms_playlist_set_current_position_rel, xmms_playlist_t *, UINT32, INT32, NONE);
89
92
XMMS_CMD_DEFINE (radd, xmms_playlist_radd, xmms_playlist_t *, NONE, STRING, STRING);
91
94
#define XMMS_PLAYLIST_CHANGED_MSG(type, id, name) xmms_playlist_changed_msg_send (playlist, xmms_playlist_changed_msg_new (playlist, type, id, name))
95
#define XMMS_PLAYLIST_CURRPOS_MSG(pos, name) xmms_playlist_current_pos_msg_send (playlist, xmms_playlist_current_pos_msg_new (playlist, pos, name))
94
98
/** @defgroup Playlist Playlist
434
443
xmmsc_coll_attribute_get (plcoll, "jumplist", &jumplist)) {
436
445
xmms_collection_set_int_attr (plcoll, "position", 0);
437
xmms_object_emit_f (XMMS_OBJECT (playlist),
438
XMMS_IPC_SIGNAL_PLAYLIST_CURRENT_POS,
439
XMMS_OBJECT_CMD_ARG_UINT32,
446
XMMS_PLAYLIST_CURRPOS_MSG (0, XMMS_ACTIVE_PLAYLIST);
442
448
xmms_playlist_load (buffer, jumplist, &err);
443
449
ret = xmms_error_isok (&err);
445
xmms_collection_set_int_attr (plcoll, "position", currpos%size);
446
xmms_object_emit_f (XMMS_OBJECT (playlist),
447
XMMS_IPC_SIGNAL_PLAYLIST_CURRENT_POS,
448
XMMS_OBJECT_CMD_ARG_UINT32,
451
newpos = currpos%size;
452
xmms_collection_set_int_attr (plcoll, "position", newpos);
453
XMMS_PLAYLIST_CURRPOS_MSG (newpos, XMMS_ACTIVE_PLAYLIST);
450
454
ret = (currpos != size) || playlist->repeat_all;
483
487
if (currpos == -1 && (size > 0)) {
485
489
xmms_collection_set_int_attr (plcoll, "position", currpos);
486
xmms_object_emit_f (XMMS_OBJECT (playlist),
487
XMMS_IPC_SIGNAL_PLAYLIST_CURRENT_POS,
488
XMMS_OBJECT_CMD_ARG_UINT32, 0);
490
XMMS_PLAYLIST_CURRPOS_MSG (0, XMMS_ACTIVE_PLAYLIST);
491
493
if (currpos < size) {
570
575
xmms_playlist_load (xmms_playlist_t *playlist, gchar *name, xmms_error_t *err)
572
xmmsc_coll_t *plcoll;
577
xmmsc_coll_t *plcoll, *active_coll;
574
579
if (strcmp (name, XMMS_ACTIVE_PLAYLIST) == 0) {
575
580
xmms_error_set (err, XMMS_ERROR_INVAL, "invalid playlist to load");
584
active_coll = xmms_playlist_get_coll (playlist, XMMS_ACTIVE_PLAYLIST, err);
585
if (active_coll == NULL) {
586
xmms_error_set (err, XMMS_ERROR_GENERIC, "no active playlist");
579
590
plcoll = xmms_playlist_get_coll (playlist, name, err);
580
591
if (plcoll == NULL) {
581
592
xmms_error_set (err, XMMS_ERROR_NOENT, "no such playlist");
596
if (active_coll == plcoll) {
597
XMMS_DBG ("Not loading %s playlist, already active!", name);
585
601
XMMS_DBG ("Loading new playlist! %s", name);
586
602
xmms_collection_update_pointer (playlist->colldag, XMMS_ACTIVE_PLAYLIST,
587
603
XMMS_COLLECTION_NSID_PLAYLISTS, plcoll);
651
667
XMMS_PLAYLIST_CHANGED_MSG (XMMS_PLAYLIST_CHANGED_SHUFFLE, 0, plname);
652
xmms_object_emit_f (XMMS_OBJECT (playlist),
653
XMMS_IPC_SIGNAL_PLAYLIST_CURRENT_POS,
654
XMMS_OBJECT_CMD_ARG_UINT32,
668
XMMS_PLAYLIST_CURRPOS_MSG (currpos, plname);
657
670
g_mutex_unlock (playlist->mutex);
661
674
xmms_playlist_remove_unlocked (xmms_playlist_t *playlist, const gchar *plname,
662
675
xmmsc_coll_t *plcoll, guint pos, xmms_error_t *err)
667
680
g_return_val_if_fail (playlist, FALSE);
669
682
currpos = xmms_playlist_coll_get_currpos (plcoll);
670
size = xmms_playlist_coll_get_size (plcoll);
684
if (!xmmsc_coll_idlist_remove (plcoll, pos)) {
673
685
if (err) xmms_error_set (err, XMMS_ERROR_NOENT, "Entry was not in list!");
677
xmmsc_coll_idlist_remove (plcoll, pos);
678
xmms_collection_set_int_attr (plcoll, "size", size - 1);
680
689
/* decrease currentpos if removed entry was before or if it's
681
690
* the current entry, but only if currentpos is a valid entry.
688
697
dict = xmms_playlist_changed_msg_new (playlist, XMMS_PLAYLIST_CHANGED_REMOVE, 0, plname);
689
g_hash_table_insert (dict, (gpointer) "position",
690
xmms_object_cmd_value_int_new (pos));
698
g_tree_insert (dict, (gpointer) "position",
699
xmms_object_cmd_value_int_new (pos));
691
700
xmms_playlist_changed_msg_send (playlist, dict);
693
xmms_object_emit_f (XMMS_OBJECT (playlist),
694
XMMS_IPC_SIGNAL_PLAYLIST_CURRENT_POS,
695
XMMS_OBJECT_CMD_ARG_UINT32,
702
XMMS_PLAYLIST_CURRPOS_MSG (currpos, plname);
833
839
xmmsc_coll_idlist_get_index (plcoll, newpos, &id);
835
841
dict = xmms_playlist_changed_msg_new (playlist, XMMS_PLAYLIST_CHANGED_MOVE, id, plname);
836
g_hash_table_insert (dict, (gpointer) "position",
837
xmms_object_cmd_value_int_new (pos));
838
g_hash_table_insert (dict, (gpointer) "newposition",
839
xmms_object_cmd_value_int_new (newpos));
842
g_tree_insert (dict, (gpointer) "position",
843
xmms_object_cmd_value_int_new (pos));
844
g_tree_insert (dict, (gpointer) "newposition",
845
xmms_object_cmd_value_int_new (newpos));
840
846
xmms_playlist_changed_msg_send (playlist, dict);
842
xmms_object_emit_f (XMMS_OBJECT (playlist),
843
XMMS_IPC_SIGNAL_PLAYLIST_CURRENT_POS,
844
XMMS_OBJECT_CMD_ARG_UINT32,
848
XMMS_PLAYLIST_CURRPOS_MSG (currpos, plname);
847
850
g_mutex_unlock (playlist->mutex);
922
925
xmmsc_coll_idlist_insert (plcoll, pos, file);
923
xmms_collection_set_int_attr (plcoll, "size", len + 1);
927
/** propagate the MID ! */
928
dict = xmms_playlist_changed_msg_new (playlist, XMMS_PLAYLIST_CHANGED_INSERT, file, plname);
929
g_tree_insert (dict, (gpointer) "position",
930
xmms_object_cmd_value_int_new (pos));
931
xmms_playlist_changed_msg_send (playlist, dict);
933
/** update position once client is familiar with the new item. */
925
934
currpos = xmms_playlist_coll_get_currpos (plcoll);
926
935
if (pos <= currpos) {
927
936
xmms_playlist_set_current_position_do (playlist, currpos + 1, err);
930
/** propagate the MID ! */
931
dict = xmms_playlist_changed_msg_new (playlist, XMMS_PLAYLIST_CHANGED_INSERT, file, plname);
932
g_hash_table_insert (dict, (gpointer) "position",
933
xmms_object_cmd_value_int_new (pos));
934
xmms_playlist_changed_msg_send (playlist, dict);
936
939
g_mutex_unlock (playlist->mutex);
1041
xmms_playlist_add_idlist (xmms_playlist_t *playlist, gchar *plname,
1047
for (idlist = xmmsc_coll_get_idlist (coll); *idlist; idlist++) {
1048
if (!xmms_medialib_check_id (*idlist)) {
1049
xmms_error_set (err, XMMS_ERROR_NOENT,
1050
"Idlist contains invalid medialib id!");
1055
for (idlist = xmmsc_coll_get_idlist (coll); *idlist; idlist++) {
1056
xmms_playlist_add_entry (playlist, plname, *idlist, err);
1039
1063
xmms_playlist_add_collection (xmms_playlist_t *playlist, gchar *plname,
1040
1064
xmmsc_coll_t *coll, GList *order,
1041
1065
xmms_error_t *err)
1090
1113
xmms_error_t *err)
1092
1115
gint prev_size;
1095
1118
prev_size = xmms_playlist_coll_get_size (plcoll);
1096
1119
xmmsc_coll_idlist_append (plcoll, file);
1097
xmms_collection_set_int_attr (plcoll, "size", prev_size + 1);
1099
1121
/** propagate the MID ! */
1100
1122
dict = xmms_playlist_changed_msg_new (playlist, XMMS_PLAYLIST_CHANGED_ADD, file, plname);
1101
g_hash_table_insert (dict, (gpointer) "position",
1102
xmms_object_cmd_value_int_new (prev_size));
1123
g_tree_insert (dict, (gpointer) "position",
1124
xmms_object_cmd_value_int_new (prev_size));
1103
1125
xmms_playlist_changed_msg_send (playlist, dict);
1116
1138
plcoll = xmms_playlist_get_coll (playlist, plname, err);
1117
1139
if (plcoll == NULL) {
1140
g_mutex_unlock (playlist->mutex);
1121
1144
xmmsc_coll_idlist_clear (plcoll);
1122
1145
xmms_collection_set_int_attr (plcoll, "position", -1);
1123
xmms_collection_set_int_attr (plcoll, "size", 0);
1125
1147
XMMS_PLAYLIST_CHANGED_MSG (XMMS_PLAYLIST_CHANGED_CLEAR, 0, plname);
1126
1148
g_mutex_unlock (playlist->mutex);
1158
1180
xmmsc_coll_attribute_get (plcoll, "jumplist", &jumplist)) {
1160
1182
xmms_collection_set_int_attr (plcoll, "position", 0);
1161
xmms_object_emit_f (XMMS_OBJECT (playlist),
1162
XMMS_IPC_SIGNAL_PLAYLIST_CURRENT_POS,
1163
XMMS_OBJECT_CMD_ARG_UINT32,
1183
XMMS_PLAYLIST_CURRPOS_MSG (0, XMMS_ACTIVE_PLAYLIST);
1166
1185
xmms_playlist_load (playlist, jumplist, err);
1167
1186
if (xmms_error_iserror (err)) {
1175
1194
} else if (pos < size) {
1176
1195
XMMS_DBG ("newpos! %d", pos);
1177
1196
xmms_collection_set_int_attr (plcoll, "position", pos);
1179
xmms_object_emit_f (XMMS_OBJECT (playlist),
1180
XMMS_IPC_SIGNAL_PLAYLIST_CURRENT_POS,
1181
XMMS_OBJECT_CMD_ARG_UINT32,
1197
XMMS_PLAYLIST_CURRPOS_MSG (pos, XMMS_ACTIVE_PLAYLIST);
1184
1199
xmms_error_set (err, XMMS_ERROR_INVAL,
1185
1200
"Can't set pos outside the current playlist!");
1222
1237
if (plcoll != NULL) {
1223
1238
currpos = xmms_playlist_coll_get_currpos (plcoll);
1225
if (currpos + pos >= 0)
1226
mid = xmms_playlist_set_current_position_do (playlist, currpos + pos, err);
1240
if (playlist->repeat_all) {
1241
newpos = (pos+currpos) % (gint)xmmsc_coll_idlist_get_size (plcoll);
1244
newpos += xmmsc_coll_idlist_get_size (plcoll);
1247
mid = xmms_playlist_set_current_position_do (playlist, newpos, err);
1249
if (currpos + pos >= 0) {
1250
mid = xmms_playlist_set_current_position_do (playlist,
1254
xmms_error_set (err, XMMS_ERROR_INVAL,
1255
"Can't set pos outside the current playlist!");
1229
1260
g_mutex_unlock (playlist->mutex);
1462
1493
g_list_free (tmp);
1464
1495
XMMS_PLAYLIST_CHANGED_MSG (XMMS_PLAYLIST_CHANGED_SORT, 0, plname);
1466
xmms_object_emit_f (XMMS_OBJECT (playlist),
1467
XMMS_IPC_SIGNAL_PLAYLIST_CURRENT_POS,
1468
XMMS_OBJECT_CMD_ARG_UINT32,
1496
XMMS_PLAYLIST_CURRPOS_MSG (currpos, plname);
1471
1498
g_mutex_unlock (playlist->mutex);
1602
1629
xmms_playlist_coll_get_size (xmmsc_coll_t *plcoll)
1606
/* If absent, compute the size and save it */
1607
if (!xmms_collection_get_int_attr (plcoll, "size", &size)) {
1612
idlist = xmmsc_coll_get_idlist (plcoll);
1613
for (i = 0; idlist[i] != 0; i++) {
1617
xmms_collection_set_int_attr (plcoll, "size", size);
1631
return xmmsc_coll_idlist_get_size (plcoll);
1625
1636
xmms_playlist_changed_msg_new (xmms_playlist_t *playlist,
1626
1637
xmms_playlist_changed_actions_t type,
1627
1638
guint32 id, const gchar *plname)
1630
1641
xmms_object_cmd_value_t *val;
1631
1642
const gchar *tmp;
1633
dict = g_hash_table_new_full (g_str_hash,
1636
xmms_object_cmd_value_free);
1644
dict = g_tree_new_full ((GCompareDataFunc) strcmp, NULL,
1645
NULL, (GDestroyNotify)xmms_object_cmd_value_unref);
1637
1647
val = xmms_object_cmd_value_int_new (type);
1638
g_hash_table_insert (dict, (gpointer) "type", val);
1648
g_tree_insert (dict, (gpointer) "type", val);
1640
1651
val = xmms_object_cmd_value_uint_new (id);
1641
g_hash_table_insert (dict, (gpointer) "id", val);
1652
g_tree_insert (dict, (gpointer) "id", val);
1644
1655
tmp = xmms_playlist_canonical_name (playlist, plname);
1645
1656
val = xmms_object_cmd_value_str_new (tmp);
1646
g_hash_table_insert (dict, (gpointer) "name", val);
1657
g_tree_insert (dict, (gpointer) "name", val);
1663
xmms_playlist_current_pos_msg_new (xmms_playlist_t *playlist,
1664
guint32 pos, const gchar *plname)
1667
xmms_object_cmd_value_t *val;
1670
dict = g_tree_new_full ((GCompareDataFunc) strcmp, NULL,
1671
NULL, (GDestroyNotify)xmms_object_cmd_value_unref);
1673
val = xmms_object_cmd_value_uint_new (pos);
1674
g_tree_insert (dict, (gpointer) "position", val);
1676
tmp = xmms_playlist_canonical_name (playlist, plname);
1677
val = xmms_object_cmd_value_str_new (tmp);
1678
g_tree_insert (dict, (gpointer) "name", val);
1652
xmms_playlist_changed_msg_send (xmms_playlist_t *playlist, GHashTable *dict)
1684
xmms_playlist_changed_msg_send (xmms_playlist_t *playlist, GTree *dict)
1654
1686
xmms_object_cmd_value_t *type_cmd_val;
1655
1687
xmms_object_cmd_value_t *pl_cmd_val;
1658
1690
g_return_if_fail (dict);
1660
1692
/* If local playlist change, trigger a COLL_CHANGED signal */
1661
type_cmd_val = g_hash_table_lookup (dict, "type");
1662
pl_cmd_val = g_hash_table_lookup (dict, "name");
1693
type_cmd_val = g_tree_lookup (dict, "type");
1694
pl_cmd_val = g_tree_lookup (dict, "name");
1663
1695
if (type_cmd_val != NULL &&
1664
1696
type_cmd_val->value.int32 != XMMS_PLAYLIST_CHANGED_UPDATE &&
1665
1697
pl_cmd_val != NULL) {
1672
1704
XMMS_OBJECT_CMD_ARG_DICT,
1675
g_hash_table_destroy (dict);
1707
g_tree_destroy (dict);
1711
xmms_playlist_current_pos_msg_send (xmms_playlist_t *playlist,
1714
g_return_if_fail (playlist);
1716
g_return_if_fail (dict);
1718
xmms_object_emit_f (XMMS_OBJECT (playlist),
1719
XMMS_IPC_SIGNAL_PLAYLIST_CURRENT_POS,
1720
XMMS_OBJECT_CMD_ARG_DICT,
1723
g_tree_destroy (dict);