[UI] User can now force the audio encoding to be used
This commit is contained in:
+22
-3
@@ -23,7 +23,7 @@ namespace Database {
|
|||||||
|
|
||||||
// must be ordered
|
// must be ordered
|
||||||
const std::vector<std::size_t>
|
const std::vector<std::size_t>
|
||||||
User::audioBitrates =
|
User::audioBitrates =
|
||||||
{
|
{
|
||||||
64000,
|
64000,
|
||||||
96000,
|
96000,
|
||||||
@@ -38,7 +38,7 @@ const std::vector<std::size_t>
|
|||||||
|
|
||||||
|
|
||||||
const std::vector<std::size_t>
|
const std::vector<std::size_t>
|
||||||
User::videoBitrates =
|
User::videoBitrates =
|
||||||
{
|
{
|
||||||
256000,
|
256000,
|
||||||
512000,
|
512000,
|
||||||
@@ -47,12 +47,31 @@ const std::vector<std::size_t>
|
|||||||
4096000,
|
4096000,
|
||||||
8192000
|
8192000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const std::vector<AudioEncoding>
|
||||||
|
User::audioEncodings =
|
||||||
|
{
|
||||||
|
AudioEncoding::AUTO,
|
||||||
|
AudioEncoding::MP3,
|
||||||
|
AudioEncoding::OGA,
|
||||||
|
AudioEncoding::WEBMA,
|
||||||
|
AudioEncoding::FLA,
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::vector<VideoEncoding>
|
||||||
|
User::videoEncodings =
|
||||||
|
{
|
||||||
|
VideoEncoding::AUTO,
|
||||||
|
};
|
||||||
|
|
||||||
User::User()
|
User::User()
|
||||||
: _maxAudioBitrate(maxAudioBitrate),
|
: _maxAudioBitrate(maxAudioBitrate),
|
||||||
_maxVideoBitrate(maxVideoBitrate),
|
_maxVideoBitrate(maxVideoBitrate),
|
||||||
_isAdmin(false),
|
_isAdmin(false),
|
||||||
_audioBitrate(defaultAudioBitrate),
|
_audioBitrate(defaultAudioBitrate),
|
||||||
_videoBitrate(defaultVideoBitrate)
|
_audioEncoding(AudioEncoding::AUTO),
|
||||||
|
_videoBitrate(defaultVideoBitrate),
|
||||||
|
_videoEncoding(VideoEncoding::AUTO)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-2
@@ -32,14 +32,34 @@ typedef Wt::Auth::Dbo::AuthInfo<User> AuthInfo;
|
|||||||
|
|
||||||
class Playlist;
|
class Playlist;
|
||||||
|
|
||||||
class User {
|
// User selectable audio formats
|
||||||
|
enum class AudioEncoding
|
||||||
|
{
|
||||||
|
AUTO,
|
||||||
|
MP3,
|
||||||
|
OGA,
|
||||||
|
WEBMA,
|
||||||
|
FLA,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class VideoEncoding
|
||||||
|
{
|
||||||
|
AUTO,
|
||||||
|
};
|
||||||
|
|
||||||
|
class User
|
||||||
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static const std::size_t MaxNameLength = 15;
|
static const std::size_t MaxNameLength = 15;
|
||||||
|
|
||||||
// list of commonly used bitrates
|
// list of audio/video parameters
|
||||||
static const std::vector<std::size_t> audioBitrates;
|
static const std::vector<std::size_t> audioBitrates;
|
||||||
|
static const std::vector<AudioEncoding> audioEncodings;
|
||||||
|
|
||||||
static const std::vector<std::size_t> videoBitrates;
|
static const std::vector<std::size_t> videoBitrates;
|
||||||
|
static const std::vector<VideoEncoding> videoEncodings;
|
||||||
|
|
||||||
User();
|
User();
|
||||||
|
|
||||||
@@ -53,14 +73,18 @@ class User {
|
|||||||
// write
|
// write
|
||||||
void setAdmin(bool admin) { _isAdmin = admin; }
|
void setAdmin(bool admin) { _isAdmin = admin; }
|
||||||
void setAudioBitrate(std::size_t bitrate);
|
void setAudioBitrate(std::size_t bitrate);
|
||||||
|
void setAudioEncoding(AudioEncoding encoding) { _audioEncoding = encoding; }
|
||||||
void setVideoBitrate(std::size_t bitrate);
|
void setVideoBitrate(std::size_t bitrate);
|
||||||
|
void setVideoEncoding(VideoEncoding encoding) { _videoEncoding = encoding; }
|
||||||
void setMaxAudioBitrate(std::size_t bitrate);
|
void setMaxAudioBitrate(std::size_t bitrate);
|
||||||
void setMaxVideoBitrate(std::size_t bitrate);
|
void setMaxVideoBitrate(std::size_t bitrate);
|
||||||
|
|
||||||
// read
|
// read
|
||||||
bool isAdmin() const {return _isAdmin;}
|
bool isAdmin() const {return _isAdmin;}
|
||||||
std::size_t getAudioBitrate() const;
|
std::size_t getAudioBitrate() const;
|
||||||
|
AudioEncoding getAudioEncoding() const { return _audioEncoding;}
|
||||||
std::size_t getVideoBitrate() const;
|
std::size_t getVideoBitrate() const;
|
||||||
|
VideoEncoding getVideoEncoding() const { return _videoEncoding;}
|
||||||
std::size_t getMaxAudioBitrate() const;
|
std::size_t getMaxAudioBitrate() const;
|
||||||
std::size_t getMaxVideoBitrate() const;
|
std::size_t getMaxVideoBitrate() const;
|
||||||
|
|
||||||
@@ -71,7 +95,9 @@ class User {
|
|||||||
Wt::Dbo::field(a, _maxVideoBitrate, "max_video_bitrate");
|
Wt::Dbo::field(a, _maxVideoBitrate, "max_video_bitrate");
|
||||||
Wt::Dbo::field(a, _isAdmin, "admin");
|
Wt::Dbo::field(a, _isAdmin, "admin");
|
||||||
Wt::Dbo::field(a, _audioBitrate, "audio_bitrate");
|
Wt::Dbo::field(a, _audioBitrate, "audio_bitrate");
|
||||||
|
Wt::Dbo::field(a, _audioEncoding, "audio_encoding");
|
||||||
Wt::Dbo::field(a, _videoBitrate, "video_bitrate");
|
Wt::Dbo::field(a, _videoBitrate, "video_bitrate");
|
||||||
|
Wt::Dbo::field(a, _videoEncoding, "video_encoding");
|
||||||
Wt::Dbo::hasMany(a, _playlists, Wt::Dbo::ManyToOne, "user");
|
Wt::Dbo::hasMany(a, _playlists, Wt::Dbo::ManyToOne, "user");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +116,9 @@ class User {
|
|||||||
|
|
||||||
// User defined settings
|
// User defined settings
|
||||||
int _audioBitrate;
|
int _audioBitrate;
|
||||||
|
AudioEncoding _audioEncoding;
|
||||||
int _videoBitrate;
|
int _videoBitrate;
|
||||||
|
VideoEncoding _videoEncoding;
|
||||||
|
|
||||||
Wt::Dbo::collection< Wt::Dbo::ptr<Playlist> > _playlists;
|
Wt::Dbo::collection< Wt::Dbo::ptr<Playlist> > _playlists;
|
||||||
|
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ AvConvTranscoder::AvConvTranscoder(const Parameters& parameters)
|
|||||||
oss << " -acodec libvorbis -ac 2 -ar 44100 -vcodec libvpx -threads 4 -f webm";
|
oss << " -acodec libvorbis -ac 2 -ar 44100 -vcodec libvpx -threads 4 -f webm";
|
||||||
break;
|
break;
|
||||||
case Format::M4A:
|
case Format::M4A:
|
||||||
oss << " -acodec aac -f mp4";
|
oss << " -acodec aac -f mp4 -strict experimental";
|
||||||
break;
|
break;
|
||||||
case Format::M4V:
|
case Format::M4V:
|
||||||
oss << " -acodec aac -strict experimental -ac 2 -ar 44100 -vcodec libx264 -f m4v";
|
oss << " -acodec aac -strict experimental -ac 2 -ar 44100 -vcodec libx264 -f m4v";
|
||||||
@@ -143,6 +143,9 @@ AvConvTranscoder::AvConvTranscoder(const Parameters& parameters)
|
|||||||
case Format::FLV:
|
case Format::FLV:
|
||||||
oss << " -acodec libmp3lame -ac 2 -ar 44100 -vcodec libx264 -f flv";
|
oss << " -acodec libmp3lame -ac 2 -ar 44100 -vcodec libx264 -f flv";
|
||||||
break;
|
break;
|
||||||
|
case Format::FLA:
|
||||||
|
oss << " -acodec libmp3lame -f flv";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ const std::vector<Format> Format::_supportedFormats
|
|||||||
{Format::MP3, Format::Audio, "audio/mpeg", "MP3"},
|
{Format::MP3, Format::Audio, "audio/mpeg", "MP3"},
|
||||||
{Format::WEBMA, Format::Audio, "audio/webm", "WebM"},
|
{Format::WEBMA, Format::Audio, "audio/webm", "WebM"},
|
||||||
{Format::WEBMV, Format::Video, "video/webm", "WebM"},
|
{Format::WEBMV, Format::Video, "video/webm", "WebM"},
|
||||||
|
{Format::FLA, Format::Audio, "audio/x-flv", "Flash Audio"},
|
||||||
{Format::FLV, Format::Video, "video/x-flv", "Flash Video"},
|
{Format::FLV, Format::Video, "video/x-flv", "Flash Video"},
|
||||||
{Format::M4A, Format::Audio, "audio/mp4", "MP4"},
|
{Format::M4A, Format::Audio, "audio/mp4", "MP4"},
|
||||||
{Format::M4V, Format::Video, "video/mp4", "MP4"},
|
{Format::M4V, Format::Video, "video/mp4", "MP4"},
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class Format
|
|||||||
MP3,
|
MP3,
|
||||||
WEBMA,
|
WEBMA,
|
||||||
WEBMV,
|
WEBMV,
|
||||||
|
FLA,
|
||||||
FLV,
|
FLV,
|
||||||
M4A,
|
M4A,
|
||||||
M4V,
|
M4V,
|
||||||
|
|||||||
@@ -229,6 +229,17 @@
|
|||||||
<div class="help-block col-sm-5">
|
<div class="help-block col-sm-5">
|
||||||
${bitrate-info}
|
${bitrate-info}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-sm-2" for="${id:encoding}">
|
||||||
|
Audio Encoding
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-5">
|
||||||
|
${encoding}
|
||||||
|
</div>
|
||||||
|
<div class="help-block col-sm-5">
|
||||||
|
${encoding-info}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-offset-2 col-sm-10">
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace UserInterface {
|
|||||||
namespace Desktop {
|
namespace Desktop {
|
||||||
|
|
||||||
Wt::WMediaPlayer::Encoding
|
Wt::WMediaPlayer::Encoding
|
||||||
AudioMediaPlayer::getEncoding()
|
AudioMediaPlayer::getBestEncoding()
|
||||||
{
|
{
|
||||||
const Wt::WEnvironment& env = Wt::WApplication::instance()->environment();
|
const Wt::WEnvironment& env = Wt::WApplication::instance()->environment();
|
||||||
|
|
||||||
@@ -42,9 +42,10 @@ AudioMediaPlayer::getEncoding()
|
|||||||
return Wt::WMediaPlayer::OGA;
|
return Wt::WMediaPlayer::OGA;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioMediaPlayer::AudioMediaPlayer( Wt::WContainerWidget *parent)
|
AudioMediaPlayer::AudioMediaPlayer( Wt::WMediaPlayer::Encoding encoding, Wt::WContainerWidget *parent)
|
||||||
: Wt::WContainerWidget(parent),
|
: Wt::WContainerWidget(parent),
|
||||||
_mediaResource(nullptr)
|
_mediaResource(nullptr),
|
||||||
|
_encoding(encoding)
|
||||||
{
|
{
|
||||||
this->setStyleClass("mediaplayer");
|
this->setStyleClass("mediaplayer");
|
||||||
this->setHeight(90);
|
this->setHeight(90);
|
||||||
@@ -112,7 +113,7 @@ AudioMediaPlayer::AudioMediaPlayer( Wt::WContainerWidget *parent)
|
|||||||
controlsLayout->addWidget(shuffle);
|
controlsLayout->addWidget(shuffle);
|
||||||
|
|
||||||
_mediaPlayer = new Wt::WMediaPlayer( Wt::WMediaPlayer::Audio, btnContainer );
|
_mediaPlayer = new Wt::WMediaPlayer( Wt::WMediaPlayer::Audio, btnContainer );
|
||||||
_mediaPlayer->addSource( getEncoding(), "" );
|
_mediaPlayer->addSource( _encoding, "" );
|
||||||
_mediaPlayer->ended().connect(this, &AudioMediaPlayer::handleTrackEnded);
|
_mediaPlayer->ended().connect(this, &AudioMediaPlayer::handleTrackEnded);
|
||||||
|
|
||||||
_mediaPlayer->setControlsWidget( 0 );
|
_mediaPlayer->setControlsWidget( 0 );
|
||||||
@@ -148,15 +149,13 @@ AudioMediaPlayer::loadPlayer(void)
|
|||||||
{
|
{
|
||||||
_mediaPlayer->clearSources();
|
_mediaPlayer->clearSources();
|
||||||
|
|
||||||
_mediaInternalLink.setResource( nullptr );
|
|
||||||
if (_mediaResource)
|
if (_mediaResource)
|
||||||
delete _mediaResource;
|
delete _mediaResource;
|
||||||
|
|
||||||
assert( _currentParameters );
|
assert( _currentParameters );
|
||||||
_mediaResource = new AvConvTranscodeStreamResource( *_currentParameters, this );
|
_mediaResource = new AvConvTranscodeStreamResource( *_currentParameters, this );
|
||||||
_mediaInternalLink.setResource( _mediaResource );
|
|
||||||
|
|
||||||
_mediaPlayer->addSource( getEncoding(), _mediaInternalLink );
|
_mediaPlayer->addSource( getEncoding(), Wt::WLink(_mediaResource));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
#include <Wt/WPushButton>
|
#include <Wt/WPushButton>
|
||||||
#include <Wt/WContainerWidget>
|
#include <Wt/WContainerWidget>
|
||||||
#include <Wt/WMediaPlayer>
|
#include <Wt/WMediaPlayer>
|
||||||
#include <Wt/WLink>
|
|
||||||
#include <Wt/WText>
|
#include <Wt/WText>
|
||||||
|
|
||||||
#include "transcode/Parameters.hpp"
|
#include "transcode/Parameters.hpp"
|
||||||
@@ -38,14 +37,15 @@ namespace Desktop {
|
|||||||
class AudioMediaPlayer : public Wt::WContainerWidget
|
class AudioMediaPlayer : public Wt::WContainerWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static Wt::WMediaPlayer::Encoding getBestEncoding();
|
||||||
|
|
||||||
// Encoding is set based on environment
|
AudioMediaPlayer( Wt::WMediaPlayer::Encoding encoding, Wt::WContainerWidget *parent = 0);
|
||||||
static Wt::WMediaPlayer::Encoding getEncoding();
|
|
||||||
|
|
||||||
AudioMediaPlayer( Wt::WContainerWidget *parent = 0);
|
|
||||||
|
|
||||||
void load(const Transcode::Parameters& parameters);
|
void load(const Transcode::Parameters& parameters);
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
Wt::WMediaPlayer::Encoding getEncoding() const { return _encoding; }
|
||||||
|
|
||||||
// Signal slots
|
// Signal slots
|
||||||
Wt::Signal<void>& playbackEnded() {return _playbackEnded;}
|
Wt::Signal<void>& playbackEnded() {return _playbackEnded;}
|
||||||
Wt::Signal<void>& playNext() {return _playNext;}
|
Wt::Signal<void>& playNext() {return _playNext;}
|
||||||
@@ -53,6 +53,7 @@ class AudioMediaPlayer : public Wt::WContainerWidget
|
|||||||
Wt::Signal<bool>& shuffle() {return _shuffle;}
|
Wt::Signal<bool>& shuffle() {return _shuffle;}
|
||||||
Wt::Signal<bool>& loop() {return _loop;}
|
Wt::Signal<bool>& loop() {return _loop;}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void handlePlayOffset(int offsetSecs);
|
void handlePlayOffset(int offsetSecs);
|
||||||
@@ -76,7 +77,7 @@ class AudioMediaPlayer : public Wt::WContainerWidget
|
|||||||
// Core
|
// Core
|
||||||
Wt::WMediaPlayer* _mediaPlayer;
|
Wt::WMediaPlayer* _mediaPlayer;
|
||||||
AvConvTranscodeStreamResource* _mediaResource;
|
AvConvTranscodeStreamResource* _mediaResource;
|
||||||
Wt::WLink _mediaInternalLink;
|
Wt::WMediaPlayer::Encoding _encoding;
|
||||||
|
|
||||||
// Controls
|
// Controls
|
||||||
std::shared_ptr<Transcode::Parameters> _currentParameters;
|
std::shared_ptr<Transcode::Parameters> _currentParameters;
|
||||||
|
|||||||
@@ -110,13 +110,28 @@ _playQueue(nullptr)
|
|||||||
// Playlist/PlayQueue
|
// Playlist/PlayQueue
|
||||||
{
|
{
|
||||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||||
|
Database::User::pointer user = _db.getCurrentUser();
|
||||||
|
|
||||||
Wt::WContainerWidget* playQueueContainer = new Wt::WContainerWidget();
|
Wt::WContainerWidget* playQueueContainer = new Wt::WContainerWidget();
|
||||||
playQueueContainer->setStyleClass("playqueue");
|
playQueueContainer->setStyleClass("playqueue");
|
||||||
Wt::WVBoxLayout* playQueueLayout = new Wt::WVBoxLayout();
|
Wt::WVBoxLayout* playQueueLayout = new Wt::WVBoxLayout();
|
||||||
playQueueContainer->setLayout(playQueueLayout);
|
playQueueContainer->setLayout(playQueueLayout);
|
||||||
|
|
||||||
_mediaPlayer = new AudioMediaPlayer();
|
// Determine the encoding to be used
|
||||||
|
Wt::WMediaPlayer::Encoding encoding;
|
||||||
|
switch (user->getAudioEncoding())
|
||||||
|
{
|
||||||
|
case Database::AudioEncoding::MP3: encoding = Wt::WMediaPlayer::MP3; break;
|
||||||
|
case Database::AudioEncoding::WEBMA: encoding = Wt::WMediaPlayer::WEBMA; break;
|
||||||
|
case Database::AudioEncoding::OGA: encoding = Wt::WMediaPlayer::OGA; break;
|
||||||
|
case Database::AudioEncoding::FLA: encoding = Wt::WMediaPlayer::FLA; break;
|
||||||
|
case Database::AudioEncoding::AUTO:
|
||||||
|
default:
|
||||||
|
encoding = AudioMediaPlayer::getBestEncoding();
|
||||||
|
}
|
||||||
|
|
||||||
|
LMS_LOG(MOD_UI, SEV_INFO) << "Audio player using encoding " << encoding;
|
||||||
|
_mediaPlayer = new AudioMediaPlayer(encoding);
|
||||||
playQueueLayout->addWidget(_mediaPlayer);
|
playQueueLayout->addWidget(_mediaPlayer);
|
||||||
|
|
||||||
playQueueLayout->addWidget( _playQueue, 1);
|
playQueueLayout->addWidget( _playQueue, 1);
|
||||||
@@ -505,11 +520,12 @@ Audio::playTrack(boost::filesystem::path p)
|
|||||||
|
|
||||||
// Determine the output format using the encoding of the player
|
// Determine the output format using the encoding of the player
|
||||||
Transcode::Format::Encoding encoding;
|
Transcode::Format::Encoding encoding;
|
||||||
switch(AudioMediaPlayer::getEncoding())
|
switch (_mediaPlayer->getEncoding())
|
||||||
{
|
{
|
||||||
case Wt::WMediaPlayer::MP3: encoding = Transcode::Format::MP3; break;
|
case Wt::WMediaPlayer::MP3: encoding = Transcode::Format::MP3; break;
|
||||||
case Wt::WMediaPlayer::M4A: encoding = Transcode::Format::M4A; break;
|
case Wt::WMediaPlayer::FLA: encoding = Transcode::Format::FLA; break;
|
||||||
case Wt::WMediaPlayer::OGA: encoding = Transcode::Format::OGA; break;
|
case Wt::WMediaPlayer::OGA: encoding = Transcode::Format::OGA; break;
|
||||||
|
case Wt::WMediaPlayer::WEBMA: encoding = Transcode::Format::WEBMA; break;
|
||||||
default:
|
default:
|
||||||
encoding = Transcode::Format::MP3;
|
encoding = Transcode::Format::MP3;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#include <Wt/WApplication>
|
#include <Wt/WApplication>
|
||||||
#include <Wt/WImage>
|
#include <Wt/WImage>
|
||||||
#include <Wt/WLink>
|
|
||||||
#include <Wt/WItemDelegate>
|
#include <Wt/WItemDelegate>
|
||||||
#include <Wt/WStandardItem>
|
#include <Wt/WStandardItem>
|
||||||
#include <Wt/WFileResource>
|
#include <Wt/WFileResource>
|
||||||
|
|||||||
@@ -63,7 +63,23 @@ _db(db)
|
|||||||
Wt::WTemplate* playerTemplate = new Wt::WTemplate(this);
|
Wt::WTemplate* playerTemplate = new Wt::WTemplate(this);
|
||||||
playerTemplate->setTemplateText(Wt::WString::tr("mobile-audio-player"));
|
playerTemplate->setTemplateText(Wt::WString::tr("mobile-audio-player"));
|
||||||
|
|
||||||
AudioMediaPlayer* mediaPlayer = new AudioMediaPlayer();
|
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||||
|
Database::User::pointer user = _db.getCurrentUser();
|
||||||
|
|
||||||
|
// Determine the encoding to be used
|
||||||
|
Wt::WMediaPlayer::Encoding encoding;
|
||||||
|
switch (user->getAudioEncoding())
|
||||||
|
{
|
||||||
|
case Database::AudioEncoding::MP3: encoding = Wt::WMediaPlayer::MP3; break;
|
||||||
|
case Database::AudioEncoding::WEBMA: encoding = Wt::WMediaPlayer::WEBMA; break;
|
||||||
|
case Database::AudioEncoding::OGA: encoding = Wt::WMediaPlayer::OGA; break;
|
||||||
|
case Database::AudioEncoding::FLA: encoding = Wt::WMediaPlayer::FLA; break;
|
||||||
|
case Database::AudioEncoding::AUTO:
|
||||||
|
default:
|
||||||
|
encoding = AudioMediaPlayer::getBestEncoding();
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioMediaPlayer* mediaPlayer = new AudioMediaPlayer(encoding);
|
||||||
playerTemplate->bindWidget("player", mediaPlayer);
|
playerTemplate->bindWidget("player", mediaPlayer);
|
||||||
|
|
||||||
edit->changed().connect(std::bind([=] () {
|
edit->changed().connect(std::bind([=] () {
|
||||||
@@ -177,11 +193,12 @@ _db(db)
|
|||||||
{
|
{
|
||||||
// Determine the output format using the encoding of the player
|
// Determine the output format using the encoding of the player
|
||||||
Transcode::Format::Encoding encoding;
|
Transcode::Format::Encoding encoding;
|
||||||
switch(AudioMediaPlayer::getEncoding())
|
switch(mediaPlayer->getEncoding())
|
||||||
{
|
{
|
||||||
case Wt::WMediaPlayer::MP3: encoding = Transcode::Format::MP3; break;
|
case Wt::WMediaPlayer::MP3: encoding = Transcode::Format::MP3; break;
|
||||||
case Wt::WMediaPlayer::M4A: encoding = Transcode::Format::M4A; break;
|
case Wt::WMediaPlayer::FLA: encoding = Transcode::Format::FLA; break;
|
||||||
case Wt::WMediaPlayer::OGA: encoding = Transcode::Format::OGA; break;
|
case Wt::WMediaPlayer::OGA: encoding = Transcode::Format::OGA; break;
|
||||||
|
case Wt::WMediaPlayer::WEBMA: encoding = Transcode::Format::WEBMA; break;
|
||||||
default:
|
default:
|
||||||
encoding = Transcode::Format::MP3;
|
encoding = Transcode::Format::MP3;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace UserInterface {
|
|||||||
namespace Mobile {
|
namespace Mobile {
|
||||||
|
|
||||||
Wt::WMediaPlayer::Encoding
|
Wt::WMediaPlayer::Encoding
|
||||||
AudioMediaPlayer::getEncoding()
|
AudioMediaPlayer::getBestEncoding()
|
||||||
{
|
{
|
||||||
const Wt::WEnvironment& env = Wt::WApplication::instance()->environment();
|
const Wt::WEnvironment& env = Wt::WApplication::instance()->environment();
|
||||||
|
|
||||||
@@ -38,20 +38,24 @@ AudioMediaPlayer::getEncoding()
|
|||||||
return Wt::WMediaPlayer::OGA;
|
return Wt::WMediaPlayer::OGA;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioMediaPlayer::AudioMediaPlayer(Wt::WContainerWidget *parent)
|
AudioMediaPlayer::AudioMediaPlayer(Wt::WMediaPlayer::Encoding encoding, Wt::WContainerWidget *parent)
|
||||||
: Wt::WContainerWidget(parent)
|
:
|
||||||
|
Wt::WContainerWidget(parent),
|
||||||
|
_player(nullptr),
|
||||||
|
_encoding(encoding)
|
||||||
{
|
{
|
||||||
_player = new Wt::WMediaPlayer(Wt::WMediaPlayer::Audio, this);
|
_player = new Wt::WMediaPlayer(Wt::WMediaPlayer::Audio, this);
|
||||||
_player->addSource( getEncoding(), "" );
|
_player->addSource( _encoding, "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioMediaPlayer::play(const Transcode::Parameters& parameters)
|
AudioMediaPlayer::play(const Transcode::Parameters& parameters)
|
||||||
{
|
{
|
||||||
|
// FIXME memleak here
|
||||||
AvConvTranscodeStreamResource *resource = new AvConvTranscodeStreamResource( parameters, this );
|
AvConvTranscodeStreamResource *resource = new AvConvTranscodeStreamResource( parameters, this );
|
||||||
|
|
||||||
_player->clearSources();
|
_player->clearSources();
|
||||||
_player->addSource( getEncoding(), Wt::WLink(resource));
|
_player->addSource( _encoding, Wt::WLink(resource));
|
||||||
|
|
||||||
_player->play();
|
_player->play();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,15 +32,18 @@ class AudioMediaPlayer : public Wt::WContainerWidget
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static Wt::WMediaPlayer::Encoding getEncoding();
|
static Wt::WMediaPlayer::Encoding getBestEncoding();
|
||||||
|
|
||||||
AudioMediaPlayer(Wt::WContainerWidget *parent = 0);
|
AudioMediaPlayer(Wt::WMediaPlayer::Encoding encoding, Wt::WContainerWidget *parent = 0);
|
||||||
|
|
||||||
void play(const Transcode::Parameters& parameters);
|
void play(const Transcode::Parameters& parameters);
|
||||||
|
|
||||||
|
Wt::WMediaPlayer::Encoding getEncoding() const { return _encoding; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Wt::WMediaPlayer *_player;
|
Wt::WMediaPlayer *_player;
|
||||||
|
Wt::WMediaPlayer::Encoding _encoding;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -63,10 +63,7 @@ _sessionData(sessionData)
|
|||||||
|
|
||||||
::Database::User::pointer user = sessionData.getDatabaseHandler().getCurrentUser();
|
::Database::User::pointer user = sessionData.getDatabaseHandler().getCurrentUser();
|
||||||
|
|
||||||
// Must be logged in here
|
menu->addItem("Audio", new AudioFormView(sessionData));
|
||||||
assert(user);
|
|
||||||
|
|
||||||
menu->addItem("Audio", new AudioFormView(sessionData, Database::User::getId(user)));
|
|
||||||
if (user->isAdmin())
|
if (user->isAdmin())
|
||||||
{
|
{
|
||||||
MediaDirectories* mediaDirectory = new MediaDirectories(sessionData);
|
MediaDirectories* mediaDirectory = new MediaDirectories(sessionData);
|
||||||
|
|||||||
@@ -30,6 +30,23 @@
|
|||||||
|
|
||||||
#include "SettingsAudioFormView.hpp"
|
#include "SettingsAudioFormView.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::string encodingToString(Database::AudioEncoding encoding)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (encoding)
|
||||||
|
{
|
||||||
|
case Database::AudioEncoding::AUTO: return "Automatic";
|
||||||
|
case Database::AudioEncoding::MP3: return "MP3";
|
||||||
|
case Database::AudioEncoding::OGA: return "OGG";
|
||||||
|
case Database::AudioEncoding::WEBMA: return "WebM";
|
||||||
|
case Database::AudioEncoding::FLA: return "Flash";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
|
|
||||||
@@ -39,34 +56,35 @@ class AudioFormModel : public Wt::WFormModel
|
|||||||
|
|
||||||
// Associate each field with a unique string literal.
|
// Associate each field with a unique string literal.
|
||||||
static const Field BitrateField;
|
static const Field BitrateField;
|
||||||
|
static const Field EncodingField;
|
||||||
|
|
||||||
AudioFormModel(SessionData& sessionData, std::string userId, Wt::WObject *parent = 0)
|
AudioFormModel(SessionData& sessionData, Wt::WObject *parent = 0)
|
||||||
: Wt::WFormModel(parent),
|
: Wt::WFormModel(parent),
|
||||||
_db(sessionData.getDatabaseHandler()),
|
_db(sessionData.getDatabaseHandler())
|
||||||
_userId(userId)
|
|
||||||
{
|
{
|
||||||
initializeModels();
|
initializeModels();
|
||||||
|
|
||||||
addField(BitrateField);
|
addField(BitrateField);
|
||||||
|
addField(EncodingField, "Session must be reloaded to apply this setting");
|
||||||
|
|
||||||
setValidator(BitrateField, new Wt::WValidator(true)); // mandatory
|
setValidator(BitrateField, new Wt::WValidator(true)); // mandatory
|
||||||
|
setValidator(EncodingField, new Wt::WValidator(true)); // mandatory
|
||||||
|
|
||||||
// populate the model with initial data
|
// populate the model with initial data
|
||||||
loadData();
|
loadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
Wt::WAbstractItemModel *bitrateModel() { return _bitrateModel; }
|
Wt::WAbstractItemModel *bitrateModel() { return _bitrateModel; }
|
||||||
|
Wt::WAbstractItemModel *encodingModel() { return _encodingModel; }
|
||||||
|
|
||||||
void loadData()
|
void loadData()
|
||||||
{
|
{
|
||||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||||
|
Database::User::pointer user = _db.getCurrentUser();
|
||||||
|
|
||||||
Database::User::pointer user = Database::User::getById( _db.getSession(), _userId);
|
setValue(BitrateField, std::min(user->getMaxAudioBitrate(), user->getAudioBitrate()) / 1000); // in kps
|
||||||
|
int encodingRow = getAudioEncodingRow( user->getAudioEncoding());
|
||||||
if (user)
|
setValue(EncodingField, getAudioEncodingString(encodingRow));
|
||||||
setValue(BitrateField, std::min(user->getMaxAudioBitrate(), user->getAudioBitrate()) / 1000); // in kps
|
|
||||||
else
|
|
||||||
setValue(BitrateField, Wt::WString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool saveData(Wt::WString& error)
|
bool saveData(Wt::WString& error)
|
||||||
@@ -74,14 +92,13 @@ class AudioFormModel : public Wt::WFormModel
|
|||||||
// DBO transaction active here
|
// DBO transaction active here
|
||||||
try {
|
try {
|
||||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||||
|
Database::User::pointer user = _db.getCurrentUser();
|
||||||
|
|
||||||
Database::User::pointer user = Database::User::getById( _db.getSession(), _userId);
|
|
||||||
// user may have been deleted by someone else
|
// user may have been deleted by someone else
|
||||||
if (user)
|
user.modify()->setAudioBitrate( Wt::asNumber(value(BitrateField)) * 1000); // in kbps
|
||||||
{
|
|
||||||
user.modify()->setAudioBitrate( Wt::asNumber(value(BitrateField)) * 1000); // in kbps
|
|
||||||
}
|
|
||||||
|
|
||||||
|
int encodingRow = getAudioEncodingRow( boost::any_cast<Wt::WString>(value((EncodingField))));
|
||||||
|
user.modify()->setAudioEncoding( getAudioEncodingValue(encodingRow));
|
||||||
}
|
}
|
||||||
catch(Wt::Dbo::Exception& exception)
|
catch(Wt::Dbo::Exception& exception)
|
||||||
{
|
{
|
||||||
@@ -92,33 +109,77 @@ class AudioFormModel : public Wt::WFormModel
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getAudioEncodingRow( Database::AudioEncoding encoding)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _encodingModel->rowCount(); ++i)
|
||||||
|
{
|
||||||
|
if (getAudioEncodingValue(i) == encoding)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getAudioEncodingRow( Wt::WString encoding)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _encodingModel->rowCount(); ++i)
|
||||||
|
{
|
||||||
|
if (getAudioEncodingString(i) == encoding)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Database::AudioEncoding getAudioEncodingValue(int row)
|
||||||
|
{
|
||||||
|
return boost::any_cast<Database::AudioEncoding>
|
||||||
|
(_encodingModel->data(_encodingModel->index(row, 0), Wt::UserRole));
|
||||||
|
}
|
||||||
|
|
||||||
|
Wt::WString getAudioEncodingString(int row)
|
||||||
|
{
|
||||||
|
return boost::any_cast<Wt::WString>
|
||||||
|
(_encodingModel->data(_encodingModel->index(row, 0), Wt::DisplayRole));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initializeModels()
|
void initializeModels()
|
||||||
{
|
{
|
||||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||||
|
|
||||||
Database::User::pointer user = Database::User::getById(_db.getSession(), _userId);
|
Database::User::pointer user = _db.getCurrentUser();
|
||||||
|
|
||||||
_bitrateModel = new Wt::WStringListModel(this);
|
_bitrateModel = new Wt::WStringListModel(this);
|
||||||
BOOST_FOREACH(std::size_t bitrate, Database::User::audioBitrates)
|
BOOST_FOREACH(std::size_t bitrate, Database::User::audioBitrates)
|
||||||
{
|
{
|
||||||
if (user && bitrate <= user->getMaxAudioBitrate())
|
if (bitrate <= user->getMaxAudioBitrate())
|
||||||
_bitrateModel->addString( Wt::WString("{1}").arg( bitrate / 1000 ) ); // in kbps
|
_bitrateModel->addString( Wt::WString("{1}").arg( bitrate / 1000 ) ); // in kbps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_encodingModel = new Wt::WStringListModel(this);
|
||||||
|
int row = 0;
|
||||||
|
BOOST_FOREACH(Database::AudioEncoding encoding, Database::User::audioEncodings)
|
||||||
|
{
|
||||||
|
_encodingModel->addString(encodingToString(encoding));
|
||||||
|
_encodingModel->setData(row, 0, encoding, Wt::UserRole);
|
||||||
|
row++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Database::Handler& _db;
|
Database::Handler& _db;
|
||||||
std::string _userId;
|
std::string _userId;
|
||||||
Wt::WStringListModel* _bitrateModel;
|
Wt::WStringListModel* _bitrateModel;
|
||||||
|
Wt::WStringListModel* _encodingModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Wt::WFormModel::Field AudioFormModel::BitrateField = "bitrate";
|
const Wt::WFormModel::Field AudioFormModel::BitrateField = "bitrate";
|
||||||
|
const Wt::WFormModel::Field AudioFormModel::EncodingField = "encoding";
|
||||||
|
|
||||||
AudioFormView::AudioFormView(SessionData& sessionData, std::string userId, Wt::WContainerWidget *parent)
|
AudioFormView::AudioFormView(SessionData& sessionData, Wt::WContainerWidget *parent)
|
||||||
: Wt::WTemplateFormView(parent)
|
: Wt::WTemplateFormView(parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
_model = new AudioFormModel(sessionData, userId, this);
|
_model = new AudioFormModel(sessionData, this);
|
||||||
|
|
||||||
setTemplateText(tr("audioForm-template"));
|
setTemplateText(tr("audioForm-template"));
|
||||||
addFunction("id", &WTemplate::Functions::id);
|
addFunction("id", &WTemplate::Functions::id);
|
||||||
@@ -136,6 +197,12 @@ AudioFormView::AudioFormView(SessionData& sessionData, std::string userId, Wt::W
|
|||||||
bitrateCB->setModel(_model->bitrateModel());
|
bitrateCB->setModel(_model->bitrateModel());
|
||||||
bitrateCB->changed().connect(_applyInfo, &Wt::WWidget::hide);
|
bitrateCB->changed().connect(_applyInfo, &Wt::WWidget::hide);
|
||||||
|
|
||||||
|
// Encoding
|
||||||
|
Wt::WComboBox *encodingCB = new Wt::WComboBox();
|
||||||
|
setFormWidget(AudioFormModel::EncodingField, encodingCB);
|
||||||
|
encodingCB->setModel(_model->encodingModel());
|
||||||
|
encodingCB->changed().connect(_applyInfo, &Wt::WWidget::hide);
|
||||||
|
|
||||||
// Title & Buttons
|
// Title & Buttons
|
||||||
bindString("title", "Audio settings");
|
bindString("title", "Audio settings");
|
||||||
|
|
||||||
@@ -148,9 +215,7 @@ AudioFormView::AudioFormView(SessionData& sessionData, std::string userId, Wt::W
|
|||||||
bindWidget("cancel-button", cancelButton);
|
bindWidget("cancel-button", cancelButton);
|
||||||
cancelButton->clicked().connect(this, &AudioFormView::processCancel);
|
cancelButton->clicked().connect(this, &AudioFormView::processCancel);
|
||||||
|
|
||||||
|
|
||||||
updateView(_model);
|
updateView(_model);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class AudioFormModel;
|
|||||||
class AudioFormView : public Wt::WTemplateFormView
|
class AudioFormView : public Wt::WTemplateFormView
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AudioFormView(SessionData& sessionData, std::string userId, Wt::WContainerWidget *parent = 0);
|
AudioFormView(SessionData& sessionData, Wt::WContainerWidget *parent = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void processCancel(); // reload from DB
|
void processCancel(); // reload from DB
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ convert(Transcode::Format format)
|
|||||||
case Transcode::Format::MP3: return Wt::WMediaPlayer::MP3;
|
case Transcode::Format::MP3: return Wt::WMediaPlayer::MP3;
|
||||||
case Transcode::Format::WEBMA: return Wt::WMediaPlayer::WEBMA;
|
case Transcode::Format::WEBMA: return Wt::WMediaPlayer::WEBMA;
|
||||||
case Transcode::Format::WEBMV: return Wt::WMediaPlayer::WEBMV;
|
case Transcode::Format::WEBMV: return Wt::WMediaPlayer::WEBMV;
|
||||||
|
case Transcode::Format::FLA: return Wt::WMediaPlayer::FLA;
|
||||||
case Transcode::Format::FLV: return Wt::WMediaPlayer::FLV;
|
case Transcode::Format::FLV: return Wt::WMediaPlayer::FLV;
|
||||||
case Transcode::Format::M4A: return Wt::WMediaPlayer::M4A;
|
case Transcode::Format::M4A: return Wt::WMediaPlayer::M4A;
|
||||||
case Transcode::Format::M4V: return Wt::WMediaPlayer::M4V;
|
case Transcode::Format::M4V: return Wt::WMediaPlayer::M4V;
|
||||||
|
|||||||
Reference in New Issue
Block a user