diff --git a/approot/templates.xml b/approot/templates.xml
index b55f513b..1e9d1148 100644
--- a/approot/templates.xml
+++ b/approot/templates.xml
@@ -311,6 +311,30 @@
+
${apply-button} ${discard-button} ${immediate-scan-button}
diff --git a/src/database-updater/DatabaseUpdater.cpp b/src/database-updater/DatabaseUpdater.cpp
index c747713d..eba1e54b 100644
--- a/src/database-updater/DatabaseUpdater.cpp
+++ b/src/database-updater/DatabaseUpdater.cpp
@@ -128,20 +128,6 @@ _metadataParser(parser)
_ioService.setThreadCount(1);
}
-void
-Updater::setAudioExtensions(const std::vector& extensions)
-{
- for (const std::string& extension : extensions)
- _audioExtensions.push_back("." + extension);
-}
-
-void
-Updater::setVideoExtensions(const std::vector& extensions)
-{
- for (const std::string& extension : extensions)
- _videoExtensions.push_back("." + extension);
-}
-
void
Updater::start(void)
{
@@ -233,6 +219,8 @@ Updater::process(boost::system::error_code err)
{
if (!err)
{
+ updateFileExtensions();
+
Stats stats;
checkAudioFiles(stats);
@@ -284,6 +272,15 @@ Updater::process(boost::system::error_code err)
}
}
+void
+Updater::updateFileExtensions()
+{
+ Wt::Dbo::Transaction transaction(_db.getSession());
+
+ _audioFileExtensions = MediaDirectorySettings::get(_db.getSession())->getAudioFileExtensions();
+ _videoFileExtensions = MediaDirectorySettings::get(_db.getSession())->getVideoFileExtensions();
+}
+
Artist::pointer
Updater::getArtist( const boost::filesystem::path& file, const std::string& name, const std::string& mbid)
{
@@ -574,13 +571,13 @@ Updater::processRootDirectory(RootDirectory rootDirectory, Stats& stats)
switch( rootDirectory.type )
{
case Database::MediaDirectory::Audio:
- if (isFileSupported(*itPath, _audioExtensions))
+ if (isFileSupported(*itPath, _audioFileExtensions))
processAudioFile( *itPath, stats );
break;
case Database::MediaDirectory::Video:
- if (isFileSupported(*itPath, _videoExtensions))
+ if (isFileSupported(*itPath, _videoFileExtensions))
processVideoFile( *itPath, stats);
break;
}
@@ -655,7 +652,7 @@ Updater::checkAudioFiles( Stats& stats )
if (!_running)
return;
- if (!checkFile(trackPath, rootDirs, _audioExtensions))
+ if (!checkFile(trackPath, rootDirs, _audioFileExtensions))
{
Wt::Dbo::Transaction transaction(_db.getSession());
@@ -723,7 +720,7 @@ Updater::checkVideoFiles( Stats& stats )
if (!_running)
return;
- if (!checkFile(videoPath, rootDirs, _videoExtensions))
+ if (!checkFile(videoPath, rootDirs, _videoFileExtensions))
{
Wt::Dbo::Transaction transaction(_db.getSession());
diff --git a/src/database-updater/DatabaseUpdater.hpp b/src/database-updater/DatabaseUpdater.hpp
index f614426b..ed90ebdf 100644
--- a/src/database-updater/DatabaseUpdater.hpp
+++ b/src/database-updater/DatabaseUpdater.hpp
@@ -80,6 +80,7 @@ class Updater
Database::Artist::pointer getArtist( const boost::filesystem::path& file, const std::string& name, const std::string& MBID);
Database::Release::pointer getRelease( const boost::filesystem::path& file, const std::string& name, const std::string& MBID);
std::vector getGenres( const std::list& names);
+ void updateFileExtensions();
// Audio
void checkAudioFiles( Stats& stats );
@@ -96,11 +97,8 @@ class Updater
Database::Handler _db;
- std::vector _audioExtensions
- = {".mp3", ".ogg", ".oga", ".aac", ".m4a", ".flac", ".wav", ".wma", ".aif", ".aiff", ".ape", ".mpc", ".shn"}; // TODO parametrize
-
- std::vector _videoExtensions
- = {".flv", ".avi", ".mpg", ".mpeg", ".mp4", ".m4v", ".mkv", ".mov", ".wmv", ".ogv", ".divx", ".m2ts"}; // TODO parametrize
+ std::vector _audioFileExtensions;
+ std::vector _videoFileExtensions;
MetaData::Parser& _metadataParser;
diff --git a/src/database/MediaDirectory.cpp b/src/database/MediaDirectory.cpp
index ca4209a1..75f25724 100644
--- a/src/database/MediaDirectory.cpp
+++ b/src/database/MediaDirectory.cpp
@@ -21,11 +21,40 @@
#include "Types.hpp"
+static std::string pathsToString(const std::vector& paths)
+{
+ std::ostringstream oss;
+
+ bool first = true;
+ for (auto& path : paths)
+ {
+ if (!first)
+ oss << " ";
+
+ oss << path.string();
+ first = false;
+ }
+
+ return oss.str();
+}
+
+static std::vector stringToPaths(const std::string value)
+{
+ std::vector res;
+ std::istringstream iss(value);
+
+ std::copy(std::istream_iterator(iss), std::istream_iterator(), std::back_inserter(res));
+
+ return std::vector(res.begin(), res.end());
+}
+
namespace Database {
MediaDirectorySettings::MediaDirectorySettings()
: _manualScanRequested(false),
-_updatePeriod(Never)
+_updatePeriod(Never),
+_audioFileExtensions(".mp3 .ogg .oga .aac .m4a .flac .wav .wma .aif .aiff .ape .mpc .shn"),
+_videoFileExtensions(".flv .avi .mpg .mpeg .mp4 .m4v .mkv .mov .wmv .ogv .divx .m2ts")
{
}
@@ -48,6 +77,31 @@ MediaDirectorySettings::get(Wt::Dbo::Session& session)
return res;
}
+std::vector
+MediaDirectorySettings::getAudioFileExtensions(void) const
+{
+ return stringToPaths(_audioFileExtensions);
+}
+
+std::vector
+MediaDirectorySettings::getVideoFileExtensions(void) const
+{
+ return stringToPaths(_videoFileExtensions);
+}
+
+void
+MediaDirectorySettings::setAudioFileExtensions(std::vector extensions)
+{
+ _audioFileExtensions = pathsToString(extensions);
+}
+
+void
+MediaDirectorySettings::setVideoFileExtensions(std::vector extensions)
+{
+ _videoFileExtensions = pathsToString(extensions);
+}
+
+
MediaDirectory::pointer
MediaDirectory::create(Wt::Dbo::Session& session, boost::filesystem::path p, Type type)
{
@@ -84,4 +138,5 @@ MediaDirectory::get(Wt::Dbo::Session& session, boost::filesystem::path p, Type t
return session.find().where("path = ?").where("type = ?").bind( p.string()).bind(type);
}
+
} // namespace Database
diff --git a/src/database/MediaDirectory.hpp b/src/database/MediaDirectory.hpp
index 6eae74bb..f4085be5 100644
--- a/src/database/MediaDirectory.hpp
+++ b/src/database/MediaDirectory.hpp
@@ -55,6 +55,8 @@ class MediaDirectorySettings
void setUpdateStartTime(boost::posix_time::time_duration dur) { _updateStartTime = dur;}
void setLastUpdate(boost::posix_time::ptime time) { _lastUpdate = time; }
void setLastScan(boost::posix_time::ptime time) { _lastScan = time; }
+ void setAudioFileExtensions(std::vector extensions);
+ void setVideoFileExtensions(std::vector extensions);
// Read accessors
bool getManualScanRequested(void) const { return _manualScanRequested; }
@@ -62,6 +64,8 @@ class MediaDirectorySettings
boost::posix_time::time_duration getUpdateStartTime(void) const { return _updateStartTime; }
boost::posix_time::ptime getLastUpdated(void) const { return _lastUpdate; }
boost::posix_time::ptime getLastScan(void) const { return _lastScan; }
+ std::vector getAudioFileExtensions(void) const;
+ std::vector getVideoFileExtensions(void) const;
template
void persist(Action& a)
@@ -69,6 +73,8 @@ class MediaDirectorySettings
Wt::Dbo::field(a, _manualScanRequested, "manual_scan_requested");
Wt::Dbo::field(a, _updatePeriod, "update_period");
Wt::Dbo::field(a, _updateStartTime, "update_start_time");
+ Wt::Dbo::field(a, _audioFileExtensions, "audio_file_extensions");
+ Wt::Dbo::field(a, _videoFileExtensions, "video_file_extensions");
Wt::Dbo::field(a, _lastUpdate, "last_update");
Wt::Dbo::field(a, _lastScan, "last_scan");
Wt::Dbo::hasMany(a, _mediaDirectories, Wt::Dbo::ManyToOne, "media_directory_settings");
@@ -79,6 +85,8 @@ class MediaDirectorySettings
bool _manualScanRequested; // Immadiate scan has been requested by user
UpdatePeriod _updatePeriod; // How long between updates
boost::posix_time::time_duration _updateStartTime; // Time of day to begin the update
+ std::string _audioFileExtensions; // Extension of the audio files to be scanned
+ std::string _videoFileExtensions; // Extension of the video files to be scanned
boost::posix_time::ptime _lastUpdate; // last time the database has changed
boost::posix_time::ptime _lastScan; // last time the database has been scanned
Wt::Dbo::collection< Wt::Dbo::ptr > _mediaDirectories; // list of media directories
diff --git a/src/ui/settings/Settings.cpp b/src/ui/settings/Settings.cpp
index bdde115b..c2e8d727 100644
--- a/src/ui/settings/Settings.cpp
+++ b/src/ui/settings/Settings.cpp
@@ -77,7 +77,7 @@ Settings::Settings(Wt::WContainerWidget* parent)
DatabaseFormView* databaseFormView = new DatabaseFormView();
databaseFormView->changed().connect(this, &Settings::restartDatabaseUpdateService);
- menu->addItem("Database Update", databaseFormView);
+ menu->addItem("Database", databaseFormView);
menu->addItem("Users", new Users());
}
diff --git a/src/ui/settings/SettingsDatabaseFormView.cpp b/src/ui/settings/SettingsDatabaseFormView.cpp
index a2fafeb8..d0c8cb16 100644
--- a/src/ui/settings/SettingsDatabaseFormView.cpp
+++ b/src/ui/settings/SettingsDatabaseFormView.cpp
@@ -22,6 +22,8 @@
#include
#include
#include
+#include
+#include
#include
#include
@@ -37,12 +39,16 @@
namespace UserInterface {
namespace Settings {
+using namespace Database;
+
class DatabaseFormModel : public Wt::WFormModel
{
public:
// Associate each field with a unique string literal.
static const Field UpdatePeriodField;
static const Field UpdateStartTimeField;
+ static const Field AudioFileExtensionsField;
+ static const Field VideoFileExtensionsField;
DatabaseFormModel(Wt::WObject *parent = 0)
: Wt::WFormModel(parent)
@@ -51,9 +57,13 @@ class DatabaseFormModel : public Wt::WFormModel
addField(UpdatePeriodField);
addField(UpdateStartTimeField);
+ addField(AudioFileExtensionsField);
+ addField(VideoFileExtensionsField);
- setValidator(UpdatePeriodField, createUpdatePeriodValidator());
- setValidator(UpdateStartTimeField, createStartTimeValidator());
+ setValidator(UpdatePeriodField, createUpdatePeriodValidator());
+ setValidator(UpdateStartTimeField, createStartTimeValidator());
+ setValidator(AudioFileExtensionsField, createFileExtensionValidator());
+ setValidator(VideoFileExtensionsField, createFileExtensionValidator());
// populate the model with initial data
loadData();
@@ -67,7 +77,7 @@ class DatabaseFormModel : public Wt::WFormModel
Wt::Dbo::Transaction transaction(DboSession());
// Get refresh settings
- ::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(DboSession());
+ MediaDirectorySettings::pointer settings = MediaDirectorySettings::get(DboSession());
int periodRow = getUpdatePeriodModelRow( settings->getUpdatePeriod() );
if (periodRow != -1)
@@ -77,13 +87,30 @@ class DatabaseFormModel : public Wt::WFormModel
if (startTimeRow != -1)
setValue(UpdateStartTimeField, updateStartTime( startTimeRow ) );
+ std::vector audioFileExtensions = settings->getAudioFileExtensions();
+ {
+ std::ostringstream oss;
+ for (auto& fileExtension : audioFileExtensions)
+ oss << fileExtension.string() << " ";
+
+ setValue(AudioFileExtensionsField, oss.str());
+ }
+
+ std::vector videoFileExtensions = settings->getVideoFileExtensions();
+ {
+ std::ostringstream oss;
+ for (auto& fileExtension : videoFileExtensions)
+ oss << fileExtension.string() << " ";
+
+ setValue(VideoFileExtensionsField, oss.str());
+ }
}
void saveData()
{
Wt::Dbo::Transaction transaction(DboSession());
- ::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(DboSession());
+ MediaDirectorySettings::pointer settings = MediaDirectorySettings::get(DboSession());
int periodRow = getUpdatePeriodModelRow( boost::any_cast(value(UpdatePeriodField)));
assert(periodRow != -1);
@@ -93,14 +120,32 @@ class DatabaseFormModel : public Wt::WFormModel
assert(startTimeRow != -1);
settings.modify()->setUpdateStartTime( updateStartTimeDuration( startTimeRow ) );
+ {
+ std::vector res;
+ std::istringstream iss(boost::any_cast(value(AudioFileExtensionsField)).toUTF8());
+
+ std::copy(std::istream_iterator(iss), std::istream_iterator(), std::back_inserter(res));
+
+ settings.modify()->setAudioFileExtensions( std::vector(res.begin(), res.end()) );
+ }
+
+ {
+ std::vector res;
+ std::istringstream iss(boost::any_cast(value(VideoFileExtensionsField)).toUTF8());
+
+ std::copy(std::istream_iterator(iss), std::istream_iterator(), std::back_inserter(res));
+
+ settings.modify()->setVideoFileExtensions( std::vector(res.begin(), res.end()) );
+ }
}
bool setImmediateScan(Wt::WString& error)
{
- try {
+ try
+ {
Wt::Dbo::Transaction transaction( DboSession());
- ::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(DboSession() );
+ MediaDirectorySettings::pointer settings = MediaDirectorySettings::get(DboSession() );
settings.modify()->setManualScanRequested( true );
}
@@ -123,7 +168,7 @@ class DatabaseFormModel : public Wt::WFormModel
return -1;
}
- int getUpdatePeriodModelRow(Database::MediaDirectorySettings::UpdatePeriod duration)
+ int getUpdatePeriodModelRow(MediaDirectorySettings::UpdatePeriod duration)
{
for (int i = 0; i < _updatePeriodModel->rowCount(); ++i)
{
@@ -134,8 +179,8 @@ class DatabaseFormModel : public Wt::WFormModel
return -1;
}
- Database::MediaDirectorySettings::UpdatePeriod updatePeriodDuration(int row) {
- return boost::any_cast
+ MediaDirectorySettings::UpdatePeriod updatePeriodDuration(int row) {
+ return boost::any_cast
(_updatePeriodModel->data(_updatePeriodModel->index(row, 0), Wt::UserRole));
}
@@ -185,16 +230,16 @@ class DatabaseFormModel : public Wt::WFormModel
_updatePeriodModel = new Wt::WStringListModel(this);
_updatePeriodModel->addString("Never");
- _updatePeriodModel->setData(0, 0, Database::MediaDirectorySettings::Never, Wt::UserRole);
+ _updatePeriodModel->setData(0, 0, MediaDirectorySettings::Never, Wt::UserRole);
_updatePeriodModel->addString("Daily");
- _updatePeriodModel->setData(1, 0, Database::MediaDirectorySettings::Daily, Wt::UserRole);
+ _updatePeriodModel->setData(1, 0, MediaDirectorySettings::Daily, Wt::UserRole);
_updatePeriodModel->addString("Weekly");
- _updatePeriodModel->setData(2, 0, Database::MediaDirectorySettings::Weekly, Wt::UserRole);
+ _updatePeriodModel->setData(2, 0, MediaDirectorySettings::Weekly, Wt::UserRole);
_updatePeriodModel->addString("Monthly");
- _updatePeriodModel->setData(3, 0, Database::MediaDirectorySettings::Monthly, Wt::UserRole);
+ _updatePeriodModel->setData(3, 0, MediaDirectorySettings::Monthly, Wt::UserRole);
_updateStartTimeModel = new Wt::WStringListModel(this);
@@ -216,18 +261,25 @@ class DatabaseFormModel : public Wt::WFormModel
}
- Wt::WValidator *createUpdatePeriodValidator() {
+ Wt::WValidator *createUpdatePeriodValidator()
+ {
Wt::WValidator* v = new Wt::WValidator();
v->setMandatory(true);
return v;
}
- Wt::WValidator *createStartTimeValidator() {
+ Wt::WValidator *createStartTimeValidator()
+ {
Wt::WValidator* v = new Wt::WValidator();
v->setMandatory(true);
return v;
}
+ Wt::WValidator *createFileExtensionValidator()
+ {
+ Wt::WRegExpValidator *v = new Wt::WRegExpValidator("(?:\\.\\w+(?:\\s*))+");
+ return v;
+ }
Wt::WStringListModel* _updatePeriodModel;
Wt::WStringListModel* _updateStartTimeModel;
@@ -236,6 +288,8 @@ class DatabaseFormModel : public Wt::WFormModel
const Wt::WFormModel::Field DatabaseFormModel::UpdatePeriodField = "update-period";
const Wt::WFormModel::Field DatabaseFormModel::UpdateStartTimeField = "update-start-time";
+const Wt::WFormModel::Field DatabaseFormModel::AudioFileExtensionsField = "audio-file-extensions";
+const Wt::WFormModel::Field DatabaseFormModel::VideoFileExtensionsField = "video-file-extensions";
DatabaseFormView::DatabaseFormView(Wt::WContainerWidget *parent)
@@ -264,8 +318,18 @@ DatabaseFormView::DatabaseFormView(Wt::WContainerWidget *parent)
updateStartTimeCB->setModel(_model->updateStartTimeModel());
updateStartTimeCB->changed().connect(_applyInfo, &Wt::WWidget::hide);
+ // Audio file extensions
+ Wt::WLineEdit *audioFileExtensionsEdit = new Wt::WLineEdit();
+ setFormWidget(DatabaseFormModel::AudioFileExtensionsField, audioFileExtensionsEdit);
+ audioFileExtensionsEdit->changed().connect(_applyInfo, &Wt::WWidget::hide);
+
+ // Video file extensions
+ Wt::WLineEdit *videoFileExtensionsEdit = new Wt::WLineEdit();
+ setFormWidget(DatabaseFormModel::VideoFileExtensionsField, videoFileExtensionsEdit);
+ videoFileExtensionsEdit->changed().connect(_applyInfo, &Wt::WWidget::hide);
+
// Title & Buttons
- bindString("title", "Database update settings");
+ bindString("title", "Database settings");
Wt::WPushButton *saveButton = new Wt::WPushButton("Apply");
bindWidget("apply-button", saveButton);