Merge remote-tracking branch 'nithinphilips/master' into test

This commit is contained in:
Trevor Squillario 2012-09-27 16:36:49 -04:00
commit 1cfe48e0d8
10 changed files with 267 additions and 24 deletions

18
README
View file

@ -1,18 +0,0 @@
MiniSub - HTML5 Mini Player for Subsonic
Imagine you can stream all your music from home, to any device, where ever you are. That is Subsonic! Now imagine having a Web App to stream your music that is as beautiful and well designed as it is functional, that is MiniSub!
MiniSub is an HTML5 Mini Player for the Subsonic streaming server.
Features
- Flexible Layout (will scale to whatever size your browser window is)
- Customizable (features can be turned on/off and settings are saved)
- Keyboard shortcuts (back, forward, play/pause, skip to artist)
- Playlists (create new, add to existing, delete)
- Artist/Album Ratings
- Chat and Now Playing
- Last.fm
You will need a Subsonic server to be able to play your own music. Subsonic is a free, web-based media streamer, providing ubiquitous access to your music. Use it to share your music with friends, or to listen to your own music while at work. Please see http://www.subsonic.org
Change Log inside...

51
README.rst Executable file
View file

@ -0,0 +1,51 @@
=======
MiniSub
=======
**HTML5 Mini Player for Subsonic**
Imagine you can stream all your music from home, to any device, where ever you
are. That is Subsonic! Now imagine having a Web App to stream your music that
is as beautiful and well designed as it is functional, that is MiniSub!
MiniSub is an HTML5 Mini Player for the Subsonic streaming server.
Features
````````
* Flexible Layout (will scale to whatever size your browser window is)
* Customizable (features can be turned on/off and settings are saved)
* Keyboard shortcuts (back, forward, play/pause, skip to artist)
* Playlists (create new, add to existing, delete)
* Artist/Album Ratings
* Chat and Now Playing
* Last.fm
* Supports Podcasts.
You will need a Subsonic server to be able to play your own music. Subsonic is
a free, web-based media streamer, providing ubiquitous access to your music.
Use it to share your music with friends, or to listen to your own music while
at work. Please see http://www.subsonic.org
Change Log inside...
License
```````
Copyright (c) 2011-2012 Trevor Squillario
https://github.com/tsquillario/MiniSub
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

BIN
images/podcast_16x16.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,019 B

30
index.html Normal file → Executable file
View file

@ -38,6 +38,7 @@
<div id="nav">
<ul class="tabs">
<li><a href="#tabLibrary" class="first" title="Library"><img src="images/headphones_gd_16x14.png" /></a></li>
<li><a href="#tabPodcasts" title="Podcasts"><img src="images/podcast_16x16.png" /></a></li>
<li><a href="#tabCurrent" title="Current Playlist"><img src="images/play_alt_gd_16x16.png" /></a></li>
<li><a href="#tabPlaylists" title="Playlists"><img src="images/list_gd_16x14.png" /></a></li>
<li><a href="#tabPreferences" class="last" title="Preferences"><img src="images/cog_16x16.png" /></a></li>
@ -142,6 +143,29 @@
</table>
</div>
</div>
<div id="tabPodcasts" class="tabcontent">
<div class="actions floatleft">
<a href="#" class="button" id="action_RefreshPodcasts" title="Refresh Podcasts"><img src="images/reload_9x11.png" /></a>
<a href="#" class="button" id="action_DecreaseWidthPodcasts" title="Decrease Width"><img src="images/minus_8x2.png" /></a>
<a href="#" class="button" id="action_IncreaseWidthPodcasts" title="Increase Width"><img src="images/plus_8x8.png" /></a>
</div>
<div class="subactions floatleft">
</div>
<div class="clear"></div>
<div id="Podcasts" class="lgsection floatleft noselect">
<div class="loading"></div>
<div id="PodcastList" class="smsection floatleft noselect">
<div class="padder">
<ul class="simplelist"><li class="index">Podcasts</li></ul>
<ul id="ChannelsContainer" class="simplelist mainlist"></ul>
</div>
</div>
<table id="PodcastContainer" class="simplelist songlist">
<thead></thead>
<tbody></tbody>
</table>
</div>
</div>
<div id="tabPreferences" class="tabcontent">
<div class="actions floatleft">
<a href="#" class="button" id="ResetPreferences" title="Reset Preferences">Reset</a>
@ -229,6 +253,12 @@
<span class="changes"></span>
</li>
-->
<li class="log"><span class="version">9/25/2012 - 2.0.7</span>
<span class="changes">Added support for Podcasts</span>
</li>
<li class="log"><span class="version">8/13/2012 - 2.0.6</span>
<span class="changes">Minor bugfix</span>
</li>
<li class="log"><span class="version">7/20/2012 - 2.0.5</span>
<span class="changes">Fixed Mp3 only folder issue</span>
<span class="changes">Launch server URL from the Subsonic icon!</span>

4
js/app.js Normal file → Executable file
View file

@ -85,6 +85,10 @@ function loadTabContent(tab) {
if (debug) { console.log("TAG PLAYLIST"); }
loadPlaylists();
break;
case '#tabPodcasts':
if (debug) { console.log("TAG PODCAST"); }
loadPodcasts();
break;
case '#tabPreferences':
break;
default:

114
js/libs/api.js Normal file → Executable file
View file

@ -688,3 +688,117 @@ function getPlaylist(id, action, appendto) {
}
});
}
function loadPodcasts(refresh) {
if (debug) { console.log("LOAD PODCASTS"); }
if (refresh) {
$('#ChannelsContainer').empty();
}
var content = $('#ChannelsContainer').html();
if (content === "") {
// Load Podcasts
$.ajax({
url: baseURL + '/getPodcasts.view?u=' + username + '&p=' + password + '&v=' + version + '&c=' + applicationName + '&f=jsonp',
method: 'GET',
dataType: 'jsonp',
timeout: 10000,
success: function (data) {
var playlists = [];
if (data["subsonic-response"].podcasts.channel.length > 0) {
podcasts = data["subsonic-response"].podcasts.channel;
} else {
podcasts[0] = data["subsonic-response"].podcasts.channel;
}
$.each(podcasts, function (i, podcast) {
var albumId = (podcast.episode === undefined || podcast.episode.length <= 0) ? "0" : podcast.episode[0].parent;
var html = "";
html += '<li id=\"' + podcast.id + '\" albumid=\"' + albumId + '\" class=\"item\">';
html += '<span>' + podcast.title + '</span>';
html += '<div class=\"floatright\"><a class=\"play\" href=\"\" title=\"Play\"></a></div>';
html += '<div class=\"floatright\"><a class=\"download\" href=\"\" title=\"Download\"></a></div>';
html += '<div class=\"floatright\"><a class=\"add\" href=\"\" title=\"Add To Current Playlist\"></a></div>';
html += '</li>';
$(html).appendTo("#ChannelsContainer");
});
}
});
}
}
function getPodcast(id, action, appendto) {
$.ajax({
url: baseURL + '/getPodcasts.view?u=' + username + '&p=' + password + '&v=' + version + '&c=' + applicationName + '&f=jsonp',
method: 'GET',
dataType: 'jsonp',
timeout: 10000,
success: function (data) {
var channels = data["subsonic-response"].podcasts.channel;
// we hope that the result is ordered by id
var channel = channels[id - 1];
if(channel === undefined || channel.id != id){
// sometimes we have to do some extra work.
for (var i = 0; i < channels.length; i++) {
if(podcasts[i].id == id)
{
channel = channels[i];
break;
}
}
}
if (channel.episode !== undefined) {
if (appendto === '#PodcastContainer tbody') {
$(appendto).empty();
var header = generatePodcastHeaderHTML();
$("#PodcastContainer thead").html(header);
}
if (action === 'autoplay') {
$(appendto).empty();
}
var children = channel.episode;
var rowcolor;
var html;
var count = children.length;
$.each(children, function (i, child) {
if(child.status == "skipped") return; // Skip podcasts that are not yet downloaded
if (i % 2 === 0) {
rowcolor = 'even';
} else {
rowcolor = 'odd';
}
var date = parseDate(child.publishDate);
var time = secondsToTime(child.duration);
html = generatePodcastHTML(rowcolor, child.streamId, child.parent, date, child.title, child.artist, child.album, child.coverArt, child.userRating, time['m'], time['s']);
$(html).appendTo(appendto);
});
updateMessage(count + ' Songs');
if (appendto === '#CurrentPlaylistContainer tbody') {
updateMessage(children.length + ' Song(s) Added');
}
if (action === 'autoplay') {
autoPlay();
}
} else {
if (appendto === '#PodcastContainer tbody') {
$(appendto).empty();
}
}
}
});
}
function parseDate(date) {
// input: "2012-09-23 20:00:00.0"
var months = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ];
var parts = date.split(" ");
var dateParts = parts[0].split("-");
var month = parseInt(dateParts[1], 10) - 1;
var date = months[month] + " " + dateParts[2] + ", " + dateParts[0];
return date;
}

28
js/libs/generators.js Normal file → Executable file
View file

@ -57,7 +57,33 @@ function generateSongHTML(rowcolor, childid, parentid, track, title, artist, alb
html += '</tr>';
return html;
}
function generatePodcastHeaderHTML() {
var html;
html = '<tr><th></th><th>Published</th><th>Title</th><th>Artist</th><th>Album</th><th class=\"alignright\">Time</th></tr>';
return html;
}
function generatePodcastHTML(rowcolor, childid, parentid, published, title, artist, album, coverart, rating, m, s) {
var html;
html = '<tr class=\"song ' + rowcolor + '\" childid=\"' + childid + '\" parentid=\"' + parentid + '\" userrating=\"' + rating + '\">';
html += '<td class=\"itemactions\"><a class=\"add\" href=\"\" title=\"Add To Current Playlist\"></a>';
html += '<a class=\"remove\" href=\"\" title=\"Remove\"></a>';
html += '<a class=\"play\" href=\"\" title=\"Play\"></a>';
html += '<a class=\"download\" href=\"\" title=\"Download\"></a>';
html += '</td>';
html += '<td class=\"published\">' + published + '</td>';
html += '<td class=\"title\">' + title + '</td>';
html += '<td class=\"artist\">' + artist + '</td>';
var coverartSrc;
if (coverart == undefined) {
coverartSrc = 'images/albumdefault_25.jpg';
} else {
coverartSrc = baseURL + '/getCoverArt.view?v=' + version + '&c=' + applicationName + '&f=jsonp&size=25&id=' + coverart;
}
html += '<td class=\"album\"><a href="javascript:getAlbums(\'' + parentid + '\',\'\',\'#AlbumRows\')">' + album + '<img src=\"' + coverartSrc + '\" /></a></td>';
html += '<td class=\"time\">' + m + ':' + s + '</td>';
html += '</tr>';
return html;
}
function refreshRowColor(el) {
$.each($(el + ' tr.song'), function (i) {
$(this).removeClass('even odd');

3
js/ui-load.js Normal file → Executable file
View file

@ -46,7 +46,7 @@ function resizeContent() {
}
}
var tabwidth = $('.tabcontent').width();
$('#AlbumContainer, #TrackContainer, #CurrentPlaylistContainer').css({ 'width': (tabwidth - smwidth - 30) + 'px' });
$('#AlbumContainer, #TrackContainer, #PodcastContainer, #CurrentPlaylistContainer').css({ 'width': (tabwidth - smwidth - 30) + 'px' });
$('#CurrentPlaylistContainer').css({ 'width': (tabwidth - 30) + 'px' });
$('#player').css({ 'width': tabwidth + 'px' });
}
@ -63,5 +63,6 @@ function resizeSMSection(x) {
var ulwidth = newsmwidth + 6;
$('#AlbumContainer').css({ 'margin-left': ulwidth + 'px' });
$('#TrackContainer').css({ 'margin-left': ulwidth + 'px' });
$('#PodcastContainer').css({ 'margin-left': ulwidth + 'px' });
}
}

31
js/ui-ready.js Normal file → Executable file
View file

@ -340,6 +340,14 @@
resizeSMSection(-50);
return false;
});
$('#action_IncreaseWidthPodcasts').click(function () {
resizeSMSection(50);
return false;
});
$('#action_DecreaseWidthPodcasts').click(function () {
resizeSMSection(-50);
return false;
});
$('#action_SelectAll').click(function () {
$('#Albums tr.song').each(function () {
$(this).addClass('selected');
@ -435,6 +443,29 @@
getPlaylist($(this).parent().parent().attr("id"), '', '#CurrentPlaylistContainer tbody');
return false;
});
$('#ChannelsContainer li.item').live('click', function () {
$('#AutoChannelsContainer li').removeClass('selected');
$('#ChannelsContainer li').removeClass('selected');
$(this).addClass('selected');
getPodcast($(this).attr("id"), '', '#PodcastContainer tbody');
});
$('#ChannelsContainer li.item a.play').live('click', function () {
getPodcast($(this).parent().parent().attr("id"), 'autoplay', '#CurrentPlaylistContainer tbody');
return false;
});
$('#ChannelsContainer li.item a.download').live('click', function (event) {
var itemid = $(this).parent().parent().attr('albumid');
downloadItem(itemid, 'item');
return false;
});
$('#ChannelsContainer li.item a.add').live('click', function () {
getPodcast($(this).parent().parent().attr("id"), '', '#CurrentPlaylistContainer tbody');
return false;
});
$('#action_RefreshPodcasts').click(function () {
loadPodcasts(true);
return false;
});
$('#action_RefreshPlaylists').click(function () {
loadPlaylists(true);
return false;

6
style/Style.css Normal file → Executable file
View file

@ -313,7 +313,7 @@ ul.mainlist li.item a.add:hover
{
margin: 5px 5px 5px 206px;
}
#TrackContainer
#TrackContainer, #PodcastContainer
{
margin: 5px 5px 5px 206px;
}
@ -471,6 +471,10 @@ table.songlist tr.song td.track
width: 40px;
text-align: right;
}
table.songlist tr.song td.published
{
width: 80px;
}
table.songlist tr.song td.title
{
}