6 #include "../src/mark.h"
11 #include "../src/settings.h"
12 #include "../src/dir_seperator.h"
14 #include "../src/opticalflow.h"
17 /* functions to load directory */
19 typedef struct dir_entry {
20 struct dir_entry *next;
24 static int cmpstringp(const void *p1, const void *p2)
26 dir_t *entry1 = *(dir_t **)p1;
27 dir_t *entry2 = *(dir_t **)p2;
29 return strcmp(entry1->name, entry2->name);
32 static dir_t *fetch_dir(const char *path) /* NOTE: if path is not empty, it must end with DIR_SEPERATOR */
36 struct dirent dirent, *result;
37 dir_t *head = NULL, *entry, **entryp = &head;
42 /* read linked list */
47 rc = readdir_r(dir, &dirent, &result);
52 if (result->d_type != DT_REG && result->d_type != DT_LNK)
54 entry = calloc(1, sizeof(dir_t) + strlen(path) + strlen(result->d_name) + 1);
56 fprintf(stderr, "no memory");
60 entryp = &entry->next;
61 strcpy(entry->name, path);
62 strcat(entry->name, result->d_name);
67 /* sort linked list */
68 list = calloc(count, sizeof(*list));
70 fprintf(stderr, "no memory");
74 for (entry = head; entry; entry = entry->next) {
78 qsort(list, count, sizeof(*list), cmpstringp);
80 for (i = 0; i < count; i++) {
85 entryp = &entry->next;
92 static void free_dir(dir_t *dir)
105 struct frame_list *frame_list = NULL;
107 /* currently loaded image */
108 GdkPixbuf *timeline_pixbuf = NULL;
109 int timeline_selected = 0;
110 int timeline_frames = 0;
111 int timeline_scale = 10;
112 int timeline_width, timeline_height = 30;
114 static void draw_timeline_frame(int frame)
120 if (!timeline_pixbuf)
123 if (frame == timeline_selected) {
127 if (frame_list && frame_list[frame].marked) {
136 if (frame_list && frame_list[frame].marked) {
143 data = gdk_pixbuf_get_pixels(timeline_pixbuf);
144 rs = gdk_pixbuf_get_rowstride(timeline_pixbuf);
146 for (i = 0; i < timeline_height; i++) {
147 data[rs*i + frame*timeline_scale*3 + 0] = 0;
148 data[rs*i + frame*timeline_scale*3 + 1] = 0;
149 data[rs*i + frame*timeline_scale*3 + 2] = 0;
150 for (j = 1; j < timeline_scale; j++) {
151 data[rs*i + (frame*timeline_scale+j)*3 + 0] = r;
152 data[rs*i + (frame*timeline_scale+j)*3 + 1] = g;
153 data[rs*i + (frame*timeline_scale+j)*3 + 2] = b;
156 if (frame_list && frame_list[frame].keyframe) {
160 for (i = 0; i < timeline_scale/2; i++) {
161 for (j = i + 1; j < timeline_scale - i; j++) {
162 data[rs*i + (frame*timeline_scale+j)*3 + 0] = r;
163 data[rs*i + (frame*timeline_scale+j)*3 + 1] = g;
164 data[rs*i + (frame*timeline_scale+j)*3 + 2] = b;
166 data[rs*(timeline_height-1-i) + (frame*timeline_scale+j)*3 + 0] = r;
167 data[rs*(timeline_height-1-i) + (frame*timeline_scale+j)*3 + 1] = g;
168 data[rs*(timeline_height-1-i) + (frame*timeline_scale+j)*3 + 2] = b;
174 /* get path of given file name */
175 static char *get_path(const char *filename)
177 static char path[256];
180 strcpy(path, filename);
181 /* remove until DIR_SEPERATOR */
183 if (path[strlen(path) - 1] == DIR_SEPERATOR)
185 path[strlen(path) - 1] = '\0';
191 /* load directory and create pixbuf */
192 void create_timeline(const char *filename)
196 char temp[256], suffix[256];
203 while ((q = strchr(p, '.')))
206 printerror("File '%s' does not have a 'prefix.suffix' format\n", filename);
209 strcpy(suffix, p - 1);
212 if ((strlen(filename) < 5 || !!strcmp(suffix, ".ppm"))) {
213 printerror("File '%s' does not have '.ppm' suffix\n", filename);
223 p = filename + strlen(filename) - strlen(suffix);
224 while (p != filename) {
226 if (*p < '0' || *p > '9') {
231 if (*p < '0' || *p > '9') {
233 // printf("single file\n");
234 frame_list = malloc(sizeof(struct frame_list));
235 memset(frame_list, 0, sizeof(struct frame_list));
236 strcpy(frame_list[0].filename, filename);
239 /* create list of files that have same base name, same number of digits and suffix */
240 int suffix_offset = strlen(filename) - strlen(suffix);
241 int digits_offset = p - filename;
242 int digits = filename + strlen(filename) - strlen(suffix) - p;
243 const char *path = get_path(filename);
244 dir_t *dir_head = fetch_dir(path), *dir, **dirp;
251 /* remove files that do not have equal prefix */
252 if (!!strncmp(filename, dir->name, p - filename)) {
260 /* remove files that have no digits where expected */
261 for (i = 0; i < digits; i++) {
262 if (dir->name[digits_offset+i] < '0' || dir->name[digits_offset+i] > '9')
268 /* remove files that have different suffix */
269 if (!!strcmp(suffix, dir->name + suffix_offset)) {
285 frame_list = malloc(sizeof(struct frame_list) * count);
286 memset(frame_list, 0, sizeof(struct frame_list) * count);
288 for (i = 0; i < count; i++) {
289 strcpy(frame_list[i].filename, dir->name);
292 timeline_frames = count;
295 /* get marked frames */
296 for (i = 0; i < timeline_frames; i++) {
297 sprintf(temp, "%s_marked", frame_list[i].filename);
298 frame_list[i].marked = 0;
299 fp = fopen(temp, "r");
303 frame_list[i].marked = 1;
309 if (timeline_frames == 0)
312 if (timeline_frames > 1)
313 gtk_widget_show(timeline_scroll);
315 timeline_width = timeline_frames * timeline_scale;
317 timeline_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, timeline_width, timeline_height);
319 for (i = 0; i < timeline_frames; i++)
320 draw_timeline_frame(i);
322 gtk_widget_set_size_request(timeline_drawing_area, timeline_width, timeline_height);
325 /* disable optical flow and set default */
332 load_settings(frame_list[0].filename);
333 load_palette(frame_list[0].filename);
334 for (i = 0; i < 255; i++)
340 void destroy_timeline(void)
342 gtk_widget_hide(timeline_scroll);
344 if (!timeline_pixbuf)
347 g_object_unref(timeline_pixbuf);
348 timeline_pixbuf = NULL;
353 timeline_selected = 0;
356 /* draw (area) of pixbuf */
357 void draw_timeline(int x, int y, int w, int h)
359 GdkDrawable *draw = gtk_widget_get_window(timeline_drawing_area);
361 if (!timeline_pixbuf)
366 if (x >= timeline_width)
370 if (y >= timeline_height)
372 if (x + w > timeline_width)
373 w = timeline_width - x;
374 if (y + h > timeline_height)
375 h = timeline_height - y;
377 //printf("%d %d %d %d\n", x, y, w, h);
379 if (!timeline_pixbuf)
382 gdk_draw_pixbuf(draw, NULL, timeline_pixbuf, x, y, x, y, w, h, GDK_RGB_DITHER_NONE, 0, 0);
385 int timeline_select_and_save(int old_frame, int new_frame)
388 /* no frame loaded, no list */
389 if (!frame_list|| !img_pixbuf)
393 if (anything_modified) {
394 if (img_mark_buffer) {
395 if (save_marked(img_mark_buffer, img_width, img_height, frame_list[old_frame].filename) > 0)
396 frame_list[old_frame].marked = 1;
398 frame_list[old_frame].marked = 0;
402 save_palette(frame_list[0].filename);
403 if (timeline_frames > 1)
404 save_settings(frame_list[0].filename);
409 timeline_selected = new_frame;
411 create_image(frame_list[new_frame].filename, 0);
413 if (flowview && flow_enable && img_grey_buffer)
415 (new_frame > 0) ? frame_list[new_frame - 1].filename : NULL,
416 (new_frame < timeline_frames - 1) ? frame_list[new_frame + 1].filename : NULL,
418 img_width, img_height,
424 if (timeline_frames > 1) {
425 GdkDrawable *draw = gtk_widget_get_window(timeline_drawing_area);
426 draw_timeline_frame(old_frame);
427 draw_timeline_frame(new_frame);
428 gdk_draw_pixbuf(draw, NULL, timeline_pixbuf, 0, 0, 0, 0, timeline_width, timeline_height, GDK_RGB_DITHER_NONE, 0, 0);
431 /* adjust position of timeline scroll */
433 GtkAdjustment *adjustment;
435 x = new_frame * timeline_scale;
436 w = timeline_scroll->allocation.width - timeline_scale - 4;
437 adjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(timeline_scroll));
438 pos = gtk_adjustment_get_value(adjustment);
440 gtk_adjustment_set_value(adjustment, x);
441 gtk_scrolled_window_set_hadjustment(GTK_SCROLLED_WINDOW(timeline_scroll), adjustment);
444 gtk_adjustment_set_value(adjustment, pos + x + - (pos + w));
445 gtk_scrolled_window_set_hadjustment(GTK_SCROLLED_WINDOW(timeline_scroll), adjustment);
451 /* while pointing at timeline, show current frame that we point to */
452 int timeline_point(int x, int y)
454 int frame = x / timeline_scale;
456 if (x < 0 || y < 0 || frame < 0 || frame >= timeline_frames) {
457 timeline_show_name(timeline_selected);
461 timeline_show_name(frame);
465 void timeline_show_name(int frame)
473 if (frame != timeline_selected) {
474 sprintf(text, "Click to select frame %d", frame);
476 p = frame_list[frame].filename;
477 while (strchr(p, DIR_SEPERATOR))
478 p = strchr(p, DIR_SEPERATOR) + 1;
479 if (timeline_frames > 1)
480 sprintf(text, "Frame %d: %s", frame, p);
483 if (img_scale_x != 16)
484 sprintf(strchr(text, '\0'), " (%d%%)", img_scale_x*100/16);
486 gtk_label_set_text(img_label, text);
489 int timeline_clicked(int x, int y)
491 int old_frame = timeline_selected;
492 int new_frame = x / timeline_scale;
496 if (new_frame >= timeline_frames)
499 if (old_frame == new_frame)
502 return timeline_select_and_save(old_frame, new_frame);
506 /* get filename of first grey image directory */
507 static char *get_sequence_name(const char *filename)
509 static char name[256];
512 strcpy(name, get_path(filename));
513 /* add palette name */
514 strcat(name, "sequence");
519 int save_sequence(void)
528 if (timeline_frames <= 1)
531 name = get_sequence_name(frame_list[0].filename);
532 // printf("save sequence '%s'\n", name);
533 fp = fopen(name, "w");
535 printf("failed to save sequence '%s'\n", name);
538 for (i = 0; i < timeline_frames; i++) {
539 p = frame_list[i].filename;
540 while (p && strchr(p, DIR_SEPERATOR))
541 p = strchr(p, DIR_SEPERATOR) + 1;
542 fprintf(fp, "\"%s\"%s\n", p, (frame_list[i].keyframe) ? " keyframe" : "");
549 int load_sequence(void)
560 if (timeline_frames <= 1)
563 name = get_sequence_name(frame_list[0].filename);
564 // printf("load sequence '%s'\n", name);
565 fp = fopen(name, "r");
567 printf("no sequence file '%s' created yet\n", name);
570 for (i = 0; i < timeline_frames; i++) {
571 rc = fgets(buffer, sizeof(buffer), fp);
574 p = strchr(buffer + 1, '\"');
578 if (strstr(p, "keyframe"))
579 frame_list[i].keyframe = 1;
581 frame_list[i].keyframe = 0;
588 void toggle_keyframe(void)
590 if (!frame_list|| !img_pixbuf)
593 anything_modified = 1;
595 GdkDrawable *draw = gtk_widget_get_window(timeline_drawing_area);
597 frame_list[timeline_selected].keyframe = 1 - frame_list[timeline_selected].keyframe;
598 draw_timeline_frame(timeline_selected);
599 gdk_draw_pixbuf(draw, NULL, timeline_pixbuf, 0, 0, 0, 0, timeline_width, timeline_height, GDK_RGB_DITHER_NONE, 0, 0);