mirror of
https://gitlab.com/thebiblelover7/dotfiles.git
synced 2025-09-14 07:33:49 +00:00
initial commit
This commit is contained in:
@@ -0,0 +1,241 @@
|
||||
'use strict';
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
|
||||
const Config = imports.config;
|
||||
const PluginBase = imports.service.plugin;
|
||||
|
||||
|
||||
var Metadata = {
|
||||
label: _('Photo'),
|
||||
description: _('Request the paired device to take a photo and transfer it to this PC'),
|
||||
id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Photo',
|
||||
incomingCapabilities: [
|
||||
'kdeconnect.photo',
|
||||
'kdeconnect.photo.request',
|
||||
],
|
||||
outgoingCapabilities: [
|
||||
'kdeconnect.photo',
|
||||
'kdeconnect.photo.request',
|
||||
],
|
||||
actions: {
|
||||
photo: {
|
||||
label: _('Photo'),
|
||||
icon_name: 'camera-photo-symbolic',
|
||||
|
||||
parameter_type: null,
|
||||
incoming: ['kdeconnect.photo'],
|
||||
outgoing: ['kdeconnect.photo.request'],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Photo Plugin
|
||||
* https://github.com/KDE/kdeconnect-kde/tree/master/plugins/photo
|
||||
*
|
||||
* TODO: use Cheese?
|
||||
* check for /dev/video*
|
||||
*/
|
||||
var Plugin = GObject.registerClass({
|
||||
GTypeName: 'GSConnectPhotoPlugin',
|
||||
}, class Plugin extends PluginBase.Plugin {
|
||||
|
||||
_init(device) {
|
||||
super._init(device, 'photo');
|
||||
|
||||
// A reusable launcher for silence procs
|
||||
this._launcher = new Gio.SubprocessLauncher({
|
||||
flags: (Gio.SubprocessFlags.STDOUT_SILENCE |
|
||||
Gio.SubprocessFlags.STDERR_SILENCE),
|
||||
});
|
||||
}
|
||||
|
||||
handlePacket(packet) {
|
||||
switch (packet.type) {
|
||||
case 'kdeconnect.photo':
|
||||
this._receivePhoto(packet);
|
||||
break;
|
||||
|
||||
case 'kdeconnect.photo.request':
|
||||
this._sendPhoto(packet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure we have a directory set for storing files that exists.
|
||||
*
|
||||
* @return {string} An absolute directory path
|
||||
*/
|
||||
_ensureReceiveDirectory() {
|
||||
if (this._receiveDir !== undefined)
|
||||
return this._receiveDir;
|
||||
|
||||
// Ensure a directory is set
|
||||
this._receiveDir = this.settings.get_string('receive-directory');
|
||||
|
||||
if (this._receiveDir === '') {
|
||||
this._receiveDir = GLib.get_user_special_dir(
|
||||
GLib.UserDirectory.DIRECTORY_PICTURES
|
||||
);
|
||||
|
||||
// Fallback to ~/Pictures
|
||||
const homeDir = GLib.get_home_dir();
|
||||
|
||||
if (!this._receiveDir || this._receiveDir === homeDir) {
|
||||
this._receiveDir = GLib.build_filenamev([homeDir, 'Pictures']);
|
||||
this.settings.set_string('receive-directory', this._receiveDir);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the directory exists
|
||||
if (!GLib.file_test(this._receiveDir, GLib.FileTest.IS_DIR))
|
||||
GLib.mkdir_with_parents(this._receiveDir, 448);
|
||||
|
||||
return this._receiveDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a GFile for @filename, while ensuring the directory exists and the
|
||||
* file is unique.
|
||||
*
|
||||
* @param {string} filename - A filename (eg. `image.jpg`)
|
||||
* @return {Gio.File} a file object
|
||||
*/
|
||||
_getFile(filename) {
|
||||
const dirpath = this._ensureReceiveDirectory();
|
||||
const basepath = GLib.build_filenamev([dirpath, filename]);
|
||||
let filepath = basepath;
|
||||
let copyNum = 0;
|
||||
|
||||
while (GLib.file_test(filepath, GLib.FileTest.EXISTS))
|
||||
filepath = `${basepath} (${++copyNum})`;
|
||||
|
||||
return Gio.File.new_for_path(filepath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive a photo taken by the remote device.
|
||||
*
|
||||
* @param {Core.Packet} packet - a `kdeconnect.photo`
|
||||
*/
|
||||
async _receivePhoto(packet) {
|
||||
let file, transfer;
|
||||
|
||||
try {
|
||||
// Remote device cancelled the photo operation
|
||||
if (packet.body.hasOwnProperty('cancel'))
|
||||
return;
|
||||
|
||||
// Open the target path and create a transfer
|
||||
file = this._getFile(packet.body.filename);
|
||||
|
||||
transfer = this.device.createTransfer();
|
||||
transfer.addFile(packet, file);
|
||||
|
||||
// Open the photo if successful, delete on failure
|
||||
await transfer.start();
|
||||
|
||||
const uri = file.get_uri();
|
||||
Gio.AppInfo.launch_default_for_uri_async(uri, null, null, null);
|
||||
} catch (e) {
|
||||
debug(e, this.device.name);
|
||||
|
||||
if (file)
|
||||
file.delete_async(GLib.PRIORITY_DEFAULT, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a photo using the Webcam and return the path.
|
||||
*
|
||||
* @param {Core.Packet} packet - A `kdeconnect.photo.request`
|
||||
* @return {Promise<string>} A file path
|
||||
*/
|
||||
_takePhoto(packet) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const time = GLib.DateTime.new_now_local().format('%T');
|
||||
const path = GLib.build_filenamev([GLib.get_tmp_dir(), `${time}.jpg`]);
|
||||
const proc = this._launcher.spawnv([
|
||||
Config.FFMPEG_PATH,
|
||||
'-f', 'video4linux2',
|
||||
'-ss', '0:0:2',
|
||||
'-i', '/dev/video0',
|
||||
'-frames', '1',
|
||||
path,
|
||||
]);
|
||||
|
||||
proc.wait_check_async(null, (proc, res) => {
|
||||
try {
|
||||
proc.wait_check_finish(res);
|
||||
resolve(path);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a photo to the remote device.
|
||||
*
|
||||
* @param {Core.Packet} packet - A `kdeconnect.photo.request`
|
||||
*/
|
||||
async _sendPhoto(packet) {
|
||||
if (this.settings.get_boolean('share-camera'))
|
||||
return;
|
||||
|
||||
let file, transfer;
|
||||
|
||||
try {
|
||||
// Take a photo
|
||||
const path = await this._takePhoto();
|
||||
|
||||
if (path.startsWith('file://'))
|
||||
file = Gio.File.new_for_uri(path);
|
||||
else
|
||||
file = Gio.File.new_for_path(path);
|
||||
|
||||
// Create the transfer
|
||||
transfer = this.device.createTransfer();
|
||||
|
||||
transfer.addFile({
|
||||
type: 'kdeconnect.photo',
|
||||
body: {
|
||||
filename: file.get_basename(),
|
||||
},
|
||||
}, file);
|
||||
|
||||
await transfer.start();
|
||||
} catch (e) {
|
||||
debug(e, this.device.name);
|
||||
|
||||
if (transfer) {
|
||||
this.device.showNotification({
|
||||
id: transfer.uuid,
|
||||
title: _('Transfer Failed'),
|
||||
// TRANSLATORS: eg. Failed to send "photo.jpg" to Google Pixel
|
||||
body: _('Failed to send “%s” to %s').format(
|
||||
file.get_basename(),
|
||||
this.device.name
|
||||
),
|
||||
icon: new Gio.ThemedIcon({name: 'dialog-warning-symbolic'}),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the remote device begin a photo operation.
|
||||
*/
|
||||
photo() {
|
||||
this.device.sendPacket({
|
||||
type: 'kdeconnect.photo.request',
|
||||
body: {},
|
||||
});
|
||||
}
|
||||
});
|
Reference in New Issue
Block a user