admin: add settings section
Signed-off-by: Varun Patil <varunpatil@ucla.edu>pull/563/head
parent
5e32987932
commit
f73b82bdd5
|
@ -47,6 +47,10 @@ Memories is a *batteries-included* photo management solution for Nextcloud with
|
||||||
<command>OCA\Memories\Command\PlacesSetup</command>
|
<command>OCA\Memories\Command\PlacesSetup</command>
|
||||||
<command>OCA\Memories\Command\MigrateGoogleTakeout</command>
|
<command>OCA\Memories\Command\MigrateGoogleTakeout</command>
|
||||||
</commands>
|
</commands>
|
||||||
|
<settings>
|
||||||
|
<admin>OCA\Memories\Settings\Admin</admin>
|
||||||
|
<admin-section>OCA\Memories\Settings\AdminSection</admin-section>
|
||||||
|
</settings>
|
||||||
<navigations>
|
<navigations>
|
||||||
<navigation>
|
<navigation>
|
||||||
<name>Memories</name>
|
<name>Memories</name>
|
||||||
|
|
|
@ -83,6 +83,8 @@ return [
|
||||||
|
|
||||||
// Config API
|
// Config API
|
||||||
['name' => 'Other#setUserConfig', 'url' => '/api/config/{key}', 'verb' => 'PUT'],
|
['name' => 'Other#setUserConfig', 'url' => '/api/config/{key}', 'verb' => 'PUT'],
|
||||||
|
['name' => 'Other#getSystemConfig', 'url' => '/api/system-config', 'verb' => 'GET'],
|
||||||
|
['name' => 'Other#setSystemConfig', 'url' => '/api/system-config/{key}', 'verb' => 'PUT'],
|
||||||
|
|
||||||
// Service worker
|
// Service worker
|
||||||
['name' => 'Other#serviceWorker', 'url' => '/service-worker.js', 'verb' => 'GET'],
|
['name' => 'Other#serviceWorker', 'url' => '/service-worker.js', 'verb' => 'GET'],
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
id="svg2"
|
||||||
|
sodipodi:docname="app.svg"
|
||||||
|
viewBox="0 0 650 650"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||||
|
inkscape:export-filename="C:\Users\varun\Downloads\app.png"
|
||||||
|
inkscape:export-xdpi="44.700001"
|
||||||
|
inkscape:export-ydpi="44.700001"
|
||||||
|
width="650"
|
||||||
|
height="650"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<defs
|
||||||
|
id="defs16" />
|
||||||
|
<title
|
||||||
|
id="title3629">Camera</title>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
bordercolor="#666666"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
inkscape:window-height="991"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:zoom="0.35355339"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
showgrid="false"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:cx="89.095455"
|
||||||
|
inkscape:cy="148.49242"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0" />
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="bg"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
transform="translate(-151.94602,-318.77312)">
|
||||||
|
<path
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke-width:2.13333"
|
||||||
|
d="m 197.73165,860.67627 c -18.61338,-6.82684 -36.75782,-26.01129 -41.74653,-44.13937 -1.829,-6.64627 -2.33554,-48.09549 -1.88392,-154.15716 l 0.6177,-145.06666 4.93339,-10.01572 c 16.12451,-32.73596 27.47173,-36.77498 105.46662,-37.5407 l 63.46666,-0.62308 0.0128,-8.97692 c 0.0286,-21.53158 14.50791,-42.38798 33.30228,-47.9693 14.35532,-4.26306 208.49298,-3.66246 220.80965,0.68312 18.77632,6.62468 31.61107,24.94489 31.69598,45.2426 l 0.0459,11.2 h 65.04378 c 84.02378,0 95.74352,3.94726 112.45,37.8737 l 7.03955,14.29547 0.63814,134.29886 c 0.8464,178.12549 -1.26265,188.01876 -43.44674,203.80184 -15.31511,5.73014 -542.98637,6.76314 -558.44531,1.09332 z M 510.98557,774.6975 c 88.64983,-31.88148 102.45316,-145.666 23.87294,-196.79099 -102.54562,-66.7171 -220.77781,66.53341 -142.78216,160.91892 29.81079,36.0752 77.95716,50.59979 118.90922,35.87207 z m -60.78933,-42.43819 c -25.88523,-9.13355 -42.15328,-37.1623 -39.9792,-68.88145 5.67091,-82.737 128.4049,-82.50709 133.37154,0.24984 3.13721,52.27458 -43.21406,86.33693 -93.39234,68.63161 z"
|
||||||
|
id="path3940" />
|
||||||
|
<path
|
||||||
|
style="fill:#000000;stroke-width:2.13333"
|
||||||
|
id="path3510"
|
||||||
|
d="" />
|
||||||
|
<path
|
||||||
|
style="fill:#000000;stroke-width:2.13333"
|
||||||
|
id="path3490"
|
||||||
|
d="" />
|
||||||
|
<path
|
||||||
|
style="fill:#000000;stroke-width:2.13333"
|
||||||
|
id="path3452"
|
||||||
|
d="" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="layer2"
|
||||||
|
inkscape:label="camera"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
transform="translate(-151.94602,-318.77312)" />
|
||||||
|
<metadata
|
||||||
|
id="metadata13">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:title>Camera</dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
|
@ -56,6 +56,59 @@ class OtherController extends GenericApiController
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @AdminRequired
|
||||||
|
*
|
||||||
|
* @NoCSRFRequired
|
||||||
|
*/
|
||||||
|
public function getSystemConfig(): Http\Response
|
||||||
|
{
|
||||||
|
return Util::guardEx(function () {
|
||||||
|
$config = [];
|
||||||
|
foreach (Util::systemConfigDefaults() as $key => $default) {
|
||||||
|
$config[$key] = $this->config->getSystemValue($key, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JSONResponse($config, Http::STATUS_OK);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @AdminRequired
|
||||||
|
*
|
||||||
|
* @NoCSRFRequired
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
|
*/
|
||||||
|
public function setSystemConfig(string $key, $value): Http\Response
|
||||||
|
{
|
||||||
|
return Util::guardEx(function () use ($key, $value) {
|
||||||
|
// Make sure not running in read-only mode
|
||||||
|
if ($this->config->getSystemValue('memories.readonly', false)) {
|
||||||
|
throw Exceptions::Forbidden('Cannot change settings in readonly mode');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the key is valid
|
||||||
|
$defaults = Util::systemConfigDefaults();
|
||||||
|
if (!\array_key_exists($key, $defaults)) {
|
||||||
|
throw Exceptions::BadRequest('Invalid key');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the value has the same type as the default value
|
||||||
|
if (\gettype($value) !== \gettype($defaults[$key])) {
|
||||||
|
throw Exceptions::BadRequest('Invalid value type');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($value === $defaults[$key]) {
|
||||||
|
$this->config->deleteSystemValue($key);
|
||||||
|
} else {
|
||||||
|
$this->config->setSystemValue($key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JSONResponse([], Http::STATUS_OK);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace OCA\Memories\Settings;
|
||||||
|
|
||||||
|
use OCP\AppFramework\Http\TemplateResponse;
|
||||||
|
use OCP\IConfig;
|
||||||
|
use OCP\IL10N;
|
||||||
|
use OCP\Settings\ISettings;
|
||||||
|
|
||||||
|
class Admin implements ISettings
|
||||||
|
{
|
||||||
|
/** @var IConfig */
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
/** @var IL10N */
|
||||||
|
private $l;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
IConfig $config,
|
||||||
|
IL10N $l
|
||||||
|
) {
|
||||||
|
$this->config = $config;
|
||||||
|
$this->l = $l;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return TemplateResponse
|
||||||
|
*/
|
||||||
|
public function getForm()
|
||||||
|
{
|
||||||
|
$parameters = [
|
||||||
|
];
|
||||||
|
|
||||||
|
\OCP\Util::addScript('memories', 'memories-main');
|
||||||
|
|
||||||
|
return new TemplateResponse('memories', 'admin', $parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSection()
|
||||||
|
{
|
||||||
|
return 'memories';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPriority()
|
||||||
|
{
|
||||||
|
return 50;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace OCA\Memories\Settings;
|
||||||
|
|
||||||
|
use OCP\AppFramework\Http\TemplateResponse;
|
||||||
|
use OCP\IL10N;
|
||||||
|
use OCP\IURLGenerator;
|
||||||
|
use OCP\Settings\IIconSection;
|
||||||
|
|
||||||
|
class AdminSection implements IIconSection
|
||||||
|
{
|
||||||
|
/** @var IL10N */
|
||||||
|
private $l;
|
||||||
|
|
||||||
|
/** @var IURLGenerator */
|
||||||
|
private $urlGenerator;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
IL10N $l,
|
||||||
|
IURLGenerator $urlGenerator
|
||||||
|
) {
|
||||||
|
$this->l = $l;
|
||||||
|
$this->urlGenerator = $urlGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return TemplateResponse
|
||||||
|
*/
|
||||||
|
public function getForm()
|
||||||
|
{
|
||||||
|
$parameters = [
|
||||||
|
];
|
||||||
|
|
||||||
|
return new TemplateResponse('memories', 'admin', $parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getID()
|
||||||
|
{
|
||||||
|
return 'memories';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->l->t('Memories');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPriority()
|
||||||
|
{
|
||||||
|
return 75;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIcon()
|
||||||
|
{
|
||||||
|
return $this->urlGenerator->imagePath('memories', 'app-dark.svg');
|
||||||
|
}
|
||||||
|
}
|
64
lib/Util.php
64
lib/Util.php
|
@ -279,7 +279,69 @@ class Util
|
||||||
*/
|
*/
|
||||||
public static function placesGISType(): int
|
public static function placesGISType(): int
|
||||||
{
|
{
|
||||||
return (int) \OC::$server->get(\OCP\IConfig::class)->getSystemValue('memories.gis_type', -1);
|
return self::getSystemConfig('memories.gis_type');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a system config key with the correct default.
|
||||||
|
*
|
||||||
|
* @param null|mixed $default
|
||||||
|
*/
|
||||||
|
public static function getSystemConfig(string $key, $default = null)
|
||||||
|
{
|
||||||
|
$config = \OC::$server->get(\OCP\IConfig::class);
|
||||||
|
|
||||||
|
return $config->getSystemValue($key, $default ?? self::systemConfigDefaults()[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get list of defaults for all system config keys. */
|
||||||
|
public static function systemConfigDefaults(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
// Places database type identifier
|
||||||
|
'memories.gis_type' => -1,
|
||||||
|
|
||||||
|
// Disable transcoding
|
||||||
|
'memories.vod.disable' => true,
|
||||||
|
|
||||||
|
// VA-API configuration options
|
||||||
|
'memories.vod.vaapi' => false, // Transcode with VA-API
|
||||||
|
'memories.vod.vaapi.low_power' => false, // Use low_power mode for VA-API
|
||||||
|
|
||||||
|
// NVENC configuration options
|
||||||
|
'memories.vod.nvenc' => false, // Transcode with NVIDIA NVENC
|
||||||
|
'memories.vod.nvenc.temporal_aq' => false,
|
||||||
|
'memories.vod.nvenc.scale' => 'npp', // npp or cuda
|
||||||
|
|
||||||
|
// Paths to ffmpeg and ffprobe binaries
|
||||||
|
'memories.vod.ffmpeg' => '',
|
||||||
|
'memories.vod.ffprobe' => '',
|
||||||
|
|
||||||
|
// Path to go-vod binary
|
||||||
|
'memories.vod.path' => '',
|
||||||
|
|
||||||
|
// Path to use for transcoded files (/tmp/go-vod/instanceid)
|
||||||
|
// Make sure this has plenty of space
|
||||||
|
'memories.vod.tempdir' => '',
|
||||||
|
|
||||||
|
// Bind address to use when starting the transcoding server
|
||||||
|
'memories.vod.bind' => '127.0.0.1:47788',
|
||||||
|
|
||||||
|
// Address used to connect to the transcoding server
|
||||||
|
// If not specified, the bind address above will be used
|
||||||
|
'memories.vod.connect' => '127.0.0.1:47788',
|
||||||
|
|
||||||
|
// Mark go-vod as external. If true, Memories will not attempt to
|
||||||
|
// start go-vod if it is not running already.
|
||||||
|
'memories.vod.external' => false,
|
||||||
|
|
||||||
|
// Set the default video quality for a first time user
|
||||||
|
// 0 => Auto (default)
|
||||||
|
// -1 => Original (max quality with transcoding)
|
||||||
|
// -2 => Direct (disable transcoding)
|
||||||
|
// 1080 => 1080p (and so on)
|
||||||
|
'memories.video_default_quality' => '0',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,384 @@
|
||||||
|
<template>
|
||||||
|
<div class="outer" v-if="loaded">
|
||||||
|
<div>
|
||||||
|
<h2>{{ t("memories", "Video Streaming") }}</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
{{
|
||||||
|
t(
|
||||||
|
"memories",
|
||||||
|
"Live transcoding provides for adaptive streaming of videos using HLS."
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
<br />
|
||||||
|
{{
|
||||||
|
t(
|
||||||
|
"memories",
|
||||||
|
"Note that this may be very CPU intensive without hardware acceleration."
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
|
||||||
|
<NcCheckboxRadioSwitch
|
||||||
|
:checked.sync="enableTranscoding"
|
||||||
|
@update:checked="update('enableTranscoding')"
|
||||||
|
type="switch"
|
||||||
|
>
|
||||||
|
{{ t("memories", "Enable Transcoding") }}
|
||||||
|
</NcCheckboxRadioSwitch>
|
||||||
|
|
||||||
|
<NcTextField
|
||||||
|
:label="t('memories', 'ffmpeg path')"
|
||||||
|
:label-visible="true"
|
||||||
|
:value="ffmpegPath"
|
||||||
|
@change="update('ffmpegPath', $event.target.value)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<NcTextField
|
||||||
|
:label="t('memories', 'ffprobe path')"
|
||||||
|
:label-visible="true"
|
||||||
|
:value="ffprobePath"
|
||||||
|
@change="update('ffprobePath', $event.target.value)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
{{ t("memories", "Global default video quality (user may override)") }}
|
||||||
|
<NcCheckboxRadioSwitch
|
||||||
|
:checked.sync="videoDefaultQuality"
|
||||||
|
value="0"
|
||||||
|
name="vdq_radio"
|
||||||
|
type="radio"
|
||||||
|
@update:checked="update('videoDefaultQuality')"
|
||||||
|
>{{ t("memories", "Auto (adaptive transcode)") }}
|
||||||
|
</NcCheckboxRadioSwitch>
|
||||||
|
<NcCheckboxRadioSwitch
|
||||||
|
:checked.sync="videoDefaultQuality"
|
||||||
|
value="-1"
|
||||||
|
name="vdq_radio"
|
||||||
|
type="radio"
|
||||||
|
@update:checked="update('videoDefaultQuality')"
|
||||||
|
>{{ t("memories", "Original (transcode with max quality)") }}
|
||||||
|
</NcCheckboxRadioSwitch>
|
||||||
|
<NcCheckboxRadioSwitch
|
||||||
|
:checked.sync="videoDefaultQuality"
|
||||||
|
value="-2"
|
||||||
|
name="vdq_radio"
|
||||||
|
type="radio"
|
||||||
|
@update:checked="update('videoDefaultQuality')"
|
||||||
|
>{{ t("memories", "Direct (original video file without transcode)") }}
|
||||||
|
</NcCheckboxRadioSwitch>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>{{ t("memories", "Transcoder configuration") }}</h3>
|
||||||
|
<p>
|
||||||
|
{{
|
||||||
|
t(
|
||||||
|
"memories",
|
||||||
|
"Memories uses the go-vod transcoder. You can run go-vod exernally (e.g. in a separate Docker container for hardware acceleration) or use the built-in transcoder. To use an external transcoder, enable the following option and follow the instructions at this link:"
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href="https://github.com/pulsejet/memories/wiki/HW-Transcoding"
|
||||||
|
>
|
||||||
|
{{ t("memories", "external transcoder configuration") }}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<NcCheckboxRadioSwitch
|
||||||
|
:checked.sync="enableExternalTranscoder"
|
||||||
|
@update:checked="update('enableExternalTranscoder')"
|
||||||
|
type="switch"
|
||||||
|
>
|
||||||
|
{{ t("memories", "Enable external transcoder (go-vod)") }}
|
||||||
|
</NcCheckboxRadioSwitch>
|
||||||
|
|
||||||
|
<NcTextField
|
||||||
|
:label="t('memories', 'Binary path (local only)')"
|
||||||
|
:label-visible="true"
|
||||||
|
:value="goVodPath"
|
||||||
|
@change="update('goVodPath', $event.target.value)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<NcTextField
|
||||||
|
:label="t('memories', 'Bind address (local only)')"
|
||||||
|
:label-visible="true"
|
||||||
|
:value="goVodBind"
|
||||||
|
@change="update('goVodBind', $event.target.value)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<NcTextField
|
||||||
|
:label="t('memories', 'Connection address (same as bind if local)')"
|
||||||
|
:label-visible="true"
|
||||||
|
:value="goVodConnect"
|
||||||
|
@change="update('goVodConnect', $event.target.value)"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>{{ t("memories", "Hardware Acceleration") }}</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
{{
|
||||||
|
t(
|
||||||
|
"memories",
|
||||||
|
"You must first make sure the correct drivers are installed before configuring acceleration."
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
<br />
|
||||||
|
{{
|
||||||
|
t(
|
||||||
|
"memories",
|
||||||
|
"Make sure you test hardware acceleration with various options after enabling."
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
<br />
|
||||||
|
{{
|
||||||
|
t(
|
||||||
|
"memories",
|
||||||
|
"Do not enable multiple types of hardware acceleration simultaneously."
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
{{
|
||||||
|
t(
|
||||||
|
"memories",
|
||||||
|
"Intel processors supporting QuickSync Video (QSV) as well as some AMD GPUs can be used for transcoding using VA-API acceleration."
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
{{
|
||||||
|
t(
|
||||||
|
"memories",
|
||||||
|
"For more details on driver installation, check the following link:"
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href="https://github.com/pulsejet/memories/wiki/HW-Transcoding#va-api"
|
||||||
|
>
|
||||||
|
VA-API configuration
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<NcNoteCard type="warning">
|
||||||
|
{{
|
||||||
|
t(
|
||||||
|
"memories",
|
||||||
|
"/dev/dri/renderD128 is required for VA-API acceleration."
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</NcNoteCard>
|
||||||
|
|
||||||
|
<NcCheckboxRadioSwitch
|
||||||
|
:checked.sync="enableVaapi"
|
||||||
|
@update:checked="update('enableVaapi')"
|
||||||
|
type="switch"
|
||||||
|
>
|
||||||
|
{{ t("memories", "Enable acceleration with VA-API") }}
|
||||||
|
</NcCheckboxRadioSwitch>
|
||||||
|
|
||||||
|
<NcCheckboxRadioSwitch
|
||||||
|
:checked.sync="enableVaapiLowPower"
|
||||||
|
@update:checked="update('enableVaapiLowPower')"
|
||||||
|
type="switch"
|
||||||
|
>
|
||||||
|
{{ t("memories", "Enable low-power mode (QSV)") }}
|
||||||
|
</NcCheckboxRadioSwitch>
|
||||||
|
|
||||||
|
{{
|
||||||
|
t(
|
||||||
|
"memories",
|
||||||
|
"NVIDIA GPUs can be used for transcoding using the NVENC encoder with the proper drivers."
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
<br />
|
||||||
|
{{
|
||||||
|
t(
|
||||||
|
"memories",
|
||||||
|
"Depending on the versions of the installed SDK and ffmpeg, you need to specify the scaler to use"
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
|
||||||
|
<NcNoteCard type="warning">
|
||||||
|
{{
|
||||||
|
t(
|
||||||
|
"memories",
|
||||||
|
"No automated tests are available for NVIDIA acceleration."
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</NcNoteCard>
|
||||||
|
|
||||||
|
<NcCheckboxRadioSwitch
|
||||||
|
:checked.sync="enableNvenc"
|
||||||
|
@update:checked="update('enableNvenc')"
|
||||||
|
type="switch"
|
||||||
|
>
|
||||||
|
{{ t("memories", "Enable acceleration with NVENC") }}
|
||||||
|
</NcCheckboxRadioSwitch>
|
||||||
|
<NcCheckboxRadioSwitch
|
||||||
|
:checked.sync="enableNvencTemporalAQ"
|
||||||
|
@update:checked="update('enableNvencTemporalAQ')"
|
||||||
|
type="switch"
|
||||||
|
>
|
||||||
|
{{ t("memories", "Enable NVENC Temporal AQ") }}
|
||||||
|
</NcCheckboxRadioSwitch>
|
||||||
|
|
||||||
|
<NcCheckboxRadioSwitch
|
||||||
|
:checked.sync="nvencScaler"
|
||||||
|
value="npp"
|
||||||
|
name="nvence_scaler_radio"
|
||||||
|
type="radio"
|
||||||
|
@update:checked="update('nvencScaler')"
|
||||||
|
class="m-radio"
|
||||||
|
>{{ t("memories", "NPP scaler") }}
|
||||||
|
</NcCheckboxRadioSwitch>
|
||||||
|
<NcCheckboxRadioSwitch
|
||||||
|
:checked.sync="nvencScaler"
|
||||||
|
value="cuda"
|
||||||
|
name="nvence_scaler_radio"
|
||||||
|
type="radio"
|
||||||
|
class="m-radio"
|
||||||
|
@update:checked="update('nvencScaler')"
|
||||||
|
>{{ t("memories", "CUDA scaler") }}</NcCheckboxRadioSwitch
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from "vue";
|
||||||
|
|
||||||
|
import axios from "@nextcloud/axios";
|
||||||
|
import { API } from "./services/API";
|
||||||
|
import { showError } from "@nextcloud/dialogs";
|
||||||
|
|
||||||
|
const NcCheckboxRadioSwitch = () =>
|
||||||
|
import("@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch");
|
||||||
|
const NcNoteCard = () => import("@nextcloud/vue/dist/Components/NcNoteCard");
|
||||||
|
const NcTextField = () => import("@nextcloud/vue/dist/Components/NcTextField");
|
||||||
|
|
||||||
|
/** Map from UI to backend settings */
|
||||||
|
const settings = {
|
||||||
|
enableTranscoding: "memories.vod.disable",
|
||||||
|
ffmpegPath: "memories.vod.ffmpeg",
|
||||||
|
ffprobePath: "memories.vod.ffprobe",
|
||||||
|
goVodPath: "memories.vod.path",
|
||||||
|
goVodBind: "memories.vod.bind",
|
||||||
|
goVodConnect: "memories.vod.connect",
|
||||||
|
enableExternalTranscoder: "memories.vod.external",
|
||||||
|
videoDefaultQuality: "memories.video_default_quality",
|
||||||
|
|
||||||
|
enableVaapi: "memories.vod.vaapi",
|
||||||
|
enableVaapiLowPower: "memories.vod.vaapi.low_power",
|
||||||
|
|
||||||
|
enableNvenc: "memories.vod.nvenc",
|
||||||
|
enableNvencTemporalAQ: "memories.vod.nvenc.temporal_aq",
|
||||||
|
nvencScaler: "memories.vod.nvenc.scale",
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Invert setting before saving */
|
||||||
|
const invertedBooleans = ["enableTranscoding"];
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "Admin",
|
||||||
|
components: {
|
||||||
|
NcCheckboxRadioSwitch,
|
||||||
|
NcNoteCard,
|
||||||
|
NcTextField,
|
||||||
|
},
|
||||||
|
|
||||||
|
data: () => ({
|
||||||
|
loaded: false,
|
||||||
|
|
||||||
|
enableTranscoding: false,
|
||||||
|
ffmpegPath: "",
|
||||||
|
ffprobePath: "",
|
||||||
|
goVodPath: "",
|
||||||
|
goVodBind: "",
|
||||||
|
goVodConnect: "",
|
||||||
|
enableExternalTranscoder: false,
|
||||||
|
videoDefaultQuality: "",
|
||||||
|
|
||||||
|
enableVaapi: false,
|
||||||
|
enableVaapiLowPower: false,
|
||||||
|
|
||||||
|
enableNvenc: false,
|
||||||
|
enableNvencTemporalAQ: false,
|
||||||
|
nvencScaler: "",
|
||||||
|
}),
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.reload();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async reload() {
|
||||||
|
const res = await axios.get(API.SYSTEM_CONFIG(null));
|
||||||
|
for (const key in settings) {
|
||||||
|
if (!res.data.hasOwnProperty(settings[key])) {
|
||||||
|
console.error(
|
||||||
|
`Setting ${settings[key]} not found in backend response`
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this[key] = res.data[settings[key]];
|
||||||
|
|
||||||
|
if (invertedBooleans.includes(key)) {
|
||||||
|
this[key] = !this[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loaded = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
async update(key: string, value = null) {
|
||||||
|
value ||= this[key];
|
||||||
|
const setting = settings[key];
|
||||||
|
|
||||||
|
// Inversion
|
||||||
|
if (invertedBooleans.includes(key)) {
|
||||||
|
value = !value;
|
||||||
|
}
|
||||||
|
|
||||||
|
axios
|
||||||
|
.put(API.SYSTEM_CONFIG(setting), {
|
||||||
|
value: value,
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
showError(this.t("memories", "Failed to update setting"));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.outer {
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
.checkbox-radio-switch {
|
||||||
|
margin: 2px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-radio {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.2em;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--color-primary-element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
23
src/main.ts
23
src/main.ts
|
@ -8,6 +8,7 @@ import XImg from "./components/frame/XImg.vue";
|
||||||
import GlobalMixin from "./mixins/GlobalMixin";
|
import GlobalMixin from "./mixins/GlobalMixin";
|
||||||
|
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
|
import Admin from "./Admin.vue";
|
||||||
import router from "./router";
|
import router from "./router";
|
||||||
import { Route } from "vue-router";
|
import { Route } from "vue-router";
|
||||||
import { generateFilePath } from "@nextcloud/router";
|
import { generateFilePath } from "@nextcloud/router";
|
||||||
|
@ -103,8 +104,20 @@ window.addEventListener("DOMContentLoaded", () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
export default new Vue({
|
let app = null;
|
||||||
el: "#content",
|
|
||||||
router,
|
const adminSection = document.getElementById("memories-admin-content");
|
||||||
render: (h) => h(App),
|
if (adminSection) {
|
||||||
});
|
app = new Vue({
|
||||||
|
el: "#memories-admin-content",
|
||||||
|
render: (h) => h(Admin),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
app = new Vue({
|
||||||
|
el: "#content",
|
||||||
|
router,
|
||||||
|
render: (h) => h(App),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default app;
|
||||||
|
|
|
@ -184,6 +184,12 @@ export class API {
|
||||||
return gen(`${BASE}/config/{setting}`, { setting });
|
return gen(`${BASE}/config/{setting}`, { setting });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SYSTEM_CONFIG(setting: string | null) {
|
||||||
|
return setting
|
||||||
|
? gen(`${BASE}/system-config/{setting}`, { setting })
|
||||||
|
: gen(`${BASE}/system-config`);
|
||||||
|
}
|
||||||
|
|
||||||
static MAP_CLUSTERS() {
|
static MAP_CLUSTERS() {
|
||||||
return tok(gen(`${BASE}/map/clusters`));
|
return tok(gen(`${BASE}/map/clusters`));
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,12 +297,17 @@ export const constants = {
|
||||||
|
|
||||||
/** Cache store */
|
/** Cache store */
|
||||||
let staticCache: Cache | null = null;
|
let staticCache: Cache | null = null;
|
||||||
const cacheName = `memories-${loadState("memories", "version")}-${
|
let cacheName: string;
|
||||||
getCurrentUser()?.uid
|
let memoriesVersion: string;
|
||||||
}`;
|
|
||||||
openCache().then((cache) => {
|
try {
|
||||||
staticCache = cache;
|
memoriesVersion = loadState("memories", "version");
|
||||||
});
|
const uid = getCurrentUser()?.uid;
|
||||||
|
cacheName = `memories-${memoriesVersion}-${uid}`;
|
||||||
|
openCache().then((cache) => (staticCache = cache));
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Failed to open cache");
|
||||||
|
}
|
||||||
|
|
||||||
// Clear all caches except the current one
|
// Clear all caches except the current one
|
||||||
window.caches?.keys().then((keys) => {
|
window.caches?.keys().then((keys) => {
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<div id="memories-admin-content"></div>
|
Loading…
Reference in New Issue