6 #include "../src/mark.h"
11 #include "../src/settings.h"
12 #include "../src/dir_seperator.h"
14 #include "../src/opticalflow.h"
17 // Uncomment this to test some filename processing
18 //#define DEBUG_FILENAME
20 /* functions to load directory */
22 typedef struct dir_entry {
23 struct dir_entry *next;
27 static int cmpstringp(const void *p1, const void *p2)
29 dir_t *entry1 = *(dir_t **)p1;
30 dir_t *entry2 = *(dir_t **)p2;
32 return strcmp(entry1->name, entry2->name);
35 static dir_t *fetch_dir(const char *path) /* NOTE: if path is not empty, it must end with DIR_SEPERATOR */
38 struct dirent *dirent;
39 dir_t *head = NULL, *entry, **entryp = &head;
44 /* read linked list */
45 if (path == NULL || path[0] == '\0')
51 printf("Failed to open directory: path='%s'\n", path);
56 dirent = readdir(dir);
59 if (dirent->d_type != DT_REG && dirent->d_type != DT_LNK)
61 entry = calloc(1, sizeof(dir_t) + strlen(path) + strlen(dirent->d_name) + 1);
63 fprintf(stderr, "no memory");
67 entryp = &entry->next;
69 printf("Fetching entry: path='%s' filename='%s'\n", path, dirent->d_name);
71 strcpy(entry->name, path);
72 strcat(entry->name, dirent->d_name);
77 /* sort linked list */
78 list = calloc(count, sizeof(*list));
80 fprintf(stderr, "no memory");
84 for (entry = head; entry; entry = entry->next) {
88 qsort(list, count, sizeof(*list), cmpstringp);
90 for (i = 0; i < count; i++) {
94 printf("Sorted full name: '%s'\n", entry->name);
98 entryp = &entry->next;
105 static void free_dir(dir_t *dir)
118 struct frame_list *frame_list = NULL;
120 /* currently loaded image */
121 GdkPixbuf *timeline_pixbuf = NULL;
122 int timeline_selected = 0;
123 int timeline_frames = 0;
124 int timeline_scale = 10;
125 int timeline_width, timeline_height = 30;
127 static void draw_timeline_frame(int frame)
133 if (!timeline_pixbuf)
136 if (frame == timeline_selected) {
140 if (frame_list && frame_list[frame].marked) {
149 if (frame_list && frame_list[frame].marked) {
156 data = gdk_pixbuf_get_pixels(timeline_pixbuf);
157 rs = gdk_pixbuf_get_rowstride(timeline_pixbuf);
159 for (i = 0; i < timeline_height; i++) {
160 data[rs*i + frame*timeline_scale*3 + 0] = 0;
161 data[rs*i + frame*timeline_scale*3 + 1] = 0;
162 data[rs*i + frame*timeline_scale*3 + 2] = 0;
163 for (j = 1; j < timeline_scale; j++) {
164 data[rs*i + (frame*timeline_scale+j)*3 + 0] = r;
165 data[rs*i + (frame*timeline_scale+j)*3 + 1] = g;
166 data[rs*i + (frame*timeline_scale+j)*3 + 2] = b;
169 if (frame_list && frame_list[frame].keyframe) {
173 for (i = 0; i < timeline_scale/2; i++) {
174 for (j = i + 1; j < timeline_scale - i; j++) {
175 data[rs*i + (frame*timeline_scale+j)*3 + 0] = r;
176 data[rs*i + (frame*timeline_scale+j)*3 + 1] = g;
177 data[rs*i + (frame*timeline_scale+j)*3 + 2] = b;
179 data[rs*(timeline_height-1-i) + (frame*timeline_scale+j)*3 + 0] = r;
180 data[rs*(timeline_height-1-i) + (frame*timeline_scale+j)*3 + 1] = g;
181 data[rs*(timeline_height-1-i) + (frame*timeline_scale+j)*3 + 2] = b;
187 /* get path of given file name */
188 static const char *get_path(const char *filename)
190 static char path[256];
193 strcpy(path, filename);
194 /* remove until DIR_SEPERATOR */
196 if (path[strlen(path) - 1] == DIR_SEPERATOR)
198 path[strlen(path) - 1] = '\0';
204 /* load directory and create pixbuf */
205 void create_timeline(const char *filename)
209 char temp[256], suffix[256];
216 while ((q = strchr(p, '.')))
219 printerror("File '%s' does not have a 'prefix.suffix' format\n", filename);
222 strcpy(suffix, p - 1);
225 if ((strlen(filename) < 5 || !!strcmp(suffix, ".ppm"))) {
226 printerror("File '%s' does not have '.ppm' suffix\n", filename);
236 p = filename + strlen(filename) - strlen(suffix);
237 while (p != filename) {
239 if (*p < '0' || *p > '9') {
244 if (*p < '0' || *p > '9') {
246 frame_list = malloc(sizeof(struct frame_list));
247 memset(frame_list, 0, sizeof(struct frame_list));
248 strcpy(frame_list[0].filename, filename);
251 /* create list of files that have same base name, same number of digits and suffix */
252 int suffix_offset = strlen(filename) - strlen(suffix);
253 int digits_offset = p - filename;
254 int digits = filename + strlen(filename) - strlen(suffix) - p;
255 const char *path = get_path(filename);
256 dir_t *dir_head = fetch_dir(path), *dir, **dirp;
263 /* remove files that do not have equal prefix */
264 if (!!strncmp(filename, dir->name, p - filename)) {
272 /* remove files that have no digits where expected */
273 for (i = 0; i < digits; i++) {
274 if (dir->name[digits_offset+i] < '0' || dir->name[digits_offset+i] > '9')
280 /* remove files that have different suffix */
281 if (!!strcmp(suffix, dir->name + suffix_offset)) {
297 frame_list = malloc(sizeof(struct frame_list) * count);
298 memset(frame_list, 0, sizeof(struct frame_list) * count);
300 for (i = 0; i < count; i++) {
301 strcpy(frame_list[i].filename, dir->name);
304 timeline_frames = count;
307 /* get marked frames */
308 for (i = 0; i < timeline_frames; i++) {
309 sprintf(temp, "%s_marked", frame_list[i].filename);
310 frame_list[i].marked = 0;
311 fp = fopen(temp, "r");
315 frame_list[i].marked = 1;
321 if (timeline_frames == 0)
324 if (timeline_frames > 1)
325 gtk_widget_show(timeline_scroll);
327 timeline_width = timeline_frames * timeline_scale;
329 timeline_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, timeline_width, timeline_height);
331 for (i = 0; i < timeline_frames; i++)
332 draw_timeline_frame(i);
334 gtk_widget_set_size_request(timeline_drawing_area, timeline_width, timeline_height);
337 /* disable optical flow and set default */
344 load_settings(frame_list[0].filename);
345 load_palette(frame_list[0].filename);
346 for (i = 0; i < 255; i++)
352 void destroy_timeline(void)
354 gtk_widget_hide(timeline_scroll);
356 if (!timeline_pixbuf)
359 g_object_unref(timeline_pixbuf);
360 timeline_pixbuf = NULL;
365 timeline_selected = 0;
368 /* draw (area) of pixbuf */
369 void draw_timeline(int x, int y, int w, int h)
371 GdkDrawable *draw = gtk_widget_get_window(timeline_drawing_area);
373 if (!timeline_pixbuf)
378 if (x >= timeline_width)
382 if (y >= timeline_height)
384 if (x + w > timeline_width)
385 w = timeline_width - x;
386 if (y + h > timeline_height)
387 h = timeline_height - y;
389 //printf("%d %d %d %d\n", x, y, w, h);
391 if (!timeline_pixbuf)
394 gdk_draw_pixbuf(draw, NULL, timeline_pixbuf, x, y, x, y, w, h, GDK_RGB_DITHER_NONE, 0, 0);
397 int timeline_select_and_save(int old_frame, int new_frame)
400 /* no frame loaded, no list */
401 if (!frame_list|| !img_pixbuf)
405 if (anything_modified) {
406 if (img_mark_buffer) {
407 if (save_marked(img_mark_buffer, img_width, img_height, frame_list[old_frame].filename) > 0)
408 frame_list[old_frame].marked = 1;
410 frame_list[old_frame].marked = 0;
414 save_palette(frame_list[0].filename);
415 if (timeline_frames > 1)
416 save_settings(frame_list[0].filename);
421 timeline_selected = new_frame;
423 create_image(frame_list[new_frame].filename, 0);
425 if (flowview && flow_enable && img_grey_buffer)
427 (new_frame > 0) ? frame_list[new_frame - 1].filename : NULL,
428 (new_frame < timeline_frames - 1) ? frame_list[new_frame + 1].filename : NULL,
430 img_width, img_height,
436 if (timeline_frames > 1) {
437 GdkDrawable *draw = gtk_widget_get_window(timeline_drawing_area);
438 draw_timeline_frame(old_frame);
439 draw_timeline_frame(new_frame);
440 gdk_draw_pixbuf(draw, NULL, timeline_pixbuf, 0, 0, 0, 0, timeline_width, timeline_height, GDK_RGB_DITHER_NONE, 0, 0);
443 /* adjust position of timeline scroll */
445 GtkAdjustment *adjustment;
447 x = new_frame * timeline_scale;
448 w = timeline_scroll->allocation.width - timeline_scale - 4;
449 adjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(timeline_scroll));
450 pos = gtk_adjustment_get_value(adjustment);
452 gtk_adjustment_set_value(adjustment, x);
453 gtk_scrolled_window_set_hadjustment(GTK_SCROLLED_WINDOW(timeline_scroll), adjustment);
456 gtk_adjustment_set_value(adjustment, pos + x + - (pos + w));
457 gtk_scrolled_window_set_hadjustment(GTK_SCROLLED_WINDOW(timeline_scroll), adjustment);
463 /* while pointing at timeline, show current frame that we point to */
464 int timeline_point(int x, int y)
466 int frame = x / timeline_scale;
468 if (x < 0 || y < 0 || frame < 0 || frame >= timeline_frames) {
469 timeline_show_name(timeline_selected);
473 timeline_show_name(frame);
477 void timeline_show_name(int frame)
485 if (frame != timeline_selected) {
486 sprintf(text, "Click to select frame %d", frame);
488 p = frame_list[frame].filename;
489 while (strchr(p, DIR_SEPERATOR))
490 p = strchr(p, DIR_SEPERATOR) + 1;
491 if (timeline_frames > 1)
492 sprintf(text, "Frame %d: %s", frame, p);
495 if (img_scale_x != 16)
496 sprintf(strchr(text, '\0'), " (%d%%)", img_scale_x*100/16);
498 gtk_label_set_text(img_label, text);
501 int timeline_clicked(int x, int y)
503 int old_frame = timeline_selected;
504 int new_frame = x / timeline_scale;
508 if (new_frame >= timeline_frames)
511 if (old_frame == new_frame)
514 return timeline_select_and_save(old_frame, new_frame);
518 /* get filename of first grey image directory */
519 static char *get_sequence_name(const char *filename)
521 static char name[256];
524 strcpy(name, get_path(filename));
525 /* add palette name */
526 strcat(name, "sequence");
531 int save_sequence(void)
540 if (timeline_frames <= 1)
543 name = get_sequence_name(frame_list[0].filename);
544 // printf("save sequence '%s'\n", name);
545 fp = fopen(name, "w");
547 printf("failed to save sequence '%s'\n", name);
550 for (i = 0; i < timeline_frames; i++) {
551 p = frame_list[i].filename;
552 while (p && strchr(p, DIR_SEPERATOR))
553 p = strchr(p, DIR_SEPERATOR) + 1;
554 fprintf(fp, "\"%s\"%s\n", p, (frame_list[i].keyframe) ? " keyframe" : "");
561 int load_sequence(void)
572 if (timeline_frames <= 1)
575 name = get_sequence_name(frame_list[0].filename);
576 // printf("load sequence '%s'\n", name);
577 fp = fopen(name, "r");
579 printf("no sequence file '%s' created yet\n", name);
582 for (i = 0; i < timeline_frames; i++) {
583 rc = fgets(buffer, sizeof(buffer), fp);
586 p = strchr(buffer + 1, '\"');
590 if (strstr(p, "keyframe"))
591 frame_list[i].keyframe = 1;
593 frame_list[i].keyframe = 0;
600 void toggle_keyframe(void)
602 if (!frame_list|| !img_pixbuf)
605 anything_modified = 1;
607 GdkDrawable *draw = gtk_widget_get_window(timeline_drawing_area);
609 frame_list[timeline_selected].keyframe = 1 - frame_list[timeline_selected].keyframe;
610 draw_timeline_frame(timeline_selected);
611 gdk_draw_pixbuf(draw, NULL, timeline_pixbuf, 0, 0, 0, 0, timeline_width, timeline_height, GDK_RGB_DITHER_NONE, 0, 0);