2 * playlist.c -- GTK+ 2 omnplay
3 * Copyright (C) 2011 Maksym Veremeyenko <verem@m1stereo.tv>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #include <gdk/gdkkeysyms.h>
35 static int load_file_ply(omnplay_instance_t
* app
, char* filename
)
38 char *ID
, *CH
, *B
, *IN
, *OUT
, *DUR
, *REST
, *l
;
40 playlist_item_t
* items
;
42 /* allocate space for strings and items */
43 items
= malloc(sizeof(playlist_item_t
) * MAX_PLAYLIST_ITEMS
);
44 memset(items
, 0, sizeof(playlist_item_t
) * MAX_PLAYLIST_ITEMS
);
45 ID
= malloc(PATH_MAX
);
46 CH
= malloc(PATH_MAX
);
48 IN
= malloc(PATH_MAX
);
49 OUT
= malloc(PATH_MAX
);
50 DUR
= malloc(PATH_MAX
);
51 REST
= malloc(PATH_MAX
);
54 /* open and process file */
55 f
= fopen(filename
, "rt");
63 memset(l
, 0, PATH_MAX
);
64 fgets(l
, PATH_MAX
, f
);
67 if( (s
= strchr(l
, '\n')) ) *s
= 0;
68 if( (s
= strchr(l
, '\r')) ) *s
= 0;
69 if( (s
= strchr(l
, '\t')) ) *s
= 0;
71 /* check for empty line */
72 if(l
[0] && l
[0] != '#')
74 if (6 != sscanf(l
, "%128[^,],%128[^,],%128[^,],%128[^,],%128[^,],%128[^,],%s",
75 ID
, CH
, B
, IN
, OUT
, DUR
, REST
))
78 tc2frames(IN
, 25.0, &items
[count
].in
);
79 tc2frames(DUR
, 25.0, &items
[count
].dur
);
80 strncpy(items
[count
].id
, ID
, PATH_MAX
);
81 items
[count
].player
= atol(CH
) - 1;
84 case 1: items
[count
].type
= OMNPLAY_PLAYLIST_ITEM_BLOCK_SINGLE
; break;
85 case 2: items
[count
].type
= OMNPLAY_PLAYLIST_ITEM_LOOP_BEGIN
; break;
86 case 3: items
[count
].type
= OMNPLAY_PLAYLIST_ITEM_LOOP_BODY
; break;
87 case 4: items
[count
].type
= OMNPLAY_PLAYLIST_ITEM_LOOP_END
; break;
88 case 6: items
[count
].type
= OMNPLAY_PLAYLIST_ITEM_BLOCK_END
; break;
91 items
[count
].type
= OMNPLAY_PLAYLIST_ITEM_BLOCK_BEGIN
;
92 else if(items
[count
- 1].type
== OMNPLAY_PLAYLIST_ITEM_BLOCK_BEGIN
||
93 items
[count
- 1].type
== OMNPLAY_PLAYLIST_ITEM_BLOCK_BODY
)
94 items
[count
].type
= OMNPLAY_PLAYLIST_ITEM_BLOCK_BODY
;
96 items
[count
].type
= OMNPLAY_PLAYLIST_ITEM_BLOCK_BEGIN
;
102 switch(items
[count
].type
)
104 case OMNPLAY_PLAYLIST_ITEM_BLOCK_BEGIN
: n
= "BLOCK_BEGIN"; break;
105 case OMNPLAY_PLAYLIST_ITEM_BLOCK_BODY
: n
= "BLOCK_BODY"; break;
106 case OMNPLAY_PLAYLIST_ITEM_BLOCK_END
: n
= "BLOCK_END"; break;
107 case OMNPLAY_PLAYLIST_ITEM_BLOCK_SINGLE
: n
= "BLOCK_SINGLE"; break;
108 case OMNPLAY_PLAYLIST_ITEM_LOOP_BEGIN
: n
= "LOOP_BEGIN"; break;
109 case OMNPLAY_PLAYLIST_ITEM_LOOP_BODY
: n
= "LOOP_BODY"; break;
110 case OMNPLAY_PLAYLIST_ITEM_LOOP_END
: n
= "LOOP_END"; break;
111 case OMNPLAY_PLAYLIST_ITEM_LOOP_SINGLE
: n
= "LOOP_SINGLE"; break;
113 fprintf(stderr
, "src=[%s]\ndst=[idx=%d,block=%s,block_id=%d,in=%d,out=%d]\n",
114 l
, count
, n
, items
[count
].type
, items
[count
].in
, items
[count
].dur
);
126 /* add loaded items to playlist */
129 pthread_mutex_lock(&app
->playlist
.lock
);
130 for(i
= 0; i
< count
&& app
->playlist
.count
+ 1 < MAX_PLAYLIST_ITEMS
; i
++)
132 omnplay_library_normalize_item(app
, &items
[i
]);
133 app
->playlist
.item
[app
->playlist
.count
++] = items
[i
];
135 app
->playlist
.ver_curr
++;
136 pthread_mutex_unlock(&app
->playlist
.lock
);
152 void omnplay_playlist_load(omnplay_instance_t
* app
)
157 dialog
= gtk_file_chooser_dialog_new("Open File",
158 GTK_WINDOW (app
->window
),
159 GTK_FILE_CHOOSER_ACTION_OPEN
,
160 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
161 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
,
164 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog
),
165 (app
->playlist
.path
)?app
->playlist
.path
:getenv("HOME"));
167 r
= gtk_dialog_run(GTK_DIALOG(dialog
));
169 if(r
== GTK_RESPONSE_ACCEPT
)
173 filename
= gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog
));
175 r
= load_file_ply(app
, filename
);
178 omnplay_playlist_draw(app
);
180 if(app
->playlist
.path
)
181 g_free(app
->playlist
.path
);
182 if((app
->playlist
.path
= filename
))
184 char* e
= strrchr(app
->playlist
.path
, '/');
189 gtk_widget_destroy (dialog
);
192 void omnplay_playlist_save(omnplay_instance_t
* app
)
196 void omnplay_playlist_draw(omnplay_instance_t
* app
)
199 char tc1
[12], tc2
[12];
200 GtkListStore
*list_store
;
203 list_store
= GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(app
->playlist_grid
)));
204 gtk_list_store_clear(list_store
);
206 pthread_mutex_lock(&app
->playlist
.lock
);
208 for(i
= 0;i
< app
->playlist
.count
; i
++)
210 gtk_list_store_append(list_store
, &iter
);
212 gtk_list_store_set(list_store
, &iter
,
214 1, app
->playlist
.block_icons
[app
->playlist
.item
[i
].type
],
215 2, (0 == app
->playlist
.item
[i
].player
)?
"A":"B",
216 3, app
->playlist
.item
[i
].id
,
217 4, frames2tc(app
->playlist
.item
[i
].in
, 25.0, tc1
),
218 5, frames2tc(app
->playlist
.item
[i
].dur
, 25.0, tc2
),
219 6, app
->playlist
.item
[i
].title
,
224 app
->playlist
.ver_prev
= app
->playlist
.ver_curr
;
226 pthread_mutex_unlock(&app
->playlist
.lock
);
229 typedef struct omnplay_playlist_draw_item_desc
231 GtkListStore
*list_store
;
232 omnplay_instance_t
* app
;
234 } omnplay_playlist_draw_item_t
;
236 static gboolean
omnplay_playlist_draw_item_proc(
237 GtkTreeModel
*model
, GtkTreePath
*path
, GtkTreeIter
*iter
, gpointer user_data
)
240 char tc1
[12], tc2
[12];
241 omnplay_playlist_draw_item_t
* item
= (omnplay_playlist_draw_item_t
*)user_data
;
242 omnplay_instance_t
* app
= item
->app
;
244 gtk_tree_model_get(model
, iter
, 7, &i
, -1);
246 if(i
!= item
->idx
) return FALSE
;
248 gtk_list_store_set(item
->list_store
, iter
,
250 1, app
->playlist
.block_icons
[app
->playlist
.item
[i
].type
],
251 2, (0 == app
->playlist
.item
[i
].player
)?
"A":"B",
252 3, app
->playlist
.item
[i
].id
,
253 4, frames2tc(app
->playlist
.item
[i
].in
, 25.0, tc1
),
254 5, frames2tc(app
->playlist
.item
[i
].dur
, 25.0, tc2
),
255 6, app
->playlist
.item
[i
].title
,
262 void omnplay_playlist_draw_item(omnplay_instance_t
* app
, int idx
)
264 GtkListStore
*list_store
;
265 omnplay_playlist_draw_item_t item
;
267 list_store
= GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(app
->playlist_grid
)));
269 pthread_mutex_lock(&app
->playlist
.lock
);
273 item
.list_store
= list_store
;
274 gtk_tree_model_foreach(GTK_TREE_MODEL(list_store
), omnplay_playlist_draw_item_proc
, &item
);
276 pthread_mutex_unlock(&app
->playlist
.lock
);
279 static gboolean
omnplay_playlist_draw_item_rem_proc(
280 GtkTreeModel
*model
, GtkTreePath
*path
, GtkTreeIter
*iter
, gpointer user_data
)
283 void** args
= (void**)user_data
;
284 GtkListStore
*list_store
= (GtkListStore
*)args
[1];
285 int idx
= (int)args
[2];
286 char* rem
= (char*)args
[3];
288 gtk_tree_model_get(model
, iter
, 7, &i
, -1);
290 if(i
!= idx
) return FALSE
;
292 gtk_list_store_set(list_store
, iter
, 0, rem
, -1);
297 void omnplay_playlist_draw_item_rem(omnplay_instance_t
* app
, int idx
, char* rem
)
300 GtkListStore
*list_store
;
302 list_store
= GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(app
->playlist_grid
)));
304 item
[0] = (void*)app
;
305 item
[1] = (void*)list_store
;
306 item
[2] = (void*)idx
;
307 item
[3] = (void*)rem
;
309 gtk_tree_model_foreach(GTK_TREE_MODEL(list_store
), omnplay_playlist_draw_item_rem_proc
, item
);