[UI] Various improvments in audio view

This commit is contained in:
emeric
2014-12-13 18:21:57 +01:00
parent c5937ead52
commit a03a890f5b
13 changed files with 78 additions and 30 deletions
+13
View File
@@ -114,6 +114,19 @@ InputFormatContext::getMetadata(void)
} }
std::size_t
InputFormatContext::getNbPictures(void) const
{
std::size_t res = 0;
for (std::size_t i = 0; i < native()->nb_streams; ++i)
{
if (native()->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC)
++res;
}
return res;
}
void void
InputFormatContext::getPictures(std::vector< std::vector<unsigned char> >& pictures) const InputFormatContext::getPictures(std::vector< std::vector<unsigned char> >& pictures) const
{ {
+1
View File
@@ -46,6 +46,7 @@ class InputFormatContext : public FormatContext
// Get attached pictures // Get attached pictures
std::size_t getNbPictures(void) const;
void getPictures(std::vector< std::vector<unsigned char> >& pictures) const; void getPictures(std::vector< std::vector<unsigned char> >& pictures) const;
// Get the streams // Get the streams
+5
View File
@@ -402,6 +402,11 @@ Updater::processAudioFile( const boost::filesystem::path& file, Stats& stats)
track.modify()->setDate( boost::any_cast<boost::posix_time::ptime>(items[MetaData::Type::OriginalDate]) ); track.modify()->setDate( boost::any_cast<boost::posix_time::ptime>(items[MetaData::Type::OriginalDate]) );
} }
if (items.find(MetaData::Type::HasCover) != items.end())
{
track.modify()->setHasCover( boost::any_cast<bool>(items[MetaData::Type::HasCover]));
}
transaction.commit(); transaction.commit();
} }
+4
View File
@@ -117,6 +117,7 @@ class Track
void setOriginalDate(const boost::posix_time::ptime& date) { _originalDate = date; } void setOriginalDate(const boost::posix_time::ptime& date) { _originalDate = date; }
void setGenres(const std::string& genreList) { _genreList = genreList; } void setGenres(const std::string& genreList) { _genreList = genreList; }
void setGenres(std::vector<Genre::pointer> genres); void setGenres(std::vector<Genre::pointer> genres);
void setHasCover(bool hasCover) { _hasCover = hasCover; }
int getTrackNumber(void) const { return _trackNumber; } int getTrackNumber(void) const { return _trackNumber; }
int getDiscNumber(void) const { return _discNumber; } int getDiscNumber(void) const { return _discNumber; }
@@ -132,6 +133,7 @@ class Track
boost::posix_time::ptime getLastWriteTime(void) const { return _fileLastWrite; } boost::posix_time::ptime getLastWriteTime(void) const { return _fileLastWrite; }
const std::vector<unsigned char>& getChecksum(void) const { return _fileChecksum; } const std::vector<unsigned char>& getChecksum(void) const { return _fileChecksum; }
bool hasCover(void) const { return _hasCover; }
template<class Action> template<class Action>
void persist(Action& a) void persist(Action& a)
@@ -148,6 +150,7 @@ class Track
Wt::Dbo::field(a, _filePath, "path"); Wt::Dbo::field(a, _filePath, "path");
Wt::Dbo::field(a, _fileLastWrite, "last_write"); Wt::Dbo::field(a, _fileLastWrite, "last_write");
Wt::Dbo::field(a, _fileChecksum, "checksum"); Wt::Dbo::field(a, _fileChecksum, "checksum");
Wt::Dbo::field(a, _hasCover, "has_cover");
Wt::Dbo::hasMany(a, _genres, Wt::Dbo::ManyToMany, "track_genre", "", Wt::Dbo::OnDeleteCascade); Wt::Dbo::hasMany(a, _genres, Wt::Dbo::ManyToMany, "track_genre", "", Wt::Dbo::OnDeleteCascade);
} }
@@ -167,6 +170,7 @@ class Track
std::string _filePath; std::string _filePath;
std::vector<unsigned char> _fileChecksum; std::vector<unsigned char> _fileChecksum;
boost::posix_time::ptime _fileLastWrite; boost::posix_time::ptime _fileLastWrite;
bool _hasCover;
Wt::Dbo::collection< Genre::pointer > _genres; // Tracks that belong to this genre Wt::Dbo::collection< Genre::pointer > _genres; // Tracks that belong to this genre
}; };
+2 -1
View File
@@ -29,7 +29,8 @@ Track::Track(const boost::filesystem::path& p)
: :
_trackNumber(0), _trackNumber(0),
_discNumber(0), _discNumber(0),
_filePath( p.string() ) _filePath( p.string() ),
_hasCover(false)
{ {
} }
+3
View File
@@ -114,6 +114,9 @@ AvFormat::parse(const boost::filesystem::path& p, Items& items)
// Duration // Duration
items.insert( std::make_pair(MetaData::Type::Duration, boost::posix_time::time_duration( boost::posix_time::seconds( input.getDurationSecs() )) )); items.insert( std::make_pair(MetaData::Type::Duration, boost::posix_time::time_duration( boost::posix_time::seconds( input.getDurationSecs() )) ));
// Cover
items.insert( std::make_pair(MetaData::Type::HasCover, input.getNbPictures() > 0));
// Embedded MetaData // Embedded MetaData
// Make sure to convert strings into UTF-8 // Make sure to convert strings into UTF-8
std::map<std::string, std::string>::const_iterator it; std::map<std::string, std::string>::const_iterator it;
+1 -7
View File
@@ -39,18 +39,12 @@ namespace MetaData
DiscNumber, // size_t DiscNumber, // size_t
Date, // boost::posix_time::ptime Date, // boost::posix_time::ptime
OriginalDate, // boost::posix_time::ptime OriginalDate, // boost::posix_time::ptime
Cover, // GenericData HasCover, // bool
AudioStreams, // vector<AudioStream> AudioStreams, // vector<AudioStream>
VideoStreams, // vector<VideoStream> VideoStreams, // vector<VideoStream>
SubtitleStreams, // vector<SubtitleStream> SubtitleStreams, // vector<SubtitleStream>
}; };
// Used by Cover
struct GenericData {
std::string mimeType;
std::vector<unsigned char> data;
};
// Used by Streams // Used by Streams
struct AudioStream { struct AudioStream {
std::size_t nbChannels; std::size_t nbChannels;
+8 -3
View File
@@ -21,6 +21,7 @@
#include <Wt/WMediaPlayer> #include <Wt/WMediaPlayer>
#include <Wt/WProgressBar> #include <Wt/WProgressBar>
#include <Wt/WCheckBox> #include <Wt/WCheckBox>
#include <Wt/WTemplate>
#include "AudioMediaPlayer.hpp" #include "AudioMediaPlayer.hpp"
@@ -30,6 +31,9 @@ AudioMediaPlayer::AudioMediaPlayer( Wt::WContainerWidget *parent)
: Wt::WContainerWidget(parent), : Wt::WContainerWidget(parent),
_mediaResource(nullptr) _mediaResource(nullptr)
{ {
this->setStyleClass("mediaplayer");
_mediaPlayer = new Wt::WMediaPlayer( Wt::WMediaPlayer::Audio, this ); _mediaPlayer = new Wt::WMediaPlayer( Wt::WMediaPlayer::Audio, this );
// _mediaPlayer->setAlternativeContent (new Wt::WText("You don't have HTML5 audio support!")); // _mediaPlayer->setAlternativeContent (new Wt::WText("You don't have HTML5 audio support!"));
// _mediaPlayer->setOptions( Wt::WMediaPlayer::Autoplay ); // _mediaPlayer->setOptions( Wt::WMediaPlayer::Autoplay );
@@ -52,14 +56,15 @@ AudioMediaPlayer::AudioMediaPlayer( Wt::WContainerWidget *parent)
_shuffle.emit( shuffle->checkState() == Wt::Checked); _shuffle.emit( shuffle->checkState() == Wt::Checked);
})); }));
_curTime = new Wt::WText("00:00:00", container);
_timeSlider = new Wt::WSlider( container );
_duration = new Wt::WText("00:00:00", container);
Wt::WPushButton *prevBtn = new Wt::WPushButton("<<", container ); Wt::WPushButton *prevBtn = new Wt::WPushButton("<<", container );
_playBtn = new Wt::WPushButton("Play", container ); _playBtn = new Wt::WPushButton("Play", container );
_pauseBtn = new Wt::WPushButton("Pause", container ); _pauseBtn = new Wt::WPushButton("Pause", container );
Wt::WPushButton *nextBtn = new Wt::WPushButton(">>", container ); Wt::WPushButton *nextBtn = new Wt::WPushButton(">>", container );
_curTime = new Wt::WText(container);
_timeSlider = new Wt::WSlider( container );
_duration = new Wt::WText(container);
_volumeSlider = new Wt::WSlider( container ); _volumeSlider = new Wt::WSlider( container );
_volumeSlider->setRange(0,100); _volumeSlider->setRange(0,100);
+19 -14
View File
@@ -20,10 +20,12 @@
#include <boost/random/mersenne_twister.hpp> #include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp> #include <boost/random/uniform_int_distribution.hpp>
#include <Wt/WApplication>
#include <Wt/WImage> #include <Wt/WImage>
#include <Wt/WLink> #include <Wt/WLink>
#include <Wt/WItemDelegate> #include <Wt/WItemDelegate>
#include <Wt/WStandardItem> #include <Wt/WStandardItem>
#include <Wt/WFileResource>
#include "resource/CoverResource.hpp" #include "resource/CoverResource.hpp"
@@ -82,8 +84,8 @@ class TrackSelector
void setShuffle(bool enable); void setShuffle(bool enable);
void setLoop(bool enable) { _loop = enable; } void setLoop(bool enable) { _loop = enable; }
int getPrevious(void); int previous(void);
int getNext(void); int next(void);
int getCurrent(void); int getCurrent(void);
// Set the internal pos thanks to the track pos // Set the internal pos thanks to the track pos
@@ -125,7 +127,7 @@ TrackSelector::refreshPositions()
_trackPos.push_back(i); _trackPos.push_back(i);
// Now shuffle // Now shuffle
// Perform size/2 permutations // Source: http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
boost::random::mt19937 rng; // produces randomness out of thin air boost::random::mt19937 rng; // produces randomness out of thin air
rng.seed(static_cast<unsigned int>(std::time(0))); rng.seed(static_cast<unsigned int>(std::time(0)));
@@ -157,7 +159,7 @@ TrackSelector::setShuffle(bool enable)
} }
int int
TrackSelector::getNext() TrackSelector::next()
{ {
if (_size == 0) if (_size == 0)
return trackPosInvalid; return trackPosInvalid;
@@ -176,7 +178,7 @@ TrackSelector::getNext()
} }
int int
TrackSelector::getPrevious() TrackSelector::previous()
{ {
if (_size == 0) if (_size == 0)
return trackPosInvalid; return trackPosInvalid;
@@ -229,16 +231,17 @@ class PlayQueueItemDelegate : public Wt::WItemDelegate
{ {
Wt::WWidget* res; Wt::WWidget* res;
LMS_LOG(MOD_UI, SEV_DEBUG) << "Update called! widget = " << widget << ", row = " << index.row() << ", col = " << index.column();
Wt::WString path = Wt::asString(index.data(CoverRole)); Wt::WString path = Wt::asString(index.data(CoverRole));
if (!path.empty()) if (!path.empty())
{ {
LMS_LOG(MOD_UI, SEV_DEBUG) << "Path = " << path ;
// Create an image for this track // Create an image for this track
Wt::WImage *image = new Wt::WImage( ); Wt::WImage* image = new Wt::WImage( );
CoverResource *resource = new CoverResource(boost::filesystem::path(path.toUTF8()), 64, image); Wt::WResource* resource;
if (path != "none")
resource = new CoverResource(boost::filesystem::path(path.toUTF8()), 64, image);
else
resource = new Wt::WFileResource("image/jpeg", Wt::WApplication::instance()->docRoot() + "/images/unknown-cover.jpg", image);
image->setImageLink(Wt::WLink(resource)); image->setImageLink(Wt::WLink(resource));
res = image; res = image;
@@ -351,7 +354,7 @@ PlayQueue::addTracks(const std::vector<Database::Track::id_type>& trackIds)
_model->setData(dataRow, COLUMN_ID_TRACK_ID, track.id(), Wt::UserRole); _model->setData(dataRow, COLUMN_ID_TRACK_ID, track.id(), Wt::UserRole);
_model->setData(dataRow, COLUMN_ID_POS, dataRow + 1); _model->setData(dataRow, COLUMN_ID_POS, dataRow + 1);
_model->setData(dataRow, COLUMN_ID_COVER, track->getPath(), CoverRole); _model->setData(dataRow, COLUMN_ID_COVER, track->hasCover() ? track->getPath() : "none", CoverRole);
_model->setData(dataRow, COLUMN_ID_NAME, track->getArtistName() + " - " + track->getName()); _model->setData(dataRow, COLUMN_ID_NAME, track->getArtistName() + " - " + track->getName());
_model->setData(dataRow, COLUMN_ID_DURATION, track->getDuration()); _model->setData(dataRow, COLUMN_ID_DURATION, track->getDuration());
} }
@@ -383,7 +386,7 @@ PlayQueue::playNext(void)
while (nbTries > 0) while (nbTries > 0)
{ {
int pos = _trackSelector->getNext(); int pos = _trackSelector->next();
if (pos == trackPosInvalid) if (pos == trackPosInvalid)
break; break;
@@ -401,7 +404,7 @@ PlayQueue::playPrevious(void)
while (nbTries > 0) while (nbTries > 0)
{ {
int pos = _trackSelector->getPrevious(); int pos = _trackSelector->previous();
if (pos == trackPosInvalid) if (pos == trackPosInvalid)
break; break;
@@ -427,6 +430,8 @@ PlayQueue::readTrack(int rowPos)
_sigTrackPlay.emit(track->getPath()); _sigTrackPlay.emit(track->getPath());
this->scrollTo( _model->index(_trackSelector->getCurrent(), 0));
return true; return true;
} }
else else
+8 -5
View File
@@ -41,6 +41,8 @@ _field(field)
this->setAlternatingRowColors(true); this->setAlternatingRowColors(true);
this->setModel(&_queryModel); this->setModel(&_queryModel);
this->setColumnWidth(1, 50);
this->selectionChanged().connect(this, &TableFilter::emitUpdate); this->selectionChanged().connect(this, &TableFilter::emitUpdate);
setLayoutSizeAware(true); setLayoutSizeAware(true);
@@ -66,14 +68,15 @@ _field(field)
void void
TableFilter::layoutSizeChanged (int width, int height) TableFilter::layoutSizeChanged (int width, int height)
{ {
LMS_LOG(MOD_UI, SEV_DEBUG) << "LAYOUT CHANGED!"; LMS_LOG(MOD_UI, SEV_DEBUG) << "LAYOUT CHANGED, new width = " << width;
/* TODO LMS_LOG(MOD_UI, SEV_DEBUG) << "Before: sizes = " << this->columnWidth(0).toPixels() << ", " << this->columnWidth(1).toPixels();
std::size_t trackColumnSize = this->columnWidth(1).toPixels() + 30 ;
std::size_t trackColumnSize = this->columnWidth(1).toPixels();
// Set the remaining size for the name column // Set the remaining size for the name column
this->setColumnWidth(0, width - 7 - trackColumnSize); this->setColumnWidth(0, width - 7 - trackColumnSize - 23 /*Asc wdth */);
*/
LMS_LOG(MOD_UI, SEV_DEBUG) << "After: sizes = " << this->columnWidth(0).toPixels() << ", " << this->columnWidth(1).toPixels();
} }
// Set constraints on this filter // Set constraints on this filter
+13
View File
@@ -2,6 +2,14 @@
margin-bottom: 0px; margin-bottom: 0px;
} }
.Wt-hrh2 {
background-color: white;
}
.Wt-vrh2 {
background-color: white;
}
div.contents { div.contents {
padding: 0px 12px 6px; padding: 0px 12px 6px;
} }
@@ -10,3 +18,8 @@ div.contents {
font-weight: bold; font-weight: bold;
} }
.mediaplayer {
background-color: #ccc;
border-radius: 15px;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

+1
View File
@@ -51,6 +51,7 @@ _sessionData(sessionData)
contents->setStyleClass("contents"); contents->setStyleClass("contents");
contents->setOverflow(WContainerWidget::OverflowHidden); contents->setOverflow(WContainerWidget::OverflowHidden);
// TODO menu style on hover
Wt::WMenu *menu = new Wt::WMenu(contents, Wt::Vertical); Wt::WMenu *menu = new Wt::WMenu(contents, Wt::Vertical);
menu->setStyleClass("nav nav-pills nav-stacked submenu"); menu->setStyleClass("nav nav-pills nav-stacked submenu");
menu->setWidth(150); menu->setWidth(150);