This commit is contained in:
Trevor Squillario 2012-03-10 11:46:25 -05:00
parent 7de6c89b74
commit ed43a7875d
6 changed files with 354 additions and 76 deletions

40
README
View file

@ -1,27 +1,21 @@
MiniSub
External Subsonic Music Player
MiniSub - HTML5 Mini Player for Subsonic
8/15/2011 .001 Initial Release
8/15/2011 .003 Fixed song details on player
8/17/2011 .004 https fix, audio player tweaks
8/24/2011 .005 playlist fixes, added auto playlists
8/25/2011 .006 flexible layout, added buttons to player
9/17/2011 .007 display tweaks for tablet, chat feature added
9/17/2011 .008 pause/play button tweak
9/30/2011 .009 now playing support, added back button to track list, other tweaks
10/1/2011 .010 fix for subdirectory custom installs
10/2/2011 .011 added play button from album list
10/13/2011 .012 added Current Playlist, fixed some bugs
10/14/2011 .013 moved auto playlists, album display tweaks
10/14/2011 .014 multiple api call issue fix
11/15/2011 .015 fixed search issue, added last.fm support from @smrq
11/22/2011 .016 single artist bug fix, added API error notification
1/5/2012 .017 added FancyBox to CoverArt, improved current playlist functions
1/9/2012 .018 added media keyboard bindings from @itchy
1/18/2012 .019 rating support, random playlist, new preferences added
1/25/2012 .020 table layout for songs, bug fixes, display tweaks
2/22/2012 .021 added sidebar for chat and now playing, bug fixes
3/6/2012 .022 can be installed anywhere, Chrome App support, JSONP implementation
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...
TO DO: (In no particular order...)
- Jukebox Control

BIN
images/cog_16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 B

BIN
images/headphones_16x14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

View file

@ -91,6 +91,8 @@
// spacebar
} else if (unicode == 32 || unicode == 179 || unicode == 0179) {
playPauseSong();
} else if (unicode == 36) {
$('#Artists').stop().scrollTo('#auto', 400);
}
}
});
@ -435,6 +437,28 @@
if (applicationname != "") {
$.cookie('ApplicationName', applicationname, { expires: 365 });
}
location.reload(true);
});
$('#HideAZ').live('click', function () {
if ($('#HideAZ').is(':checked')) {
$.cookie('HideAZ', '1', { expires: 365 });
$('#BottomContainer').hide();
}
});
$('#EnableNotifications').live('click', function () {
if ($('#EnableNotifications').is(':checked')) {
requestPermissionIfRequired();
if (hasNotificationPermission()) {
$.cookie('EnableNotifications', '1', { expires: 365 });
}
} else {
$.cookie('EnableNotifications', null);
}
});
$('#ScrollTitle').live('click', function () {
if ($('#ScrollTitle').is(':checked')) {
$.cookie('ScrollTitle', '1', { expires: 365 });
}
});
$('input#Password').keydown(function (e) {
var unicode = e.charCode ? e.charCode : e.keyCode;
@ -449,9 +473,17 @@
$.cookie('AutoPlaylistSize', null);
$.cookie('Server', null);
$.cookie('ApplicationName', null);
$.cookie('HideAZ', null);
location.reload(true);
});
}); // End document.ready
$('#ChangeLogShowMore').live('click', function () {
$('ul#ChangeLog li.log').each(function (i, el) {
$(el).show();
});
return false;
});
}); // End document.ready
$(window).load(function () {
if ($.cookie('defaultsmwidth')) {
@ -468,15 +500,26 @@
updateChatMessages();
updateNowPlaying();
}
if ($.cookie('HideAZ')) {
$('#BottomContainer').hide();
}
$('ul#ChangeLog li.log').each(function (i, el) {
if (i > 3) {
$(el).hide();
}
});
resizeContent();
});
window.onbeforeunload = function() {
closeAllNotifications();
};
$(window).resize(function () {
resizeContent();
});
function resizeContent() {
var screenwidth = $(window).width();
$('.tabcontent').css({ 'height': (($(window).height() - 160)) + 'px' });
$('.smsection').css({ 'height': (($(window).height() - 200)) + 'px' });
$('.tabcontent').css({ 'height': (($(window).height() - 152)) + 'px' });
$('.smsection').css({ 'height': (($(window).height() - 192)) + 'px' });
var smheight = $('.smsection').height();
var smwidth = $('.smsection').width();
$('#BottomContainer').css({ 'top': smheight + 75 + 'px' });
@ -485,7 +528,7 @@
if (tabwidth >= 700) {
$('.tabcontent').css({ 'width': tabwidth + 'px' });
}
var sbheight = $(window).height() - 160;
var sbheight = $(window).height() - 152;
$('#SideBar').css({ 'height': sbheight + 'px' });
$('#ChatMsgs').css({ 'height': (sbheight - 270) + 'px' });
} else {
@ -560,7 +603,7 @@
<li><a href="#tabLibrary">Music Library</a></li>
<li><a href="#tabCurrent">Current Playlist</a></li>
<li><a href="#tabPlaylists">Playlists</a></li>
<li><a href="#tabPreferences" class="last">Preferences</a></li>
<li><a href="#tabPreferences" class="last" title="Preferences"><img src="images/cog_16x16.png" /></a></li>
</ul>
<div class="toploading"></div>
<div id="messages"></div>
@ -569,8 +612,8 @@
<div id="tabLibrary" class="tabcontent">
<div id="MainActions" class="actions floatleft">
<a href="#" class="button" id="action_RefreshArtists" title="Refresh Artist List"><img src="images/reload_9x11.png" /></a>
<a href="#" class="button" id="action_DecreaseWidth" title="Decrease Width"><img src="images/minus_8x2.png" /></a></li>
<a href="#" class="button" id="action_IncreaseWidth" title="Increase Width"><img src="images/plus_8x8.png" /></a></li>
<a href="#" class="button" id="action_DecreaseWidth" title="Decrease Width"><img src="images/minus_8x2.png" /></a>
<a href="#" class="button" id="action_IncreaseWidth" title="Increase Width"><img src="images/plus_8x8.png" /></a>
</div>
<div class="actions floatleft">
<a href="#" class="button" id="action_AddToPlaylist" title="Add Selected To Playlist">+ Playlist</a>
@ -654,6 +697,21 @@
$('#AutoPlaylistSize').val($.cookie('AutoPlaylistSize'));
$('#Server').val($.cookie('Server'));
$('#ApplicationName').val($.cookie('ApplicationName'));
if ($.cookie('HideAZ')) {
$('#HideAZ').attr('checked', true);
} else {
$('#HideAZ').attr('checked', false);
}
if ($.cookie('EnableNotifications')) {
$('#EnableNotifications').attr('checked', true);
} else {
$('#EnableNotifications').attr('checked', false);
}
if ($.cookie('ScrollTitle')) {
$('#ScrollTitle').attr('checked', true);
} else {
$('#ScrollTitle').attr('checked', false);
}
});
</script>
<div class="actions floatleft">
@ -671,6 +729,17 @@
<label for="Server">Server <span class="red">*</span></label><br />
<input type="text" id="Server" name="Server" class="xlarge" title="Subsonic Server URL Ex: http://host:port/subsonic"/><br />
</div>
<div class="subsection floatleft">
<h3 class="title">Keyboard Shortcuts</h3>
<ul class="preferences">
<li><em>[a-z]</em> Use to Quickly Browse to an Artist</li>
<li><em>Home</em> Scroll to Top of Artist List</li>
<li><em>Spacebar</em> Play/Pause</li>
<li><em>&rarr;</em> Next Track</li>
<li><em>&larr;</em> Previous Track</li>
<li><span></span></li>
</ul>
</div>
<div class="clear"></div>
<div class="subsection floatleft">
<h3 class="title">Options</h3>
@ -682,16 +751,59 @@
<input type="text" id="ApplicationName" name="ApplicationName" class="large" title="Custom Player Name"/><br />
</div>
<div class="subsection floatleft">
<h3 class="title">Keyboard Shortcuts</h3>
<ul class="preferences">
<li><em>[a-z]</em> Click the Album list, use to quickly browse to an artist</li>
<li><em>Spacebar</em> Play/Pause</li>
<li><em>&rarr;</em> Next Track</li>
<li><em>&larr;</em> Previous Track</li>
<li><span></span></li>
<div class="checkboxes">
<div class="inputwrap"><input type="checkbox" id="HideAZ" name="HideAZ" value="1" title="Hide A-Z at Bottom of Artists"/></div>
<label for="HideAZ">Hide A-Z</label>
<div class="clear"></div>
<div class="inputwrap"><input type="checkbox" id="EnableNotifications" name="EnableNotifications" value="1" title="Enable Notifications When Tracks Change"/></div>
<label for="EnableNotifications">Desktop Notifications <small>[Beta]</small></label>
<div class="clear"></div>
<div class="inputwrap"><input type="checkbox" id="ScrollTitle" name="ScrollTitle" value="1" title="Scroll the Title Once"/></div>
<label for="ScrollTitle">Scroll Title</label>
</div>
</div>
<div class="clear"></div>
<div class="subsection floatleft">
<h3 class="title">Change Log</h3>
<ul id="ChangeLog" class="preferences">
<!--<li class="log">- </li>-->
<li class="log"><span class="version">3/9/2012 - 1.7</span>
<span class="changes">- Ability to hide A-Z bar on Artists list</span>
<span class="changes">- Desktop Notifications on browsers that support <span class="code">webkitNotifications</span></span>
<span class="changes">- Redesigned player to utilize entire width of screen</span>
</li>
<li class="log"><span class="version">3/6/2012</span><span class="changes">.022 can be installed anywhere, Chrome App support, JSONP implementation</li>
<li class="log"><span class="version">2/22/2012</span><span class="changes">.021 added sidebar for chat and now playing, bug fixes</li>
<li class="log"><span class="version">1/25/2012</span><span class="changes">.020 table layout for songs, bug fixes, display tweaks</li>
<li class="log"><span class="version">1/18/2012</span><span class="changes">.019 rating support, random playlist, new preferences added</li>
<li class="log"><span class="version">1/9/2012</span><span class="changes">.018 added media keyboard bindings from @itchy</li>
<li class="log"><span class="version">1/5/2012</span><span class="changes">.017 added FancyBox to CoverArt, improved current playlist functions</li>
<li class="log"><span class="version">11/22/2011</span><span class="changes">.016 single artist bug fix, added API error notification</li>
<li class="log"><span class="version">11/15/2011</span><span class="changes">.015 fixed search issue, added last.fm support from @smrq</li>
<li class="log"><span class="version">10/14/2011</span><span class="changes">.014 multiple api call issue fix</li>
<li class="log"><span class="version">10/14/2011</span><span class="changes">.013 moved auto playlists, album display tweaks</li>
<li class="log"><span class="version">10/13/2011</span><span class="changes">.012 added Current Playlist, fixed some bugs</li>
<li class="log"><span class="version">10/2/2011</span><span class="changes">.011 added play button from album list</li>
<li class="log"><span class="version">10/1/2011</span><span class="changes">.010 fix for subdirectory custom installs</li>
<li class="log"><span class="version">9/30/2011</span><span class="changes">.009 now playing support, added back button to track list, other tweaks</li>
<li class="log"><span class="version">9/17/2011</span><span class="changes">.008 pause/play button tweak</li>
<li class="log"><span class="version">9/17/2011</span><span class="changes">.007 display tweaks for tablet, chat feature added</li>
<li class="log"><span class="version">8/25/2011</span><span class="changes">.006 flexible layout, added buttons to player</li>
<li class="log"><span class="version">8/24/2011</span><span class="changes">.005 playlist fixes, added auto playlists</li>
<li class="log"><span class="version">8/17/2011</span><span class="changes">.004 https fix, audio player tweaks</li>
<li class="log"><span class="version">8/15/2011</span><span class="changes">.003 Fixed song details on player </li>
<li class="log"><span class="version">8/15/2011</span><span class="changes">.001 Initial Release</li>
<li><a href="#" id="ChangeLogShowMore">Show More</a></li>
</ul>
</div>
<div class="clear"></div>
<div class="subsection floatleft">
<h3 class="title">Thanks</h3>
<ul class="preferences">
<li>Icons - <a href="http://somerandomdude.com/work/iconic" target="_blank">http://somerandomdude.com/work/iconic</a></li>
<li>Audio Library - <a href="http://kolber.github.com/audiojs" target="_blank">http://kolber.github.com/audiojs</a></li>
</ul>
</div>
</div>
<div class="clear"></div>
</div>
@ -710,25 +822,27 @@
<!-- Audio Player -->
<div class="clear"></div>
<div id="player">
<div class="playeractions floatleft">
<a href="#" class="button" id="PreviousTrack" title="Previous Track"><img src="images/first_24x24.png" /></a>
<a href="#" class="button" id="PlayTrack" title="Play/Pause"><img src="images/play_24x32.png" /></a>
<a href="#" class="button" id="NextTrack" title="Next Track"><img src="images/last_24x24.png" /></a>
</div>
<div id="coverart"><a id="coverartimage" href="images/albumdefault_120.jpg"><img src="images/albumdefault_56.jpg" alt=""/></a></div>
<div id="songdetails" class="floatleft">
<ul>
<li id="songdetails_song"></li>
<li id="songdetails_artist"></li>
</ul>
<div id="audiocontainer" class="floatleft">
<div class="floatleft"><audio src="" preload="none" /></div>
<div id="playerleft" class="floatleft">
<div class="playeractions floatleft">
<a href="#" class="button" id="PreviousTrack" title="Previous Track"><img src="images/first_24x24.png" /></a>
<a href="#" class="button" id="PlayTrack" title="Play/Pause"><img src="images/play_24x32.png" /></a>
<a href="#" class="button" id="NextTrack" title="Next Track"><img src="images/last_24x24.png" /></a>
</div>
<div id="songdetails">
<div id="coverart"><a id="coverartimage" href="images/albumdefault_120.jpg"><img src="images/albumdefault_56.jpg" alt=""/></a></div>
<ul>
<li id="songdetails_song" class="song"></li>
<li id="songdetails_artist" class="album"></li>
</ul>
<div class="vertshade"></div>
</div>
</div>
<div class="playeractionssmall floatright"><a href="#" class="button" id="action_ToggleSideBar" title="Toggle Side Bar"><img src="images/arrow_right_gl_12x12.png" /></a></div>
<div class="playeractionssmall"><a href="#" class="button" id="action_ToggleSideBar" title="Toggle Side Bar"><img src="images/arrow_right_gl_12x12.png" /></a></div>
<div id="playermiddle">
<div id="audiocontainer"><audio src="" preload="none" /></div>
</div>
<div class="clear"></div>
</div>
<div class="clear"></div>
</div><!-- end #content -->
</div><!-- end #container -->

View file

@ -341,7 +341,9 @@ function playSong(el, songid, albumid) {
$('#songdetails_song').attr('childid', songid);
$('#songdetails_artist').html(artist + ' - ' + album);
$('#coverartimage').attr('href', baseURL + '/getCoverArt.view?v=1.6.0&c=' + applicationName + '&f=jsonp&id=' + coverart);
$('#coverartimage img').attr('src', baseURL + '/getCoverArt.view?v=1.6.0&c=' + applicationName + '&f=jsonp&size=56&id=' + coverart);
$('#coverartimage img').attr('src', baseURL + '/getCoverArt.view?v=1.6.0&c=' + applicationName + '&f=jsonp&size=50&id=' + coverart);
$('#playermiddle').css('visibility', 'visible');
$('#songdetails').css('visibility', 'visible');
audio.load(baseURL + '/stream.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + songid);
audio.play();
$('table.songlist tr.song').removeClass('playing');
@ -350,6 +352,16 @@ function playSong(el, songid, albumid) {
$('#PlayTrack').addClass('playing');
scrobbleSong(false);
scrobbled = false;
if ($.cookie('EnableNotifications')) {
showNotification(baseURL + '/getCoverArt.view?v=1.6.0&c=' + applicationName + '&f=jsonp&size=50&id=' + coverart, title, artist + ' - ' + album);
}
if ($.cookie('ScrollTitle')) {
//clearTimeout(timer);
scrollTitle(artist + ' - ' + title);
} else {
setTitle(artist + ' - ' + title);
}
}
});
}
@ -939,3 +951,66 @@ function updateMessage(msg) {
$('#messages').fadeIn();
setTimeout(function () { $('#messages').fadeOut(); }, 5000);
}
function setTitle(text) {
if (text != "") {
document.title = text;
}
}
var timer = null;
var scrollMsg = "";
var pos = 0;
function scrollTitle(text) {
if (scrollMsg === "") {
if (text === "") {
scrollMsg = document.title;
} else {
scrollMsg = text;
}
} else {
if (text != undefined && text != scrollMsg) {
scrollMsg = text;
}
}
var msg = scrollMsg;
var speed = 1200;
var endChar = " ";
var ml = msg.length;
title = msg.substr(pos, ml) + endChar + msg.substr(0, pos);
document.title = title;
pos++;
if (pos > ml) {
pos = 0;
} else {
timer = window.setTimeout("scrollTitle()", speed);
}
// To stop timer, clearTimeout(timer);
}
function requestPermissionIfRequired() {
if (!hasNotificationPermission() && (window.webkitNotifications)) {
window.webkitNotifications.requestPermission();
}
}
function hasNotificationPermission() {
return !!(window.webkitNotifications) && (window.webkitNotifications.checkPermission() == 0);
}
var notifications = new Array();
function showNotification(pic, title, text) {
if (hasNotificationPermission()) {
closeAllNotifications()
var popup = window.webkitNotifications.createNotification(pic, title, text);
notifications.push(popup);
setTimeout(function (notWin) {
notWin.cancel();
}, 10000, popup);
popup.show();
} else {
console.log("showNotification: No Permission");
}
}
function closeAllNotifications() {
for (notification in notifications) {
notifications[notification].cancel();
}
}

View file

@ -81,7 +81,24 @@ h3.title
border-left: 1px solid #CBCBCB;
border-right: 1px solid #CBCBCB;
}
#nav a:hover { color: #545454; }
#nav a:hover
{
color: #545454;
border-top: 1px solid #CBCBCB;
border-left: 1px solid #CBCBCB;
border-right: 1px solid #CBCBCB;
}
#nav a img
{
display: block;
margin: 3px 0 4px 0;
}
#nav a.active img
{
display: block;
margin: 3px 0 4px 0;
}
#content
{
border-top: 1px solid #cbcbcb;
@ -468,7 +485,7 @@ table.songlist tr.playing
}
table.songlist tr.playing td:first-child
{
background: url('../images/play_alt_16x16.png') 6px 10px no-repeat;
background: url('../images/play_alt_16x16.png') 6px 11px no-repeat;
}
table.songlist tr.selected
{
@ -694,10 +711,9 @@ background-color: #8dbdd8;
.audiojs
{
width: auto;
height: 17px;
margin: 0 9px 2px 0;
height: 56px;
margin: 0;
background: none;
background: #404040;
font-family: inherit;
font-size: 10px;
box-shadow: none;
@ -708,49 +724,83 @@ background-color: #8dbdd8;
}
.audiojs .scrubber
{
height: 5px;
margin: 5px;
height: 2px;
margin: 26px 5px 0px 5px;
float: none;
width: auto;
}
.audiojs .time
{
float: right;
border: none;
line-height: 17px;
padding: 0 6px 0 6px;
padding: 0 5px;
font-size: 11px;
color: #333333;
text-shadow: none;
}
.audiojs .time em
{
color: #333333;
}
.playeractions
{
margin: 9px 20px;
margin: 5px 20px 0 20px;
width: 160px;
}
.playeractionssmall
{
margin: 18px 5px;
margin: 14px 8px 0 14px;
width: 50px;
float: right;
}
#playermiddle
{
width: 100%;
visibility: hidden;
}
#coverart
{
width: 56px;
height: 56px;
width: 50px;
height: 50px;
overflow: hidden;
margin: 2px 0 2px 0;
margin: 2px 8px 0 0;
float: left;
padding: 2px;
border: 1px solid #DEDEDE;
}
#songdetails
{
width: 250px;
margin: 0 8px;
float: left;
visibility: hidden;
}
#songdetails ul
{
list-style-type: none;
margin: 6px 0;
margin: 4px 0;
padding: 0;
height: 30px;
height: 52px;
width: 185px;
overflow: hidden;
white-space: nowrap;
float: left;
}
#songdetails li
{
}
#songdetails li.song
{
font-size: 12px;
font-weight: bold;
line-height: 14px;
margin: 12px 0 2px 0;
}
#songdetails li.album
{
font-size: 11px;
line-height: 14px;
}
#songdetails li span.label
{
@ -760,6 +810,14 @@ background-color: #8dbdd8;
text-align: right;
width: 37px;
}
.vertshade {
position: relative;
top: 0;
left: 229px;
width: 20px;
height: 60px;
background-image: -webkit-gradient( linear, left top, right top, from(rgba(255, 255, 255, 0)), to(rgba(255, 255, 255, 1)));
}
ul.preferences
{
list-style-type: none;
@ -779,13 +837,6 @@ ul.preferences li.title
font-variant: small-caps;
padding: 0;
}
ul.preferences li span
{
clear: both;
display: block;
float: left;
width: 80px;
}
ul.preferences li em
{
background: none repeat scroll 0 0 #D3D3D3;
@ -796,7 +847,30 @@ ul.preferences li em
padding: 3px 9px 3px;
position: relative;
}
ul.preferences li.log
{
padding: 2px 0;
}
ul.preferences li span.version
{
color: #646464;
font-weight: bold;
font-size: 11px;
padding: 0;
display: block;
}
ul.preferences li.log span.changes
{
color: #646464;
font-size: 11px;
padding: 0 0 0 5px;
display: block;
}
span.code
{
font-family:"Courier New",Courier,mono;
font-size: 11px;
}
@ -882,4 +956,25 @@ label
{
font-size: 12px;
margin: 0 5px;
}
.inputwrap
{
float: left;
border: 1px solid #DCDCDC;
padding: 3px;
margin-bottom: 5px;
}
.checkboxes
{
margin: 10px 5px;
vertical-align: middle;
}
.checkboxes input
{
float: left;
}
.checkboxes label
{
float: left;
margin: 5px 5px 0 5px;
}