eefce46050a53bd464a38b17e5db84623b3db8f1
[melted_gui] / src / library.c
1 /*
2 * playlist.c -- GTK+ 2 omnplay
3 * Copyright (C) 2011 Maksym Veremeyenko <verem@m1stereo.tv>
4 *
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.
9 *
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.
14 *
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.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <gtk/gtk.h>
28 #include <gdk/gdkkeysyms.h>
29 #include <pthread.h>
30
31 #include "omnplay.h"
32 #include "ui.h"
33 #include "timecode.h"
34
35 playlist_item_t* omnplay_library_find(omnplay_instance_t* app, char* id)
36 {
37 int i;
38 playlist_item_t* item = NULL;
39
40 pthread_mutex_lock(&app->library.lock);
41
42 for(i = 0; i < app->library.count && !item; i++)
43 if(!strcasecmp(id, app->library.item[i].id))
44 item = &app->library.item[i];
45
46 pthread_mutex_unlock(&app->library.lock);
47
48 return item;
49 };
50
51 void omnplay_library_normalize_item(omnplay_instance_t* app, playlist_item_t* item)
52 {
53 playlist_item_t* lib;
54
55 pthread_mutex_lock(&app->library.lock);
56
57 lib = omnplay_library_find(app, item->id);
58
59 item->error = 0;
60
61 if(lib)
62 {
63
64 if(!item->title[0])
65 strcpy(item->title, lib->title);
66
67 if(!item->dur)
68 {
69 item->dur = lib->dur;
70 item->in = lib->in;
71 };
72 }
73 else
74 item->error = PLAYLIST_ITEM_ERROR_LIB;
75
76 pthread_mutex_unlock(&app->library.lock);
77 };
78
79 void omnplay_library_sort(omnplay_instance_t* app)
80 {
81 int i, j, m;
82 playlist_item_t item;
83
84 for(i = 0; i < app->library.count; i++)
85 {
86 /* find max */
87 for(j = i + 1, m = i; j < app->library.count; j++)
88 if(strcasecmp(app->library.item[j].id, app->library.item[m].id) < 0)
89 m = j;
90
91 if(m != i)
92 {
93 item = app->library.item[i];
94 app->library.item[i] = app->library.item[m];
95 app->library.item[m] = item;
96 };
97 };
98 };
99
100 int omnplay_library_load_file(playlist_item_t* items, int *pcount, char* filename)
101 {
102 int i, c = 0, r = 0;
103 FILE* f;
104 char *l;
105 int limit = *pcount;
106 playlist_item_t item;
107
108 /* allocate space for strings and items */
109 l = malloc(PATH_MAX);
110
111 *pcount = 0;
112
113 /* open and process file */
114 if((f = fopen(filename, "rt")))
115 {
116 while( !feof(f) && c < (limit -1))
117 {
118 char *s, *sp_r, *sp_b;
119
120 /* load string */
121 memset(l, 0, PATH_MAX);
122 fgets(l, PATH_MAX, f);
123
124 /* remove newlines */
125 if( (s = strchr(l, '\n')) ) *s = 0;
126 if( (s = strchr(l, '\r')) ) *s = 0;
127
128 /* check for empty line */
129 if(l[0] && l[0] != '#' && l[0] != '|')
130 {
131 memset(&item, 0, sizeof(playlist_item_t));
132
133 for(i = 0, sp_b = l; (NULL != (sp_r = strtok(sp_b, "\t"))); i++, sp_b = NULL)
134 {
135 switch(i)
136 {
137 case 0: strncpy(item.id, sp_r, PATH_MAX); break;
138 case 1: tc2frames(sp_r, 25.0, &item.in); break;
139 case 2: tc2frames(sp_r, 25.0, &item.dur); break;
140 case 3: strncpy(item.title, sp_r, PATH_MAX); break;
141 };
142 };
143
144 /* insert item */
145 items[c++] = item;
146 };
147 }
148
149 fclose(f);
150 }
151 else
152 r = -1;
153
154 /* free data */
155 free(l);
156
157 *pcount = c;
158
159 return r;
160 };
161
162 void omnplay_library_load(omnplay_instance_t* app)
163 {
164 pthread_mutex_lock(&app->library.lock);
165
166 if(app->library.filename[0])
167 {
168 app->library.count = MAX_LIBRARY_ITEMS;
169 omnplay_library_load_file(app->library.item, &app->library.count, app->library.filename);
170 };
171
172 omnplay_library_sort(app);
173
174 pthread_mutex_unlock(&app->library.lock);
175
176 omnplay_library_draw(app);
177 };
178
179 static void omnplay_library_save_file(playlist_item_t* item, int count, char* filename)
180 {
181 int i;
182 FILE* f;
183
184 if((f = fopen(filename, "wt")))
185 {
186 char tc_in[32], tc_dur[32];
187
188 for(i = 0; i < count; i++)
189 fprintf(f, "%s\t%s\t%s\t%s\n",
190 item[i].id,
191 frames2tc(item[i].in, 25.0, tc_in),
192 frames2tc(item[i].dur, 25.0, tc_dur),
193 item[i].title);
194
195 fclose(f);
196 };
197 };
198
199 void omnplay_library_save(omnplay_instance_t* app)
200 {
201 pthread_mutex_lock(&app->library.lock);
202
203 if(app->library.filename[0])
204 omnplay_library_save_file(app->library.item, app->library.count,
205 app->library.filename);
206
207 pthread_mutex_unlock(&app->library.lock);
208 };
209
210 static void omnplay_get_content_cb(omnplay_instance_t* app, playlist_item_t* item, void* data)
211 {
212 fprintf(stderr, "requested: id=[%s]\n", item->id);
213 };
214
215 void omnplay_library_refresh(omnplay_instance_t* app)
216 {
217 int count, i;
218 playlist_item_t* items;
219
220
221 items = (playlist_item_t*)malloc(sizeof(playlist_item_t) * MAX_LIBRARY_ITEMS);
222
223 count = omnplay_get_content(app, items, MAX_LIBRARY_ITEMS, omnplay_get_content_cb, NULL);
224
225 if(count > 0)
226 {
227 if(app->library.whois[0])
228 omnplay_whois_list(app, items, &count);
229
230 pthread_mutex_lock(&app->library.lock);
231
232 for(i = 0; i < count; i++)
233 app->library.item[i] = items[i];
234
235 app->library.count = count;
236
237 omnplay_library_sort(app);
238
239 pthread_mutex_unlock(&app->library.lock);
240
241 omnplay_library_draw(app);
242 };
243
244 free(items);
245 };
246
247 void omnplay_library_draw(omnplay_instance_t* app)
248 {
249 int i;
250 char tc[12];
251 GtkListStore *list_store;
252 GtkTreeIter iter;
253
254 list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(app->library_grid)));
255 gtk_list_store_clear(list_store);
256
257 pthread_mutex_lock(&app->library.lock);
258
259 for(i = 0;i < app->library.count; i++)
260 {
261 gtk_list_store_append(list_store, &iter);
262
263 gtk_list_store_set(list_store, &iter,
264 0, app->library.item[i].id,
265 1, frames2tc(app->library.item[i].dur, 25.0, tc),
266 2, app->library.item[i].title,
267 3, i,
268 4, FALSE,
269 5, "red",
270 -1 );
271 }
272
273 pthread_mutex_unlock(&app->library.lock);
274 };
275
276 static void get_selected_idx_library_proc(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
277 {
278 int idx, *list = (int*)data;
279 gtk_tree_model_get(model, iter, 3, &idx, -1);
280 list[list[0] + 1] = idx;
281 list[0] = list[0] + 1;
282 };
283
284 static int* get_selected_idx_library(omnplay_instance_t* app)
285 {
286 int* list = NULL;
287 GtkTreeSelection *selection;
288
289 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(app->library_grid));
290 if(selection)
291 {
292 list = (int*)malloc(sizeof(int) * (MAX_LIBRARY_ITEMS + 1));
293 memset(list, 0, sizeof(int) * (MAX_LIBRARY_ITEMS + 1));
294
295 gtk_tree_selection_selected_foreach(
296 selection,
297 get_selected_idx_library_proc,
298 list);
299
300 if(!list[0])
301 {
302 free(list);
303 list = NULL;
304 };
305 };
306
307 return list;
308 };
309
310
311 playlist_item_t* omnplay_library_get_selected(omnplay_instance_t* app, int *count)
312 {
313 int* idxs;
314 playlist_item_t* items = NULL;
315
316 pthread_mutex_lock(&app->library.lock);
317
318 *count = 0;
319
320 idxs = get_selected_idx_library(app);
321
322 if(idxs)
323 {
324 int i;
325
326 /* alloc items */
327 items = (playlist_item_t*)malloc(sizeof(playlist_item_t) * (idxs[0] + 1));
328
329 /* clear last item */
330 memset(&items[idxs[0]], 0, sizeof(playlist_item_t));
331
332 /* copy items */
333 for(i = 0; i < idxs[0]; i++)
334 items[i] = app->library.item[idxs[i + 1]];
335
336 *count = idxs[0];
337 free(idxs);
338 };
339
340 pthread_mutex_unlock(&app->library.lock);
341
342 return items;
343 };