156
static void up_cb (GtkWidget* widget, gpointer data) {
159
GtkTreeSelection *sel;
161
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
163
if (gtk_tree_selection_get_selected (sel, NULL, &iter)) {
171
path = gtk_tree_model_get_path (GTK_TREE_MODEL (pl_store), &iter);
172
indices = gtk_tree_path_get_indices (path);
174
gtk_tree_path_free (path);
176
logprintf ("playlist: got selection, pos=%d\n", pos);
181
item = playlist_get_item (pos);
183
if (pos == cur_list_pos)
184
--cur_list_pos; /* we're moving the item being played */
185
else if (pos == cur_list_pos + 1)
186
++cur_list_pos; /* we're swapping the item with the one being played */
188
/* FIXME: use gtk_list_store_swap () */
189
marked = item_marked_current (&iter);
190
gtk_list_store_remove (GTK_LIST_STORE (pl_store), &iter);
191
playlist_add (item, --pos);
195
snprintf (str, 20, "%d", pos);
196
path = gtk_tree_path_new_from_string (str);
197
gtk_tree_selection_select_path (sel, path);
198
gtk_tree_path_free (path);
201
logprintf ("playlist: got no selection\n");
204
static void down_cb (GtkWidget* widget, gpointer data) {
207
GtkTreeSelection *sel;
209
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
211
if (gtk_tree_selection_get_selected (sel, NULL, &iter)) {
219
path = gtk_tree_model_get_path (GTK_TREE_MODEL (pl_store), &iter);
220
indices = gtk_tree_path_get_indices (path);
222
gtk_tree_path_free (path);
224
logprintf ("playlist: got selection, pos=%d\n", pos);
226
if (pos>=(playlist_size()-1))
229
item = playlist_get_item (pos);
231
if (pos == cur_list_pos)
232
++cur_list_pos; /* we're moving the item being played */
233
else if (pos == cur_list_pos - 1)
234
--cur_list_pos; /* we're swapping the item with the one being played */
236
/* FIXME: use gtk_list_store_swap () */
237
marked = item_marked_current (&iter);
238
gtk_list_store_remove (GTK_LIST_STORE (pl_store), &iter);
239
playlist_add (item, ++pos);
243
snprintf (str, 20, "%d", pos);
244
path = gtk_tree_path_new_from_string (str);
245
gtk_tree_selection_select_path (sel, path);
246
gtk_tree_path_free (path);
249
logprintf ("playlist: got no selection\n");
124
252
static void edit_cb (GtkWidget* widget, gpointer data) {
126
254
GtkTreeView *tree = (GtkTreeView *) data;
492
void playlist_insert (play_item_t *play_item, int pos) {
496
gtk_list_store_insert (pl_store, &iter, pos);
497
gtk_list_store_set (pl_store, &iter, 0, play_item->title,
498
1, play_item->mrl, 2, play_item, -1);
502
static gint playlist_add_int (const char *mrl) {
627
static gint playlist_add_int (const char *mrl, gint ins_pos)
504
629
play_item_t *play_item;
506
play_item = play_item_new (mrl, mrl, 0);
508
return playlist_add (play_item);
631
char *retitle = NULL;
634
/* don't add duplicate items */
636
for (i = 0; i < playlist_size (); ++i)
637
if (!strcmp (playlist_get_item (i)->mrl, mrl))
640
/* find the leafname of the MRL */
641
title = strrchr (mrl, '/');
642
if (title && !title[1]) /* ends in '/' - look for preceding '/' */
644
while (*title == '/')
647
while (*title != '/')
652
/* at this point, title >= mrl - 1, but mrl[-1] is invalid - this is OK
653
* in the case where title == mrl - 1, we use the full MRL as the title
656
if (title >= mrl && title[1])
661
/* URL-decode the leafname */
662
title = retitle = strdup (title + 1);
668
char c[3] = { title[i+1], title[i+2], 0 };
670
retitle[++j] = (char) strtol (c, NULL, 16);
673
retitle[++j] = title[i];
675
/* NUL-terminate, strip trailing / */
676
retitle[j + (retitle[j] != '/')] = 0;
678
/* Strip the extension (if present) */
679
dot = strrchr (retitle, '.');
686
play_item = play_item_new (title, mrl, 0);
689
return playlist_add (play_item, ins_pos);
511
static int playlist_load_ram (const char *mrl) {
692
static int playlist_load_ram (const char *mrl, gint ins_pos) {
512
693
gboolean retval = FALSE;
513
694
char contents[1024], mime_type[256], **lines;
514
695
char *contents_ptr;
515
696
int size, i, first;
516
#if 0 /* FIXME: remove ? */
873
printf("playlist: sorry, asx version %d not implemented yet\n",
1023
printf(_("playlist: sorry, ASX version %d not implemented yet\n"),
877
printf("playlist: no ASX tag\n");
1027
printf(_("playlist: no ASX tag\n"));
884
int playlist_add_mrl (const char *mrl) {
886
/* printf ("playlist_add called >%s<\n", mrl); */
1032
static int playlist_add_playlist_mrl (const char *mrl, gint ins_pos)
1034
const char *extension = strrchr(mrl, '.');
1037
if (!strncasecmp (extension, ".pls", 4))
1038
return playlist_load_pls (mrl, ins_pos);
1040
if (!strncasecmp (extension, ".m3u", 4))
1041
return playlist_load_m3u (mrl, ins_pos);
1043
if (!strcasecmp (extension, ".ra") ||
1044
!strcasecmp (extension, ".rm") ||
1045
!strncasecmp (extension, ".ram", 4) ||
1046
!strncasecmp (extension, ".rpm", 4) ||
1047
!strncasecmp (extension, ".lsc", 4) ||
1048
!strncasecmp (extension, ".pl", 3))
1049
return playlist_load_ram (mrl, ins_pos);
1051
if (!strncasecmp (extension, ".asx", 4))
1052
return playlist_load_asx (mrl, ins_pos);
1054
if (!strncasecmp (extension, ".smi", 4))
1055
return playlist_load_smil (mrl, ins_pos);
1058
return -2; /* not recognised */
1061
static int playlist_add_mrl_internal (const char *mrl, gint ins_pos)
1063
/* Helper function. Call only from playlist_add_mrl(). */
889
1067
* is this mrl in fact a simple filename?
892
1070
if ( !strstr (mrl, ":/") ) {
896
1072
/* is it a playlist file? */
898
extension = strrchr(mrl, '.');
900
if (extension && !strncasecmp (extension, ".pls", 4)) {
902
return playlist_load_pls (mrl);
904
} else if (extension && !strncasecmp (extension, ".m3u", 4)) {
906
return playlist_load_m3u (mrl);
908
} else if (extension && !strncasecmp (extension, ".ra", 4)) {
910
return playlist_load_ram (mrl);
912
} else if (extension && !strncasecmp (extension, ".rm", 4)) {
914
return playlist_load_ram (mrl);
916
} else if (extension && !strncasecmp (extension, ".ram", 4)) {
918
return playlist_load_ram (mrl);
920
} else if (extension && !strncasecmp (extension, ".rpm", 4)) {
922
return playlist_load_ram (mrl);
924
} else if (extension && !strncasecmp (extension, ".lsc", 4)) {
926
return playlist_load_ram (mrl);
928
} else if (extension && !strncasecmp (extension, ".pl", 3)) {
930
return playlist_load_ram (mrl);
932
} else if (extension && !strncasecmp (extension, ".asx", 4)) {
934
return playlist_load_asx (mrl);
936
} else if (extension && !strncasecmp (extension, ".smi", 4)) {
938
return playlist_load_smil (mrl);
940
} else if (!strncmp (mrl, "cdda:", 5)) {
942
return playlist_add_int (strdup(mrl));
944
} else if (mrl[0]!='/') {
1073
ret = playlist_add_playlist_mrl (mrl, ins_pos);
1077
if (!strncasecmp (mrl, "cdda:", 5))
1078
return playlist_add_int (mrl, ins_pos);
946
1082
/* make filename an absolute pathname */
1088
getcwd (buf, sizeof (buf));
954
1090
l1 = strlen(buf);
955
1091
l2 = strlen(mrl);
960
1096
memcpy (&pathname[l1+1], mrl, l2);
961
1097
pathname[l1+l2+1]=0;
963
return playlist_add_int (pathname);
966
return playlist_add_int (strdup(mrl));
969
} else if (!strncasecmp (mrl, "http://", 7)) {
1099
return playlist_add_int (pathname, ins_pos);
1102
return playlist_add_int (mrl, ins_pos);
1105
if (!strncasecmp (mrl, "http://", 7)) {
972
1107
* could still be a pls/asx playlist, but if so we
973
1108
* need to download it first
978
1111
/* is it a playlist file? */
980
extension = strrchr(mrl, '.');
982
if (extension && !strncasecmp (extension, ".pls", 4)) {
984
return playlist_load_pls (mrl);
986
} else if (extension && !strncasecmp (extension, ".m3u", 4)) {
988
return playlist_load_m3u (mrl);
990
} else if (extension && !strncasecmp (extension, ".ra", 4)) {
992
return playlist_load_ram (mrl);
994
} else if (extension && !strncasecmp (extension, ".rm", 4)) {
996
return playlist_load_ram (mrl);
998
} else if (extension && !strncasecmp (extension, ".ram", 4)) {
1000
return playlist_load_ram (mrl);
1002
} else if (extension && !strncasecmp (extension, ".rpm", 4)) {
1004
return playlist_load_ram (mrl);
1006
} else if (extension && !strncasecmp (extension, ".lsc", 4)) {
1008
return playlist_load_ram (mrl);
1010
} else if (extension && !strncasecmp (extension, ".pl", 3)) {
1012
return playlist_load_ram (mrl);
1014
} else if (extension && !strncasecmp (extension, ".asx", 4)) {
1016
return playlist_load_asx (mrl);
1018
} else if (extension && !strncasecmp (extension, ".smi", 4)) {
1020
return playlist_load_smil (mrl);
1023
return playlist_add_int (strdup(mrl));
1025
} else if (!strncasecmp (mrl, "mmshttp://", 10)) {
1028
printf ("playlist: adding regular asx from mmshttp %s\n", mrl);
1031
return playlist_load_asx (&mrl[3]);
1035
printf ("playlist: adding regular mrl %s\n", mrl);
1037
return playlist_add_int (strdup(mrl));
1041
printf ("playlist: help, how did i get here? \n");
1047
static void show_metadata () {
1052
if ( (t=gtk_xine_get_meta_info (GTK_XINE(gtx), XINE_META_INFO_TITLE)) ) {
1055
if ( (a=gtk_xine_get_meta_info (GTK_XINE(gtx), XINE_META_INFO_ARTIST)) ) {
1056
snprintf (title, 2048, "%s (%s) - gxine %s", t, a, VERSION);
1057
infobar_line1 (bar, "%s (%s)", t, a);
1059
snprintf (title, 2048, "%s - gxine %s", t, VERSION);
1060
infobar_line1 (bar, "%s", t);
1063
if (strlen (cur_mrl) > 0) {
1065
char *str = strrchr (cur_mrl, '/');
1068
snprintf (title, 2048, "%s - gxine %s", str+1, VERSION);
1069
infobar_line1 (bar, "%s", str+1);
1071
snprintf (title, 2048, "%s - gxine %s", cur_mrl, VERSION);
1072
infobar_line1 (bar, "%s", cur_mrl);
1075
snprintf (title, 2048, "gxine %s", VERSION);
1076
infobar_line1 (bar, "%s", title);
1079
normalize_to_ascii (title);
1080
gtk_window_set_title (GTK_WINDOW (app), title);
1083
* display some metainfo
1086
if (gtk_xine_get_stream_info (GTK_XINE(gtx), XINE_STREAM_INFO_HAS_AUDIO)
1087
&& gtk_xine_get_meta_info (GTK_XINE(gtx), XINE_META_INFO_VIDEOCODEC)
1088
&& gtk_xine_get_stream_info (GTK_XINE(gtx), XINE_STREAM_INFO_HAS_VIDEO)
1089
&& gtk_xine_get_meta_info (GTK_XINE(gtx), XINE_META_INFO_AUDIOCODEC))
1090
infobar_line2 (bar, "%d kBit/s %s, %dx%d %s, %d kHz %d kBit/s %s",
1091
gtk_xine_get_stream_info (GTK_XINE(gtx), XINE_STREAM_INFO_BITRATE)/1000,
1092
gtk_xine_get_meta_info (GTK_XINE(gtx), XINE_META_INFO_SYSTEMLAYER),
1093
gtk_xine_get_stream_info (GTK_XINE(gtx), XINE_STREAM_INFO_VIDEO_WIDTH),
1094
gtk_xine_get_stream_info (GTK_XINE(gtx), XINE_STREAM_INFO_VIDEO_HEIGHT),
1095
gtk_xine_get_meta_info (GTK_XINE(gtx), XINE_META_INFO_VIDEOCODEC),
1096
gtk_xine_get_stream_info (GTK_XINE(gtx), XINE_STREAM_INFO_AUDIO_SAMPLERATE)/1000,
1097
gtk_xine_get_stream_info (GTK_XINE(gtx), XINE_STREAM_INFO_AUDIO_BITRATE)/1000,
1098
gtk_xine_get_meta_info (GTK_XINE(gtx), XINE_META_INFO_AUDIOCODEC));
1099
else if (gtk_xine_get_stream_info (GTK_XINE(gtx), XINE_STREAM_INFO_HAS_AUDIO)
1100
&& gtk_xine_get_meta_info (GTK_XINE(gtx), XINE_META_INFO_AUDIOCODEC))
1101
infobar_line2 (bar, "%s, %d kHz %d kBit/s %s",
1102
gtk_xine_get_meta_info (GTK_XINE(gtx), XINE_META_INFO_SYSTEMLAYER),
1103
gtk_xine_get_stream_info (GTK_XINE(gtx), XINE_STREAM_INFO_AUDIO_SAMPLERATE)/1000,
1104
gtk_xine_get_stream_info (GTK_XINE(gtx), XINE_STREAM_INFO_AUDIO_BITRATE)/1000,
1105
gtk_xine_get_meta_info (GTK_XINE(gtx), XINE_META_INFO_AUDIOCODEC));
1106
else if (gtk_xine_get_stream_info (GTK_XINE(gtx), XINE_STREAM_INFO_HAS_VIDEO)
1107
&& gtk_xine_get_meta_info (GTK_XINE(gtx), XINE_META_INFO_VIDEOCODEC))
1108
infobar_line2 (bar, "%s, %dx%d %s",
1109
gtk_xine_get_meta_info (GTK_XINE(gtx), XINE_META_INFO_SYSTEMLAYER),
1110
gtk_xine_get_stream_info (GTK_XINE(gtx), XINE_STREAM_INFO_VIDEO_WIDTH),
1111
gtk_xine_get_stream_info (GTK_XINE(gtx), XINE_STREAM_INFO_VIDEO_HEIGHT),
1112
gtk_xine_get_meta_info (GTK_XINE(gtx), XINE_META_INFO_VIDEOCODEC));
1116
static void *play_exec (void *queue_gen) {
1118
pthread_mutex_lock (&engine_lock);
1120
gdk_threads_enter();
1121
infobar_line1 (bar, "opening...");
1122
infobar_line2 (bar, "");
1123
gdk_threads_leave();
1125
if (!gtk_xine_open (GTK_XINE(gtx), cur_mrl)) {
1127
gdk_threads_enter();
1128
switch (gtk_xine_get_error (GTK_XINE (gtx))) {
1129
case XINE_ERROR_NO_INPUT_PLUGIN:
1131
display_error ("xine engine error",
1132
"xine engine failed to start.\n\n"
1133
"No input plugin found.\n"
1134
"Maybe the file does not exist, has wrong "
1135
"permissions or\nurl syntax error");
1138
case XINE_ERROR_NO_DEMUX_PLUGIN:
1140
display_error ("xine engine error",
1141
"xine engine failed to start.\n\n"
1142
"No demuxer found - stream format not recognized");
1147
display_error ("xine engine error",
1148
"xine engine failed to start.\n\n"
1152
infobar_line1 (bar, "gxine %s", VERSION);
1153
infobar_line2 (bar, "");
1155
gdk_threads_leave();
1157
pthread_mutex_unlock (&engine_lock);
1158
pthread_exit (NULL);
1163
gdk_threads_enter();
1166
sprintf (title, "gxine %s", VERSION);
1167
infobar_line1 (bar, title);
1168
infobar_line2 (bar, "");
1169
gtk_window_set_title (GTK_WINDOW (app), title);
1172
gdk_threads_leave();
1174
gtk_xine_play (GTK_XINE(gtx), goto_pos, goto_time);
1178
pthread_mutex_unlock (&engine_lock);
1180
pthread_exit (NULL);
1185
void playlist_play_from (int list_pos, int pos, int pos_time) {
1190
play_item_t *play_item;
1198
play_item = playlist_get_item (list_pos);
1206
cur_mrl = play_item->mrl;
1208
goto_time = pos_time;
1210
snprintf (indices, 10, "%d", list_pos);
1211
path = gtk_tree_path_new_from_string (indices);
1212
gtk_tree_view_set_cursor (GTK_TREE_VIEW (tree_view),
1214
gtk_tree_path_free (path);
1216
cur_list_pos = list_pos;
1219
* execute any optional commands which may be associated with this play item
1220
* (e.g. set volume etc.)
1223
option = play_item->options;
1227
char *cmd = (char *) option->data;
1229
action_exec (cmd, NULL, NULL);
1231
option = g_list_next (option);
1235
* start seperate thread, so xine_open will not block ui
1238
if ((err = pthread_create (&play_thread,
1239
NULL, play_exec, NULL)) != 0) {
1240
printf ("playlist: can't create new thread (%s)\n",
1245
pthread_detach (play_thread);
1112
ret = playlist_add_playlist_mrl (mrl, ins_pos);
1116
return playlist_add_int (mrl, ins_pos);
1119
if (!strncasecmp (mrl, "mmshttp://", 10)) {
1120
logprintf ("playlist: adding regular ASX from mmshttp %s\n", mrl);
1121
return playlist_load_asx (&mrl[3], ins_pos);
1124
logprintf ("playlist: adding regular mrl %s\n", mrl);
1125
return playlist_add_int (mrl, ins_pos);
1128
int playlist_add_mrl (const char *mrl, gint ins_pos /* -1 => append */)
1130
static GSList *queued = NULL;
1133
/* printf ("playlist_add called >%s<\n", mrl); */
1135
/* handle recursive playlists */
1136
if (g_slist_find_custom (queued, mrl, (GCompareFunc) strcmp))
1138
printf (_("recursion in playlist: %s\n"), mrl);
1142
queued = g_slist_prepend (queued, (char *)mrl);
1143
ret = playlist_add_mrl_internal (mrl, ins_pos);
1144
queued = g_slist_remove (queued, mrl);
1248
1149
void playlist_play (int list_pos) {
1452
1356
item = play_item_new (ref->mrl, ref->mrl, 0);
1454
playlist_insert (item, playlist_get_list_pos()+1);
1358
playlist_add (item, playlist_get_list_pos()+1);
1458
1362
case XINE_EVENT_UI_MESSAGE:
1460
1364
xine_ui_message_data_t *data = (xine_ui_message_data_t *) event->data;
1365
void (*msg)(const gchar *, const gchar *, ...);
1462
1367
gdk_threads_enter();
1464
/* TODO: use all parameters, provide customized messages, hints... */
1372
puts ("xine_event_cb: unknown XINE_MSG_*");
1373
case XINE_MSG_AUDIO_OUT_UNAVAILABLE:
1374
case XINE_MSG_ENCRYPTED_SOURCE:
1378
case XINE_MSG_GENERAL_WARNING:
1379
case XINE_MSG_NETWORK_UNREACHABLE:
1380
case XINE_MSG_UNKNOWN_HOST:
1381
msg = display_warning;
1384
case XINE_MSG_READ_ERROR:
1385
case XINE_MSG_LIBRARY_LOAD_ERROR:
1387
case XINE_MSG_CONNECTION_REFUSED:
1388
case XINE_MSG_FILE_NOT_FOUND:
1389
case XINE_MSG_PERMISSION_ERROR:
1390
case XINE_MSG_SECURITY:
1391
case XINE_MSG_UNKNOWN_DEVICE:
1392
msg = display_error;
1396
/* TODO: provide customized messages, hints... */
1465
1397
if (data->num_parameters) {
1469
param = data->messages + strlen (data->messages) +1;
1471
display_info ("xine engine message", "%s %s",
1472
data->messages, param);
1474
display_info ("xine engine message", data->messages);
1399
const char *param = data->messages + strlen (data->messages) + 1;
1400
char *txt = strdup (data->messages);
1401
for (i = 0; i < data->num_parameters; ++i)
1403
asreprintf (&txt, "%s %s", txt, param);
1404
param += strlen (param) + 1;
1406
msg (_("xine engine message"), "%s", txt);
1410
msg (_("xine engine message"), "%s", data->messages);
1476
1411
gdk_threads_leave();
1423
static const GtkTargetEntry target_table[] = {
1424
{ "text/uri-list", 0, 0 },
1427
static void drop_cb (GtkWidget *widget,
1428
GdkDragContext *context,
1431
GtkSelectionData *data,
1439
logprintf ("drag_drop: drop callback, length=%d, format=%d\n, x=%d, y=%d\n",
1440
data->length, data->format, x, y);
1442
if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (tree_view), x, y, &path,
1447
indices = gtk_tree_path_get_indices (path);
1448
ins_pos = indices[0];
1450
logprintf ("playlist: mapping to tree view worked: cx=%d, cy=%d, path=%s, row=%d\n",
1451
cx, cy, gtk_tree_path_to_string (path), ins_pos);
1453
gtk_tree_path_free (path);
1458
if (data->format == 8) {
1461
gchar str[MAX_MRL_LEN];
1465
while (i<data->length) {
1471
if ( (len<(MAX_MRL_LEN-1))
1476
} else if (c=='\r') {
1480
playlist_add_mrl (str, ins_pos);
1482
if (ins_pos >= 0 && ins_pos++ <= cur_list_pos)
1492
gtk_drag_finish (context, TRUE, FALSE, time);
1499
static JSBool js_playlist_get_item (JSContext *cx, JSObject *obj, uintN argc,
1500
jsval *argv, jsval *rval) {
1502
/* se_t *se = (se_t *) JS_GetContextPrivate(cx); */
1505
se_log_fncall ("playlist_get_item");
1507
speed = xine_get_param (stream, XINE_PARAM_SPEED);
1509
*rval = INT_TO_JSVAL (playlist_get_list_pos());
1514
static JSBool js_playlist_clear (JSContext *cx, JSObject *obj, uintN argc,
1515
jsval *argv, jsval *rval) {
1517
/* se_t *se = (se_t *) JS_GetContextPrivate(cx); */
1519
se_log_fncall ("playlist_clear");
1526
static JSBool js_playlist_add (JSContext *cx, JSObject *obj, uintN argc,
1527
jsval *argv, jsval *rval) {
1529
se_t *se = (se_t *) JS_GetContextPrivate(cx);
1534
se_log_fncall ("playlist_add");
1536
se_argc_check (1, "playlist_add");
1537
se_arg_is_string (0, "playlist_add");
1539
str = JS_ValueToString (cx, argv[0]);
1540
mrl = JS_GetStringBytes (str);
1542
logprintf ("playlist_add: MRL=%s\n", mrl);
1543
item = playlist_add_mrl (mrl, -1);
1545
*rval = INT_TO_JSVAL (item);
1550
static JSBool js_playlist_play (JSContext *cx, JSObject *obj, uintN argc,
1551
jsval *argv, jsval *rval) {
1553
se_t *se = (se_t *) JS_GetContextPrivate(cx);
1556
se_log_fncall ("playlist_play");
1558
se_argc_check (1, "playlist_play");
1559
se_arg_is_int (0, "playlist_play");
1561
JS_ValueToInt32 (cx, argv[0], &item);
1566
playlist_play (item);
1571
static JSBool js_playlist_show (JSContext *cx, JSObject *obj, uintN argc,
1572
jsval *argv, jsval *rval) {
1574
/* se_t *se = (se_t *) JS_GetContextPrivate(cx); */
1576
se_log_fncall ("playlist_show");
1583
void playlist_play_from (int list_pos, int pos, int pos_time) {
1588
play_item_t *play_item;
1595
unmark_play_item ();
1597
play_item = playlist_get_item (list_pos);
1605
play_item_play (play_item);
1607
snprintf (indices, 10, "%d", list_pos);
1608
path = gtk_tree_path_new_from_string (indices);
1609
gtk_tree_view_set_cursor (GTK_TREE_VIEW (tree_view),
1611
gtk_tree_path_free (path);
1613
cur_list_pos = list_pos;
1484
1619
void playlist_init (void) {
1486
1621
GtkWidget *hbox, *button, *scrolled_window;
1519
1679
G_CALLBACK(button_press_lcb), NULL);
1521
1681
cell = gtk_cell_renderer_text_new ();
1522
column = gtk_tree_view_column_new_with_attributes ("title",
1526
gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
1527
GTK_TREE_VIEW_COLUMN (column));
1529
column = gtk_tree_view_column_new_with_attributes ("mrl",
1533
gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
1534
GTK_TREE_VIEW_COLUMN (column));
1536
gtk_tree_view_set_reorderable (GTK_TREE_VIEW (tree_view), TRUE);
1682
column = gtk_tree_view_column_new_with_attributes (" ", cell,
1684
gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
1685
GTK_TREE_VIEW_COLUMN (column));
1687
cell = gtk_cell_renderer_text_new ();
1688
column = gtk_tree_view_column_new_with_attributes (_("Title"), cell,
1690
gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
1691
GTK_TREE_VIEW_COLUMN (column));
1693
column = gtk_tree_view_column_new_with_attributes ("MRL", cell,
1695
gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
1696
GTK_TREE_VIEW_COLUMN (column));
1698
/* FIXME: interacts badly with own drag&drop stuff
1699
gtk_tree_view_set_reorderable (GTK_TREE_VIEW (tree_view), TRUE);
1702
g_signal_connect (G_OBJECT (tree_view), "drag_data_received",
1703
G_CALLBACK (drop_cb), NULL);
1704
gtk_drag_dest_set (tree_view, GTK_DEST_DEFAULT_ALL,
1705
target_table, 1, GDK_ACTION_COPY);
1707
gtk_widget_show (tree_view);
1538
1709
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
1539
1710
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),