Some more renaming

This commit is contained in:
emeric
2023-11-13 09:25:22 +01:00
parent 87d70465e9
commit 9e2040b449
17 changed files with 442 additions and 453 deletions
+14 -14
View File
@@ -245,8 +245,8 @@
<message id="Lms.Settings.backend.listenbrainz">ListenBrainz</message> <message id="Lms.Settings.backend.listenbrainz">ListenBrainz</message>
<message id="Lms.Settings.backend.listenbrainz-token">ListenBrainz API token</message> <message id="Lms.Settings.backend.listenbrainz-token">ListenBrainz API token</message>
<message id="Lms.Settings.change-password">Change password</message> <message id="Lms.Settings.change-password">Change password</message>
<message id="Lms.Settings.default-transcode-bitrate">Default transcode bitrate</message> <message id="Lms.Settings.default-transcoding-output-bitrate">Default transcoding output bitrate</message>
<message id="Lms.Settings.default-transcode-format">Default transcode format</message> <message id="Lms.Settings.default-transcoding-output-format">Default transcoding output format</message>
<message id="Lms.Settings.demo-cannot-save">Cannot save using a demo account!</message> <message id="Lms.Settings.demo-cannot-save">Cannot save using a demo account!</message>
<message id="Lms.Settings.feedback">Feedback</message> <message id="Lms.Settings.feedback">Feedback</message>
<message id="Lms.Settings.menu-settings"><i class="fa fa-fw fa-cog" aria-hidden="true"></i> Settings</message> <message id="Lms.Settings.menu-settings"><i class="fa fa-fw fa-cog" aria-hidden="true"></i> Settings</message>
@@ -267,18 +267,18 @@
<message id="Lms.Settings.subsonic-artist-list-mode.release-artists">Album artists</message> <message id="Lms.Settings.subsonic-artist-list-mode.release-artists">Album artists</message>
<message id="Lms.Settings.subsonic-artist-list-mode.track-artists">Track artists</message> <message id="Lms.Settings.subsonic-artist-list-mode.track-artists">Track artists</message>
<message id="Lms.Settings.subsonic-api">Subsonic API</message> <message id="Lms.Settings.subsonic-api">Subsonic API</message>
<message id="Lms.Settings.transcode">Transcoding</message> <message id="Lms.Settings.transcoding">Transcoding</message>
<message id="Lms.Settings.transcode-bitrate">Transcode bitrate</message> <message id="Lms.Settings.transcoding-output-bitrate">Transcoding output bitrate</message>
<message id="Lms.Settings.transcode-format">Transcode format</message> <message id="Lms.Settings.transcoding-output-format">Transcoding output format</message>
<message id="Lms.Settings.transcode-format.matroska_opus">Matroska/Opus</message> <message id="Lms.Settings.transcoding-output-format.matroska_opus">Matroska/Opus</message>
<message id="Lms.Settings.transcode-format.mp3">MP3</message> <message id="Lms.Settings.transcoding-output-format.mp3">MP3</message>
<message id="Lms.Settings.transcode-format.ogg_opus">Ogg/Opus</message> <message id="Lms.Settings.transcoding-output-format.ogg_opus">Ogg/Opus</message>
<message id="Lms.Settings.transcode-format.ogg_vorbis">Ogg/Vorbis</message> <message id="Lms.Settings.transcoding-output-format.ogg_vorbis">Ogg/Vorbis</message>
<message id="Lms.Settings.transcode-format.webm_vorbis">WebM/Vorbis</message> <message id="Lms.Settings.transcoding-output-format.webm_vorbis">WebM/Vorbis</message>
<message id="Lms.Settings.transcode-mode">Enable transcoding</message> <message id="Lms.Settings.transcoding-mode">Enable transcoding</message>
<message id="Lms.Settings.transcode-mode.always">Always</message> <message id="Lms.Settings.transcoding-mode.always">Always</message>
<message id="Lms.Settings.transcode-mode.if-format-not-supported">Only when format is not supported</message> <message id="Lms.Settings.transcoding-mode.if-format-not-supported">Only when format is not supported by the browser</message>
<message id="Lms.Settings.transcode-mode.never">Never</message> <message id="Lms.Settings.transcoding-mode.never">Never</message>
<message id="Lms.Settings.settings-saved">New settings saved!</message> <message id="Lms.Settings.settings-saved">New settings saved!</message>
</messages> </messages>
+14 -14
View File
@@ -245,8 +245,8 @@
<message id="Lms.Settings.backend.listenbrainz">ListenBrainz</message> <message id="Lms.Settings.backend.listenbrainz">ListenBrainz</message>
<message id="Lms.Settings.backend.listenbrainz-token">Jeton d'API ListenBrainz</message> <message id="Lms.Settings.backend.listenbrainz-token">Jeton d'API ListenBrainz</message>
<message id="Lms.Settings.change-password">Changement de mot de passe</message> <message id="Lms.Settings.change-password">Changement de mot de passe</message>
<message id="Lms.Settings.default-transcode-bitrate">Bitrate par defaut du transcodage</message> <message id="Lms.Settings.default-transcoding-output-bitrate">Bitrate par defaut du transcodage</message>
<message id="Lms.Settings.default-transcode-format">Format par defaut du transcodage</message> <message id="Lms.Settings.default-transcoding-output-format">Format par defaut du transcodage</message>
<message id="Lms.Settings.demo-cannot-save">Impossible de sauvegarder en utilisant un compte de démo !</message> <message id="Lms.Settings.demo-cannot-save">Impossible de sauvegarder en utilisant un compte de démo !</message>
<message id="Lms.Settings.feedback">Feedback</message> <message id="Lms.Settings.feedback">Feedback</message>
<message id="Lms.Settings.menu-settings"><i class="fa fa-fw fa-cog" aria-hidden="true"></i> Paramètres</message> <message id="Lms.Settings.menu-settings"><i class="fa fa-fw fa-cog" aria-hidden="true"></i> Paramètres</message>
@@ -267,18 +267,18 @@
<message id="Lms.Settings.subsonic-artist-list-mode.release-artists">Tous les artistes d'album</message> <message id="Lms.Settings.subsonic-artist-list-mode.release-artists">Tous les artistes d'album</message>
<message id="Lms.Settings.subsonic-artist-list-mode.track-artists">Tous les artistes de piste</message> <message id="Lms.Settings.subsonic-artist-list-mode.track-artists">Tous les artistes de piste</message>
<message id="Lms.Settings.subsonic-api">API Subsonic</message> <message id="Lms.Settings.subsonic-api">API Subsonic</message>
<message id="Lms.Settings.transcode">Transcodage</message> <message id="Lms.Settings.transcoding">Transcodage</message>
<message id="Lms.Settings.transcode-bitrate">Bitrate du transcodage</message> <message id="Lms.Settings.transcoding-output-bitrate">Bitrate du transcodage</message>
<message id="Lms.Settings.transcode-format">Format du transcodage</message> <message id="Lms.Settings.transcoding-output-format">Format du transcodage</message>
<message id="Lms.Settings.transcode-format.matroska_opus">Matroska/Opus</message> <message id="Lms.Settings.transcoding-output-format.matroska_opus">Matroska/Opus</message>
<message id="Lms.Settings.transcode-format.mp3">MP3</message> <message id="Lms.Settings.transcoding-output-format.mp3">MP3</message>
<message id="Lms.Settings.transcode-format.ogg_opus">Ogg/Opus</message> <message id="Lms.Settings.transcoding-output-format.ogg_opus">Ogg/Opus</message>
<message id="Lms.Settings.transcode-format.ogg_vorbis">Ogg/Vorbis</message> <message id="Lms.Settings.transcoding-output-format.ogg_vorbis">Ogg/Vorbis</message>
<message id="Lms.Settings.transcode-format.webm_vorbis">WebM/Vorbis</message> <message id="Lms.Settings.transcoding-output-format.webm_vorbis">WebM/Vorbis</message>
<message id="Lms.Settings.transcode-mode">Appliquer le transcodage</message> <message id="Lms.Settings.transcoding-mode">Appliquer le transcodage</message>
<message id="Lms.Settings.transcode-mode.always">Toujours</message> <message id="Lms.Settings.transcoding-mode.always">Toujours</message>
<message id="Lms.Settings.transcode-mode.if-format-not-supported">Seulement lorsque le format n'est pas pris en charge</message> <message id="Lms.Settings.transcoding-mode.if-format-not-supported">Seulement lorsque le format n'est pas pris en charge par votre navigateur</message>
<message id="Lms.Settings.transcode-mode.never">Jamais</message> <message id="Lms.Settings.transcoding-mode.never">Jamais</message>
<message id="Lms.Settings.settings-saved">Paramètres sauvegardés !</message> <message id="Lms.Settings.settings-saved">Paramètres sauvegardés !</message>
<!--Wt--> <!--Wt-->
+12 -12
View File
@@ -267,18 +267,18 @@
<message id="Lms.Settings.subsonic-artist-list-mode.release-artists">Artisti album</message> <message id="Lms.Settings.subsonic-artist-list-mode.release-artists">Artisti album</message>
<message id="Lms.Settings.subsonic-artist-list-mode.track-artists">Artisti tracce</message> <message id="Lms.Settings.subsonic-artist-list-mode.track-artists">Artisti tracce</message>
<message id="Lms.Settings.subsonic-api">Subsonic API</message> <message id="Lms.Settings.subsonic-api">Subsonic API</message>
<message id="Lms.Settings.transcode">Transcodifica</message> <message id="Lms.Settings.transcoding">Transcodifica</message>
<message id="Lms.Settings.transcode-bitrate">Bitrate transcodifica</message> <message id="Lms.Settings.transcoding-output-bitrate">Bitrate transcodifica</message>
<message id="Lms.Settings.transcode-format">Formato di transcodifica</message> <message id="Lms.Settings.transcoding-output-format">Formato di transcodifica</message>
<message id="Lms.Settings.transcode-format.matroska_opus">Matroska/Opus</message> <message id="Lms.Settings.transcoding-output-format.matroska_opus">Matroska/Opus</message>
<message id="Lms.Settings.transcode-format.mp3">MP3</message> <message id="Lms.Settings.transcoding-output-format.mp3">MP3</message>
<message id="Lms.Settings.transcode-format.ogg_opus">Ogg/Opus</message> <message id="Lms.Settings.transcoding-output-format.ogg_opus">Ogg/Opus</message>
<message id="Lms.Settings.transcode-format.ogg_vorbis">Ogg/Vorbis</message> <message id="Lms.Settings.transcoding-output-format.ogg_vorbis">Ogg/Vorbis</message>
<message id="Lms.Settings.transcode-format.webm_vorbis">WebM/Vorbis</message> <message id="Lms.Settings.transcoding-output-format.webm_vorbis">WebM/Vorbis</message>
<message id="Lms.Settings.transcode-mode">Abilita transcodifica</message> <message id="Lms.Settings.transcoding-mode">Abilita transcodifica</message>
<message id="Lms.Settings.transcode-mode.always">Sempre</message> <message id="Lms.Settings.transcoding-mode.always">Sempre</message>
<message id="Lms.Settings.transcode-mode.if-format-not-supported">Quando il formato non è supportato</message> <message id="Lms.Settings.transcoding-mode.if-format-not-supported">Quando il formato non è supportato</message>
<message id="Lms.Settings.transcode-mode.never">Mai</message> <message id="Lms.Settings.transcoding-mode.never">Mai</message>
<message id="Lms.Settings.settings-saved">Nuove impostazioni salvate!</message> <message id="Lms.Settings.settings-saved">Nuove impostazioni salvate!</message>
<!--Wt--> <!--Wt-->
+12 -12
View File
@@ -267,18 +267,18 @@
<message id="Lms.Settings.subsonic-artist-list-mode.release-artists">专辑歌手</message> <message id="Lms.Settings.subsonic-artist-list-mode.release-artists">专辑歌手</message>
<message id="Lms.Settings.subsonic-artist-list-mode.track-artists">音轨歌手</message> <message id="Lms.Settings.subsonic-artist-list-mode.track-artists">音轨歌手</message>
<message id="Lms.Settings.subsonic-api">Subsonic 应用程序接口</message> <message id="Lms.Settings.subsonic-api">Subsonic 应用程序接口</message>
<message id="Lms.Settings.transcode">转码</message> <message id="Lms.Settings.transcoding">转码</message>
<message id="Lms.Settings.transcode-bitrate">转码比特率</message> <message id="Lms.Settings.transcoding-output-bitrate">转码比特率</message>
<message id="Lms.Settings.transcode-format">转码格式</message> <message id="Lms.Settings.transcoding-output-format">转码格式</message>
<message id="Lms.Settings.transcode-format.matroska_opus">Matroska/Opus</message> <message id="Lms.Settings.transcoding-output-format.matroska_opus">Matroska/Opus</message>
<message id="Lms.Settings.transcode-format.mp3">MP3</message> <message id="Lms.Settings.transcoding-output-format.mp3">MP3</message>
<message id="Lms.Settings.transcode-format.ogg_opus">Ogg/Opus</message> <message id="Lms.Settings.transcoding-output-format.ogg_opus">Ogg/Opus</message>
<message id="Lms.Settings.transcode-format.ogg_vorbis">Ogg/Vorbis</message> <message id="Lms.Settings.transcoding-output-format.ogg_vorbis">Ogg/Vorbis</message>
<message id="Lms.Settings.transcode-format.webm_vorbis">WebM/Vorbis</message> <message id="Lms.Settings.transcoding-output-format.webm_vorbis">WebM/Vorbis</message>
<message id="Lms.Settings.transcode-mode">启动转码</message> <message id="Lms.Settings.transcoding-mode">启动转码</message>
<message id="Lms.Settings.transcode-mode.always">总是</message> <message id="Lms.Settings.transcoding-mode.always">总是</message>
<message id="Lms.Settings.transcode-mode.if-format-not-supported">仅当格式不支持时使用</message> <message id="Lms.Settings.transcoding-mode.if-format-not-supported">仅当格式不支持时使用</message>
<message id="Lms.Settings.transcode-mode.never">从不</message> <message id="Lms.Settings.transcoding-mode.never">从不</message>
<message id="Lms.Settings.settings-saved">新设置已保存!</message> <message id="Lms.Settings.settings-saved">新设置已保存!</message>
<!--Wt--> <!--Wt-->
+20 -20
View File
@@ -10,33 +10,33 @@
${tr:Lms.Settings.audio-settings-are-local} ${tr:Lms.Settings.audio-settings-are-local}
</div> </div>
<div class="col-lg-4"> <div class="col-lg-4">
<label class="form-label" for="${id:transcode-mode}"> <label class="form-label" for="${id:transcoding-mode}">
${tr:Lms.Settings.transcode-mode} ${tr:Lms.Settings.transcoding-mode}
</label> </label>
${transcode-mode class="form-control"} ${transcoding-mode class="form-control"}
<div class="invalid-feedback"> <div class="invalid-feedback">
${transcode-mode-info} ${transcoding-mode-info}
</div> </div>
</div> </div>
<div class="col-lg-4"> <div class="col-lg-4">
<label class="form-label" for="${id:transcode-format}"> <label class="form-label" for="${id:transcoding-output-format}">
${tr:Lms.Settings.transcode-format} ${tr:Lms.Settings.transcoding-output-format}
</label> </label>
${transcode-format class="form-control"} ${transcoding-output-format class="form-control"}
<div class="invalid-feedback"> <div class="invalid-feedback">
${transcode-format-info} ${transcoding-output-format-info}
</div> </div>
</div> </div>
<div class="col-lg-4"> <div class="col-lg-4">
<label class="form-label" for="${id:transcode-bitrate}"> <label class="form-label" for="${id:transcoding-output-bitrate}">
${tr:Lms.Settings.transcode-bitrate} ${tr:Lms.Settings.transcoding-output-bitrate}
</label> </label>
<div class="input-group mb-3"> <div class="input-group mb-3">
${transcode-bitrate class="form-control"} ${transcoding-output-bitrate class="form-control"}
<span class="input-group-text">kbps</span> <span class="input-group-text">kbps</span>
</div> </div>
<div class="invalid-feedback"> <div class="invalid-feedback">
${transcode-bitrate-info} ${transcoding-output-bitrate-info}
</div> </div>
</div> </div>
<div class="col-lg-4"> <div class="col-lg-4">
@@ -75,24 +75,24 @@
${<if-has-subsonic-api>} ${<if-has-subsonic-api>}
<legend>${tr:Lms.Settings.subsonic-api}</legend> <legend>${tr:Lms.Settings.subsonic-api}</legend>
<div class="col-lg-6"> <div class="col-lg-6">
<label class="form-label" for="${id:subsonic-transcode-format}"> <label class="form-label" for="${id:subsonic-transcoding-output-format}">
${tr:Lms.Settings.default-transcode-format} ${tr:Lms.Settings.default-transcoding-output-format}
</label> </label>
${subsonic-transcode-format class="form-control"} ${subsonic-transcoding-output-format class="form-control"}
<div class="invalid-feedback"> <div class="invalid-feedback">
${subsonic-transcode-format-info class="help-block"} ${subsonic-transcoding-output-format-info class="help-block"}
</div> </div>
</div> </div>
<div class="col-lg-6"> <div class="col-lg-6">
<label class="form-label" for="${id:subsonic-transcode-bitrate}"> <label class="form-label" for="${id:subsonic-transcoding-output-bitrate}">
${tr:Lms.Settings.default-transcode-bitrate} ${tr:Lms.Settings.default-transcoding-output-bitrate}
</label> </label>
<div class="input-group mb-3"> <div class="input-group mb-3">
${subsonic-transcode-bitrate class="form-control"} ${subsonic-transcoding-output-bitrate class="form-control"}
<span class="input-group-text">kbps</span> <span class="input-group-text">kbps</span>
</div> </div>
<div class="invalid-feedback"> <div class="invalid-feedback">
${subsonic-transcode-bitrate-info class="help-block"} ${subsonic-transcoding-output-bitrate-info class="help-block"}
</div> </div>
</div> </div>
<div class="col-12"> <div class="col-12">
+12 -12
View File
@@ -2,15 +2,15 @@
var LMS = LMS || {}; var LMS = LMS || {};
// Keep in sync with MediaPlayer::TranscodeMode cpp // Keep in sync with MediaPlayer::TranscodingMode cpp
const TranscodeMode = { const TranscodingMode = {
Never: 0, Never: 0,
Always: 1, Always: 1,
IfFormatNotSupported: 2, IfFormatNotSupported: 2,
} }
const Mode = { const Mode = {
Transcode: 1, Transcoding: 1,
File: 2, File: 2,
} }
Object.freeze(Mode); Object.freeze(Mode);
@@ -22,7 +22,7 @@ LMS.mediaplayer = function () {
let _trackId = null; let _trackId = null;
let _duration = 0; let _duration = 0;
let _audioNativeSrc; let _audioNativeSrc;
let _audioTranscodeSrc; let _audioTranscodingSrc;
let _settings = {}; let _settings = {};
let _playedDuration = 0; let _playedDuration = 0;
let _lastStartPlaying = null; let _lastStartPlaying = null;
@@ -236,10 +236,10 @@ LMS.mediaplayer = function () {
let selectedOffset = parseInt(_elems.seek.value, 10); let selectedOffset = parseInt(_elems.seek.value, 10);
switch (mode) { switch (mode) {
case Mode.Transcode: case Mode.Transcoding:
_offset = selectedOffset; _offset = selectedOffset;
_removeAudioSources(); _removeAudioSources();
_addAudioSource(_audioTranscodeSrc + "&offset=" + _offset); _addAudioSource(_audioTranscodingSrc + "&offset=" + _offset);
_elems.audio.load(); _elems.audio.load();
_elems.audio.currentTime = 0; _elems.audio.currentTime = 0;
_playTrack(); _playTrack();
@@ -270,7 +270,7 @@ LMS.mediaplayer = function () {
}); });
_elems.audio.addEventListener("canplay", function() { _elems.audio.addEventListener("canplay", function() {
if (_getAudioMode() == Mode.Transcode) { if (_getAudioMode() == Mode.Transcoding) {
_elems.transcodingActive.style.display = "inline"; _elems.transcodingActive.style.display = "inline";
} }
else { else {
@@ -337,7 +337,7 @@ LMS.mediaplayer = function () {
let _getAudioMode = function() { let _getAudioMode = function() {
if (_elems.audio.currentSrc) { if (_elems.audio.currentSrc) {
if (_elems.audio.currentSrc.includes("format")) if (_elems.audio.currentSrc.includes("format"))
return Mode.Transcode; return Mode.Transcoding;
else else
return Mode.File; return Mode.File;
} }
@@ -353,19 +353,19 @@ LMS.mediaplayer = function () {
_offset = 0; _offset = 0;
_duration = params.duration; _duration = params.duration;
_audioNativeSrc = params.nativeResource; _audioNativeSrc = params.nativeResource;
_audioTranscodeSrc = params.transcodeResource + "&bitrate=" + _settings.transcode.bitrate + "&format=" + _settings.transcode.format; _audioTranscodingSrc = params.transcodingResource + "&bitrate=" + _settings.transcoding.bitrate + "&format=" + _settings.transcoding.format;
_elems.seek.max = _duration; _elems.seek.max = _duration;
_removeAudioSources(); _removeAudioSources();
// ! order is important // ! order is important
if (_settings.transcode.mode == TranscodeMode.Never || _settings.transcode.mode == TranscodeMode.IfFormatNotSupported) if (_settings.transcoding.mode == TranscodingMode.Never || _settings.transcoding.mode == TranscodingMode.IfFormatNotSupported)
{ {
_addAudioSource(_audioNativeSrc); _addAudioSource(_audioNativeSrc);
} }
if (_settings.transcode.mode == TranscodeMode.Always || _settings.transcode.mode == TranscodeMode.IfFormatNotSupported) if (_settings.transcoding.mode == TranscodingMode.Always || _settings.transcoding.mode == TranscodingMode.IfFormatNotSupported)
{ {
_addAudioSource(_audioTranscodeSrc); _addAudioSource(_audioTranscodingSrc);
} }
_elems.audio.load(); _elems.audio.load();
+1 -1
View File
@@ -31,7 +31,7 @@
namespace Av::Transcoding namespace Av::Transcoding
{ {
#define LOG(sev) LMS_LOG(TRANSCODE, sev) << "[" << _debugId << "] - " #define LOG(sev) LMS_LOG(TRANSCODING, sev) << "[" << _debugId << "] - "
static std::atomic<size_t> globalId{}; static std::atomic<size_t> globalId{};
static std::filesystem::path ffmpegPath; static std::filesystem::path ffmpegPath;
@@ -43,9 +43,9 @@ namespace Av::Transcoding
, _transcoder{ inputParameters, outputParameters } , _transcoder{ inputParameters, outputParameters }
{ {
if (_estimatedContentLength) if (_estimatedContentLength)
LMS_LOG(TRANSCODE, DEBUG) << "Estimated content length = " << *_estimatedContentLength; LMS_LOG(TRANSCODING, DEBUG) << "Estimated content length = " << *_estimatedContentLength;
else else
LMS_LOG(TRANSCODE, DEBUG) << "Not using estimated content length"; LMS_LOG(TRANSCODING, DEBUG) << "Not using estimated content length";
} }
Wt::Http::ResponseContinuation* TranscodingResourceHandler::processRequest(const Wt::Http::Request& /*request*/, Wt::Http::Response& response) Wt::Http::ResponseContinuation* TranscodingResourceHandler::processRequest(const Wt::Http::Request& /*request*/, Wt::Http::Response& response)
@@ -53,11 +53,11 @@ namespace Av::Transcoding
if (_estimatedContentLength) if (_estimatedContentLength)
response.setContentLength(*_estimatedContentLength); response.setContentLength(*_estimatedContentLength);
response.setMimeType(_transcoder.getOutputMimeType()); response.setMimeType(_transcoder.getOutputMimeType());
LMS_LOG(TRANSCODE, DEBUG) << "Transcoder finished = " << _transcoder.finished() << ", total served bytes = " << _totalServedByteCount << ", mime type = " << _transcoder.getOutputMimeType(); LMS_LOG(TRANSCODING, DEBUG) << "Transcoder finished = " << _transcoder.finished() << ", total served bytes = " << _totalServedByteCount << ", mime type = " << _transcoder.getOutputMimeType();
if (_bytesReadyCount > 0) if (_bytesReadyCount > 0)
{ {
LMS_LOG(TRANSCODE, DEBUG) << "Writing " << _bytesReadyCount << " bytes back to client"; LMS_LOG(TRANSCODING, DEBUG) << "Writing " << _bytesReadyCount << " bytes back to client";
response.out().write(reinterpret_cast<const char*>(&_buffer[0]), _bytesReadyCount); response.out().write(reinterpret_cast<const char*>(&_buffer[0]), _bytesReadyCount);
_totalServedByteCount += _bytesReadyCount; _totalServedByteCount += _bytesReadyCount;
@@ -70,7 +70,7 @@ namespace Av::Transcoding
continuation->waitForMoreData(); continuation->waitForMoreData();
_transcoder.asyncRead(_buffer.data(), _buffer.size(), [=](std::size_t nbBytesRead) _transcoder.asyncRead(_buffer.data(), _buffer.size(), [=](std::size_t nbBytesRead)
{ {
LMS_LOG(TRANSCODE, DEBUG) << "Have " << nbBytesRead << " more bytes to send back"; LMS_LOG(TRANSCODING, DEBUG) << "Have " << nbBytesRead << " more bytes to send back";
assert(_bytesReadyCount == 0); assert(_bytesReadyCount == 0);
_bytesReadyCount = nbBytesRead; _bytesReadyCount = nbBytesRead;
@@ -86,7 +86,7 @@ namespace Av::Transcoding
{ {
const std::size_t padSize{ *_estimatedContentLength - _totalServedByteCount }; const std::size_t padSize{ *_estimatedContentLength - _totalServedByteCount };
LMS_LOG(TRANSCODE, DEBUG) << "Adding " << padSize << " padding bytes"; LMS_LOG(TRANSCODING, DEBUG) << "Adding " << padSize << " padding bytes";
for (std::size_t i{}; i < padSize; ++i) for (std::size_t i{}; i < padSize; ++i)
response.out().put(0); response.out().put(0);
@@ -94,7 +94,7 @@ namespace Av::Transcoding
_totalServedByteCount += padSize; _totalServedByteCount += padSize;
} }
LMS_LOG(TRANSCODE, DEBUG) << "Transcoding finished. Total served byte count = " << _totalServedByteCount; LMS_LOG(TRANSCODING, DEBUG) << "Transcoding finished. Total served byte count = " << _totalServedByteCount;
} }
return {}; return {};
+38 -38
View File
@@ -21,59 +21,59 @@
const char* getModuleName(Module mod) const char* getModuleName(Module mod)
{ {
switch (mod) switch (mod)
{ {
case Module::API_SUBSONIC: return "API_SUBSONIC"; case Module::API_SUBSONIC: return "API_SUBSONIC";
case Module::AUTH: return "AUTH"; case Module::AUTH: return "AUTH";
case Module::AV: return "AV"; case Module::AV: return "AV";
case Module::CHILDPROCESS: return "CHILDPROC"; case Module::CHILDPROCESS: return "CHILDPROC";
case Module::COVER: return "COVER"; case Module::COVER: return "COVER";
case Module::DB: return "DB"; case Module::DB: return "DB";
case Module::DBUPDATER: return "DB UPDATER"; case Module::DBUPDATER: return "DB UPDATER";
case Module::FEATURE: return "FEATURE"; case Module::FEATURE: return "FEATURE";
case Module::FEEDBACK: return "FEEDBACK"; case Module::FEEDBACK: return "FEEDBACK";
case Module::HTTP: return "HTTP"; case Module::HTTP: return "HTTP";
case Module::MAIN: return "MAIN"; case Module::MAIN: return "MAIN";
case Module::METADATA: return "METADATA"; case Module::METADATA: return "METADATA";
case Module::REMOTE: return "REMOTE"; case Module::REMOTE: return "REMOTE";
case Module::SCROBBLING: return "SCROBBLING"; case Module::SCROBBLING: return "SCROBBLING";
case Module::SERVICE: return "SERVICE"; case Module::SERVICE: return "SERVICE";
case Module::RECOMMENDATION: return "RECOMMENDATION"; case Module::RECOMMENDATION: return "RECOMMENDATION";
case Module::TRANSCODE: return "TRANSCODE"; case Module::TRANSCODING: return "TRANSCODING";
case Module::UI: return "UI"; case Module::UI: return "UI";
case Module::UTILS: return "UTILS"; case Module::UTILS: return "UTILS";
} }
return ""; return "";
} }
const char* getSeverityName(Severity sev) const char* getSeverityName(Severity sev)
{ {
switch (sev) switch (sev)
{ {
case Severity::FATAL: return "fatal"; case Severity::FATAL: return "fatal";
case Severity::ERROR: return "error"; case Severity::ERROR: return "error";
case Severity::WARNING: return "warning"; case Severity::WARNING: return "warning";
case Severity::INFO: return "info"; case Severity::INFO: return "info";
case Severity::DEBUG: return "debug"; case Severity::DEBUG: return "debug";
} }
return ""; return "";
} }
Log::Log(Logger* logger, Module module, Severity severity) Log::Log(Logger* logger, Module module, Severity severity)
: _module {module}, : _module{ module },
_severity {severity}, _severity{ severity },
_logger {logger} _logger{ logger }
{} {}
Log::~Log() Log::~Log()
{ {
if (_logger) if (_logger)
_logger->processLog(*this); _logger->processLog(*this);
} }
std::string std::string
Log::getMessage() const Log::getMessage() const
{ {
return _oss.str(); return _oss.str();
} }
+1 -1
View File
@@ -51,7 +51,7 @@ enum class Module
SCROBBLING, SCROBBLING,
SERVICE, SERVICE,
RECOMMENDATION, RECOMMENDATION,
TRANSCODE, TRANSCODING,
UI, UI,
UTILS, UTILS,
}; };
+1 -1
View File
@@ -44,7 +44,7 @@ add_executable(lms
ui/explore/TrackListsView.cpp ui/explore/TrackListsView.cpp
ui/explore/TracksView.cpp ui/explore/TracksView.cpp
ui/resource/AudioFileResource.cpp ui/resource/AudioFileResource.cpp
ui/resource/AudioTranscodeResource.cpp ui/resource/AudioTranscodingResource.cpp
ui/resource/CoverResource.cpp ui/resource/CoverResource.cpp
ui/resource/DownloadResource.cpp ui/resource/DownloadResource.cpp
) )
+1 -1
View File
@@ -49,7 +49,7 @@
#include "explore/Explore.hpp" #include "explore/Explore.hpp"
#include "explore/Filters.hpp" #include "explore/Filters.hpp"
#include "resource/AudioFileResource.hpp" #include "resource/AudioFileResource.hpp"
#include "resource/AudioTranscodeResource.hpp" #include "resource/AudioTranscodingResource.hpp"
#include "resource/DownloadResource.hpp" #include "resource/DownloadResource.hpp"
#include "resource/CoverResource.hpp" #include "resource/CoverResource.hpp"
#include "Auth.hpp" #include "Auth.hpp"
+240 -249
View File
@@ -35,7 +35,7 @@
#include "services/database/User.hpp" #include "services/database/User.hpp"
#include "resource/CoverResource.hpp" #include "resource/CoverResource.hpp"
#include "resource/AudioTranscodeResource.hpp" #include "resource/AudioTranscodingResource.hpp"
#include "resource/AudioFileResource.hpp" #include "resource/AudioFileResource.hpp"
#include "utils/String.hpp" #include "utils/String.hpp"
@@ -44,304 +44,295 @@
#include "LmsApplication.hpp" #include "LmsApplication.hpp"
#include "Utils.hpp" #include "Utils.hpp"
namespace UserInterface { namespace UserInterface
static std::string settingsToJSString(const MediaPlayer::Settings& settings)
{ {
namespace Json = Wt::Json; namespace
{
std::string settingsToJSString(const MediaPlayer::Settings& settings)
{
namespace Json = Wt::Json;
Json::Object res; Json::Object res;
{ {
Json::Object transcode; Json::Object transcoding;
transcode["mode"] = static_cast<int>(settings.transcode.mode); transcoding["mode"] = static_cast<int>(settings.transcoding.mode);
transcode["format"] = static_cast<int>(settings.transcode.format); transcoding["format"] = static_cast<int>(settings.transcoding.format);
transcode["bitrate"] = static_cast<int>(settings.transcode.bitrate); transcoding["bitrate"] = static_cast<int>(settings.transcoding.bitrate);
res["transcode"] = std::move(transcode); res["transcoding"] = std::move(transcoding);
} }
{ {
Json::Object replayGain; Json::Object replayGain;
replayGain["mode"] = static_cast<int>(settings.replayGain.mode); replayGain["mode"] = static_cast<int>(settings.replayGain.mode);
replayGain["preAmpGain"] = settings.replayGain.preAmpGain; replayGain["preAmpGain"] = settings.replayGain.preAmpGain;
replayGain["preAmpGainIfNoInfo"] = settings.replayGain.preAmpGainIfNoInfo; replayGain["preAmpGainIfNoInfo"] = settings.replayGain.preAmpGainIfNoInfo;
res["replayGain"] = std::move(replayGain); res["replayGain"] = std::move(replayGain);
} }
return Json::serialize(res); return Json::serialize(res);
} }
static std::optional<MediaPlayer::Settings::Transcoding::Mode> transcodingModeFromString(const std::string& str)
std::optional<MediaPlayer::Settings::Transcode::Mode> {
transcodeModeFromString(const std::string& str) const auto value{ StringUtils::readAs<int>(str) };
{ if (!value)
const auto value {StringUtils::readAs<int>(str)}; return std::nullopt;
if (!value)
return std::nullopt;
MediaPlayer::Settings::Transcode::Mode mode {static_cast<MediaPlayer::Settings::Transcode::Mode>(*value)}; MediaPlayer::Settings::Transcoding::Mode mode{ static_cast<MediaPlayer::Settings::Transcoding::Mode>(*value) };
switch (mode) switch (mode)
{ {
case MediaPlayer::Settings::Transcode::Mode::Never: case MediaPlayer::Settings::Transcoding::Mode::Never:
case MediaPlayer::Settings::Transcode::Mode::Always: case MediaPlayer::Settings::Transcoding::Mode::Always:
case MediaPlayer::Settings::Transcode::Mode::IfFormatNotSupported: case MediaPlayer::Settings::Transcoding::Mode::IfFormatNotSupported:
return mode; return mode;
} }
return std::nullopt; return std::nullopt;
} }
static std::optional<MediaPlayer::Format> formatFromString(const std::string& str)
std::optional<MediaPlayer::Format> {
formatFromString(const std::string& str) const auto value{ StringUtils::readAs<int>(str) };
{ if (!value)
const auto value {StringUtils::readAs<int>(str)}; return std::nullopt;
if (!value)
return std::nullopt;
MediaPlayer::Format format {static_cast<MediaPlayer::Format>(*value)}; MediaPlayer::Format format{ static_cast<MediaPlayer::Format>(*value) };
switch (format) switch (format)
{ {
case MediaPlayer::Format::MP3: case MediaPlayer::Format::MP3:
case MediaPlayer::Format::OGG_OPUS: case MediaPlayer::Format::OGG_OPUS:
case MediaPlayer::Format::MATROSKA_OPUS: case MediaPlayer::Format::MATROSKA_OPUS:
case MediaPlayer::Format::OGG_VORBIS: case MediaPlayer::Format::OGG_VORBIS:
case MediaPlayer::Format::WEBM_VORBIS: case MediaPlayer::Format::WEBM_VORBIS:
return format; return format;
} }
return std::nullopt; return std::nullopt;
} }
static std::optional<MediaPlayer::Bitrate> bitrateFromString(const std::string& str)
std::optional<MediaPlayer::Bitrate> {
bitrateFromString(const std::string& str) const auto value{ StringUtils::readAs<int>(str) };
{ if (!value)
const auto value {StringUtils::readAs<int>(str)}; return std::nullopt;
if (!value)
return std::nullopt;
if (!Database::isAudioBitrateAllowed(*value)) if (!Database::isAudioBitrateAllowed(*value))
return std::nullopt; return std::nullopt;
return *value; return *value;
} }
static std::optional<MediaPlayer::Settings::ReplayGain::Mode> replayGainModeFromString(const std::string& str)
std::optional<MediaPlayer::Settings::ReplayGain::Mode> {
replayGainModeFromString(const std::string& str) const auto value{ StringUtils::readAs<int>(str) };
{ if (!value)
const auto value {StringUtils::readAs<int>(str)}; return std::nullopt;
if (!value)
return std::nullopt;
MediaPlayer::Settings::ReplayGain::Mode mode {static_cast<MediaPlayer::Settings::ReplayGain::Mode>(*value)}; MediaPlayer::Settings::ReplayGain::Mode mode{ static_cast<MediaPlayer::Settings::ReplayGain::Mode>(*value) };
switch (mode) switch (mode)
{ {
case MediaPlayer::Settings::ReplayGain::Mode::None: case MediaPlayer::Settings::ReplayGain::Mode::None:
case MediaPlayer::Settings::ReplayGain::Mode::Auto: case MediaPlayer::Settings::ReplayGain::Mode::Auto:
case MediaPlayer::Settings::ReplayGain::Mode::Track: case MediaPlayer::Settings::ReplayGain::Mode::Track:
case MediaPlayer::Settings::ReplayGain::Mode::Release: case MediaPlayer::Settings::ReplayGain::Mode::Release:
return mode; return mode;
} }
return std::nullopt; return std::nullopt;
} }
static std::optional<float> replayGainPreAmpGainFromString(const std::string& str)
std::optional<float> {
replayGainPreAmpGainFromString(const std::string& str) const auto value{ StringUtils::readAs<double>(str) };
{ if (!value)
const auto value {StringUtils::readAs<double>(str)}; return std::nullopt;
if (!value)
return std::nullopt;
return ::Utils::clamp(*value, (double)MediaPlayer::Settings::ReplayGain::minPreAmpGain, (double)MediaPlayer::Settings::ReplayGain::maxPreAmpGain); return ::Utils::clamp(*value, (double)MediaPlayer::Settings::ReplayGain::minPreAmpGain, (double)MediaPlayer::Settings::ReplayGain::maxPreAmpGain);
} }
static MediaPlayer::Settings settingsfromJSString(const std::string& strSettings) MediaPlayer::Settings settingsfromJSString(const std::string& strSettings)
{ {
using Settings = MediaPlayer::Settings; using Settings = MediaPlayer::Settings;
namespace Json = Wt::Json; namespace Json = Wt::Json;
Json::Object parsedSettings; Json::Object parsedSettings;
Json::parse(strSettings, parsedSettings); Json::parse(strSettings, parsedSettings);
MediaPlayer::Settings settings; MediaPlayer::Settings settings;
{ {
const Json::Value transcodeValue {parsedSettings.get("transcode")}; const Json::Value transcodingValue{ parsedSettings.get("transcoding") };
if (transcodeValue.type() == Json::Type::Object) if (transcodingValue.type() == Json::Type::Object)
{ {
const Json::Object transcode {transcodeValue}; const Json::Object transcoding{ transcodingValue };
settings.transcode.mode = transcodeModeFromString(transcode.get("mode").toString().orIfNull("")).value_or(Settings::Transcode::defaultMode); settings.transcoding.mode = transcodingModeFromString(transcoding.get("mode").toString().orIfNull("")).value_or(Settings::Transcoding::defaultMode);
settings.transcode.format = formatFromString(transcode.get("format").toString().orIfNull("")).value_or(Settings::Transcode::defaultFormat); settings.transcoding.format = formatFromString(transcoding.get("format").toString().orIfNull("")).value_or(Settings::Transcoding::defaultFormat);
settings.transcode.bitrate = bitrateFromString(transcode.get("bitrate").toString().orIfNull("")).value_or(Settings::Transcode::defaultBitrate); settings.transcoding.bitrate = bitrateFromString(transcoding.get("bitrate").toString().orIfNull("")).value_or(Settings::Transcoding::defaultBitrate);
} }
} }
{ {
const Json::Value replayGainValue {parsedSettings.get("replayGain")}; const Json::Value replayGainValue{ parsedSettings.get("replayGain") };
if (replayGainValue.type() == Json::Type::Object) if (replayGainValue.type() == Json::Type::Object)
{ {
const Json::Object replayGain {replayGainValue}; const Json::Object replayGain{ replayGainValue };
settings.replayGain.mode = replayGainModeFromString(replayGain.get("mode").toString().orIfNull("")).value_or(Settings::ReplayGain::defaultMode); settings.replayGain.mode = replayGainModeFromString(replayGain.get("mode").toString().orIfNull("")).value_or(Settings::ReplayGain::defaultMode);
settings.replayGain.preAmpGain = replayGainPreAmpGainFromString(replayGain.get("preAmpGain").toString().orIfNull("")).value_or(Settings::ReplayGain::defaultPreAmpGain); settings.replayGain.preAmpGain = replayGainPreAmpGainFromString(replayGain.get("preAmpGain").toString().orIfNull("")).value_or(Settings::ReplayGain::defaultPreAmpGain);
settings.replayGain.preAmpGainIfNoInfo = replayGainPreAmpGainFromString(replayGain.get("preAmpGainIfNoInfo").toString().orIfNull("")).value_or(Settings::ReplayGain::defaultPreAmpGain); settings.replayGain.preAmpGainIfNoInfo = replayGainPreAmpGainFromString(replayGain.get("preAmpGainIfNoInfo").toString().orIfNull("")).value_or(Settings::ReplayGain::defaultPreAmpGain);
} }
} }
return settings; return settings;
} }
}
MediaPlayer::MediaPlayer() MediaPlayer::MediaPlayer()
: Wt::WTemplate {Wt::WString::tr("Lms.MediaPlayer.template")} : Wt::WTemplate{ Wt::WString::tr("Lms.MediaPlayer.template") }
, playPrevious {this, "playPrevious"} , playPrevious{ this, "playPrevious" }
, playNext {this, "playNext"} , playNext{ this, "playNext" }
, scrobbleListenNow {this, "scrobbleListenNow"} , scrobbleListenNow{ this, "scrobbleListenNow" }
, scrobbleListenFinished {this, "scrobbleListenFinished"} , scrobbleListenFinished{ this, "scrobbleListenFinished" }
, playbackEnded {this, "playbackEnded"} , playbackEnded{ this, "playbackEnded" }
, _settingsLoaded {this, "settingsLoaded"} , _settingsLoaded{ this, "settingsLoaded" }
{ {
addFunction("tr", &Wt::WTemplate::Functions::tr); addFunction("tr", &Wt::WTemplate::Functions::tr);
_audioTranscodeResource = std::make_unique<AudioTranscodeResource>(); _audioTranscodingResource = std::make_unique<AudioTranscodingResource>();
_audioFileResource = std::make_unique<AudioFileResource>(); _audioFileResource = std::make_unique<AudioFileResource>();
_title = bindNew<Wt::WText>("title"); _title = bindNew<Wt::WText>("title");
_artist = bindNew<Wt::WAnchor>("artist"); _artist = bindNew<Wt::WAnchor>("artist");
_release = bindNew<Wt::WAnchor>("release"); _release = bindNew<Wt::WAnchor>("release");
_separator = bindNew<Wt::WText>("separator"); _separator = bindNew<Wt::WText>("separator");
_playQueue = bindNew<Wt::WPushButton>("playqueue-btn", Wt::WString::tr("Lms.MediaPlayer.template.playqueue-btn").arg(0), Wt::TextFormat::XHTML); _playQueue = bindNew<Wt::WPushButton>("playqueue-btn", Wt::WString::tr("Lms.MediaPlayer.template.playqueue-btn").arg(0), Wt::TextFormat::XHTML);
_playQueue->setLink(Wt::WLink {Wt::LinkType::InternalPath, "/playqueue"}); _playQueue->setLink(Wt::WLink{ Wt::LinkType::InternalPath, "/playqueue" });
_playQueue->setToolTip(tr("Lms.PlayQueue.playqueue")); _playQueue->setToolTip(tr("Lms.PlayQueue.playqueue"));
_settingsLoaded.connect([this](const std::string& settings) _settingsLoaded.connect([this](const std::string& settings)
{ {
LMS_LOG(UI, DEBUG) << "Settings loaded! '" << settings << "'"; LMS_LOG(UI, DEBUG) << "Settings loaded! '" << settings << "'";
_settings = settingsfromJSString(settings); _settings = settingsfromJSString(settings);
settingsLoaded.emit(); settingsLoaded.emit();
}); });
{ {
Settings defaultSettings; Settings defaultSettings;
std::ostringstream oss; std::ostringstream oss;
oss << "LMS.mediaplayer.init(" oss << "LMS.mediaplayer.init("
<< jsRef() << jsRef()
<< ", defaultSettings = " << settingsToJSString(defaultSettings) << ", defaultSettings = " << settingsToJSString(defaultSettings)
<< ")"; << ")";
LMS_LOG(UI, DEBUG) << "Running js = '" << oss.str() << "'"; LMS_LOG(UI, DEBUG) << "Running js = '" << oss.str() << "'";
doJavaScript(oss.str()); doJavaScript(oss.str());
} }
} }
void void MediaPlayer::loadTrack(Database::TrackId trackId, bool play, float replayGain)
MediaPlayer::loadTrack(Database::TrackId trackId, bool play, float replayGain) {
{ LMS_LOG(UI, DEBUG) << "Playing track ID = " << trackId.toString();
LMS_LOG(UI, DEBUG) << "Playing track ID = " << trackId.toString();
std::ostringstream oss; std::ostringstream oss;
{ {
auto transaction {LmsApp->getDbSession().createSharedTransaction()}; auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
const auto track {Database::Track::find(LmsApp->getDbSession(), trackId)}; const auto track{ Database::Track::find(LmsApp->getDbSession(), trackId) };
if (!track) if (!track)
return; return;
const std::string transcodeResource {_audioTranscodeResource->getUrl(trackId)}; const std::string transcodingResource{ _audioTranscodingResource->getUrl(trackId) };
const std::string nativeResource {_audioFileResource->getUrl(trackId)}; const std::string nativeResource{ _audioFileResource->getUrl(trackId) };
const auto artists {track->getArtists({Database::TrackArtistLinkType::Artist})}; const auto artists{ track->getArtists({Database::TrackArtistLinkType::Artist}) };
oss oss
<< "var params = {" << "var params = {"
<< " trackId :\"" << trackId.toString() << "\"," << " trackId :\"" << trackId.toString() << "\","
<< " nativeResource: \"" << nativeResource << "\"," << " nativeResource: \"" << nativeResource << "\","
<< " transcodeResource: \"" << transcodeResource << "\"," << " transcodingResource: \"" << transcodingResource << "\","
<< " duration: " << std::chrono::duration_cast<std::chrono::seconds>(track->getDuration()).count() << "," << " duration: " << std::chrono::duration_cast<std::chrono::seconds>(track->getDuration()).count() << ","
<< " replayGain: " << replayGain << "," << " replayGain: " << replayGain << ","
<< " title: \"" << StringUtils::jsEscape(track->getName()) << "\"," << " title: \"" << StringUtils::jsEscape(track->getName()) << "\","
<< " artist: \"" << (!artists.empty() ? StringUtils::jsEscape(artists.front()->getName()) : "") << "\"," << " artist: \"" << (!artists.empty() ? StringUtils::jsEscape(artists.front()->getName()) : "") << "\","
<< " release: \"" << (track->getRelease() ? StringUtils::jsEscape(track->getRelease()->getName()) : "") << "\"," << " release: \"" << (track->getRelease() ? StringUtils::jsEscape(track->getRelease()->getName()) : "") << "\","
<< " artwork: [" << " artwork: ["
<< " { src: \"" << LmsApp->getCoverResource()->getTrackUrl(trackId, CoverResource::Size::Small) << "\", sizes: \"128x128\", type: \"image/jpeg\" }," << " { src: \"" << LmsApp->getCoverResource()->getTrackUrl(trackId, CoverResource::Size::Small) << "\", sizes: \"128x128\", type: \"image/jpeg\" },"
<< " { src: \"" << LmsApp->getCoverResource()->getTrackUrl(trackId, CoverResource::Size::Large) << "\", sizes: \"512x512\", type: \"image/jpeg\" }," << " { src: \"" << LmsApp->getCoverResource()->getTrackUrl(trackId, CoverResource::Size::Large) << "\", sizes: \"512x512\", type: \"image/jpeg\" },"
<< " ]" << " ]"
<< "};"; << "};";
oss << "LMS.mediaplayer.loadTrack(params, " << (play ? "true" : "false") << ")"; // true to autoplay // Update 'sizes' above to match this:
static_assert(static_cast<std::underlying_type_t<CoverResource::Size>>(CoverResource::Size::Small) == 128);
static_assert(static_cast<std::underlying_type_t<CoverResource::Size>>(CoverResource::Size::Large) == 512);
oss << "LMS.mediaplayer.loadTrack(params, " << (play ? "true" : "false") << ")"; // true to autoplay
_title->setTextFormat(Wt::TextFormat::Plain); _title->setTextFormat(Wt::TextFormat::Plain);
_title->setText(Wt::WString::fromUTF8(track->getName())); _title->setText(Wt::WString::fromUTF8(track->getName()));
bool needSeparator {true}; bool needSeparator{ true };
if (!artists.empty()) if (!artists.empty())
{ {
_artist->setTextFormat(Wt::TextFormat::Plain); _artist->setTextFormat(Wt::TextFormat::Plain);
_artist->setText(Wt::WString::fromUTF8(artists.front()->getName())); _artist->setText(Wt::WString::fromUTF8(artists.front()->getName()));
_artist->setLink(Utils::createArtistLink(artists.front())); _artist->setLink(Utils::createArtistLink(artists.front()));
} }
else else
{ {
_artist->setText(""); _artist->setText("");
_artist->setLink({}); _artist->setLink({});
needSeparator = false; needSeparator = false;
} }
if (track->getRelease()) if (track->getRelease())
{ {
_release->setTextFormat(Wt::TextFormat::Plain); _release->setTextFormat(Wt::TextFormat::Plain);
_release->setText(Wt::WString::fromUTF8(track->getRelease()->getName())); _release->setText(Wt::WString::fromUTF8(track->getRelease()->getName()));
_release->setLink(Utils::createReleaseLink(track->getRelease())); _release->setLink(Utils::createReleaseLink(track->getRelease()));
} }
else else
{ {
_release->setText(""); _release->setText("");
_release->setLink({}); _release->setLink({});
needSeparator = false; needSeparator = false;
} }
if (needSeparator) if (needSeparator)
_separator->setText(""); _separator->setText("");
else else
_separator->setText(""); _separator->setText("");
} }
LMS_LOG(UI, DEBUG) << "Running js = '" << oss.str() << "'"; LMS_LOG(UI, DEBUG) << "Running js = '" << oss.str() << "'";
doJavaScript(oss.str()); doJavaScript(oss.str());
_trackIdLoaded = trackId; _trackIdLoaded = trackId;
trackLoaded.emit(*_trackIdLoaded); trackLoaded.emit(*_trackIdLoaded);
} }
void void MediaPlayer::stop()
MediaPlayer::stop() {
{ doJavaScript("LMS.mediaplayer.stop()");
doJavaScript("LMS.mediaplayer.stop()"); }
}
void void MediaPlayer::setSettings(const Settings& settings)
MediaPlayer::setSettings(const Settings& settings) {
{ _settings = settings;
_settings = settings;
{ {
std::ostringstream oss; std::ostringstream oss;
oss << "LMS.mediaplayer.setSettings(settings = " << settingsToJSString(settings) << ")"; oss << "LMS.mediaplayer.setSettings(settings = " << settingsToJSString(settings) << ")";
LMS_LOG(UI, DEBUG) << "Running js = '" << oss.str() << "'"; LMS_LOG(UI, DEBUG) << "Running js = '" << oss.str() << "'";
doJavaScript(oss.str()); doJavaScript(oss.str());
} }
} }
void void MediaPlayer::onPlayQueueUpdated(std::size_t trackCount)
MediaPlayer::onPlayQueueUpdated(std::size_t trackCount) {
{ _playQueue->setText(Wt::WString::tr("Lms.MediaPlayer.template.playqueue-btn").arg(trackCount));
_playQueue->setText(Wt::WString::tr("Lms.MediaPlayer.template.playqueue-btn").arg(trackCount)); }
}
} // namespace UserInterface } // namespace UserInterface
+5 -7
View File
@@ -33,7 +33,7 @@
namespace UserInterface namespace UserInterface
{ {
class AudioFileResource; class AudioFileResource;
class AudioTranscodeResource; class AudioTranscodingResource;
class MediaPlayer : public Wt::WTemplate class MediaPlayer : public Wt::WTemplate
{ {
@@ -47,7 +47,7 @@ namespace UserInterface
struct Settings struct Settings
{ {
struct Transcode struct Transcoding
{ {
enum class Mode enum class Mode
{ {
@@ -84,16 +84,14 @@ namespace UserInterface
Gain preAmpGainIfNoInfo{ defaultPreAmpGain }; Gain preAmpGainIfNoInfo{ defaultPreAmpGain };
}; };
Transcode transcode; Transcoding transcoding;
ReplayGain replayGain; ReplayGain replayGain;
}; };
MediaPlayer(); MediaPlayer();
~MediaPlayer() = default;
MediaPlayer(const MediaPlayer&) = delete; MediaPlayer(const MediaPlayer&) = delete;
MediaPlayer(MediaPlayer&&) = delete;
MediaPlayer& operator=(const MediaPlayer&) = delete; MediaPlayer& operator=(const MediaPlayer&) = delete;
MediaPlayer& operator=(MediaPlayer&&) = delete;
std::optional<Database::TrackId> getTrackLoaded() const { return _trackIdLoaded; } std::optional<Database::TrackId> getTrackLoaded() const { return _trackIdLoaded; }
@@ -118,7 +116,7 @@ namespace UserInterface
private: private:
std::unique_ptr<AudioFileResource> _audioFileResource; std::unique_ptr<AudioFileResource> _audioFileResource;
std::unique_ptr<AudioTranscodeResource> _audioTranscodeResource; std::unique_ptr<AudioTranscodingResource> _audioTranscodingResource;
std::optional<Database::TrackId> _trackIdLoaded; std::optional<Database::TrackId> _trackIdLoaded;
std::optional<Settings> _settings; std::optional<Settings> _settings;
+58 -58
View File
@@ -44,23 +44,23 @@
#include "LmsApplication.hpp" #include "LmsApplication.hpp"
#include "MediaPlayer.hpp" #include "MediaPlayer.hpp"
namespace UserInterface { namespace UserInterface
{
using namespace Database; using namespace Database;
class SettingsModel : public Wt::WFormModel class SettingsModel : public Wt::WFormModel
{ {
public: public:
// Associate each field with a unique string literal. // Associate each field with a unique string literal.
static inline const Field TranscodeModeField{ "transcode-mode" }; static inline const Field TranscodingModeField{ "transcoding-mode" };
static inline const Field TranscodeFormatField{ "transcode-format" }; static inline const Field TranscodeFormatField{ "transcoding-output-format" };
static inline const Field TranscodeBitrateField{ "transcode-bitrate" }; static inline const Field TranscodeBitrateField{ "transcoding-output-bitrate" };
static inline const Field ReplayGainModeField{ "replaygain-mode" }; static inline const Field ReplayGainModeField{ "replaygain-mode" };
static inline const Field ReplayGainPreAmpGainField{ "replaygain-preamp" }; static inline const Field ReplayGainPreAmpGainField{ "replaygain-preamp" };
static inline const Field ReplayGainPreAmpGainIfNoInfoField{ "replaygain-preamp-no-rg-info" }; static inline const Field ReplayGainPreAmpGainIfNoInfoField{ "replaygain-preamp-no-rg-info" };
static inline const Field SubsonicArtistListModeField{ "subsonic-artist-list-mode" }; static inline const Field SubsonicArtistListModeField{ "subsonic-artist-list-mode" };
static inline const Field SubsonicTranscodingOutputFormatField{ "subsonic-transcode-format" }; static inline const Field SubsonicTranscodingOutputFormatField{ "subsonic-transcoding-output-format" };
static inline const Field SubsonicTranscodingOutputBitrateField{ "subsonic-transcode-bitrate" }; static inline const Field SubsonicTranscodingOutputBitrateField{ "subsonic-transcoding-output-bitrate" };
static inline const Field FeedbackBackendField{ "feedback-backend" }; static inline const Field FeedbackBackendField{ "feedback-backend" };
static inline const Field ScrobblingBackendField{ "scrobbling-backend" }; static inline const Field ScrobblingBackendField{ "scrobbling-backend" };
static inline const Field ListenBrainzTokenField{ "listenbrainz-token" }; static inline const Field ListenBrainzTokenField{ "listenbrainz-token" };
@@ -68,7 +68,7 @@ namespace UserInterface {
static inline const Field PasswordField{ "password" }; static inline const Field PasswordField{ "password" };
static inline const Field PasswordConfirmField{ "password-confirm" }; static inline const Field PasswordConfirmField{ "password-confirm" };
using TranscodingModeModel = ValueStringModel<MediaPlayer::Settings::Transcode::Mode>; using TranscodingModeModel = ValueStringModel<MediaPlayer::Settings::Transcoding::Mode>;
using ReplayGainModeModel = ValueStringModel<MediaPlayer::Settings::ReplayGain::Mode>; using ReplayGainModeModel = ValueStringModel<MediaPlayer::Settings::ReplayGain::Mode>;
using FeedbackBackendModel = ValueStringModel<FeedbackBackend>; using FeedbackBackendModel = ValueStringModel<FeedbackBackend>;
using ScrobblingBackendModel = ValueStringModel<ScrobblingBackend>; using ScrobblingBackendModel = ValueStringModel<ScrobblingBackend>;
@@ -79,7 +79,7 @@ namespace UserInterface {
{ {
initializeModels(); initializeModels();
addField(TranscodeModeField); addField(TranscodingModeField);
addField(TranscodeBitrateField); addField(TranscodeBitrateField);
addField(TranscodeFormatField); addField(TranscodeFormatField);
addField(ReplayGainModeField); addField(ReplayGainModeField);
@@ -105,7 +105,7 @@ namespace UserInterface {
addField(PasswordConfirmField); addField(PasswordConfirmField);
} }
setValidator(TranscodeModeField, createMandatoryValidator()); setValidator(TranscodingModeField, createMandatoryValidator());
setValidator(TranscodeBitrateField, createMandatoryValidator()); setValidator(TranscodeBitrateField, createMandatoryValidator());
setValidator(TranscodeFormatField, createMandatoryValidator()); setValidator(TranscodeFormatField, createMandatoryValidator());
setValidator(ReplayGainModeField, createMandatoryValidator()); setValidator(ReplayGainModeField, createMandatoryValidator());
@@ -124,7 +124,7 @@ namespace UserInterface {
std::shared_ptr<TranscodingModeModel> getTranscodingModeModel() { return _transcodingModeModeModel; } std::shared_ptr<TranscodingModeModel> getTranscodingModeModel() { return _transcodingModeModeModel; }
std::shared_ptr<Wt::WAbstractItemModel> getTranscodingOutputBitrateModel() { return _transcodingOutputBitrateModel; } std::shared_ptr<Wt::WAbstractItemModel> getTranscodingOutputBitrateModel() { return _transcodingOutputBitrateModel; }
std::shared_ptr<Wt::WAbstractItemModel> getTranscodeFormatModel() { return _transcodingOutputFormatModel; } std::shared_ptr<Wt::WAbstractItemModel> getTranscodingOutputFormatModel() { return _transcodingOutputFormatModel; }
std::shared_ptr<ReplayGainModeModel> getReplayGainModeModel() { return _replayGainModeModel; } std::shared_ptr<ReplayGainModeModel> getReplayGainModeModel() { return _replayGainModeModel; }
std::shared_ptr<Wt::WAbstractItemModel> getSubsonicArtistListModeModel() { return _subsonicArtistListModeModel; } std::shared_ptr<Wt::WAbstractItemModel> getSubsonicArtistListModeModel() { return _subsonicArtistListModeModel; }
std::shared_ptr<FeedbackBackendModel> getFeedbackBackendModel() { return _feedbackBackendModel; } std::shared_ptr<FeedbackBackendModel> getFeedbackBackendModel() { return _feedbackBackendModel; }
@@ -139,17 +139,17 @@ namespace UserInterface {
{ {
MediaPlayer::Settings settings; MediaPlayer::Settings settings;
auto transcodeModeRow{ _transcodingModeModeModel->getRowFromString(valueText(TranscodeModeField)) }; auto transcodingModeRow{ _transcodingModeModeModel->getRowFromString(valueText(TranscodingModeField)) };
if (transcodeModeRow) if (transcodingModeRow)
settings.transcode.mode = _transcodingModeModeModel->getValue(*transcodeModeRow); settings.transcoding.mode = _transcodingModeModeModel->getValue(*transcodingModeRow);
auto transcodeFormatRow{ _transcodingOutputFormatModel->getRowFromString(valueText(TranscodeFormatField)) }; auto transcodingOutputFormatRow{ _transcodingOutputFormatModel->getRowFromString(valueText(TranscodeFormatField)) };
if (transcodeFormatRow) if (transcodingOutputFormatRow)
settings.transcode.format = _transcodingOutputFormatModel->getValue(*transcodeFormatRow); settings.transcoding.format = _transcodingOutputFormatModel->getValue(*transcodingOutputFormatRow);
auto transcodeBitrateRow{ _transcodingOutputBitrateModel->getRowFromString(valueText(TranscodeBitrateField)) }; auto transcodingOutputBitrateRow{ _transcodingOutputBitrateModel->getRowFromString(valueText(TranscodeBitrateField)) };
if (transcodeBitrateRow) if (transcodingOutputBitrateRow)
settings.transcode.bitrate = _transcodingOutputBitrateModel->getValue(*transcodeBitrateRow); settings.transcoding.bitrate = _transcodingOutputBitrateModel->getValue(*transcodingOutputBitrateRow);
auto replayGainModeRow{ _replayGainModeModel->getRowFromString(valueText(ReplayGainModeField)) }; auto replayGainModeRow{ _replayGainModeModel->getRowFromString(valueText(ReplayGainModeField)) };
if (replayGainModeRow) if (replayGainModeRow)
@@ -205,22 +205,22 @@ namespace UserInterface {
{ {
const auto settings{ *LmsApp->getMediaPlayer().getSettings() }; const auto settings{ *LmsApp->getMediaPlayer().getSettings() };
auto transcodeModeRow{ _transcodingModeModeModel->getRowFromValue(settings.transcode.mode) }; auto transcodingModeRow{ _transcodingModeModeModel->getRowFromValue(settings.transcoding.mode) };
if (transcodeModeRow) if (transcodingModeRow)
setValue(TranscodeModeField, _transcodingModeModeModel->getString(*transcodeModeRow)); setValue(TranscodingModeField, _transcodingModeModeModel->getString(*transcodingModeRow));
auto transcodeFormatRow{ _transcodingOutputFormatModel->getRowFromValue(settings.transcode.format) }; auto transcodingOutputFormatRow{ _transcodingOutputFormatModel->getRowFromValue(settings.transcoding.format) };
if (transcodeFormatRow) if (transcodingOutputFormatRow)
setValue(TranscodeFormatField, _transcodingOutputFormatModel->getString(*transcodeFormatRow)); setValue(TranscodeFormatField, _transcodingOutputFormatModel->getString(*transcodingOutputFormatRow));
auto transcodeBitrateRow{ _transcodingOutputBitrateModel->getRowFromValue(settings.transcode.bitrate) }; auto transcodingOutputBitrateRow{ _transcodingOutputBitrateModel->getRowFromValue(settings.transcoding.bitrate) };
if (transcodeBitrateRow) if (transcodingOutputBitrateRow)
setValue(TranscodeBitrateField, _transcodingOutputBitrateModel->getString(*transcodeBitrateRow)); setValue(TranscodeBitrateField, _transcodingOutputBitrateModel->getString(*transcodingOutputBitrateRow));
{ {
const bool usesTranscode{ settings.transcode.mode != MediaPlayer::Settings::Transcode::Mode::Never }; const bool useTranscoding{ settings.transcoding.mode != MediaPlayer::Settings::Transcoding::Mode::Never };
setReadOnly(SettingsModel::TranscodeFormatField, !usesTranscode); setReadOnly(SettingsModel::TranscodeFormatField, !useTranscoding);
setReadOnly(SettingsModel::TranscodeBitrateField, !usesTranscode); setReadOnly(SettingsModel::TranscodeBitrateField, !useTranscoding);
} }
auto replayGainModeRow{ _replayGainModeModel->getRowFromValue(settings.replayGain.mode) }; auto replayGainModeRow{ _replayGainModeModel->getRowFromValue(settings.replayGain.mode) };
@@ -316,9 +316,9 @@ namespace UserInterface {
void initializeModels() void initializeModels()
{ {
_transcodingModeModeModel = std::make_shared<TranscodingModeModel>(); _transcodingModeModeModel = std::make_shared<TranscodingModeModel>();
_transcodingModeModeModel->add(Wt::WString::tr("Lms.Settings.transcode-mode.always"), MediaPlayer::Settings::Transcode::Mode::Always); _transcodingModeModeModel->add(Wt::WString::tr("Lms.Settings.transcoding-mode.always"), MediaPlayer::Settings::Transcoding::Mode::Always);
_transcodingModeModeModel->add(Wt::WString::tr("Lms.Settings.transcode-mode.never"), MediaPlayer::Settings::Transcode::Mode::Never); _transcodingModeModeModel->add(Wt::WString::tr("Lms.Settings.transcoding-mode.never"), MediaPlayer::Settings::Transcoding::Mode::Never);
_transcodingModeModeModel->add(Wt::WString::tr("Lms.Settings.transcode-mode.if-format-not-supported"), MediaPlayer::Settings::Transcode::Mode::IfFormatNotSupported); _transcodingModeModeModel->add(Wt::WString::tr("Lms.Settings.transcoding-mode.if-format-not-supported"), MediaPlayer::Settings::Transcoding::Mode::IfFormatNotSupported);
_transcodingOutputBitrateModel = std::make_shared<ValueStringModel<Bitrate>>(); _transcodingOutputBitrateModel = std::make_shared<ValueStringModel<Bitrate>>();
visitAllowedAudioBitrates([&](const Bitrate bitrate) visitAllowedAudioBitrates([&](const Bitrate bitrate)
@@ -327,11 +327,11 @@ namespace UserInterface {
}); });
_transcodingOutputFormatModel = std::make_shared<ValueStringModel<TranscodingOutputFormat>>(); _transcodingOutputFormatModel = std::make_shared<ValueStringModel<TranscodingOutputFormat>>();
_transcodingOutputFormatModel->add(Wt::WString::tr("Lms.Settings.transcode-format.mp3"), TranscodingOutputFormat::MP3); _transcodingOutputFormatModel->add(Wt::WString::tr("Lms.Settings.transcoding-output-format.mp3"), TranscodingOutputFormat::MP3);
_transcodingOutputFormatModel->add(Wt::WString::tr("Lms.Settings.transcode-format.ogg_opus"), TranscodingOutputFormat::OGG_OPUS); _transcodingOutputFormatModel->add(Wt::WString::tr("Lms.Settings.transcoding-output-format.ogg_opus"), TranscodingOutputFormat::OGG_OPUS);
_transcodingOutputFormatModel->add(Wt::WString::tr("Lms.Settings.transcode-format.matroska_opus"), TranscodingOutputFormat::MATROSKA_OPUS); _transcodingOutputFormatModel->add(Wt::WString::tr("Lms.Settings.transcoding-output-format.matroska_opus"), TranscodingOutputFormat::MATROSKA_OPUS);
_transcodingOutputFormatModel->add(Wt::WString::tr("Lms.Settings.transcode-format.ogg_vorbis"), TranscodingOutputFormat::OGG_VORBIS); _transcodingOutputFormatModel->add(Wt::WString::tr("Lms.Settings.transcoding-output-format.ogg_vorbis"), TranscodingOutputFormat::OGG_VORBIS);
_transcodingOutputFormatModel->add(Wt::WString::tr("Lms.Settings.transcode-format.webm_vorbis"), TranscodingOutputFormat::WEBM_VORBIS); _transcodingOutputFormatModel->add(Wt::WString::tr("Lms.Settings.transcoding-output-format.webm_vorbis"), TranscodingOutputFormat::WEBM_VORBIS);
_replayGainModeModel = std::make_shared<ReplayGainModeModel>(); _replayGainModeModel = std::make_shared<ReplayGainModeModel>();
_replayGainModeModel->add(Wt::WString::tr("Lms.Settings.replaygain-mode.none"), MediaPlayer::Settings::ReplayGain::Mode::None); _replayGainModeModel->add(Wt::WString::tr("Lms.Settings.replaygain-mode.none"), MediaPlayer::Settings::ReplayGain::Mode::None);
@@ -431,24 +431,24 @@ namespace UserInterface {
// Audio // Audio
{ {
// Transcode // Transcode
auto transcodeMode{ std::make_unique<Wt::WComboBox>() }; auto transcodingMode{ std::make_unique<Wt::WComboBox>() };
auto* transcodeModeRaw{ transcodeMode.get() }; auto* transcodingModeRaw{ transcodingMode.get() };
transcodeMode->setModel(model->getTranscodingModeModel()); transcodingMode->setModel(model->getTranscodingModeModel());
t->setFormWidget(SettingsModel::TranscodeModeField, std::move(transcodeMode)); t->setFormWidget(SettingsModel::TranscodingModeField, std::move(transcodingMode));
// Format // Format
auto transcodeFormat{ std::make_unique<Wt::WComboBox>() }; auto transcodingOutputFormat{ std::make_unique<Wt::WComboBox>() };
transcodeFormat->setModel(model->getTranscodeFormatModel()); transcodingOutputFormat->setModel(model->getTranscodingOutputFormatModel());
t->setFormWidget(SettingsModel::TranscodeFormatField, std::move(transcodeFormat)); t->setFormWidget(SettingsModel::TranscodeFormatField, std::move(transcodingOutputFormat));
// Bitrate // Bitrate
auto transcodeBitrate{ std::make_unique<Wt::WComboBox>() }; auto transcodingOutputBitrate{ std::make_unique<Wt::WComboBox>() };
transcodeBitrate->setModel(model->getTranscodingOutputBitrateModel()); transcodingOutputBitrate->setModel(model->getTranscodingOutputBitrateModel());
t->setFormWidget(SettingsModel::TranscodeBitrateField, std::move(transcodeBitrate)); t->setFormWidget(SettingsModel::TranscodeBitrateField, std::move(transcodingOutputBitrate));
transcodeModeRaw->activated().connect([=](int row) transcodingModeRaw->activated().connect([=](int row)
{ {
const bool enable{ model->getTranscodingModeModel()->getValue(row) != MediaPlayer::Settings::Transcode::Mode::Never }; const bool enable{ model->getTranscodingModeModel()->getValue(row) != MediaPlayer::Settings::Transcoding::Mode::Never };
model->setReadOnly(SettingsModel::TranscodeFormatField, !enable); model->setReadOnly(SettingsModel::TranscodeFormatField, !enable);
model->setReadOnly(SettingsModel::TranscodeBitrateField, !enable); model->setReadOnly(SettingsModel::TranscodeBitrateField, !enable);
t->updateModel(model.get()); t->updateModel(model.get());
@@ -491,14 +491,14 @@ namespace UserInterface {
t->setCondition("if-has-subsonic-api", Service<IConfig>::get()->getBool("api-subsonic", true)); t->setCondition("if-has-subsonic-api", Service<IConfig>::get()->getBool("api-subsonic", true));
// Format // Format
auto transcodeFormat{ std::make_unique<Wt::WComboBox>() }; auto transcodingOutputFormat{ std::make_unique<Wt::WComboBox>() };
transcodeFormat->setModel(model->getTranscodeFormatModel()); transcodingOutputFormat->setModel(model->getTranscodingOutputFormatModel());
t->setFormWidget(SettingsModel::SubsonicTranscodingOutputFormatField, std::move(transcodeFormat)); t->setFormWidget(SettingsModel::SubsonicTranscodingOutputFormatField, std::move(transcodingOutputFormat));
// Bitrate // Bitrate
auto transcodeBitrate{ std::make_unique<Wt::WComboBox>() }; auto transcodingOutputBitrate{ std::make_unique<Wt::WComboBox>() };
transcodeBitrate->setModel(model->getTranscodingOutputBitrateModel()); transcodingOutputBitrate->setModel(model->getTranscodingOutputBitrateModel());
t->setFormWidget(SettingsModel::SubsonicTranscodingOutputBitrateField, std::move(transcodeBitrate)); t->setFormWidget(SettingsModel::SubsonicTranscodingOutputBitrateField, std::move(transcodingOutputBitrate));
// Artist list mode // Artist list mode
auto artistListMode{ std::make_unique<Wt::WComboBox>() }; auto artistListMode{ std::make_unique<Wt::WComboBox>() };
@@ -17,7 +17,7 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>. * along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "AudioTranscodeResource.hpp" #include "AudioTranscodingResource.hpp"
#include <optional> #include <optional>
#include <Wt/Http/Response.h> #include <Wt/Http/Response.h>
@@ -159,17 +159,17 @@ namespace UserInterface
} }
} }
AudioTranscodeResource:: ~AudioTranscodeResource() AudioTranscodingResource:: ~AudioTranscodingResource()
{ {
beingDeleted(); beingDeleted();
} }
std::string AudioTranscodeResource::getUrl(Database::TrackId trackId) const std::string AudioTranscodingResource::getUrl(Database::TrackId trackId) const
{ {
return url() + "&trackid=" + trackId.toString(); return url() + "&trackid=" + trackId.toString();
} }
void AudioTranscodeResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Response& response) void AudioTranscodingResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Response& response)
{ {
std::shared_ptr<IResourceHandler> resourceHandler; std::shared_ptr<IResourceHandler> resourceHandler;
@@ -31,10 +31,10 @@ namespace Database
namespace UserInterface namespace UserInterface
{ {
class AudioTranscodeResource : public Wt::WResource class AudioTranscodingResource : public Wt::WResource
{ {
public: public:
~AudioTranscodeResource(); ~AudioTranscodingResource();
// Url depends on the user since settings are used in parameters // Url depends on the user since settings are used in parameters
std::string getUrl(Database::TrackId trackId) const; std::string getUrl(Database::TrackId trackId) const;