2.0.7 Pre-release testing

This commit is contained in:
Trevor Squillario 2012-09-28 11:30:06 -04:00
parent 1cfe48e0d8
commit b4f7009ebf
11 changed files with 148 additions and 107 deletions

18
README Normal file
View file

@ -0,0 +1,18 @@
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...

Binary file not shown.

Before

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

BIN
images/rss_16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

View file

@ -38,9 +38,9 @@
<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="#tabPodcasts" title="Podcasts"><img src="images/rss_16x16.png" /></a></li>
<li><a href="#tabPreferences" class="last" title="Preferences"><img src="images/cog_16x16.png" /></a></li>
</ul>
<div class="toploading"></div>
@ -146,8 +146,6 @@
<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>
@ -254,7 +252,7 @@
</li>
-->
<li class="log"><span class="version">9/25/2012 - 2.0.7</span>
<span class="changes">Added support for Podcasts</span>
<span class="changes">Added support for Podcasts (Thanks to <a href="https://github.com/nithinphilips/MiniSub" target="_blank">nithinphilips</a>)</span>
</li>
<li class="log"><span class="version">8/13/2012 - 2.0.6</span>
<span class="changes">Minor bugfix</span>

View file

@ -8,6 +8,7 @@ var username;
var password;
var passwordenc;
var server;
var smwidth;
//Sound manager
soundManager.url = 'js/sm/swf';

View file

@ -64,6 +64,7 @@ function loadArtists(id, refresh) {
$(indexlist).appendTo("#BottomIndex");
}
if (data["subsonic-response"].indexes.child !== undefined) {
var rowcolor;
if (data["subsonic-response"].indexes.child.length > 0) {
indexes = data["subsonic-response"].indexes.child;
} else {
@ -72,11 +73,19 @@ function loadArtists(id, refresh) {
var appendto = '#AlbumRows';
$(appendto).empty();
$.each(indexes, function (i, child) {
var html = generateRowHTML(child, appendto);
if (i % 2 === 0) {
rowcolor = 'even';
} else {
rowcolor = 'odd';
}
var html = generateRowHTML(child, appendto, rowcolor);
$(html).appendTo(appendto);
});
header = generateSongHeaderHTML();
}
if (smwidth) {
resizeSMSection(0);
}
} else {
var error = data["subsonic-response"].status;
var errorcode = data["subsonic-response"].error.code;
@ -145,10 +154,16 @@ function getAlbums(id, action, appendto) {
}
var isDir = false;
var rowcolor;
var header;
$.each(children, function (i, child) {
if (i % 2 === 0) {
rowcolor = 'even';
} else {
rowcolor = 'odd';
}
if (child.isDir == true) { isDir = true; }
var html = generateRowHTML(child, appendto);
var html = generateRowHTML(child, appendto, rowcolor);
$(html).appendTo(appendto);
});
if (appendto == '#CurrentPlaylistContainer') {
@ -168,28 +183,6 @@ function getAlbums(id, action, appendto) {
}
});
}
function generateRowHTML(child, appendto) {
var rowcolor;
var albumhtml;
var isDir;
var i;
if (i % 2 === 0) {
rowcolor = 'even';
} else {
rowcolor = 'odd';
}
isDir = child.isDir;
if (isDir === true) {
albumhtml = generateAlbumHTML(rowcolor, child.id, child.parent, child.coverArt, child.title, child.artist, child.userRating);
} else {
var track;
if (child.track === undefined) { track = "&nbsp;"; } else { track = child.track; }
var time = secondsToTime(child.duration);
albumhtml = generateSongHTML(rowcolor, child.id, child.parent, track, child.title, child.artist, child.album, child.coverArt, child.userRating, time['m'], time['s']);
}
return albumhtml;
//$(albumhtml).appendTo(appendto);
}
function getAlbumListBy(id) {
var size;
if ($.cookie('AutoAlbumSize') === null) {
@ -429,13 +422,16 @@ function loadPlaylists(refresh) {
$.each(playlists, function (i, playlist) {
var html = "";
html += '<li id=\"' + playlist.id + '\" class=\"item\">';
html += '<span>' + playlist.name + '</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 += '<div class="name"><span>' + playlist.name + '</span></div>';
html += '</li>';
$(html).appendTo("#PlaylistContainer");
});
if (smwidth) {
resizeSMSection(0);
}
}
});
}
@ -652,10 +648,11 @@ function getPlaylist(id, action, appendto) {
}
// There is a bug in the API that doesn't return a JSON array for one artist
var children = [];
if (data["subsonic-response"].playlist.entry.length > 0) {
children = data["subsonic-response"].playlist.entry;
var playlist = data["subsonic-response"].playlist;
if (playlist.entry.length > 0) {
children = playlist.entry;
} else {
children[0] = data["subsonic-response"].playlist.entry;
children[0] = playlist.entry;
}
var rowcolor;
@ -673,7 +670,9 @@ function getPlaylist(id, action, appendto) {
html = generateSongHTML(rowcolor, child.id, child.parent, track, child.title, child.artist, child.album, child.coverArt, child.userRating, time['m'], time['s']);
$(html).appendTo(appendto);
});
updateMessage(count + ' Songs');
if (appendto === '#TrackContainer tbody') {
updateMessage(playlist.name + ': ' + count + ' Songs');
}
if (appendto === '#CurrentPlaylistContainer tbody') {
updateMessage(children.length + ' Song(s) Added');
}
@ -703,7 +702,7 @@ function loadPodcasts(refresh) {
dataType: 'jsonp',
timeout: 10000,
success: function (data) {
var playlists = [];
var podcasts = [];
if (data["subsonic-response"].podcasts.channel.length > 0) {
podcasts = data["subsonic-response"].podcasts.channel;
} else {
@ -714,13 +713,16 @@ function loadPodcasts(refresh) {
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 += '<div class=\"name\"><span>' + podcast.title + '</span></div>';
html += '</li>';
$(html).appendTo("#ChannelsContainer");
});
if (smwidth) {
resizeSMSection(0);
}
}
});
}
@ -732,26 +734,23 @@ function getPodcast(id, action, appendto) {
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;
}
var podcasts = [];
if (data["subsonic-response"].podcasts.channel.length > 0) {
podcasts = data["subsonic-response"].podcasts.channel;
} else {
podcasts[0] = data["subsonic-response"].podcasts.channel;
}
var channel = [];
$.each(podcasts, function (i, podcast) {
if (podcast.id == id) {
channel = podcast;
}
});
if (channel.episode !== undefined) {
if (appendto === '#PodcastContainer tbody') {
$(appendto).empty();
var header = generatePodcastHeaderHTML();
var header = generateSongHeaderHTML;
$("#PodcastContainer thead").html(header);
}
if (action === 'autoplay') {
@ -762,9 +761,8 @@ function getPodcast(id, action, appendto) {
var rowcolor;
var html;
var count = children.length;
var count = 0;
$.each(children, function (i, child) {
if (child.status == "skipped") return; // Skip podcasts that are not yet downloaded
if (i % 2 === 0) {
@ -773,14 +771,19 @@ function getPodcast(id, action, appendto) {
rowcolor = 'odd';
}
var date = parseDate(child.publishDate);
var description = 'Published: ' + date + '\n\n';
description += child.description;
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 = generatePodcastHTML(rowcolor, child.streamId, child.parent, child.track, child.title, description, child.artist, child.album, child.coverArt, child.userRating, time['m'], time['s']);
$(html).appendTo(appendto);
count++;
});
updateMessage(count + ' Songs');
if (appendto === '#PodcastContainer tbody') {
updateMessage(channel.title + ': ' + count + ' Songs');
}
if (appendto === '#CurrentPlaylistContainer tbody') {
updateMessage(children.length + ' Song(s) Added');
updateMessage(count + ' Song(s) Added');
}
if (action === 'autoplay') {
autoPlay();

View file

@ -1,3 +1,19 @@
function generateRowHTML(child, appendto, rowcolor) {
var albumhtml;
var isDir;
var i;
isDir = child.isDir;
if (isDir === true) {
albumhtml = generateAlbumHTML(rowcolor, child.id, child.parent, child.coverArt, child.title, child.artist, child.userRating);
} else {
var track;
if (child.track === undefined) { track = "&nbsp;"; } else { track = child.track; }
var time = secondsToTime(child.duration);
albumhtml = generateSongHTML(rowcolor, child.id, child.parent, track, child.title, child.artist, child.album, child.coverArt, child.userRating, time['m'], time['s']);
}
return albumhtml;
//$(albumhtml).appendTo(appendto);
}
function generateAlbumHeaderHTML() {
var html;
html = '<tr><th></th><th></th><th>Album</th><th>Artist</th></tr>';
@ -57,21 +73,21 @@ 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) {
function generatePodcastHTML(rowcolor, childid, parentid, track, title, description, 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>';
if (rating === 5) {
html += '<a class=\"favorite\" href=\"\" title=\"Favorite\"></a>';
} else {
html += '<a class=\"rate\" href=\"\" title=\"Add To Favorites\"></a>';
}
html += '</td>';
html += '<td class=\"published\">' + published + '</td>';
html += '<td class=\"title\">' + title + '</td>';
html += '<td class=\"track\">' + track + '</td>';
html += '<td class=\"title\" title=\"' + description + '\">' + title + '</td>';
html += '<td class=\"artist\">' + artist + '</td>';
var coverartSrc;
if (coverart == undefined) {

View file

@ -105,6 +105,15 @@ function playSong(el, songid, albumid) {
});
});
},
onpause: function () {
if (debug) { console.log('Pause Event: ' + ' playState:' + this.playState + ', readyState:' + this.readyState + ', position:' + this.position + ', duration:' + this.duration + ', durationEstimate:' + this.durationEstimate + ', isBuffering:' + this.isBuffering); }
},
onresume: function () {
if (debug) { console.log('Resume Event: ' + ' playState:' + this.playState + ', readyState:' + this.readyState + ', position:' + this.position + ', duration:' + this.duration + ', durationEstimate:' + this.durationEstimate + ', isBuffering:' + this.isBuffering); }
},
onsuspend: function () {
if (debug) { console.log('Suspend Event: ' + ' playState:' + this.playState + ', readyState:' + this.readyState + ', position:' + this.position + ', duration:' + this.duration + ', durationEstimate:' + this.durationEstimate + ', isBuffering:' + this.isBuffering); }
},
onfinish: function () {
var next = $('#CurrentPlaylistContainer tr.playing').next();
changeTrack(next);

View file

@ -1,6 +1,7 @@
$(window).load(function () {
if ($.cookie('defaultsmwidth')) {
var width = $.cookie('defaultsmwidth');
smwidth = width;
resizeSMSection(width);
}
if ($.cookie('sidebar') && $.cookie('username') && $.cookie('passwordenc')) {

View file

@ -340,14 +340,6 @@
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');
@ -443,6 +435,29 @@
getPlaylist($(this).parent().parent().attr("id"), '', '#CurrentPlaylistContainer tbody');
return false;
});
$('#action_RefreshPlaylists').click(function () {
loadPlaylists(true);
return false;
});
$('#action_DeletePlaylist').click(function () {
if ($('#PlaylistContainer li.selected').length > 0) {
if (confirmDelete()) {
$('#PlaylistContainer li.selected').each(function () {
deletePlaylist($(this).attr("id"));
});
}
}
return false;
});
$('#action_SavePlaylist').click(function () {
if ($('#PlaylistContainer li.selected').length > 0) {
$('#PlaylistContainer li.selected').each(function () {
savePlaylist($(this).attr("id"));
});
}
return false;
});
// Podcast Click Events
$('#ChannelsContainer li.item').live('click', function () {
$('#AutoChannelsContainer li').removeClass('selected');
$('#ChannelsContainer li').removeClass('selected');
@ -466,28 +481,7 @@
loadPodcasts(true);
return false;
});
$('#action_RefreshPlaylists').click(function () {
loadPlaylists(true);
return false;
});
$('#action_DeletePlaylist').click(function () {
if ($('#PlaylistContainer li.selected').length > 0) {
if (confirmDelete()) {
$('#PlaylistContainer li.selected').each(function () {
deletePlaylist($(this).attr("id"));
});
}
}
return false;
});
$('#action_SavePlaylist').click(function () {
if ($('#PlaylistContainer li.selected').length > 0) {
$('#PlaylistContainer li.selected').each(function () {
savePlaylist($(this).attr("id"));
});
}
return false;
});
// Current Playlist Click Events
$('#action_RemoveSongs').click(function () {
if ($('#TrackContainer tr.selected').length > 0) {
$('#TrackContainer tr.selected').each(function () {

View file

@ -245,6 +245,9 @@ ul.simplelist li
padding: 8px;
border-bottom: 1px solid #f2f2f2;
}
ul.simplelist li .name
{
}
ul.simplelist li a
{
text-decoration: none;
@ -278,7 +281,6 @@ ul.mainlist li.item a.play
width: 20px;
height: 18px;
display: block;
margin: 0 5px 0 0;
background: url('../images/play_gl_6x8.png') no-repeat 6px center;
}
ul.mainlist li.item a.play:hover
@ -302,7 +304,6 @@ ul.mainlist li.item a.add
width: 20px;
height: 18px;
display: block;
margin: 0 5px 0 0;
background: url('../images/plus_gl_8x8.png') no-repeat 6px center;
}
ul.mainlist li.item a.add:hover