parent
203cb146c8
commit
8c1432af45
|
@ -83,6 +83,7 @@ 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#getSystemStatus', 'url' => '/api/system-status', 'verb' => 'GET'],
|
||||||
['name' => 'Other#getSystemConfig', 'url' => '/api/system-config', 'verb' => 'GET'],
|
['name' => 'Other#getSystemConfig', 'url' => '/api/system-config', 'verb' => 'GET'],
|
||||||
['name' => 'Other#setSystemConfig', 'url' => '/api/system-config/{key}', 'verb' => 'PUT'],
|
['name' => 'Other#setSystemConfig', 'url' => '/api/system-config/{key}', 'verb' => 'PUT'],
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace OCA\Memories\Controller;
|
||||||
|
|
||||||
use OCA\Memories\AppInfo\Application;
|
use OCA\Memories\AppInfo\Application;
|
||||||
use OCA\Memories\Exceptions;
|
use OCA\Memories\Exceptions;
|
||||||
|
use OCA\Memories\Exif;
|
||||||
use OCA\Memories\Util;
|
use OCA\Memories\Util;
|
||||||
use OCP\AppFramework\Http;
|
use OCP\AppFramework\Http;
|
||||||
use OCP\AppFramework\Http\JSONResponse;
|
use OCP\AppFramework\Http\JSONResponse;
|
||||||
|
@ -76,8 +77,6 @@ class OtherController extends GenericApiController
|
||||||
/**
|
/**
|
||||||
* @AdminRequired
|
* @AdminRequired
|
||||||
*
|
*
|
||||||
* @NoCSRFRequired
|
|
||||||
*
|
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
*/
|
*/
|
||||||
public function setSystemConfig(string $key, $value): Http\Response
|
public function setSystemConfig(string $key, $value): Http\Response
|
||||||
|
@ -109,6 +108,43 @@ class OtherController extends GenericApiController
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @AdminRequired
|
||||||
|
*
|
||||||
|
* @NoCSRFRequired
|
||||||
|
*/
|
||||||
|
public function getSystemStatus(): Http\Response
|
||||||
|
{
|
||||||
|
return Util::guardEx(function () {
|
||||||
|
$status = [];
|
||||||
|
|
||||||
|
// Check exiftool
|
||||||
|
$status['exiftool'] = $this->getExecutableStatus(Util::getSystemConfig('memories.exiftool'));
|
||||||
|
|
||||||
|
// Check for system perl
|
||||||
|
$status['perl'] = $this->getExecutableStatus(exec('which perl'));
|
||||||
|
|
||||||
|
// Check ffmpeg and ffprobe binaries
|
||||||
|
$status['ffmpeg'] = $this->getExecutableStatus(Util::getSystemConfig('memories.vod.ffmpeg'));
|
||||||
|
$status['ffprobe'] = $this->getExecutableStatus(Util::getSystemConfig('memories.vod.ffprobe'));
|
||||||
|
|
||||||
|
// Check go-vod binary
|
||||||
|
$status['govod'] = $this->getExecutableStatus(Util::getSystemConfig('memories.vod.path'));
|
||||||
|
|
||||||
|
// Check for VA-API device
|
||||||
|
$devPath = '/dev/dri/renderD128';
|
||||||
|
if (!is_file($devPath)) {
|
||||||
|
$status['vaapi_dev'] = 'not_found';
|
||||||
|
} elseif (!is_readable($devPath)) {
|
||||||
|
$status['vaapi_dev'] = 'not_readable';
|
||||||
|
} else {
|
||||||
|
$status['vaapi_dev'] = 'ok';
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JSONResponse($status, Http::STATUS_OK);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
*
|
*
|
||||||
|
@ -127,4 +163,17 @@ class OtherController extends GenericApiController
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getExecutableStatus(string $path): string
|
||||||
|
{
|
||||||
|
if (!is_file($path)) {
|
||||||
|
return 'not_found';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_executable($path)) {
|
||||||
|
return 'not_executable';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'ok';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
124
src/Admin.vue
124
src/Admin.vue
|
@ -2,6 +2,12 @@
|
||||||
<div class="outer" v-if="loaded">
|
<div class="outer" v-if="loaded">
|
||||||
<h2>{{ t("memories", "EXIF Extraction") }}</h2>
|
<h2>{{ t("memories", "EXIF Extraction") }}</h2>
|
||||||
|
|
||||||
|
<template v-if="status">
|
||||||
|
<NcNoteCard :type="binaryStatusType(status.exiftool)">
|
||||||
|
{{ binaryStatus("exiftool", status.exiftool) }}
|
||||||
|
</NcNoteCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
<NcTextField
|
<NcTextField
|
||||||
:label="t('memories', 'Path to packaged exiftool binary')"
|
:label="t('memories', 'Path to packaged exiftool binary')"
|
||||||
:label-visible="true"
|
:label-visible="true"
|
||||||
|
@ -10,6 +16,12 @@
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<template v-if="status">
|
||||||
|
<NcNoteCard :type="binaryStatusType(status.perl, false)">
|
||||||
|
{{ binaryStatus("perl", status.perl) }}
|
||||||
|
</NcNoteCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
<NcCheckboxRadioSwitch
|
<NcCheckboxRadioSwitch
|
||||||
:checked.sync="exiftoolPerl"
|
:checked.sync="exiftoolPerl"
|
||||||
@update:checked="update('exiftoolPerl')"
|
@update:checked="update('exiftoolPerl')"
|
||||||
|
@ -45,6 +57,15 @@
|
||||||
{{ t("memories", "Enable Transcoding") }}
|
{{ t("memories", "Enable Transcoding") }}
|
||||||
</NcCheckboxRadioSwitch>
|
</NcCheckboxRadioSwitch>
|
||||||
|
|
||||||
|
<template v-if="status">
|
||||||
|
<NcNoteCard :type="binaryStatusType(status.ffmpeg)">
|
||||||
|
{{ binaryStatus("ffmpeg", status.ffmpeg) }}
|
||||||
|
</NcNoteCard>
|
||||||
|
<NcNoteCard :type="binaryStatusType(status.ffprobe)">
|
||||||
|
{{ binaryStatus("ffprobe", status.ffprobe) }}
|
||||||
|
</NcNoteCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
<NcTextField
|
<NcTextField
|
||||||
:label="t('memories', 'ffmpeg path')"
|
:label="t('memories', 'ffmpeg path')"
|
||||||
:label-visible="true"
|
:label-visible="true"
|
||||||
|
@ -102,6 +123,12 @@
|
||||||
{{ t("memories", "external transcoder configuration") }}
|
{{ t("memories", "external transcoder configuration") }}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<template v-if="status">
|
||||||
|
<NcNoteCard :type="binaryStatusType(status.govod)">
|
||||||
|
{{ binaryStatus("go-vod", status.govod) }}
|
||||||
|
</NcNoteCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
<NcCheckboxRadioSwitch
|
<NcCheckboxRadioSwitch
|
||||||
:checked.sync="enableExternalTranscoder"
|
:checked.sync="enableExternalTranscoder"
|
||||||
@update:checked="update('enableExternalTranscoder')"
|
@update:checked="update('enableExternalTranscoder')"
|
||||||
|
@ -178,13 +205,8 @@
|
||||||
VA-API configuration
|
VA-API configuration
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<NcNoteCard type="warning">
|
<NcNoteCard :type="vaapiStatusType()" v-if="status">
|
||||||
{{
|
{{ vaapiStatusText() }}
|
||||||
t(
|
|
||||||
"memories",
|
|
||||||
"/dev/dri/renderD128 is required for VA-API acceleration."
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</NcNoteCard>
|
</NcNoteCard>
|
||||||
|
|
||||||
<NcCheckboxRadioSwitch
|
<NcCheckboxRadioSwitch
|
||||||
|
@ -300,6 +322,22 @@ const settings = {
|
||||||
/** Invert setting before saving */
|
/** Invert setting before saving */
|
||||||
const invertedBooleans = ["enableTranscoding"];
|
const invertedBooleans = ["enableTranscoding"];
|
||||||
|
|
||||||
|
type BinaryStatus =
|
||||||
|
| "ok"
|
||||||
|
| "not_found"
|
||||||
|
| "not_executable"
|
||||||
|
| "test_fail"
|
||||||
|
| "test_ok";
|
||||||
|
|
||||||
|
type IStatus = {
|
||||||
|
exiftool: BinaryStatus;
|
||||||
|
perl: BinaryStatus;
|
||||||
|
ffmpeg: BinaryStatus;
|
||||||
|
ffprobe: BinaryStatus;
|
||||||
|
govod: BinaryStatus;
|
||||||
|
vaapi_dev: "ok" | "not_found" | "not_readable";
|
||||||
|
};
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "Admin",
|
name: "Admin",
|
||||||
components: {
|
components: {
|
||||||
|
@ -329,10 +367,13 @@ export default defineComponent({
|
||||||
enableNvenc: false,
|
enableNvenc: false,
|
||||||
enableNvencTemporalAQ: false,
|
enableNvencTemporalAQ: false,
|
||||||
nvencScaler: "",
|
nvencScaler: "",
|
||||||
|
|
||||||
|
status: null as IStatus,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.reload();
|
this.reload();
|
||||||
|
this.refreshStatus();
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -356,6 +397,11 @@ export default defineComponent({
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async refreshStatus() {
|
||||||
|
const res = await axios.get(API.SYSTEM_STATUS());
|
||||||
|
this.status = res.data;
|
||||||
|
},
|
||||||
|
|
||||||
async update(key: string, value = null) {
|
async update(key: string, value = null) {
|
||||||
value ||= this[key];
|
value ||= this[key];
|
||||||
const setting = settings[key];
|
const setting = settings[key];
|
||||||
|
@ -374,6 +420,70 @@ export default defineComponent({
|
||||||
showError(this.t("memories", "Failed to update setting"));
|
showError(this.t("memories", "Failed to update setting"));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
binaryStatus(name: string, status: BinaryStatus): string {
|
||||||
|
if (status === "ok") {
|
||||||
|
return this.t("memories", "{name} binary exists and is executable", {
|
||||||
|
name,
|
||||||
|
});
|
||||||
|
} else if (status === "not_found") {
|
||||||
|
return this.t("memories", "{name} binary not found", { name });
|
||||||
|
} else if (status === "not_executable") {
|
||||||
|
return this.t("memories", "{name} binary is not executable", {
|
||||||
|
name,
|
||||||
|
});
|
||||||
|
} else if (status === "test_fail") {
|
||||||
|
return this.t("memories", "{name} binary exists but failed test", {
|
||||||
|
name,
|
||||||
|
});
|
||||||
|
} else if (status === "test_ok") {
|
||||||
|
return this.t("memories", "{name} binary exists and is usable", {
|
||||||
|
name,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return this.t("memories", "{name} binary status: {status}", {
|
||||||
|
name,
|
||||||
|
status,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
binaryStatusType(status: BinaryStatus, critical = true): string {
|
||||||
|
if (status === "ok" || status === "test_ok") {
|
||||||
|
return "success";
|
||||||
|
} else if (
|
||||||
|
status === "not_found" ||
|
||||||
|
status === "not_executable" ||
|
||||||
|
status === "test_fail"
|
||||||
|
) {
|
||||||
|
return critical ? "error" : "warning";
|
||||||
|
} else {
|
||||||
|
return "warning";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
vaapiStatusText(): string {
|
||||||
|
const dev = "/dev/dri/renderD128";
|
||||||
|
if (this.status.vaapi_dev === "ok") {
|
||||||
|
return this.t("memories", "VA-API device ({dev}) is readable", { dev });
|
||||||
|
} else if (this.status.vaapi_dev === "not_found") {
|
||||||
|
return this.t("memories", "VA-API device ({dev}) not found", { dev });
|
||||||
|
} else if (this.status.vaapi_dev === "not_readable") {
|
||||||
|
return this.t(
|
||||||
|
"memories",
|
||||||
|
"VA-API device ({dev}) has incorrect permissions",
|
||||||
|
{ dev }
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return this.t("memories", "VA-API device status: {status}", {
|
||||||
|
status: this.status.vaapi_dev,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
vaapiStatusType(): string {
|
||||||
|
return this.status.vaapi_dev === "ok" ? "success" : "error";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -190,6 +190,10 @@ export class API {
|
||||||
: gen(`${BASE}/system-config`);
|
: gen(`${BASE}/system-config`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SYSTEM_STATUS() {
|
||||||
|
return gen(`${BASE}/system-status`);
|
||||||
|
}
|
||||||
|
|
||||||
static MAP_CLUSTERS() {
|
static MAP_CLUSTERS() {
|
||||||
return tok(gen(`${BASE}/map/clusters`));
|
return tok(gen(`${BASE}/map/clusters`));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue