Merge branch 'develop'
Conflicts: README src/ui/approot/templates.xml
This commit is contained in:
@@ -1,17 +1,17 @@
|
||||
LMS - Lightweight Media Server
|
||||
|
||||
|
||||
LMS is a free media streaming software, released under the GPLv3 license.
|
||||
LMS is a self-hosted media streaming software, released under the GPLv3 license.
|
||||
It allows you to access your music and your videos using an https web interface.
|
||||
|
||||
Features:
|
||||
- Winamp-like interface, suited for large databases
|
||||
- Audio/Video transcode for maximum interoperability and low bandwith requirements
|
||||
- User management
|
||||
- Fast "Winamp-style" interface
|
||||
- Audio/Video transcode (including downsampling), based on the libav project (see https://www.libav.org/).
|
||||
- Custom API to access data using Protocol Buffers format over TCP/SSL (see https://github.com/google/protobuf/ and src/remote/proto)
|
||||
- API available in Protocol Buffers (see src/remote/proto/messages.proto)
|
||||
|
||||
Please note LMS is still under development and will gain more features in the future.
|
||||
An android application is being developped as well.
|
||||
A mobile application based on Kivy is being developped as well.
|
||||
|
||||
LMS is written entirely in C++. Therefore, it is suitable to run on embedded devices, where space and/or memory are limited.
|
||||
Please note some media files may require significant CPU usage to be transcoded.
|
||||
@@ -37,7 +37,7 @@ II) BUILD
|
||||
|
||||
III) Setting up SSL materials (required by the SSL server and the web server)
|
||||
|
||||
This is just a self-signed certificate example, you can set up a real CA if you want to.
|
||||
This is just a self signed certificate example, you could do use a CA if you want.
|
||||
|
||||
Generate a dh file:
|
||||
# openssl dhparam -out dh2048.pem 2048
|
||||
@@ -59,3 +59,9 @@ You must also link Wt's docroot (usually located in /usr/share/Wt) into that dir
|
||||
|
||||
Depending on your SSL parameters, you may be asked for the PEM passphrase to unlock the private key.
|
||||
|
||||
V) LINKS
|
||||
|
||||
- Wt (http://www.webtoolkit.eu/)
|
||||
- bootstrap3 (http://getbootstrap.com/)
|
||||
- libav project (https://www.libav.org/).
|
||||
- Protocol Buffers (https://github.com/google/protobuf/)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
- OGG metadata -> properly handle metadata nested in the audio stream
|
||||
|
||||
[Transcode]
|
||||
- some early end of playback spotted on flac files
|
||||
- some early end of playback spotted on flac files. Spotted on old firefox versions?
|
||||
|
||||
[UI]
|
||||
- handle internationalization
|
||||
@@ -31,6 +31,7 @@
|
||||
- "signal not exposed" problem if a user logout and login again. bad resource destruction?
|
||||
[user/transcoding]
|
||||
- Prefered codecs for audio/video?
|
||||
- use a slider instead of a combo box for the bitrates
|
||||
[admin/Users]
|
||||
- do not activate the update period/start time when 'admin' is checked
|
||||
[admin/Database update]
|
||||
@@ -39,10 +40,12 @@
|
||||
|
||||
[Audio]
|
||||
- Style eveything nicely...
|
||||
- MediaPlayer: move slider using js (http://redmine.webtoolkit.eu/boards/2/topics/7924?r=8478)
|
||||
- MediaPlayer: move the slider using js (http://redmine.webtoolkit.eu/boards/2/topics/7924?r=8478)
|
||||
- TrackView : handle duration > 1 hour
|
||||
- TrackView : Reselect the current selected item when displaying the updated search results
|
||||
- Add covers in the release filter?
|
||||
- Add a download button to get the current playlist in a streamed zip file
|
||||
- Add keyboard shortcuts
|
||||
|
||||
[Video]
|
||||
- implement a decent mediaplayer
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/log/expressions.hpp>
|
||||
#include <boost/log/sinks/text_file_backend.hpp>
|
||||
#include </usr/include/boost/log/keywords/filter.hpp>
|
||||
#include <boost/log/keywords/filter.hpp>
|
||||
#include <boost/log/utility/setup/file.hpp>
|
||||
#include <boost/log/utility/setup/common_attributes.hpp>
|
||||
#include <boost/log/utility/setup/console.hpp>
|
||||
@@ -89,6 +89,7 @@ Logger::init(const Config& config)
|
||||
boost::log::keywords::file_name = config.logPath + std::string(".%N"),
|
||||
boost::log::keywords::rotation_size = 10 * 1024 * 1024,
|
||||
boost::log::keywords::open_mode = std::ios_base::app,
|
||||
boost::log::keywords::auto_flush = true,
|
||||
boost::log::keywords::format = (
|
||||
boost::log::expressions::stream
|
||||
<< boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "[%Y-%m-%d %H:%M:%S]")
|
||||
|
||||
@@ -5,6 +5,16 @@ import "media.proto";
|
||||
|
||||
package Remote;
|
||||
|
||||
// Every request sent by the client must be a ClientMessage
|
||||
// The server will answer using a ServerMessage
|
||||
//
|
||||
// The client must authenticate first before querying data
|
||||
// If an expected message is received, the connection is dropped by the server
|
||||
//
|
||||
// A header is to be added before the serialized protobuf message in order to keep
|
||||
// track of where one message ends and the next begins.
|
||||
// Format:
|
||||
// MAGIC (4 bytes, 0xDE, 0xAD, 0xBE, 0xEF)- SIZE (4 bytes, big endian encoded) - serialized proto message
|
||||
message ClientMessage
|
||||
{
|
||||
enum Type
|
||||
|
||||
@@ -341,9 +341,7 @@
|
||||
|
||||
<message id="mobile-artist-res">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="mobile-search-entry">${name}</div>
|
||||
</div>
|
||||
<div class="col-xs-12 mobile-search-entry">${name}</div>
|
||||
</div>
|
||||
</message>
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#include "PlayQueue.hpp"
|
||||
|
||||
static const int NameRole = Wt::UserRole;
|
||||
static const int TrackInfoRole = Wt::UserRole;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -220,10 +220,11 @@ TrackSelector::setSize(std::size_t size)
|
||||
refreshPositions();
|
||||
}
|
||||
|
||||
struct Name
|
||||
struct TrackInfo
|
||||
{
|
||||
Wt::WString track;
|
||||
Wt::WString artist;
|
||||
Wt::WString release;
|
||||
};
|
||||
|
||||
class PlayQueueItemDelegate : public Wt::WItemDelegate
|
||||
@@ -235,13 +236,13 @@ class PlayQueueItemDelegate : public Wt::WItemDelegate
|
||||
{
|
||||
Wt::WWidget* res;
|
||||
|
||||
if (!index.data(NameRole).empty())
|
||||
if (!index.data(TrackInfoRole).empty())
|
||||
{
|
||||
Name name = boost::any_cast<Name>(index.data(NameRole));
|
||||
TrackInfo trackInfo = boost::any_cast<TrackInfo>(index.data(TrackInfoRole));
|
||||
|
||||
Wt::WContainerWidget *container = new Wt::WContainerWidget();
|
||||
Wt::WText* track = new Wt::WText(name.track, Wt::PlainText, container);
|
||||
Wt::WText* artist = new Wt::WText(name.artist, Wt::PlainText, container);
|
||||
Wt::WText* track = new Wt::WText(trackInfo.track, Wt::PlainText, container);
|
||||
Wt::WText* artist = new Wt::WText(trackInfo.artist + " - " + trackInfo.release, Wt::PlainText, container);
|
||||
|
||||
artist->setInline(false);
|
||||
track->setInline(false);
|
||||
@@ -382,10 +383,11 @@ PlayQueue::addTracks(const std::vector<Database::Track::id_type>& trackIds)
|
||||
coverUrl = "images/unknown-cover.jpg";
|
||||
_model->setData(dataRow, COLUMN_ID_COVER, coverUrl, Wt::DecorationRole);
|
||||
|
||||
Name name;
|
||||
name.track = Wt::WString::fromUTF8(track->getName());
|
||||
name.artist = Wt::WString::fromUTF8(track->getArtistName());
|
||||
_model->setData(dataRow, COLUMN_ID_NAME, name, NameRole);
|
||||
TrackInfo trackInfo;
|
||||
trackInfo.track = Wt::WString::fromUTF8(track->getName());
|
||||
trackInfo.artist = Wt::WString::fromUTF8(track->getArtistName());
|
||||
trackInfo.release = Wt::WString::fromUTF8(track->getReleaseName());
|
||||
_model->setData(dataRow, COLUMN_ID_NAME, trackInfo, TrackInfoRole);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,17 +45,6 @@ VideoWidget::search(const std::string& searchText)
|
||||
//TODO
|
||||
}
|
||||
|
||||
void
|
||||
VideoWidget::backToList(void)
|
||||
{
|
||||
if (_mediaPlayer)
|
||||
delete _mediaPlayer;
|
||||
|
||||
_videoDbWidget->setHidden(false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoWidget::playVideo(boost::filesystem::path p)
|
||||
{
|
||||
@@ -100,8 +89,11 @@ VideoWidget::playVideo(boost::filesystem::path p)
|
||||
parameters.setBitrate(Transcode::Stream::Audio, 0/*audioBitrate*/);
|
||||
parameters.setBitrate(Transcode::Stream::Video, 0/*videoBitrate*/);
|
||||
|
||||
_mediaPlayer = new VideoMediaPlayerWidget(parameters, this);
|
||||
_mediaPlayer->close().connect(this, &VideoWidget::backToList);
|
||||
VideoMediaPlayerWidget *mediaPlayer = new VideoMediaPlayerWidget(parameters, this);
|
||||
mediaPlayer->close().connect(std::bind([=] () {
|
||||
_videoDbWidget->setHidden(false);
|
||||
delete mediaPlayer;
|
||||
}));
|
||||
|
||||
_videoDbWidget->setHidden(true);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user