From 82a163cbae3c7f05125e435346df3c54013d5200 Mon Sep 17 00:00:00 2001 From: Al Poole Date: Sat, 5 Aug 2017 23:11:32 +0900 Subject: [PATCH] Add support for "Open with (folder)" as well as directories passed via the command line. Reviewers: raster Tags: #rage Differential Revision: https://phab.enlightenment.org/D4820 --- data/desktop/rage.desktop | 2 +- src/bin/main.c | 221 ++++++++++++++++++++++++++++++++++---- src/bin/winvid.c | 14 +++ src/bin/winvid.h | 1 + 4 files changed, 215 insertions(+), 23 deletions(-) diff --git a/data/desktop/rage.desktop b/data/desktop/rage.desktop index fcb9598..7fcf000 100644 --- a/data/desktop/rage.desktop +++ b/data/desktop/rage.desktop @@ -10,4 +10,4 @@ Exec=rage %U Icon=rage Categories=AudioVideo;Player; StartupWMClass=rage -MimeType=application/mxf;application/ogg;application/ram;application/sdp;application/smil;application/smil+xml;application/vnd.ms-wpl;application/vnd.rn-realmedia;application/x-extension-m4a;application/x-extension-mp4;application/x-flac;application/x-flash-video;application/x-matroska;application/x-netshow-channel;application/x-ogg;application/x-quicktime-media-link;application/x-quicktimeplayer;application/x-shorten;application/x-smil;application/xspf+xml;audio/3gpp;audio/ac3;audio/AMR;audio/AMR-WB;audio/basic;audio/midi;audio/mp4;audio/mpeg;audio/mpegurl;audio/ogg;audio/prs.sid;audio/vnd.rn-realaudio;audio/x-aiff;audio/x-ape;audio/x-flac;audio/x-gsm;audio/x-it;audio/x-m4a;audio/x-matroska;audio/x-mod;audio/x-mp3;audio/x-mpeg;audio/x-mpegurl;audio/x-ms-asf;audio/x-ms-asx;audio/x-ms-wax;audio/x-ms-wma;audio/x-musepack;audio/x-pn-aiff;audio/x-pn-au;audio/x-pn-realaudio;audio/x-pn-realaudio-plugin;audio/x-pn-wav;audio/x-pn-windows-acm;audio/x-realaudio;audio/x-real-audio;audio/x-sbc;audio/x-scpls;audio/x-speex;audio/x-tta;audio/x-wav;audio/x-wavpack;audio/x-vorbis;audio/x-vorbis+ogg;audio/x-xm;image/vnd.rn-realpix;image/x-pict;misc/ultravox;text/google-video-pointer;text/x-google-video-pointer;video/3gpp;video/dv;video/fli;video/flv;video/mp2t;video/mp4;video/mp4v-es;video/mpeg;video/msvideo;video/ogg;video/quicktime;video/vivo;video/vnd.divx;video/vnd.rn-realvideo;video/vnd.vivo;video/webm;video/x-anim;video/x-avi;video/x-flc;video/x-fli;video/x-flic;video/x-flv;video/x-m4v;video/x-matroska;video/x-mpeg;video/x-ms-asf;video/x-ms-asx;video/x-msvideo;video/x-ms-wm;video/x-ms-wmv;video/x-ms-wmx;video/x-ms-wvx;video/x-nsv;video/x-ogm+ogg;video/x-theora+ogg;video/x-totem-stream;x-content/video-dvd;x-content/video-vcd;x-content/video-svcd; +MimeType=application/mxf;application/ogg;application/ram;application/sdp;application/smil;application/smil+xml;application/vnd.ms-wpl;application/vnd.rn-realmedia;application/x-extension-m4a;application/x-extension-mp4;application/x-flac;application/x-flash-video;application/x-matroska;application/x-netshow-channel;application/x-ogg;application/x-quicktime-media-link;application/x-quicktimeplayer;application/x-shorten;application/x-smil;application/xspf+xml;audio/3gpp;audio/ac3;audio/AMR;audio/AMR-WB;audio/basic;audio/midi;audio/mp4;audio/mpeg;audio/mpegurl;audio/ogg;audio/prs.sid;audio/vnd.rn-realaudio;audio/x-aiff;audio/x-ape;audio/x-flac;audio/x-gsm;audio/x-it;audio/x-m4a;audio/x-matroska;audio/x-mod;audio/x-mp3;audio/x-mpeg;audio/x-mpegurl;audio/x-ms-asf;audio/x-ms-asx;audio/x-ms-wax;audio/x-ms-wma;audio/x-musepack;audio/x-pn-aiff;audio/x-pn-au;audio/x-pn-realaudio;audio/x-pn-realaudio-plugin;audio/x-pn-wav;audio/x-pn-windows-acm;audio/x-realaudio;audio/x-real-audio;audio/x-sbc;audio/x-scpls;audio/x-speex;audio/x-tta;audio/x-wav;audio/x-wavpack;audio/x-vorbis;audio/x-vorbis+ogg;audio/x-xm;image/vnd.rn-realpix;image/x-pict;misc/ultravox;text/google-video-pointer;text/x-google-video-pointer;video/3gpp;video/dv;video/fli;video/flv;video/mp2t;video/mp4;video/mp4v-es;video/mpeg;video/msvideo;video/ogg;video/quicktime;video/vivo;video/vnd.divx;video/vnd.rn-realvideo;video/vnd.vivo;video/webm;video/x-anim;video/x-avi;video/x-flc;video/x-fli;video/x-flic;video/x-flv;video/x-m4v;video/x-matroska;video/x-mpeg;video/x-ms-asf;video/x-ms-asx;video/x-msvideo;video/x-ms-wm;video/x-ms-wmv;video/x-ms-wmx;video/x-ms-wvx;video/x-nsv;video/x-ogm+ogg;video/x-theora+ogg;video/x-totem-stream;x-content/video-dvd;x-content/video-vcd;x-content/video-svcd;inode/directory; diff --git a/src/bin/main.c b/src/bin/main.c index a353f6a..a855b09 100644 --- a/src/bin/main.c +++ b/src/bin/main.c @@ -6,6 +6,140 @@ #include "browser.h" #include "config.h" +#define DEPTH_DEFAULT 99 + +typedef struct { + Evas_Object *win; + char *realpath; + int depth; + int depth_max; + Eina_Bool have_media_files; +} Recursion_Data; + +static Eina_Bool +_check_recursion(const char *path, unsigned int depth, unsigned int limit) +{ + const char *home = eina_environment_home_get(); + + if (limit == 0) + return EINA_TRUE; + + if (depth >= limit) + return EINA_FALSE; + + if (!path[0] || !path[1]) + return EINA_FALSE; + + if ((home) && (!strcmp(home, path))) + return EINA_FALSE; + + return EINA_TRUE; +} + +static int +_cb_sort(const void *d1, const void *d2) +{ + const char *text = d1; + const char *text2 = d2; + + if (!text) return 1; + if (!text2) return -1; + + return strcmp(text, text2); +} + +static void +_files_recursion(Ecore_Thread *thread, const char *path, Recursion_Data *recursion) +{ + Eina_Iterator *it; + Eina_File_Direct_Info *info; + char *dir_path; + Eina_List *files = NULL, *dirs = NULL; + + if (!ecore_file_is_dir(path)) return; + + if (!_check_recursion(path, recursion->depth, recursion->depth_max)) return; + + it = eina_file_stat_ls(path); + EINA_ITERATOR_FOREACH(it, info) + { + if (info->type == EINA_FILE_DIR) + { + dirs = eina_list_append(dirs, eina_stringshare_add(info->path)); + } + if (info->type == EINA_FILE_REG) + { + files = eina_list_append(files, eina_stringshare_add(info->path)); + } + } + + eina_iterator_free(it); + + if (files) + { + files = eina_list_sort(files, eina_list_count(files), _cb_sort); + ecore_thread_feedback(thread, files); + } + + dirs = eina_list_sort(dirs, eina_list_count(dirs), _cb_sort); + + EINA_LIST_FREE(dirs, dir_path) + { + recursion->depth++; + _files_recursion(thread, dir_path, recursion); + recursion->depth--; + eina_stringshare_del(dir_path); + } +} + +static void +_cb_start_recursion(void *data, Ecore_Thread *thread) +{ + Recursion_Data *recursion = data; + + _files_recursion(thread, recursion->realpath, recursion); +} + +static void _cb_end_recursion(void *data, Ecore_Thread *thread) +{ + Recursion_Data *recursion = data; + + free(recursion->realpath); + free(recursion); +} + +static void _cb_feedback_recursion(void *data, Ecore_Thread *thread, void *msg) +{ + Recursion_Data *recursion; + Eina_List *list; + const char *mime; + const char *path; + Eina_Bool update_content = EINA_FALSE; + + list = msg; + recursion = data; + + EINA_LIST_FREE(list, path) + { + mime = efreet_mime_type_get(path); + if (!strncmp(mime, "audio/", 6) || !strncmp(mime, "video/", 6)) + { + update_content = EINA_TRUE; + win_list_hide(recursion->win); + win_video_insert_append(recursion->win, path); + if (!recursion->have_media_files) + { + win_video_first(recursion->win); + recursion->have_media_files = EINA_TRUE; + } + } + eina_stringshare_del(path); + } + + if (update_content) + win_list_content_update(recursion->win); +} + static Eina_Bool _cb_show_timeout(void *data) { @@ -29,15 +163,15 @@ elm_main(int argc, char **argv) { Evas_Object *win; char buf[4096]; - Eina_List *list = NULL; int i; - Inf *inf; Config *config; - Winvid_Entry *vid = NULL; + Inf *inf; Eina_Bool fullscreen = EINA_FALSE; - int file_num = 0; int rotation = 0; - + int depth_max = DEPTH_DEFAULT; + Recursion_Data *recursion = NULL; + Winvid_Entry *vid = NULL; + Eina_List *list = NULL; elm_need_efreet(); config_init(); config = config_get(); @@ -65,7 +199,10 @@ elm_main(int argc, char **argv) " rage file.mp4 -sub subs.srt file2.mp4 ...\n" " -rot 0/90/180/270\n" " Rotate output by the given rotation\n" - ); + " -d DEPTH\n" + " Set maximum level of recursion.\n" + " The default is %d. Set to 0 for unlimited.\n" + , DEPTH_DEFAULT); exit(0); } else if (!strcmp(argv[i], "-e")) @@ -81,6 +218,16 @@ elm_main(int argc, char **argv) { fullscreen = EINA_TRUE; } + else if (!strcmp(argv[i], "-d")) + { + if (i < (argc - 1)) + { + i++; + depth_max = atoi(argv[i]); + if (depth_max < 0 || depth_max > DEPTH_DEFAULT) + depth_max = DEPTH_DEFAULT; + } + } else if (!strcmp(argv[i], "-rot")) { if (i < (argc - 1)) @@ -99,12 +246,30 @@ elm_main(int argc, char **argv) } else { - vid = calloc(1, sizeof(Winvid_Entry)); - if (vid) + char *realpath = strdup(argv[i]); + Efreet_Uri *uri = efreet_uri_decode(realpath); + if (uri) { - file_num++; - vid->file = eina_stringshare_add(argv[i]); - list = eina_list_append(list, vid); + free(realpath); + realpath = ecore_file_realpath(uri->path); + efreet_uri_free(uri); + } + if (ecore_file_is_dir(realpath)) + { + recursion = calloc(1, sizeof(Recursion_Data)); + recursion->realpath = realpath; + recursion->depth_max = depth_max; + recursion->depth = 1; + } + else + { + vid = calloc(1, sizeof(Winvid_Entry)); + if (vid) + { + vid->file = eina_stringshare_add(realpath); + list = eina_list_append(list, vid); + } + free(realpath); } } } @@ -139,21 +304,33 @@ elm_main(int argc, char **argv) elm_win_rotation_set(win, rotation); win_video_init(win); - win_video_file_list_set(win, list); - EINA_LIST_FREE(list, vid) - { - if (vid->file) eina_stringshare_del(vid->file); - if (vid->sub) eina_stringshare_del(vid->sub); - if (vid->uri) efreet_uri_free(vid->uri); - free(vid); - } + inf = evas_object_data_get(win, "inf"); + + if (!list && !recursion) + inf->browse_mode = EINA_TRUE; if (fullscreen) elm_win_fullscreen_set(win, EINA_TRUE); - inf = evas_object_data_get(win, "inf"); - if (file_num <= 0) + if (list) + { + win_video_file_list_set(win, list); + EINA_LIST_FREE(list, vid) + { + if (vid->file) eina_stringshare_del(vid->file); + if (vid->sub) eina_stringshare_del(vid->sub); + if (vid->uri) efreet_uri_free(vid->uri); + free(vid); + } + } + else if (recursion) + { + recursion->win = win; + ecore_thread_feedback_run(_cb_start_recursion, _cb_feedback_recursion, + _cb_end_recursion, NULL, recursion, EINA_FALSE); + } + + if (inf->browse_mode) { - inf->browse_mode = EINA_TRUE; inf->sized = EINA_TRUE; browser_show(win); // elm_layout_signal_emit(inf->lay, "about,show", "rage"); diff --git a/src/bin/winvid.c b/src/bin/winvid.c index 051c921..7c72d90 100644 --- a/src/bin/winvid.c +++ b/src/bin/winvid.c @@ -274,6 +274,20 @@ win_video_insert(Evas_Object *win, const char *file) evas_object_data_set(win, "file_list", inf->file_list); } +void +win_video_insert_append(Evas_Object *win, const char *file) +{ + Inf *inf = evas_object_data_get(win, "inf"); + Winvid_Entry *vid; + + vid = calloc(1, sizeof(Winvid_Entry)); + vid->file = eina_stringshare_add(file); + vid->uri = efreet_uri_decode(vid->file); + + inf->file_list = eina_list_append(inf->file_list, vid); + evas_object_data_set(win, "file_list", inf->file_list); +} + void win_video_free(Evas_Object *win) { diff --git a/src/bin/winvid.h b/src/bin/winvid.h index 2881067..fc27097 100644 --- a/src/bin/winvid.h +++ b/src/bin/winvid.h @@ -11,6 +11,7 @@ typedef struct _Winvid_Entry void win_video_init(Evas_Object *win); void win_video_file_list_set(Evas_Object *win, Eina_List *list); void win_video_insert(Evas_Object *win, const char *file); +void win_video_insert_append(Evas_Object *win, const char *file); void win_video_free(Evas_Object *win); void win_video_goto(Evas_Object *win, Eina_List *l);