mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-30 07:42:23 +02:00
Support opening folders with media files
D&D folder with videos onto Clapper window to play them as video playlist. If folder contains exactly one video and subtitle file, then that video will be played with subtitles automatically applied.
This commit is contained in:
@@ -38,8 +38,7 @@ class ClapperApp extends AppBase
|
||||
{
|
||||
super.vfunc_open(files, hint);
|
||||
|
||||
this._openFiles(files);
|
||||
this.activate();
|
||||
this._openFilesAsync(files).then(() => this.activate()).catch(debug);
|
||||
}
|
||||
|
||||
_onWindowMap(window)
|
||||
|
@@ -1,5 +1,6 @@
|
||||
const { Gio, GLib, GObject, Gtk } = imports.gi;
|
||||
const Debug = imports.src.debug;
|
||||
const FileOps = imports.src.fileOps;
|
||||
const Menu = imports.src.menu;
|
||||
const Misc = imports.src.misc;
|
||||
|
||||
@@ -59,9 +60,18 @@ class ClapperAppBase extends Gtk.Application
|
||||
);
|
||||
}
|
||||
|
||||
_openFiles(files)
|
||||
async _openFilesAsync(files)
|
||||
{
|
||||
const [playlist, subs] = Misc.parsePlaylistFiles(files);
|
||||
const urisArr = [];
|
||||
|
||||
for(let file of files) {
|
||||
/* If file is not a dir its URI will be returned in an array */
|
||||
const uris = await FileOps.getDirFilesUrisPromise(file).catch(debug);
|
||||
if(uris && uris.length)
|
||||
urisArr.push(...uris);
|
||||
}
|
||||
|
||||
const [playlist, subs] = Misc.parsePlaylistFiles(urisArr);
|
||||
const { player } = this.active_window.get_child();
|
||||
|
||||
if(playlist && playlist.length)
|
||||
|
@@ -62,7 +62,7 @@ class ClapperFileChooser extends Gtk.FileChooserNative
|
||||
if(isHandlesOpen)
|
||||
application.open(filesArray, "");
|
||||
else
|
||||
application._openFiles(filesArray);
|
||||
application._openFilesAsync(filesArray);
|
||||
}
|
||||
|
||||
this.unref();
|
||||
|
@@ -12,6 +12,11 @@ const LocalFilePrototype = Gio.File.new_for_path('/').constructor.prototype;
|
||||
Gio._promisify(LocalFilePrototype, 'load_bytes_async', 'load_bytes_finish');
|
||||
Gio._promisify(LocalFilePrototype, 'make_directory_async', 'make_directory_finish');
|
||||
Gio._promisify(LocalFilePrototype, 'replace_contents_bytes_async', 'replace_contents_finish');
|
||||
Gio._promisify(LocalFilePrototype, 'query_info_async', 'query_info_finish');
|
||||
Gio._promisify(LocalFilePrototype, 'enumerate_children_async', 'enumerate_children_finish');
|
||||
|
||||
Gio._promisify(Gio.FileEnumerator.prototype, 'close_async', 'close_finish');
|
||||
Gio._promisify(Gio.FileEnumerator.prototype, 'next_files_async', 'next_files_finish');
|
||||
|
||||
function createCacheDirPromise()
|
||||
{
|
||||
@@ -126,3 +131,91 @@ function getFileContentsPromise(place, subdirName, fileName)
|
||||
.catch(err => reject(err));
|
||||
});
|
||||
}
|
||||
|
||||
function _getDirUrisPromise(dir, isDeep)
|
||||
{
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const enumerator = await dir.enumerate_children_async(
|
||||
'standard::name,standard::type',
|
||||
Gio.FileQueryInfoFlags.NONE,
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
null
|
||||
).catch(debug);
|
||||
|
||||
if(!enumerator)
|
||||
return reject(new Error('could not create file enumerator'));
|
||||
|
||||
const dirPath = dir.get_path();
|
||||
const arr = [];
|
||||
|
||||
debug(`enumerating files in dir: ${dirPath}`);
|
||||
|
||||
while(true) {
|
||||
const infos = await enumerator.next_files_async(
|
||||
1,
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
null
|
||||
).catch(debug);
|
||||
|
||||
if(!infos || !infos.length)
|
||||
break;
|
||||
|
||||
const fileUri = dir.get_uri() + '/' + infos[0].get_name();
|
||||
|
||||
if(infos[0].get_file_type() !== Gio.FileType.DIRECTORY) {
|
||||
arr.push(fileUri);
|
||||
continue;
|
||||
}
|
||||
if(!isDeep)
|
||||
continue;
|
||||
|
||||
const subDir = Misc.getFileFromLocalUri(fileUri);
|
||||
const subDirUris = await _getDirUrisPromise(subDir, isDeep).catch(debug);
|
||||
|
||||
if(subDirUris && subDirUris.length)
|
||||
arr.push(...subDirUris);
|
||||
}
|
||||
|
||||
const isClosed = await enumerator.close_async(
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
null
|
||||
).catch(debug);
|
||||
|
||||
if(isClosed)
|
||||
debug(`closed enumerator for dir: ${dirPath}`);
|
||||
else
|
||||
debug(new Error(`could not close file enumerator for dir: ${dirPath}`));
|
||||
|
||||
resolve(arr);
|
||||
});
|
||||
}
|
||||
|
||||
/* Either GioFile or URI for dir arg */
|
||||
function getDirFilesUrisPromise(dir, isDeep)
|
||||
{
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if(!dir.get_path)
|
||||
dir = Misc.getFileFromLocalUri(dir);
|
||||
if(!dir)
|
||||
return reject(new Error('invalid directory'));
|
||||
|
||||
const fileInfo = await dir.query_info_async(
|
||||
'standard::type',
|
||||
Gio.FileQueryInfoFlags.NONE,
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
null
|
||||
).catch(debug);
|
||||
|
||||
if(!fileInfo)
|
||||
return reject(new Error('no file type info'));
|
||||
|
||||
if(fileInfo.get_file_type() !== Gio.FileType.DIRECTORY)
|
||||
return resolve([dir.get_uri()]);
|
||||
|
||||
const arr = await _getDirUrisPromise(dir, isDeep).catch(debug);
|
||||
if(!arr || !arr.length)
|
||||
return reject(new Error('enumerated files list is empty'));
|
||||
|
||||
resolve(arr.sort());
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user