mirror of
				https://github.com/SuperBFG7/ympd
				synced 2025-10-31 05:43:01 +00:00 
			
		
		
		
	fix crash when seeking without song, new slider
This commit is contained in:
		| @@ -7,18 +7,18 @@ body { | ||||
|   padding: 40px 15px; | ||||
| } | ||||
|  | ||||
| .slider.slider-horizontal { | ||||
|   height: 15px; | ||||
| #volumeslider { | ||||
|   width: 150px; | ||||
| } | ||||
|  | ||||
| .slider.slider-horizontal .slider-track { | ||||
|   height: 10px; | ||||
|   margin-top: -6px; | ||||
| #volumeslider .progress { | ||||
|   margin-bottom: 0; | ||||
| } | ||||
|  | ||||
| .progress { | ||||
|   margin-top: 0px; | ||||
|   margin-bottom: 0px; | ||||
| #volume-icon { | ||||
|   float: left; | ||||
|   margin-right: 10px; | ||||
|   margin-top: 2px; | ||||
| } | ||||
|  | ||||
| #counter { | ||||
| @@ -29,5 +29,44 @@ body { | ||||
| } | ||||
|  | ||||
| .btn-group-hover { | ||||
|     opacity: 0; | ||||
|     opacity: 20%; | ||||
| } | ||||
|  | ||||
| .btn:active, | ||||
| .btn.active { | ||||
|   background-image: none; | ||||
|   outline: 0; | ||||
|   -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); | ||||
|           box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); | ||||
|   color: #428bca; | ||||
|   background-color: #fdfdfd; | ||||
|   border-color: #adadad; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| #salamisandwich td:nth-child(3), th:nth-child(3) { | ||||
|   text-align: right; | ||||
| } | ||||
|  | ||||
| tbody { | ||||
|   cursor: pointer; | ||||
| } | ||||
|  | ||||
| .notifications { | ||||
|   position: fixed; | ||||
|   z-index: 9999; | ||||
| } | ||||
|  | ||||
| /* Positioning */  | ||||
| .notifications.top-right { | ||||
|   right: 10px; | ||||
|   top: 60px; | ||||
| } | ||||
|  | ||||
| /* Notification Element */ | ||||
| .notifications > div { | ||||
|   position: relative; | ||||
|   z-index: 9999; | ||||
|   margin: 5px 0px; | ||||
| } | ||||
| @@ -12,7 +12,7 @@ | ||||
|   position: relative; | ||||
| } | ||||
| .slider.slider-horizontal { | ||||
|   width: 210px; | ||||
|   width: 100%; | ||||
|   height: 20px; | ||||
| } | ||||
| .slider.slider-horizontal .slider-track { | ||||
|   | ||||
| @@ -13,7 +13,6 @@ | ||||
|   <link href="css/bootstrap.css" rel="stylesheet"> | ||||
|  | ||||
|   <!-- Custom styles for this template --> | ||||
|   <link href="css/slider.css" rel="stylesheet"> | ||||
|   <link href="css/mpd.css" rel="stylesheet"> | ||||
|   <link href="assets/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon"> | ||||
|  | ||||
| @@ -40,7 +39,7 @@ | ||||
|         <ul id="nav_links" class="nav navbar-nav"> | ||||
|           <li id="playlist"><a href="#/">Playlist</a></li> | ||||
|           <li id="browse"><a href="#/browse/">Browse database</a></li> | ||||
|           <li><a href="#" data-toggle="modal" data-target="#about">About</a></li> | ||||
|           <li><a href="#" data-toggle="modal" data-target="#about" onclick="getVersion();">About</a></li> | ||||
|         </ul> | ||||
|  | ||||
|         <div class="btn-toolbar navbar-btn navbar-right" role="toolbar"> | ||||
| @@ -48,6 +47,9 @@ | ||||
|             <button type="button" class="btn btn-default" onclick="socket.send('MPD_API_SET_NEXT');"> | ||||
|               <span class="glyphicon glyphicon-backward"></span> | ||||
|             </button> | ||||
|             <button type="button" class="btn btn-default" onclick="socket.send('MPD_API_SET_STOP');"> | ||||
|               <span id="stop-icon" class="glyphicon glyphicon-stop"></span> | ||||
|             </button> | ||||
|             <button type="button" class="btn btn-default" onclick="socket.send('MPD_API_SET_PAUSE');"> | ||||
|               <span id="play-icon" class="glyphicon glyphicon-pause"></span> | ||||
|             </button> | ||||
| @@ -58,8 +60,7 @@ | ||||
|           <div class="btn-group"> | ||||
|             <div class="btn btn-toolbar btn-default"> | ||||
|               <span id="volume-icon" class="glyphicon glyphicon-volume-up"></span> | ||||
|                  | ||||
|               <input type="text" class="span2" value="0" data-slider-min="0" data-slider-max="100" data-slider-step="5" id="volumeslider" data-slider-tooltip="hide"> | ||||
|               <div id="volumeslider"></div> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
| @@ -71,7 +72,7 @@ | ||||
|     <div class="row"> | ||||
|  | ||||
|       <div class="col-md-10 col-xs-12"> | ||||
|         <div id="alert" class="alert hide"></div> | ||||
|         <div class="notifications top-right"></div> | ||||
|          | ||||
|         <div class="panel panel-primary"> | ||||
|           <!-- Default panel contents --> | ||||
| @@ -87,10 +88,9 @@ | ||||
|             </h4> | ||||
|             <p id="counter" class="text pull-right">  </p> | ||||
|  | ||||
|             <div class="progress progress-striped active"> | ||||
|               <div id="progressbar" class="progress-bar navbar-left"  role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100"> | ||||
|               </div> | ||||
|             </div> | ||||
|             <div id="progressbar"></div> | ||||
|  | ||||
|  | ||||
|           </div><!-- /.panel-body --> | ||||
|  | ||||
|           <ol id="breadcrump" class="breadcrumb"> | ||||
| @@ -112,7 +112,7 @@ | ||||
|       </div><!-- /.col-md-10 --> | ||||
|  | ||||
|       <div class="col-md-2 col-xs-12" > | ||||
|         <div data-spy="affix" data-offset-bottom="10"> | ||||
|         <div class="btn-toolbar"> | ||||
|           <div class="btn-group-vertical btn-block btn-group-lg" data-toggle="buttons"> | ||||
|             <button id="btnrandom" type="button" class="btn btn-default"> | ||||
|               <span class="glyphicon glyphicon-random"></span> Random | ||||
| @@ -128,13 +128,15 @@ | ||||
|             </button> | ||||
|           </div> | ||||
|  | ||||
|           <button type="button" class="btn btn-block btn-default btn-lg dropdown-toggle" data-toggle="dropdown"> | ||||
|             <span class="glyphicon glyphicon-wrench"></span> Options <span class="caret"></span> | ||||
|           <div class="btn-group-vertical btn-block btn-group-lg"> | ||||
|             <button type="button" class="btn btn-default" onclick="updateDB();"> | ||||
|               <span class="glyphicon glyphicon-refresh"></span> Update DB | ||||
|             </button> | ||||
|           <ul class="dropdown-menu"> | ||||
|             <li><a href="#/" onclick="updateDB();"><span class="glyphicon glyphicon-refresh"></span> Update Database</a></li> | ||||
|             <li><a href="#/" onclick="socket.send('MPD_API_RM_ALL');"><span class="glyphicon glyphicon-trash"></span> Clear queue</a></li> | ||||
|           </ul> | ||||
|             <button type="button" class="btn btn-default" onclick="socket.send('MPD_API_RM_ALL');"> | ||||
|               <span class="glyphicon glyphicon-trash"></span> Clear queue | ||||
|             </button> | ||||
|           </div> | ||||
|  | ||||
|         </div> | ||||
|       </div><!-- /.col-md-2 --> | ||||
|     </div><!-- /.row --> | ||||
| @@ -150,9 +152,13 @@ | ||||
|         </div> | ||||
|         <div class="modal-body"> | ||||
|           <h4><span class="glyphicon glyphicon-play-circle"></span> ympd   <small>MPD Web GUI - written in C, utilizing Websockets and Bootstrap/JS</small></h4> | ||||
|           <br/> | ||||
|           <span class="glyphicon glyphicon-play-circle"></span> ympd is a lightweight MPD (Music Player Daemon) web client that runs without a dedicated werbserver or interpreters like PHP, NodeJS or Ruby. It's tuned for minimal resource usage and requires only very litte dependencies. | ||||
|           <h5><span class="glyphicon glyphicon-play-circle"></span> ympd uses following excellent software:</h5> | ||||
|           <p> | ||||
|           ympd is a lightweight MPD (Music Player Daemon) web client that runs without a dedicated werbserver or interpreters like PHP, NodeJS or Ruby. It's tuned for minimal resource usage and requires only very litte dependencies.</p> | ||||
|           <p class="text-muted"> | ||||
|           ympd <span id="ympd_version"></span><br/> | ||||
|           libmpdclient <span id="mpd_version"></span><br/> | ||||
|           </p> | ||||
|           <h5>ympd uses following excellent software:</h5> | ||||
|           <h6><a href="http://libwebsockets.org">libWebSockets</a> <small>LGPL2.1 + static link exception</small></h6> | ||||
|           <h6><a href="http://www.musicpd.org/libs/libmpdclient/">libMPDClient</a> <small>BSD License</small></h6> | ||||
|           <br/> | ||||
| @@ -162,7 +168,7 @@ | ||||
|               <strong>Andrew Karpow</strong><br> | ||||
|               <a href="mailto:andy@ympd.org">andy@ympd.org</a><br/> | ||||
|               <a href="http://www.ympd.org">www.ympd.org</a><br/> | ||||
|               XMPP: <a href="xmpp:andy@jabber.ccc.de?subscribe">andy_@jabber.ccc.de</a> | ||||
|               XMPP: <a href="xmpp:andy_@jabber.ccc.de?subscribe">andy_@jabber.ccc.de</a> | ||||
|             </address> | ||||
|           </blockquote> | ||||
|         </div> | ||||
| @@ -179,7 +185,8 @@ | ||||
|   <!-- Placed at the end of the document so the pages load faster --> | ||||
|   <script src="js/jquery-1.10.2.min.js"></script> | ||||
|   <script src="js/bootstrap.min.js"></script> | ||||
|   <script src="js/bootstrap-slider.js"></script> | ||||
|   <script src="js/bootstrap-notify.js"></script> | ||||
|   <script src="js/boostrap-slider.js"></script> | ||||
|   <script src="js/sammy.js"></script> | ||||
|   <script src="js/mpd.js"></script> | ||||
| </body> | ||||
|   | ||||
							
								
								
									
										585
									
								
								htdocs/js/bootstrap-notify.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										585
									
								
								htdocs/js/bootstrap-notify.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,585 @@ | ||||
| /** Notify.js - v0.3.1 - 2013/07/05 | ||||
|  * http://notifyjs.com/ | ||||
|  * Copyright (c) 2013 Jaime Pillora - MIT | ||||
|  */ | ||||
| (function(window,document,$,undefined) { | ||||
| 'use strict'; | ||||
|  | ||||
| var Notification, addStyle, blankFieldName, coreStyle, createElem, defaults, encode, find, findFields, getAnchorElement, getStyle, globalAnchors, hAligns, incr, inherit, insertCSS, mainPositions, opposites, parsePosition, pluginClassName, pluginName, pluginOptions, positions, realign, stylePrefixes, styles, vAligns, | ||||
|   __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; | ||||
|  | ||||
| pluginName = 'notify'; | ||||
|  | ||||
| pluginClassName = pluginName + 'js'; | ||||
|  | ||||
| blankFieldName = pluginName + "!blank"; | ||||
|  | ||||
| positions = { | ||||
|   t: 'top', | ||||
|   m: 'middle', | ||||
|   b: 'bottom', | ||||
|   l: 'left', | ||||
|   c: 'center', | ||||
|   r: 'right' | ||||
| }; | ||||
|  | ||||
| hAligns = ['l', 'c', 'r']; | ||||
|  | ||||
| vAligns = ['t', 'm', 'b']; | ||||
|  | ||||
| mainPositions = ['t', 'b', 'l', 'r']; | ||||
|  | ||||
| opposites = { | ||||
|   t: 'b', | ||||
|   m: null, | ||||
|   b: 't', | ||||
|   l: 'r', | ||||
|   c: null, | ||||
|   r: 'l' | ||||
| }; | ||||
|  | ||||
| parsePosition = function(str) { | ||||
|   var pos; | ||||
|   pos = []; | ||||
|   $.each(str.split(/\W+/), function(i, word) { | ||||
|     var w; | ||||
|     w = word.toLowerCase().charAt(0); | ||||
|     if (positions[w]) { | ||||
|       return pos.push(w); | ||||
|     } | ||||
|   }); | ||||
|   return pos; | ||||
| }; | ||||
|  | ||||
| styles = {}; | ||||
|  | ||||
| coreStyle = { | ||||
|   name: 'core', | ||||
|   html: "<div class=\"" + pluginClassName + "-wrapper\">\n  <div class=\"" + pluginClassName + "-arrow\"></div>\n  <div class=\"" + pluginClassName + "-container\"></div>\n</div>", | ||||
|   css: "." + pluginClassName + "-corner {\n  position: fixed;\n  margin: 5px;\n  z-index: 1050;\n}\n\n." + pluginClassName + "-corner ." + pluginClassName + "-wrapper,\n." + pluginClassName + "-corner ." + pluginClassName + "-container {\n  position: relative;\n  display: block;\n  height: inherit;\n  width: inherit;\n  margin: 3px;\n}\n\n." + pluginClassName + "-wrapper {\n  z-index: 1;\n  position: absolute;\n  display: inline-block;\n  height: 0;\n  width: 0;\n}\n\n." + pluginClassName + "-container {\n  display: none;\n  z-index: 1;\n  position: absolute;\n  cursor: pointer;\n}\n\n[data-notify-text],[data-notify-html] {\n  position: relative;\n}\n\n." + pluginClassName + "-arrow {\n  position: absolute;\n  z-index: 2;\n  width: 0;\n  height: 0;\n}" | ||||
| }; | ||||
|  | ||||
| stylePrefixes = { | ||||
|   "border-radius": ["-webkit-", "-moz-"] | ||||
| }; | ||||
|  | ||||
| getStyle = function(name) { | ||||
|   return styles[name]; | ||||
| }; | ||||
|  | ||||
| addStyle = function(name, def) { | ||||
|   var cssText, elem, fields, _ref; | ||||
|   if (!name) { | ||||
|     throw "Missing Style name"; | ||||
|   } | ||||
|   if (!def) { | ||||
|     throw "Missing Style definition"; | ||||
|   } | ||||
|   if (!def.html) { | ||||
|     throw "Missing Style HTML"; | ||||
|   } | ||||
|   if ((_ref = styles[name]) != null ? _ref.cssElem : void 0) { | ||||
|     if (window.console) { | ||||
|       console.warn("" + pluginName + ": overwriting style '" + name + "'"); | ||||
|     } | ||||
|     styles[name].cssElem.remove(); | ||||
|   } | ||||
|   def.name = name; | ||||
|   styles[name] = def; | ||||
|   cssText = ""; | ||||
|   if (def.classes) { | ||||
|     $.each(def.classes, function(className, props) { | ||||
|       cssText += "." + pluginClassName + "-" + def.name + "-" + className + " {\n"; | ||||
|       $.each(props, function(name, val) { | ||||
|         if (stylePrefixes[name]) { | ||||
|           $.each(stylePrefixes[name], function(i, prefix) { | ||||
|             return cssText += "  " + prefix + name + ": " + val + ";\n"; | ||||
|           }); | ||||
|         } | ||||
|         return cssText += "  " + name + ": " + val + ";\n"; | ||||
|       }); | ||||
|       return cssText += "}\n"; | ||||
|     }); | ||||
|   } | ||||
|   if (def.css) { | ||||
|     cssText += "/* styles for " + def.name + " */\n" + def.css; | ||||
|   } | ||||
|   if (cssText) { | ||||
|     def.cssElem = insertCSS(cssText); | ||||
|     def.cssElem.attr('id', "notify-" + def.name); | ||||
|   } | ||||
|   fields = {}; | ||||
|   elem = $(def.html); | ||||
|   findFields('html', elem, fields); | ||||
|   findFields('text', elem, fields); | ||||
|   return def.fields = fields; | ||||
| }; | ||||
|  | ||||
| insertCSS = function(cssText) { | ||||
|   var elem; | ||||
|   elem = createElem("style"); | ||||
|   elem.attr('type', 'text/css'); | ||||
|   $("head").append(elem); | ||||
|   try { | ||||
|     elem.html(cssText); | ||||
|   } catch (e) { | ||||
|     elem[0].styleSheet.cssText = cssText; | ||||
|   } | ||||
|   return elem; | ||||
| }; | ||||
|  | ||||
| findFields = function(type, elem, fields) { | ||||
|   var attr; | ||||
|   if (type !== 'html') { | ||||
|     type = 'text'; | ||||
|   } | ||||
|   attr = "data-notify-" + type; | ||||
|   return find(elem, "[" + attr + "]").each(function() { | ||||
|     var name; | ||||
|     name = $(this).attr(attr); | ||||
|     if (!name) { | ||||
|       name = blankFieldName; | ||||
|     } | ||||
|     return fields[name] = type; | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| find = function(elem, selector) { | ||||
|   if (elem.is(selector)) { | ||||
|     return elem; | ||||
|   } else { | ||||
|     return elem.find(selector); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| pluginOptions = { | ||||
|   clickToHide: true, | ||||
|   autoHide: true, | ||||
|   autoHideDelay: 5000, | ||||
|   arrowShow: true, | ||||
|   arrowSize: 5, | ||||
|   breakNewLines: true, | ||||
|   elementPosition: 'bottom', | ||||
|   globalPosition: 'top right', | ||||
|   style: 'bootstrap', | ||||
|   className: 'error', | ||||
|   showAnimation: 'slideDown', | ||||
|   showDuration: 400, | ||||
|   hideAnimation: 'slideUp', | ||||
|   hideDuration: 200, | ||||
|   gap: 5 | ||||
| }; | ||||
|  | ||||
| inherit = function(a, b) { | ||||
|   var F; | ||||
|   F = function() {}; | ||||
|   F.prototype = a; | ||||
|   return $.extend(true, new F(), b); | ||||
| }; | ||||
|  | ||||
| defaults = function(opts) { | ||||
|   return $.extend(pluginOptions, opts); | ||||
| }; | ||||
|  | ||||
| createElem = function(tag) { | ||||
|   return $("<" + tag + "></" + tag + ">"); | ||||
| }; | ||||
|  | ||||
| globalAnchors = {}; | ||||
|  | ||||
| getAnchorElement = function(element) { | ||||
|   var radios; | ||||
|   if (element.is('[type=radio]')) { | ||||
|     radios = element.parents('form:first').find('[type=radio]').filter(function(i, e) { | ||||
|       return $(e).attr('name') === element.attr('name'); | ||||
|     }); | ||||
|     element = radios.first(); | ||||
|   } | ||||
|   return element; | ||||
| }; | ||||
|  | ||||
| incr = function(obj, pos, val) { | ||||
|   var opp, temp; | ||||
|   if (typeof val === 'string') { | ||||
|     val = parseInt(val, 10); | ||||
|   } else if (typeof val !== 'number') { | ||||
|     return; | ||||
|   } | ||||
|   if (isNaN(val)) { | ||||
|     return; | ||||
|   } | ||||
|   opp = positions[opposites[pos.charAt(0)]]; | ||||
|   temp = pos; | ||||
|   if (obj[opp] !== undefined) { | ||||
|     pos = positions[opp.charAt(0)]; | ||||
|     val = -val; | ||||
|   } | ||||
|   if (obj[pos] === undefined) { | ||||
|     obj[pos] = val; | ||||
|   } else { | ||||
|     obj[pos] += val; | ||||
|   } | ||||
|   return null; | ||||
| }; | ||||
|  | ||||
| realign = function(alignment, inner, outer) { | ||||
|   if (alignment === 'l' || alignment === 't') { | ||||
|     return 0; | ||||
|   } else if (alignment === 'c' || alignment === 'm') { | ||||
|     return outer / 2 - inner / 2; | ||||
|   } else if (alignment === 'r' || alignment === 'b') { | ||||
|     return outer - inner; | ||||
|   } | ||||
|   throw "Invalid alignment"; | ||||
| }; | ||||
|  | ||||
| encode = function(text) { | ||||
|   encode.e = encode.e || createElem("div"); | ||||
|   return encode.e.text(text).html(); | ||||
| }; | ||||
|  | ||||
| Notification = (function() { | ||||
|  | ||||
|   function Notification(elem, data, options) { | ||||
|     if (typeof options === 'string') { | ||||
|       options = { | ||||
|         className: options | ||||
|       }; | ||||
|     } | ||||
|     this.options = inherit(pluginOptions, $.isPlainObject(options) ? options : {}); | ||||
|     this.loadHTML(); | ||||
|     this.wrapper = $(coreStyle.html); | ||||
|     this.wrapper.data(pluginClassName, this); | ||||
|     this.arrow = this.wrapper.find("." + pluginClassName + "-arrow"); | ||||
|     this.container = this.wrapper.find("." + pluginClassName + "-container"); | ||||
|     this.container.append(this.userContainer); | ||||
|     if (elem && elem.length) { | ||||
|       this.elementType = elem.attr('type'); | ||||
|       this.originalElement = elem; | ||||
|       this.elem = getAnchorElement(elem); | ||||
|       this.elem.data(pluginClassName, this); | ||||
|       this.elem.before(this.wrapper); | ||||
|     } | ||||
|     this.container.hide(); | ||||
|     this.run(data); | ||||
|   } | ||||
|  | ||||
|   Notification.prototype.loadHTML = function() { | ||||
|     var style; | ||||
|     style = this.getStyle(); | ||||
|     this.userContainer = $(style.html); | ||||
|     return this.userFields = style.fields; | ||||
|   }; | ||||
|  | ||||
|   Notification.prototype.show = function(show, userCallback) { | ||||
|     var args, callback, elems, fn, hidden, | ||||
|       _this = this; | ||||
|     callback = function() { | ||||
|       if (!show && !_this.elem) { | ||||
|         _this.destroy(); | ||||
|       } | ||||
|       if (userCallback) { | ||||
|         return userCallback(); | ||||
|       } | ||||
|     }; | ||||
|     hidden = this.container.parent().parents(':hidden').length > 0; | ||||
|     elems = this.container.add(this.arrow); | ||||
|     args = []; | ||||
|     if (hidden && show) { | ||||
|       fn = 'show'; | ||||
|     } else if (hidden && !show) { | ||||
|       fn = 'hide'; | ||||
|     } else if (!hidden && show) { | ||||
|       fn = this.options.showAnimation; | ||||
|       args.push(this.options.showDuration); | ||||
|     } else if (!hidden && !show) { | ||||
|       fn = this.options.hideAnimation; | ||||
|       args.push(this.options.hideDuration); | ||||
|     } else { | ||||
|       return callback(); | ||||
|     } | ||||
|     args.push(callback); | ||||
|     return elems[fn].apply(elems, args); | ||||
|   }; | ||||
|  | ||||
|   Notification.prototype.setGlobalPosition = function() { | ||||
|     var align, anchor, css, key, main, pAlign, pMain, position; | ||||
|     position = this.getPosition(); | ||||
|     pMain = position[0], pAlign = position[1]; | ||||
|     main = positions[pMain]; | ||||
|     align = positions[pAlign]; | ||||
|     key = pMain + "|" + pAlign; | ||||
|     anchor = globalAnchors[key]; | ||||
|     if (!anchor) { | ||||
|       anchor = globalAnchors[key] = createElem("div"); | ||||
|       css = {}; | ||||
|       css[main] = 0; | ||||
|       if (align === 'middle') { | ||||
|         css.top = '45%'; | ||||
|       } else if (align === 'center') { | ||||
|         css.left = '45%'; | ||||
|       } else { | ||||
|         css[align] = 0; | ||||
|       } | ||||
|       anchor.css(css).addClass("" + pluginClassName + "-corner"); | ||||
|       $("body").append(anchor); | ||||
|     } | ||||
|     return anchor.prepend(this.wrapper); | ||||
|   }; | ||||
|  | ||||
|   Notification.prototype.setElementPosition = function() { | ||||
|     var arrowColor, arrowCss, arrowSize, color, contH, contW, css, elemH, elemIH, elemIW, elemPos, elemW, gap, mainFull, margin, opp, oppFull, pAlign, pArrow, pMain, pos, posFull, position, wrapPos, _i, _j, _len, _len1, _ref; | ||||
|     position = this.getPosition(); | ||||
|     pMain = position[0], pAlign = position[1], pArrow = position[2]; | ||||
|     elemPos = this.elem.position(); | ||||
|     elemH = this.elem.outerHeight(); | ||||
|     elemW = this.elem.outerWidth(); | ||||
|     elemIH = this.elem.innerHeight(); | ||||
|     elemIW = this.elem.innerWidth(); | ||||
|     wrapPos = this.wrapper.position(); | ||||
|     contH = this.container.height(); | ||||
|     contW = this.container.width(); | ||||
|     mainFull = positions[pMain]; | ||||
|     opp = opposites[pMain]; | ||||
|     oppFull = positions[opp]; | ||||
|     css = {}; | ||||
|     css[oppFull] = pMain === 'b' ? elemH : pMain === 'r' ? elemW : 0; | ||||
|     incr(css, 'top', elemPos.top - wrapPos.top); | ||||
|     incr(css, 'left', elemPos.left - wrapPos.left); | ||||
|     _ref = ['top', 'left']; | ||||
|     for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||||
|       pos = _ref[_i]; | ||||
|       margin = parseInt(this.elem.css("margin-" + pos), 10); | ||||
|       if (margin) { | ||||
|         incr(css, pos, margin); | ||||
|       } | ||||
|     } | ||||
|     gap = Math.max(0, this.options.gap - (this.options.arrowShow ? arrowSize : 0)); | ||||
|     incr(css, oppFull, gap); | ||||
|     if (!this.options.arrowShow) { | ||||
|       this.arrow.hide(); | ||||
|     } else { | ||||
|       arrowSize = this.options.arrowSize; | ||||
|       arrowCss = $.extend({}, css); | ||||
|       arrowColor = this.userContainer.css("border-color") || this.userContainer.css("background-color") || 'white'; | ||||
|       for (_j = 0, _len1 = mainPositions.length; _j < _len1; _j++) { | ||||
|         pos = mainPositions[_j]; | ||||
|         posFull = positions[pos]; | ||||
|         if (pos === opp) { | ||||
|           continue; | ||||
|         } | ||||
|         color = posFull === mainFull ? arrowColor : 'transparent'; | ||||
|         arrowCss["border-" + posFull] = "" + arrowSize + "px solid " + color; | ||||
|       } | ||||
|       incr(css, positions[opp], arrowSize); | ||||
|       if (__indexOf.call(mainPositions, pAlign) >= 0) { | ||||
|         incr(arrowCss, positions[pAlign], arrowSize * 2); | ||||
|       } | ||||
|     } | ||||
|     if (__indexOf.call(vAligns, pMain) >= 0) { | ||||
|       incr(css, 'left', realign(pAlign, contW, elemW)); | ||||
|       if (arrowCss) { | ||||
|         incr(arrowCss, 'left', realign(pAlign, arrowSize, elemIW)); | ||||
|       } | ||||
|     } else if (__indexOf.call(hAligns, pMain) >= 0) { | ||||
|       incr(css, 'top', realign(pAlign, contH, elemH)); | ||||
|       if (arrowCss) { | ||||
|         incr(arrowCss, 'top', realign(pAlign, arrowSize, elemIH)); | ||||
|       } | ||||
|     } | ||||
|     if (this.container.is(":visible")) { | ||||
|       css.display = 'block'; | ||||
|     } | ||||
|     this.container.removeAttr('style').css(css); | ||||
|     if (arrowCss) { | ||||
|       return this.arrow.removeAttr('style').css(arrowCss); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   Notification.prototype.getPosition = function() { | ||||
|     var pos, text, _ref, _ref1, _ref2, _ref3, _ref4, _ref5; | ||||
|     text = this.options.position || (this.elem ? this.options.elementPosition : this.options.globalPosition); | ||||
|     pos = parsePosition(text); | ||||
|     if (pos.length === 0) { | ||||
|       pos[0] = 'b'; | ||||
|     } | ||||
|     if (_ref = pos[0], __indexOf.call(mainPositions, _ref) < 0) { | ||||
|       throw "Must be one of [" + mainPositions + "]"; | ||||
|     } | ||||
|     if (pos.length === 1 || ((_ref1 = pos[0], __indexOf.call(vAligns, _ref1) >= 0) && (_ref2 = pos[1], __indexOf.call(hAligns, _ref2) < 0)) || ((_ref3 = pos[0], __indexOf.call(hAligns, _ref3) >= 0) && (_ref4 = pos[1], __indexOf.call(vAligns, _ref4) < 0))) { | ||||
|       pos[1] = (_ref5 = pos[0], __indexOf.call(hAligns, _ref5) >= 0) ? 'm' : 'l'; | ||||
|     } | ||||
|     if (pos.length === 2) { | ||||
|       pos[2] = pos[1]; | ||||
|     } | ||||
|     return pos; | ||||
|   }; | ||||
|  | ||||
|   Notification.prototype.getStyle = function(name) { | ||||
|     var style; | ||||
|     if (!name) { | ||||
|       name = this.options.style; | ||||
|     } | ||||
|     if (!name) { | ||||
|       name = 'default'; | ||||
|     } | ||||
|     style = styles[name]; | ||||
|     if (!style) { | ||||
|       throw "Missing style: " + name; | ||||
|     } | ||||
|     return style; | ||||
|   }; | ||||
|  | ||||
|   Notification.prototype.updateClasses = function() { | ||||
|     var classes, style; | ||||
|     classes = ['base']; | ||||
|     if ($.isArray(this.options.className)) { | ||||
|       classes = classes.concat(this.options.className); | ||||
|     } else if (this.options.className) { | ||||
|       classes.push(this.options.className); | ||||
|     } | ||||
|     style = this.getStyle(); | ||||
|     classes = $.map(classes, function(n) { | ||||
|       return "" + pluginClassName + "-" + style.name + "-" + n; | ||||
|     }).join(' '); | ||||
|     return this.userContainer.attr('class', classes); | ||||
|   }; | ||||
|  | ||||
|   Notification.prototype.run = function(data, options) { | ||||
|     var d, datas, name, type, value, | ||||
|       _this = this; | ||||
|     if ($.isPlainObject(options)) { | ||||
|       $.extend(this.options, options); | ||||
|     } else if ($.type(options) === 'string') { | ||||
|       this.options.color = options; | ||||
|     } | ||||
|     if (this.container && !data) { | ||||
|       this.show(false); | ||||
|       return; | ||||
|     } else if (!this.container && !data) { | ||||
|       return; | ||||
|     } | ||||
|     datas = {}; | ||||
|     if ($.isPlainObject(data)) { | ||||
|       datas = data; | ||||
|     } else { | ||||
|       datas[blankFieldName] = data; | ||||
|     } | ||||
|     for (name in datas) { | ||||
|       d = datas[name]; | ||||
|       type = this.userFields[name]; | ||||
|       if (!type) { | ||||
|         continue; | ||||
|       } | ||||
|       if (type === 'text') { | ||||
|         d = encode(d); | ||||
|         if (this.options.breakNewLines) { | ||||
|           d = d.replace(/\n/g, '<br/>'); | ||||
|         } | ||||
|       } | ||||
|       value = name === blankFieldName ? '' : '=' + name; | ||||
|       find(this.userContainer, "[data-notify-" + type + value + "]").html(d); | ||||
|     } | ||||
|     this.updateClasses(); | ||||
|     if (this.elem) { | ||||
|       this.setElementPosition(); | ||||
|     } else { | ||||
|       this.setGlobalPosition(); | ||||
|     } | ||||
|     this.show(true); | ||||
|     if (this.options.autoHide) { | ||||
|       clearTimeout(this.autohideTimer); | ||||
|       return this.autohideTimer = setTimeout(function() { | ||||
|         return _this.show(false); | ||||
|       }, this.options.autoHideDelay); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   Notification.prototype.destroy = function() { | ||||
|     return this.wrapper.remove(); | ||||
|   }; | ||||
|  | ||||
|   return Notification; | ||||
|  | ||||
| })(); | ||||
|  | ||||
| $[pluginName] = function(elem, data, options) { | ||||
|   if ((elem && elem.nodeName) || elem.jquery) { | ||||
|     $(elem)[pluginName](data, options); | ||||
|   } else { | ||||
|     options = data; | ||||
|     data = elem; | ||||
|     new Notification(null, data, options); | ||||
|   } | ||||
|   return elem; | ||||
| }; | ||||
|  | ||||
| $.fn[pluginName] = function(data, options) { | ||||
|   $(this).each(function() { | ||||
|     var inst; | ||||
|     inst = getAnchorElement($(this)).data(pluginClassName); | ||||
|     if (inst) { | ||||
|       return inst.run(data, options); | ||||
|     } else { | ||||
|       return new Notification($(this), data, options); | ||||
|     } | ||||
|   }); | ||||
|   return this; | ||||
| }; | ||||
|  | ||||
| $.extend($[pluginName], { | ||||
|   defaults: defaults, | ||||
|   addStyle: addStyle, | ||||
|   pluginOptions: pluginOptions, | ||||
|   getStyle: getStyle, | ||||
|   insertCSS: insertCSS | ||||
| }); | ||||
|  | ||||
| $(function() { | ||||
|   insertCSS(coreStyle.css).attr('id', 'core-notify'); | ||||
|   return $(document).on('click notify-hide', "." + pluginClassName + "-wrapper", function(e) { | ||||
|     var inst; | ||||
|     inst = $(this).data(pluginClassName); | ||||
|     if (inst && (inst.options.clickToHide || e.type === 'notify-hide')) { | ||||
|       return inst.show(false); | ||||
|     } | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| }(window,document,jQuery)); | ||||
|  | ||||
| $.notify.addStyle("bootstrap", { | ||||
|   html: "<div>\n<span data-notify-text></span>\n</div>", | ||||
|   classes: { | ||||
|     base: { | ||||
|       "font-weight": "bold", | ||||
|       "padding": "8px 15px 8px 14px", | ||||
|       "text-shadow": "0 1px 0 rgba(255, 255, 255, 0.5)", | ||||
|       "background-color": "#fcf8e3", | ||||
|       "border": "1px solid #fbeed5", | ||||
|       "border-radius": "4px", | ||||
|       "white-space": "nowrap", | ||||
|       "padding-left": "25px", | ||||
|     }, | ||||
|     error: { | ||||
|       "color": "#B94A48", | ||||
|       "background-color": "#F2DEDE", | ||||
|       "border-color": "#EED3D7", | ||||
|     }, | ||||
|     success: { | ||||
|       "color": "#468847", | ||||
|       "background-color": "#DFF0D8", | ||||
|       "border-color": "#D6E9C6", | ||||
|     }, | ||||
|     info: { | ||||
|       "color": "#3A87AD", | ||||
|       "background-color": "#D9EDF7", | ||||
|       "border-color": "#BCE8F1", | ||||
|     }, | ||||
|     warn: { | ||||
|       "color": "#C09853", | ||||
|       "background-color": "#FCF8E3", | ||||
|       "border-color": "#FBEED5", | ||||
|     } | ||||
|   } | ||||
| }); | ||||
							
								
								
									
										485
									
								
								htdocs/js/bootstrap-slider.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										485
									
								
								htdocs/js/bootstrap-slider.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,388 +1,139 @@ | ||||
| /* ========================================================= | ||||
|  * bootstrap-slider.js v2.0.0 | ||||
|  * http://www.eyecon.ro/bootstrap-slider | ||||
|  * ========================================================= | ||||
|  * Copyright 2012 Stefan Petre | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  * ========================================================= */ | ||||
| (function($){ | ||||
|  | ||||
| !function( $ ) { | ||||
|  | ||||
| 	var Slider = function(element, options) { | ||||
| 		this.element = $(element); | ||||
| 		this.picker = $('<div class="slider">'+ | ||||
| 							'<div class="slider-track">'+ | ||||
| 								'<div class="slider-selection"></div>'+ | ||||
| 								'<div class="slider-handle"></div>'+ | ||||
| 								'<div class="slider-handle"></div>'+ | ||||
| 							'</div>'+ | ||||
| 							'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'+ | ||||
| 						'</div>') | ||||
| 							.insertBefore(this.element) | ||||
| 							.append(this.element); | ||||
| 		this.id = this.element.data('slider-id')||options.id; | ||||
| 		if (this.id) { | ||||
| 			this.picker[0].id = this.id; | ||||
| 		} | ||||
|  | ||||
| 		if (typeof Modernizr !== 'undefined' && Modernizr.touch) { | ||||
| 			this.touchCapable = true; | ||||
| 		} | ||||
|  | ||||
| 		var tooltip = this.element.data('slider-tooltip')||options.tooltip; | ||||
|  | ||||
| 		this.tooltip = this.picker.find('.tooltip'); | ||||
| 		this.tooltipInner = this.tooltip.find('div.tooltip-inner'); | ||||
|  | ||||
| 		this.orientation = this.element.data('slider-orientation')||options.orientation; | ||||
| 		switch(this.orientation) { | ||||
| 			case 'vertical': | ||||
| 				this.picker.addClass('slider-vertical'); | ||||
| 				this.stylePos = 'top'; | ||||
| 				this.mousePos = 'pageY'; | ||||
| 				this.sizePos = 'offsetHeight'; | ||||
| 				this.tooltip.addClass('right')[0].style.left = '100%'; | ||||
| 				break; | ||||
| 			default: | ||||
| 				this.picker | ||||
| 					.addClass('slider-horizontal') | ||||
| 					.css('width', this.element.outerWidth()); | ||||
| 				this.orientation = 'horizontal'; | ||||
| 				this.stylePos = 'left'; | ||||
| 				this.mousePos = 'pageX'; | ||||
| 				this.sizePos = 'offsetWidth'; | ||||
| 				this.tooltip.addClass('top')[0].style.top = -this.tooltip.outerHeight() - 14 + 'px'; | ||||
| 				break; | ||||
| 		} | ||||
|  | ||||
| 		this.min = this.element.data('slider-min')||options.min; | ||||
| 		this.max = this.element.data('slider-max')||options.max; | ||||
| 		this.step = this.element.data('slider-step')||options.step; | ||||
| 		this.value = this.element.data('slider-value')||options.value; | ||||
| 		if (this.value[1]) { | ||||
| 			this.range = true; | ||||
| 		} | ||||
|  | ||||
| 		this.selection = this.element.data('slider-selection')||options.selection; | ||||
| 		this.selectionEl = this.picker.find('.slider-selection'); | ||||
| 		if (this.selection === 'none') { | ||||
| 			this.selectionEl.addClass('hide'); | ||||
| 		} | ||||
| 		this.selectionElStyle = this.selectionEl[0].style; | ||||
|  | ||||
|  | ||||
| 		this.handle1 = this.picker.find('.slider-handle:first'); | ||||
| 		this.handle1Stype = this.handle1[0].style; | ||||
| 		this.handle2 = this.picker.find('.slider-handle:last'); | ||||
| 		this.handle2Stype = this.handle2[0].style; | ||||
|  | ||||
| 		var handle = this.element.data('slider-handle')||options.handle; | ||||
| 		switch(handle) { | ||||
| 			case 'round': | ||||
| 				this.handle1.addClass('round'); | ||||
| 				this.handle2.addClass('round'); | ||||
| 				break | ||||
| 			case 'triangle': | ||||
| 				this.handle1.addClass('triangle'); | ||||
| 				this.handle2.addClass('triangle'); | ||||
| 				break | ||||
| 		} | ||||
|  | ||||
| 		if (this.range) { | ||||
| 			this.value[0] = Math.max(this.min, Math.min(this.max, this.value[0])); | ||||
| 			this.value[1] = Math.max(this.min, Math.min(this.max, this.value[1])); | ||||
| 		} else { | ||||
| 			this.value = [ Math.max(this.min, Math.min(this.max, this.value))]; | ||||
| 			this.handle2.addClass('hide'); | ||||
| 			if (this.selection == 'after') { | ||||
| 				this.value[1] = this.max; | ||||
| 			} else { | ||||
| 				this.value[1] = this.min; | ||||
| 			} | ||||
| 		} | ||||
| 		this.diff = this.max - this.min; | ||||
| 		this.percentage = [ | ||||
| 			(this.value[0]-this.min)*100/this.diff, | ||||
| 			(this.value[1]-this.min)*100/this.diff, | ||||
| 			this.step*100/this.diff | ||||
| 		]; | ||||
|  | ||||
| 		this.offset = this.picker.offset(); | ||||
| 		this.size = this.picker[0][this.sizePos]; | ||||
|  | ||||
| 		this.formater = options.formater; | ||||
|  | ||||
| 		this.layout(); | ||||
|  | ||||
| 		if (this.touchCapable) { | ||||
| 			// Touch: Bind touch events: | ||||
| 			this.picker.on({ | ||||
| 				touchstart: $.proxy(this.mousedown, this) | ||||
| 			}); | ||||
| 		} else { | ||||
| 			this.picker.on({ | ||||
| 				mousedown: $.proxy(this.mousedown, this) | ||||
| 			}); | ||||
| 		} | ||||
|  | ||||
| 		if (tooltip === 'show') { | ||||
| 			this.picker.on({ | ||||
| 				mouseenter: $.proxy(this.showTooltip, this), | ||||
| 				mouseleave: $.proxy(this.hideTooltip, this) | ||||
| 			}); | ||||
| 		} else { | ||||
| 			this.tooltip.addClass('hide'); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	Slider.prototype = { | ||||
| 		constructor: Slider, | ||||
|  | ||||
| 		over: false, | ||||
| 		inDrag: false, | ||||
| 		 | ||||
| 		showTooltip: function(){ | ||||
| 			this.tooltip.addClass('in'); | ||||
| 			//var left = Math.round(this.percent*this.width); | ||||
| 			//this.tooltip.css('left', left - this.tooltip.outerWidth()/2); | ||||
| 			this.over = true; | ||||
|     function slider(options){ | ||||
|         if(typeof options === 'number'){ | ||||
|             options = $.extend( | ||||
|                 { | ||||
|                     origVal:options | ||||
|                 }, | ||||
| 		 | ||||
| 		hideTooltip: function(){ | ||||
| 			if (this.inDrag === false) { | ||||
| 				this.tooltip.removeClass('in'); | ||||
|                 defaults, | ||||
|                 { | ||||
|                     val:(( options < 0 ) ? 0 : ( (options > 100 ) ? 100 : options)) | ||||
|                 } | ||||
| 			this.over = false; | ||||
| 		}, | ||||
|  | ||||
| 		layout: function(){ | ||||
| 			this.handle1Stype[this.stylePos] = this.percentage[0]+'%'; | ||||
| 			this.handle2Stype[this.stylePos] = this.percentage[1]+'%'; | ||||
| 			if (this.orientation == 'vertical') { | ||||
| 				this.selectionElStyle.top = Math.min(this.percentage[0], this.percentage[1]) +'%'; | ||||
| 				this.selectionElStyle.height = Math.abs(this.percentage[0] - this.percentage[1]) +'%'; | ||||
| 			} else { | ||||
| 				this.selectionElStyle.left = Math.min(this.percentage[0], this.percentage[1]) +'%'; | ||||
| 				this.selectionElStyle.width = Math.abs(this.percentage[0] - this.percentage[1]) +'%'; | ||||
| 			} | ||||
| 			if (this.range) { | ||||
| 				this.tooltipInner.text( | ||||
| 					this.formater(this.value[0]) +  | ||||
| 					' : ' +  | ||||
| 					this.formater(this.value[1]) | ||||
|             ); | ||||
| 				this.tooltip[0].style[this.stylePos] = this.size * (this.percentage[0] + (this.percentage[1] - this.percentage[0])/2)/100 - (this.orientation === 'vertical' ? this.tooltip.outerHeight()/2 : this.tooltip.outerWidth()/2) +'px'; | ||||
| 			} else { | ||||
| 				this.tooltipInner.text( | ||||
| 					this.formater(this.value[0]) | ||||
| 				); | ||||
| 				this.tooltip[0].style[this.stylePos] = this.size * this.percentage[0]/100 - (this.orientation === 'vertical' ? this.tooltip.outerHeight()/2 : this.tooltip.outerWidth()/2) +'px'; | ||||
|         } | ||||
|         else if (options === "get"){ | ||||
|             var vals = []; | ||||
|  | ||||
|             $(this).each(function() { | ||||
|                 vals.push($(this).data("sliderValue")); | ||||
|             }); | ||||
|             return vals; | ||||
|         } | ||||
|         else if(typeof options === 'object'){ | ||||
|             options = $.extend({origVal:options.val,origBarColor:options.barColor},defaults,options); | ||||
|         } | ||||
|  | ||||
|         return $(this).each (function() { | ||||
|             var self=$(this); | ||||
|  | ||||
|             if(self.hasClass("slider-wrapper-jq")){ | ||||
|                 if(self.data("dragSlider") === "true") | ||||
|                     return; | ||||
|                 if(typeof options.origVal !== "undefined") | ||||
|                     self.slider._setValue.call(self,options.val,null,true); | ||||
|                 if(typeof options.origBarColor !== "undefined") | ||||
|                     self.find('.progress-bar').css("background-color",options.barColor); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             self.addClass("slider-wrapper-jq") | ||||
|             .append($("<div class='progress' style='position:relative;left:0'/>") | ||||
|             .append("<div class='progress-bar' style='position:width: 30%;background-color: "+ | ||||
|             options.barColor+"; -webkit-transition:none; transition:none;' />") | ||||
|             .append("<div class='btn btn-default ' style='position:absolute;height:100%;padding:6px 10px;margin-left:-10px;vertical-align: top'>")); | ||||
|  | ||||
|             self.find('.progress').on('mousedown', function(evt){ | ||||
|                 self.data("dragSlider","true") | ||||
|                 .data("startPoint",evt.pageX) | ||||
|                 .data("endPoint",evt.pageX); | ||||
|  | ||||
|                 if(!$(evt.target).hasClass("btn")){ | ||||
|                     self.slider._setWidthFromEvent.call(self,evt.pageX,null,true); | ||||
|                 } | ||||
|                 else{ | ||||
|                     self.data("btnTarget","true"); | ||||
|                 } | ||||
|  | ||||
|                 evt.preventDefault(); | ||||
|                 evt.stopPropagation(); | ||||
|             }); | ||||
|  | ||||
|             $(window).on('mouseup', function(evt){ | ||||
|                 if(self.data("dragSlider")==="true"){ | ||||
|                     if(!(self.data("btnTarget") === "true" && self.data("startPoint") === self.data("endPoint") )){ | ||||
|                         self.slider._setWidthFromEvent.call(self,evt.pageX); | ||||
|                     } | ||||
|  | ||||
|                     self.removeData("dragSlider") | ||||
|                     .removeData("btnTarget") | ||||
|                     .removeData("startPoint") | ||||
|                     .removeData("endPoint"); | ||||
|                 } | ||||
|             }).on('mousemove',function(evt){ | ||||
|                 if(self.data("dragSlider")==="true"){ | ||||
|                     self.slider._setWidthFromEvent.call(self,evt.pageX,null,true); | ||||
|                     self.data("endPoint",evt.pageX); | ||||
|                     evt.preventDefault(); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             self.slider._setValue.call(self,options.val); | ||||
|         }); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     var defaults={ | ||||
|         val:50, | ||||
|         barColor:"#428bca" | ||||
|     }, | ||||
|  | ||||
| 		mousedown: function(ev) { | ||||
|  | ||||
| 			// Touch: Get the original event: | ||||
| 			if (this.touchCapable && ev.type === 'touchstart') { | ||||
| 				ev = ev.originalEvent; | ||||
|     _setWidthFromEvent = function(pageX,reqVals,supress) { | ||||
|         if(!reqVals){ | ||||
|            reqVals =  this.slider._getRequiredValues.call(this); | ||||
|         } | ||||
|         else{ | ||||
|             reqVals = null; | ||||
|         } | ||||
|  | ||||
| 			this.offset = this.picker.offset(); | ||||
| 			this.size = this.picker[0][this.sizePos]; | ||||
|         var width = pageX - reqVals.pbar.offset().left, | ||||
|             perc = ((100.0*width) / (reqVals.progw)); | ||||
|  | ||||
| 			var percentage = this.getPercentage(ev); | ||||
|  | ||||
| 			if (this.range) { | ||||
| 				var diff1 = Math.abs(this.percentage[0] - percentage); | ||||
| 				var diff2 = Math.abs(this.percentage[1] - percentage); | ||||
| 				this.dragged = (diff1 < diff2) ? 0 : 1; | ||||
| 			} else { | ||||
| 				this.dragged = 0; | ||||
| 			} | ||||
|  | ||||
| 			this.percentage[this.dragged] = percentage; | ||||
| 			this.layout(); | ||||
|  | ||||
| 			if (this.touchCapable) { | ||||
| 				// Touch: Bind touch events: | ||||
| 				$(document).on({ | ||||
| 					touchmove: $.proxy(this.mousemove, this), | ||||
| 					touchend: $.proxy(this.mouseup, this) | ||||
| 				}); | ||||
| 			} else { | ||||
| 				$(document).on({ | ||||
| 					mousemove: $.proxy(this.mousemove, this), | ||||
| 					mouseup: $.proxy(this.mouseup, this) | ||||
| 				}); | ||||
| 			} | ||||
|  | ||||
| 			this.inDrag = true; | ||||
| 			var val = this.calculateValue(); | ||||
| 			this.element.trigger({ | ||||
| 					type: 'slideStart', | ||||
| 					value: val | ||||
| 				}).trigger({ | ||||
| 					type: 'slide', | ||||
| 					value: val | ||||
| 				}); | ||||
| 			return false; | ||||
|         return this.slider._setValue.call(this,perc,reqVals,supress); | ||||
|     }, | ||||
|  | ||||
| 		mousemove: function(ev) { | ||||
| 			 | ||||
| 			// Touch: Get the original event: | ||||
| 			if (this.touchCapable && ev.type === 'touchmove') { | ||||
| 				ev = ev.originalEvent; | ||||
|      _setValue = function (val,reqVals,supress) { | ||||
|         if(!reqVals){ | ||||
|            reqVals =  this.slider._getRequiredValues.call(this); | ||||
|         } | ||||
|  | ||||
| 			var percentage = this.getPercentage(ev); | ||||
| 			if (this.range) { | ||||
| 				if (this.dragged === 0 && this.percentage[1] < percentage) { | ||||
| 					this.percentage[0] = this.percentage[1]; | ||||
| 					this.dragged = 1; | ||||
| 				} else if (this.dragged === 1 && this.percentage[0] > percentage) { | ||||
| 					this.percentage[1] = this.percentage[0]; | ||||
| 					this.dragged = 0; | ||||
| 				} | ||||
| 			} | ||||
| 			this.percentage[this.dragged] = percentage; | ||||
| 			this.layout(); | ||||
| 			var val = this.calculateValue(); | ||||
| 			this.element | ||||
| 				.trigger({ | ||||
| 					type: 'slide', | ||||
| 					value: val | ||||
| 				}) | ||||
| 				.data('value', val) | ||||
| 				.prop('value', val); | ||||
| 			return false; | ||||
| 		}, | ||||
|         val = ((val<0)?0:((val>100)?100:val)); | ||||
|         var adjVal= ((val*(100-reqVals.pbutp)/100) + (reqVals.pbutp/2)); | ||||
|  | ||||
| 		mouseup: function(ev) { | ||||
| 			if (this.touchCapable) { | ||||
| 				// Touch: Bind touch events: | ||||
| 				$(document).off({ | ||||
| 					touchmove: this.mousemove, | ||||
| 					touchend: this.mouseup | ||||
| 				}); | ||||
| 			} else { | ||||
| 				$(document).off({ | ||||
| 					mousemove: this.mousemove, | ||||
| 					mouseup: this.mouseup | ||||
| 				}); | ||||
|         this.data("sliderValue",val); | ||||
|         reqVals.pbar.css({width:adjVal+"%"}); | ||||
|         this.find('div.btn').css('left',adjVal+"%"); | ||||
|  | ||||
|         if(supress !== true){ | ||||
|             this.trigger("slider.newValue",{val:Math.round(val)}); | ||||
|         } | ||||
|  | ||||
| 			this.inDrag = false; | ||||
| 			if (this.over == false) { | ||||
| 				this.hideTooltip(); | ||||
| 			} | ||||
| 			this.element; | ||||
| 			var val = this.calculateValue(); | ||||
| 			this.element | ||||
| 				.trigger({ | ||||
| 					type: 'slideStop', | ||||
| 					value: val | ||||
| 				}) | ||||
| 				.data('value', val) | ||||
| 				.prop('value', val); | ||||
| 			return false; | ||||
| 		}, | ||||
|  | ||||
| 		calculateValue: function() { | ||||
| 			var val; | ||||
| 			if (this.range) { | ||||
| 				val = [ | ||||
| 					(this.min + Math.round((this.diff * this.percentage[0]/100)/this.step)*this.step), | ||||
| 					(this.min + Math.round((this.diff * this.percentage[1]/100)/this.step)*this.step) | ||||
| 				]; | ||||
| 				this.value = val; | ||||
| 			} else { | ||||
| 				val = (this.min + Math.round((this.diff * this.percentage[0]/100)/this.step)*this.step); | ||||
| 				this.value = [val, this.value[1]]; | ||||
| 			} | ||||
|         return val; | ||||
|     }, | ||||
|     _getRequiredValues = function(){ | ||||
|         var pbar=this.find('.progress-bar'), | ||||
|             progw=this.children('.progress').get(0).clientWidth, | ||||
|             pbutp=((this.find('div.btn').get(0).clientWidth*100.0)/progw); | ||||
|  | ||||
| 		getPercentage: function(ev) { | ||||
| 			if (this.touchCapable) { | ||||
| 				ev = ev.touches[0]; | ||||
| 			} | ||||
| 			var percentage = (ev[this.mousePos] - this.offset[this.stylePos])*100/this.size; | ||||
| 			percentage = Math.round(percentage/this.percentage[2])*this.percentage[2]; | ||||
| 			return Math.max(0, Math.min(100, percentage)); | ||||
| 		}, | ||||
|  | ||||
| 		getValue: function() { | ||||
| 			if (this.range) { | ||||
| 				return this.value; | ||||
| 			} | ||||
| 			return this.value[0]; | ||||
| 		}, | ||||
|  | ||||
| 		setValue: function(val) { | ||||
| 			this.value = val; | ||||
|  | ||||
| 			if (this.range) { | ||||
| 				this.value[0] = Math.max(this.min, Math.min(this.max, this.value[0])); | ||||
| 				this.value[1] = Math.max(this.min, Math.min(this.max, this.value[1])); | ||||
| 			} else { | ||||
| 				this.value = [ Math.max(this.min, Math.min(this.max, this.value))]; | ||||
| 				this.handle2.addClass('hide'); | ||||
| 				if (this.selection == 'after') { | ||||
| 					this.value[1] = this.max; | ||||
| 				} else { | ||||
| 					this.value[1] = this.min; | ||||
| 				} | ||||
| 			} | ||||
| 			this.diff = this.max - this.min; | ||||
| 			this.percentage = [ | ||||
| 				(this.value[0]-this.min)*100/this.diff, | ||||
| 				(this.value[1]-this.min)*100/this.diff, | ||||
| 				this.step*100/this.diff | ||||
| 			]; | ||||
| 			this.layout(); | ||||
| 		} | ||||
|         return { | ||||
|             pbar:pbar, | ||||
|             progw:progw, | ||||
|             pbutp:pbutp | ||||
|         }; | ||||
|     }; | ||||
|  | ||||
| 	$.fn.slider = function ( option, val ) { | ||||
| 		return this.each(function () { | ||||
| 			var $this = $(this), | ||||
| 				data = $this.data('slider'), | ||||
| 				options = typeof option === 'object' && option; | ||||
| 			if (!data)  { | ||||
| 				$this.data('slider', (data = new Slider(this, $.extend({}, $.fn.slider.defaults,options)))); | ||||
| 			} | ||||
| 			if (typeof option == 'string') { | ||||
| 				data[option](val); | ||||
| 			} | ||||
| 		}) | ||||
| 	}; | ||||
|     $.fn.slider = slider; | ||||
|     $.fn.slider.defaults = defaults; | ||||
|     $.fn.slider._getRequiredValues = _getRequiredValues ; | ||||
|     $.fn.slider._setWidthFromEvent = _setWidthFromEvent; | ||||
|     $.fn.slider._setValue = _setValue; | ||||
|  | ||||
| 	$.fn.slider.defaults = { | ||||
| 		min: 0, | ||||
| 		max: 10, | ||||
| 		step: 1, | ||||
| 		orientation: 'horizontal', | ||||
| 		value: 5, | ||||
| 		selection: 'before', | ||||
| 		tooltip: 'show', | ||||
| 		handle: 'round', | ||||
| 		formater: function(value) { | ||||
| 			return value; | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	$.fn.slider.Constructor = Slider; | ||||
|  | ||||
| }( window.jQuery ); | ||||
| })(jQuery); | ||||
|   | ||||
| @@ -1,268 +0,0 @@ | ||||
| /** | ||||
| * simplePagination.js v1.6 | ||||
| * A simple jQuery pagination plugin. | ||||
| * http://flaviusmatis.github.com/simplePagination.js/ | ||||
| * | ||||
| * Copyright 2012, Flavius Matis | ||||
| * Released under the MIT license. | ||||
| * http://flaviusmatis.github.com/license.html | ||||
| */ | ||||
|  | ||||
| (function($){ | ||||
|  | ||||
| 	var methods = { | ||||
| 		init: function(options) { | ||||
| 			var o = $.extend({ | ||||
| 				items: 1, | ||||
| 				itemsOnPage: 1, | ||||
| 				pages: 0, | ||||
| 				displayedPages: 5, | ||||
| 				edges: 2, | ||||
| 				currentPage: 1, | ||||
| 				hrefTextPrefix: '#page-', | ||||
| 				hrefTextSuffix: '', | ||||
| 				prevText: 'Prev', | ||||
| 				nextText: 'Next', | ||||
| 				ellipseText: '…', | ||||
| 				cssStyle: 'light-theme', | ||||
| 				labelMap: [], | ||||
| 				selectOnClick: true, | ||||
| 				onPageClick: function(pageNumber, event) { | ||||
| 					// Callback triggered when a page is clicked | ||||
| 					// Page number is given as an optional parameter | ||||
| 				}, | ||||
| 				onInit: function() { | ||||
| 					// Callback triggered immediately after initialization | ||||
| 				} | ||||
| 			}, options || {}); | ||||
|  | ||||
| 			var self = this; | ||||
|  | ||||
| 			o.pages = o.pages ? o.pages : Math.ceil(o.items / o.itemsOnPage) ? Math.ceil(o.items / o.itemsOnPage) : 1; | ||||
| 			o.currentPage = o.currentPage - 1; | ||||
| 			o.halfDisplayed = o.displayedPages / 2; | ||||
|  | ||||
| 			this.each(function() { | ||||
| 				self.addClass(o.cssStyle + ' simple-pagination').data('pagination', o); | ||||
| 				methods._draw.call(self); | ||||
| 			}); | ||||
|  | ||||
| 			o.onInit(); | ||||
|  | ||||
| 			return this; | ||||
| 		}, | ||||
|  | ||||
| 		selectPage: function(page) { | ||||
| 			methods._selectPage.call(this, page - 1); | ||||
| 			return this; | ||||
| 		}, | ||||
|  | ||||
| 		prevPage: function() { | ||||
| 			var o = this.data('pagination'); | ||||
| 			if (o.currentPage > 0) { | ||||
| 				methods._selectPage.call(this, o.currentPage - 1); | ||||
| 			} | ||||
| 			return this; | ||||
| 		}, | ||||
|  | ||||
| 		nextPage: function() { | ||||
| 			var o = this.data('pagination'); | ||||
| 			if (o.currentPage < o.pages - 1) { | ||||
| 				methods._selectPage.call(this, o.currentPage + 1); | ||||
| 			} | ||||
| 			return this; | ||||
| 		}, | ||||
|  | ||||
| 		getPagesCount: function() { | ||||
| 			return this.data('pagination').pages; | ||||
| 		}, | ||||
|  | ||||
| 		getCurrentPage: function () { | ||||
| 			return this.data('pagination').currentPage + 1; | ||||
| 		}, | ||||
|  | ||||
| 		destroy: function(){ | ||||
| 			this.empty(); | ||||
| 			return this; | ||||
| 		}, | ||||
|  | ||||
| 		drawPage: function (page) { | ||||
| 			var o = this.data('pagination'); | ||||
| 			o.currentPage = page - 1; | ||||
| 			this.data('pagination', o); | ||||
| 			methods._draw.call(this); | ||||
| 			return this; | ||||
| 		}, | ||||
|  | ||||
| 		redraw: function(){ | ||||
| 			methods._draw.call(this); | ||||
| 			return this; | ||||
| 		}, | ||||
|  | ||||
| 		disable: function(){ | ||||
| 			var o = this.data('pagination'); | ||||
| 			o.disabled = true; | ||||
| 			this.data('pagination', o); | ||||
| 			methods._draw.call(this); | ||||
| 			return this; | ||||
| 		}, | ||||
|  | ||||
| 		enable: function(){ | ||||
| 			var o = this.data('pagination'); | ||||
| 			o.disabled = false; | ||||
| 			this.data('pagination', o); | ||||
| 			methods._draw.call(this); | ||||
| 			return this; | ||||
| 		}, | ||||
|  | ||||
| 		updateItems: function (newItems) { | ||||
| 			var o = this.data('pagination'); | ||||
| 			o.items = newItems; | ||||
| 			o.pages = methods._getPages(o); | ||||
| 			this.data('pagination', o); | ||||
| 			methods._draw.call(this); | ||||
| 		}, | ||||
|  | ||||
| 		updateItemsOnPage: function (itemsOnPage) { | ||||
| 			var o = this.data('pagination'); | ||||
| 			o.itemsOnPage = itemsOnPage; | ||||
| 			o.pages = methods._getPages(o); | ||||
| 			this.data('pagination', o); | ||||
| 			methods._selectPage.call(this, 0); | ||||
| 			return this; | ||||
| 		}, | ||||
|  | ||||
| 		_draw: function() { | ||||
| 			var	o = this.data('pagination'), | ||||
| 				interval = methods._getInterval(o), | ||||
| 				i, | ||||
| 				tagName; | ||||
|  | ||||
| 			methods.destroy.call(this); | ||||
| 			 | ||||
| 			tagName = (typeof this.prop === 'function') ? this.prop('tagName') : this.attr('tagName'); | ||||
|  | ||||
| 			var $panel = tagName === 'UL' ? this : $('<ul></ul>').appendTo(this); | ||||
|  | ||||
| 			// Generate Prev link | ||||
| 			if (o.prevText) { | ||||
| 				methods._appendItem.call(this, o.currentPage - 1, {text: o.prevText, classes: 'prev'}); | ||||
| 			} | ||||
|  | ||||
| 			// Generate start edges | ||||
| 			if (interval.start > 0 && o.edges > 0) { | ||||
| 				var end = Math.min(o.edges, interval.start); | ||||
| 				for (i = 0; i < end; i++) { | ||||
| 					methods._appendItem.call(this, i); | ||||
| 				} | ||||
| 				if (o.edges < interval.start && (interval.start - o.edges != 1)) { | ||||
| 					$panel.append('<li class="disabled"><span class="ellipse">' + o.ellipseText + '</span></li>'); | ||||
| 				} else if (interval.start - o.edges == 1) { | ||||
| 					methods._appendItem.call(this, o.edges); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// Generate interval links | ||||
| 			for (i = interval.start; i < interval.end; i++) { | ||||
| 				methods._appendItem.call(this, i); | ||||
| 			} | ||||
|  | ||||
| 			// Generate end edges | ||||
| 			if (interval.end < o.pages && o.edges > 0) { | ||||
| 				if (o.pages - o.edges > interval.end && (o.pages - o.edges - interval.end != 1)) { | ||||
| 					$panel.append('<li class="disabled"><span class="ellipse">' + o.ellipseText + '</span></li>'); | ||||
| 				} else if (o.pages - o.edges - interval.end == 1) { | ||||
| 					methods._appendItem.call(this, interval.end++); | ||||
| 				} | ||||
| 				var begin = Math.max(o.pages - o.edges, interval.end); | ||||
| 				for (i = begin; i < o.pages; i++) { | ||||
| 					methods._appendItem.call(this, i); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// Generate Next link | ||||
| 			if (o.nextText) { | ||||
| 				methods._appendItem.call(this, o.currentPage + 1, {text: o.nextText, classes: 'next'}); | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| 		_getPages: function(o) { | ||||
| 			var pages = Math.ceil(o.items / o.itemsOnPage); | ||||
| 			return pages || 1; | ||||
| 		}, | ||||
|  | ||||
| 		_getInterval: function(o) { | ||||
| 			return { | ||||
| 				start: Math.ceil(o.currentPage > o.halfDisplayed ? Math.max(Math.min(o.currentPage - o.halfDisplayed, (o.pages - o.displayedPages)), 0) : 0), | ||||
| 				end: Math.ceil(o.currentPage > o.halfDisplayed ? Math.min(o.currentPage + o.halfDisplayed, o.pages) : Math.min(o.displayedPages, o.pages)) | ||||
| 			}; | ||||
| 		}, | ||||
|  | ||||
| 		_appendItem: function(pageIndex, opts) { | ||||
| 			var self = this, options, $link, o = self.data('pagination'), $linkWrapper = $('<li></li>'), $ul = self.find('ul'); | ||||
|  | ||||
| 			pageIndex = pageIndex < 0 ? 0 : (pageIndex < o.pages ? pageIndex : o.pages - 1); | ||||
|  | ||||
| 			options = { | ||||
| 				text: pageIndex + 1, | ||||
| 				classes: '' | ||||
| 			}; | ||||
|  | ||||
| 			if (o.labelMap.length && o.labelMap[pageIndex]) { | ||||
| 				options.text = o.labelMap[pageIndex]; | ||||
| 			} | ||||
|  | ||||
| 			options = $.extend(options, opts || {}); | ||||
|  | ||||
| 			if (pageIndex == o.currentPage || o.disabled) { | ||||
| 				if (o.disabled) { | ||||
| 					$linkWrapper.addClass('disabled'); | ||||
| 				} else { | ||||
| 					$linkWrapper.addClass('active'); | ||||
| 				} | ||||
| 				$link = $('<span class="current">' + (options.text) + '</span>'); | ||||
| 			} else { | ||||
| 				$link = $('<a href="' + o.hrefTextPrefix + (pageIndex + 1) + o.hrefTextSuffix + '" class="page-link">' + (options.text) + '</a>'); | ||||
| 				$link.click(function(event){ | ||||
| 					return methods._selectPage.call(self, pageIndex, event); | ||||
| 				}); | ||||
| 			} | ||||
|  | ||||
| 			if (options.classes) { | ||||
| 				$link.addClass(options.classes); | ||||
| 			} | ||||
|  | ||||
| 			$linkWrapper.append($link); | ||||
|  | ||||
| 			if ($ul.length) { | ||||
| 				$ul.append($linkWrapper); | ||||
| 			} else { | ||||
| 				self.append($linkWrapper); | ||||
| 			} | ||||
| 		}, | ||||
|  | ||||
| 		_selectPage: function(pageIndex, event) { | ||||
| 			var o = this.data('pagination'); | ||||
| 			o.currentPage = pageIndex; | ||||
| 			if (o.selectOnClick) { | ||||
| 				methods._draw.call(this); | ||||
| 			} | ||||
| 			return o.onPageClick(pageIndex + 1, event); | ||||
| 		} | ||||
|  | ||||
| 	}; | ||||
|  | ||||
| 	$.fn.pagination = function(method) { | ||||
|  | ||||
| 		// Method calling logic | ||||
| 		if (methods[method] && method.charAt(0) != '_') { | ||||
| 			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); | ||||
| 		} else if (typeof method === 'object' || !method) { | ||||
| 			return methods.init.apply(this, arguments); | ||||
| 		} else { | ||||
| 			$.error('Method ' +  method + ' does not exist on jQuery.pagination'); | ||||
| 		} | ||||
|  | ||||
| 	}; | ||||
|  | ||||
| })(jQuery); | ||||
							
								
								
									
										173
									
								
								htdocs/js/mpd.js
									
									
									
									
									
								
							
							
						
						
									
										173
									
								
								htdocs/js/mpd.js
									
									
									
									
									
								
							| @@ -1,11 +1,7 @@ | ||||
| var socket; | ||||
| var last_state; | ||||
| var current_app; | ||||
| var is_firefox; | ||||
|  | ||||
| $('#volumeslider').slider().on('slide', function(event) { | ||||
| 	socket.send("MPD_API_SET_VOLUME,"+event.value); | ||||
| }); | ||||
| var current_song = new Object(); | ||||
|  | ||||
| var app = $.sammy(function() { | ||||
|     this.before('/', function(e, data) { | ||||
| @@ -17,10 +13,7 @@ var app = $.sammy(function() { | ||||
|         current_app = 'playlist'; | ||||
|         $('#breadcrump').addClass('hide'); | ||||
|         $('#salamisandwich').find("tr:gt(0)").remove(); | ||||
| 		//if(is_firefox) | ||||
|         $.get( "/api/get_playlist", socket.onmessage); | ||||
| 		//else | ||||
| 		//	socket.send("MPD_API_GET_PLAYLIST"); | ||||
|  | ||||
|         $('#panel-heading').text("Playlist"); | ||||
|         $('#playlist').addClass('active'); | ||||
| @@ -28,19 +21,14 @@ var app = $.sammy(function() { | ||||
|  | ||||
|     this.get(/\#\/browse\/(.*)/, function() { | ||||
|         current_app = 'browse'; | ||||
| 		$('#breadcrump').removeClass('hide').empty(); | ||||
|         $('#breadcrump').removeClass('hide').empty().append("<li><a href=\"#/browse/\">root</a></li>"); | ||||
|         $('#salamisandwich').find("tr:gt(0)").remove(); | ||||
| 		var path = this.params['splat']; | ||||
| 		if(path == '') | ||||
| 			path = "/"; | ||||
|         var path = this.params['splat'][0]; | ||||
|  | ||||
| 		//if(is_firefox) | ||||
|         $.get( "/api/get_browse/" + encodeURIComponent(path), socket.onmessage); | ||||
| 		//else | ||||
| 		//	socket.send("MPD_API_GET_BROWSE,"+path); | ||||
|  | ||||
|         $('#panel-heading').text("Browse database: "+path+""); | ||||
| 		var path_array = path[0].split('/'); | ||||
|         var path_array = path.split('/'); | ||||
|         var full_path = ""; | ||||
|         $.each(path_array, function(index, chunk) { | ||||
|             if(path_array.length - 1 == index) { | ||||
| @@ -61,8 +49,18 @@ var app = $.sammy(function() { | ||||
| }); | ||||
|  | ||||
| $(document).ready(function(){ | ||||
| 	is_firefox = true; | ||||
|     webSocketConnect(); | ||||
|     $("#volumeslider").slider(0); | ||||
|     $("#volumeslider").on('slider.newValue', function(evt,data){ | ||||
|         socket.send("MPD_API_SET_VOLUME,"+data.val); | ||||
|     }); | ||||
|     $('#progressbar').slider(0); | ||||
|     $("#progressbar").on('slider.newValue', function(evt,data){ | ||||
|         if(current_song) { | ||||
|             var seekVal = Math.ceil(current_song.totalTime*(data.val/100)); | ||||
|             socket.send("MPD_API_SET_SEEK,"+current_song.currentSongId+","+seekVal); | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
|  | ||||
|  | ||||
| @@ -75,15 +73,15 @@ function webSocketConnect() { | ||||
|  | ||||
|     try { | ||||
|         socket.onopen = function() { | ||||
| 			console.log("Connected"); | ||||
| 			app.run(); | ||||
|             $('.top-right').notify({ | ||||
|                 message:{text:"Connected"}, | ||||
|                 fadeOut: { enabled: true, delay: 1000 } | ||||
|             }).show(); | ||||
|  | ||||
| 			/* Push Initial state on first visit */ | ||||
| 			//$(window).trigger("statechange") | ||||
|             app.run(); | ||||
|         } | ||||
|  | ||||
|         socket.onmessage =function got_packet(msg) { | ||||
| 			console.log(typeof msg); | ||||
|             if(msg instanceof MessageEvent) { | ||||
|                 if(msg.data === last_state) | ||||
|                     return; | ||||
| @@ -131,8 +129,6 @@ function webSocketConnect() { | ||||
|  | ||||
|                     break; | ||||
|                 case "browse": | ||||
| 					//if(state.data.state !== 'nav_browse') | ||||
| 					//	break; | ||||
|                     if(current_app !== 'browse') | ||||
|                         break; | ||||
|  | ||||
| @@ -140,9 +136,9 @@ function webSocketConnect() { | ||||
|                         switch(obj.data[item].type) { | ||||
|                             case "directory": | ||||
|                                 $('#salamisandwich > tbody').append( | ||||
| 									"<tr uri=\"" + obj.data[item].dir + "\">" + | ||||
|                                     "<tr uri=\"" + obj.data[item].dir + "\" class=\"dir\">" + | ||||
|                                         "<td><span class=\"glyphicon glyphicon-folder-open\"></span></td>" +  | ||||
| 									"<td><a href=\"#/browse/"+ obj.data[item].dir +"\">" + basename(obj.data[item].dir) +"</a></td>" +  | ||||
|                                         "<td><a>" + basename(obj.data[item].dir) + "</a></td>" +  | ||||
|                                 "<td></td></tr>"); | ||||
|                             break; | ||||
|                         case "song": | ||||
| @@ -150,7 +146,7 @@ function webSocketConnect() { | ||||
|                             var seconds = obj.data[item].duration - minutes * 60; | ||||
|  | ||||
|                             $('#salamisandwich > tbody').append( | ||||
| 									"<tr uri=\"" + obj.data[item].uri + "\">" + | ||||
|                                 "<tr uri=\"" + obj.data[item].uri + "\" class=\"song\">" + | ||||
|                                     "<td><span class=\"glyphicon glyphicon-music\"></span></td>" +  | ||||
|                                     "<td>" + obj.data[item].title +"</td>" +  | ||||
|                                     "<td>"+ minutes + ":" + (seconds < 10 ? '0' : '') + seconds +"</td></tr>"); | ||||
| @@ -162,14 +158,33 @@ function webSocketConnect() { | ||||
|                     } | ||||
|  | ||||
|                     $('#salamisandwich > tbody > tr').on({ | ||||
| 						mouseover: function(){ | ||||
| 							if($(this).children().last().has("a").length == 0) | ||||
| 								if($(this).attr("uri").length > 0) | ||||
|                         mouseenter: function(){ | ||||
|                             if($(this).is(".dir")) { | ||||
|                                     $(this).children().last().append( | ||||
| 										"<a role=\"button\" class=\"pull-right btn-group-hover\" " + | ||||
| 										"onclick=\"socket.send('MPD_API_ADD_TRACK," + $(this).attr("uri") +"'); $(this).parents('tr').addClass('active');\">" + | ||||
| 										"<span class=\"glyphicon glyphicon-plus\"></span></a>") | ||||
| 										.find('a').fadeTo('fast',1); | ||||
|                                         "<a role=\"button\" class=\"pull-right btn-group-hover\">" + | ||||
|                                         "Add Directory <span class=\"glyphicon glyphicon-plus\"></span></a>") | ||||
|                                 .find('a').click(function(e) { | ||||
|                                     e.stopPropagation(); | ||||
|                                     socket.send("MPD_API_ADD_TRACK," + $(this).parents("tr").attr("uri")); | ||||
|                                     $('.top-right').notify({ | ||||
|                                         message:{ | ||||
|                                             text:"Added " + $('td:nth-child(2)', $(this).parents("tr")).text() + " to playlist " | ||||
|                                         } | ||||
|                                     }).show(); | ||||
|                                 }).fadeTo('fast',1); | ||||
|                             } | ||||
|                         }, | ||||
|                         click: function() { | ||||
|                             if($(this).is(".song")) { | ||||
|                                 socket.send("MPD_API_ADD_TRACK," + $(this).attr("uri")); | ||||
|                                 $('.top-right').notify({ | ||||
|                                     message:{ | ||||
|                                         text:"Added " + $('td:nth-child(2)', this).text() + " to playlist " | ||||
|                                     } | ||||
|                                 }).show(); | ||||
|  | ||||
|                             } else | ||||
|                                 app.setLocation("#/browse/"+$(this).attr("uri")); | ||||
|                         }, | ||||
|                         mouseleave: function(){ | ||||
|                             $(this).children().last().find("a").stop().remove(); | ||||
| @@ -178,18 +193,23 @@ function webSocketConnect() { | ||||
|  | ||||
|                     break; | ||||
|                 case "state": | ||||
|                     updatePlayIcon(obj.data.state); | ||||
|                     updateVolumeIcon(obj.data.volume); | ||||
|  | ||||
|                     if(JSON.stringify(obj) === JSON.stringify(last_state)) | ||||
|                         break; | ||||
|  | ||||
|                     current_song.totalTime  = obj.data.totalTime; | ||||
|                     current_song.currentSongId = obj.data.currentsongid; | ||||
|                     var total_minutes = Math.floor(obj.data.totalTime / 60); | ||||
|                     var total_seconds = obj.data.totalTime - total_minutes * 60; | ||||
|  | ||||
|                     var elapsed_minutes = Math.floor(obj.data.elapsedTime / 60); | ||||
|                     var elapsed_seconds = obj.data.elapsedTime - elapsed_minutes * 60; | ||||
|  | ||||
| 					$('#volumeslider').slider('setValue', obj.data.volume); | ||||
| 					var progress = Math.floor(100*obj.data.elapsedTime/obj.data.totalTime) + "%"; | ||||
| 					$('#progressbar').width(progress); | ||||
|                     $('#volumeslider').slider(obj.data.volume); | ||||
|                     var progress = Math.floor(100*obj.data.elapsedTime/obj.data.totalTime); | ||||
|                     $('#progressbar').slider(progress); | ||||
|  | ||||
|                     $('#counter') | ||||
|                     .text(elapsed_minutes + ":" +  | ||||
| @@ -219,30 +239,35 @@ function webSocketConnect() { | ||||
|                     else | ||||
|                         $('#btnrepeat').removeClass("active"); | ||||
|  | ||||
| 					if(last_state && (obj.data.state !== last_state.data.state)) | ||||
| 						updatePlayIcon(obj.data.state); | ||||
| 					if(last_state && (obj.data.volume !== last_state.data.volume)) | ||||
| 						updateVolumeIcon(obj.data.volume); | ||||
|  | ||||
|                     if(obj.data.elapsedTime <= 1) | ||||
|                         socket.send("MPD_API_GET_TRACK_INFO"); | ||||
|  | ||||
| 					$('#alert').addClass("hide"); | ||||
|                     last_state = obj; | ||||
|                     break; | ||||
|                 case "disconnected": | ||||
| 				    $('#alert') | ||||
| 				    .text("Server lost connection to MPD Host.") | ||||
| 				    .removeClass("hide alert-info") | ||||
| 				    .addClass("alert-danger"); | ||||
|                     if($('.top-right').has('div').length == 0) | ||||
|                         $('.top-right').notify({ | ||||
|                             message:{text:"ympd lost connection to MPD "}, | ||||
|                             type: "danger", | ||||
|                             fadeOut: { enabled: true, delay: 1000 }, | ||||
|                         }).show(); | ||||
|                     break; | ||||
|                 case "update_playlist": | ||||
|                     if(current_app === 'playlist') | ||||
|                         $.get( "/api/get_playlist", socket.onmessage); | ||||
|                     break; | ||||
|  | ||||
|                 case "current_song": | ||||
|                     $('#currenttrack').text(" " + obj.data.title); | ||||
|                     if(obj.data.album) | ||||
|                         $('#album').text(obj.data.album); | ||||
|                     if(obj.data.artist) | ||||
|                         $('#artist').text(obj.data.artist); | ||||
|                     break; | ||||
|                 case "error": | ||||
|                     $('.top-right').notify({ | ||||
|                         message:{text: obj.data}, | ||||
|                         type: "danger", | ||||
|                     }).show(); | ||||
|                 default: | ||||
|                     break; | ||||
|             } | ||||
| @@ -251,24 +276,13 @@ function webSocketConnect() { | ||||
|         } | ||||
|         socket.onclose = function(){ | ||||
|             console.log("Disconnected"); | ||||
|  | ||||
| 			var seconds = 5; | ||||
| 			var tm = setInterval(disconnectAlert,1000); | ||||
|  | ||||
| 			function disconnectAlert() { | ||||
| 				$('#alert') | ||||
| 				.text("Connection to MPD lost, retrying in " + seconds + " seconds") | ||||
| 				.removeClass("hide alert-info") | ||||
| 				.addClass("alert-danger"); | ||||
|  | ||||
| 				if(seconds-- <= 0) { | ||||
|             $('.top-right').notify({ | ||||
|                 message:{text:"Connection to ympd lost, retrying in 3 seconds "}, | ||||
|                 type: "danger",  | ||||
|                 onClose: function () { | ||||
|                     webSocketConnect(); | ||||
| 					seconds = 5; | ||||
| 					$('#alert').addClass("hide"); | ||||
| 					clearInterval(tm); | ||||
|                 } | ||||
| 			} | ||||
| 			 | ||||
|             }).show(); | ||||
|         } | ||||
|  | ||||
|     } catch(exception) { | ||||
| @@ -319,19 +333,18 @@ var updateVolumeIcon = function(volume) | ||||
| var updatePlayIcon = function(state) | ||||
| { | ||||
|     $("#play-icon").removeClass("glyphicon-play") | ||||
| 	.removeClass("glyphicon-pause") | ||||
| 	.removeClass("glyphicon-stop"); | ||||
|     .removeClass("glyphicon-pause"); | ||||
|     $('#track-icon').removeClass("glyphicon-play") | ||||
|     .removeClass("glyphicon-pause") | ||||
|     .removeClass("glyphicon-stop"); | ||||
|  | ||||
| 	if(state == 1) { | ||||
| 		$("#play-icon").addClass("glyphicon-stop"); | ||||
|     if(state == 1) { // stop | ||||
|         $("#play-icon").addClass("glyphicon-play"); | ||||
|         $('#track-icon').addClass("glyphicon-stop"); | ||||
| 	} else if(state == 2) { | ||||
|     } else if(state == 2) { // pause | ||||
|         $("#play-icon").addClass("glyphicon-pause"); | ||||
|         $('#track-icon').addClass("glyphicon-play"); | ||||
| 	} else { | ||||
|     } else { // play | ||||
|         $("#play-icon").addClass("glyphicon-play"); | ||||
|         $('#track-icon').addClass("glyphicon-pause"); | ||||
|     } | ||||
| @@ -340,15 +353,9 @@ var updatePlayIcon = function(state) | ||||
| function updateDB() | ||||
| { | ||||
|     socket.send('MPD_API_UPDATE_DB'); | ||||
|  | ||||
| 	$('#alert') | ||||
| 	.text("Updating MPD Database...") | ||||
| 	.removeClass("hide alert-danger") | ||||
| 	.addClass("alert-info"); | ||||
|  | ||||
| 	setTimeout(function() { | ||||
| 		$('#alert').addClass("hide"); | ||||
| 	}, 5000); | ||||
|     $('.top-right').notify({ | ||||
|         message:{text:"Updating MPD Database... "} | ||||
|     }).show(); | ||||
| } | ||||
|  | ||||
| function basename(path) { | ||||
| @@ -369,3 +376,11 @@ $('#btnsingle').on('click', function (e) { | ||||
| $('#btnrepeat').on('click', function (e) { | ||||
|     socket.send("MPD_API_TOGGLE_REPEAT," + ($(this).hasClass('active') ? 0 : 1)); | ||||
| }); | ||||
|  | ||||
| function getVersion() | ||||
| { | ||||
|     $.get( "/api/get_version", function(response) { | ||||
|         $('#ympd_version').text(response.data.ympd_version); | ||||
|         $('#mpd_version').text(response.data.mpd_version); | ||||
|     }); | ||||
| } | ||||
| @@ -2,6 +2,7 @@ | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <errno.h> | ||||
| #include <ctype.h> | ||||
| #include <mpd/client.h> | ||||
|  | ||||
| @@ -10,6 +11,7 @@ | ||||
| #include "config.h" | ||||
|  | ||||
| char *resource_path = LOCAL_RESOURCE_PATH; | ||||
| extern enum mpd_conn_states mpd_conn_state; | ||||
|  | ||||
| struct serveable { | ||||
|     const char *urlpath; | ||||
| @@ -25,6 +27,7 @@ static const struct serveable whitelist[] = { | ||||
|     { "/js/mpd.js", "text/javascript" }, | ||||
|     { "/js/jquery-1.10.2.min.js", "text/javascript" }, | ||||
|     { "/js/bootstrap-slider.js", "text/javascript" }, | ||||
|     { "/js/bootstrap-notify.js", "text/javascript" }, | ||||
|     { "/js/sammy.js", "text/javascript" }, | ||||
|  | ||||
|     { "/fonts/glyphicons-halflings-regular.woff", "application/x-font-woff"}, | ||||
| @@ -38,6 +41,11 @@ static const struct serveable whitelist[] = { | ||||
|     { "/index.html", "text/html" }, | ||||
| }; | ||||
|  | ||||
| static const char http_header[] = "HTTP/1.0 200 OK\x0d\x0a" | ||||
|                                   "Server: libwebsockets\x0d\x0a" | ||||
|                                   "Content-Type: application/json\x0d\x0a" | ||||
|                                   "Content-Length: 000000\x0d\x0a\x0d\x0a"; | ||||
|  | ||||
| /* Converts a hex character to its integer value */ | ||||
| char from_hex(char ch) { | ||||
|     return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10; | ||||
| @@ -70,34 +78,37 @@ int callback_http(struct libwebsocket_context *context, | ||||
|         void *in, size_t len) | ||||
| { | ||||
|     char *response_buffer, *p; | ||||
|     size_t n, response_size; | ||||
|     char buf[64]; | ||||
|     size_t n, response_size = 0; | ||||
|  | ||||
|     switch (reason) { | ||||
|         case LWS_CALLBACK_HTTP: | ||||
|             if(in && strncmp((const char *)in, "/api/", 5) == 0) | ||||
|             { | ||||
|                 response_buffer = (char *)malloc(MAX_SIZE + 100); | ||||
|                 p = response_buffer; | ||||
|  | ||||
|                 p = (char *)malloc(MAX_SIZE + 100); | ||||
|                 memcpy(p, http_header, sizeof(http_header) - 1); | ||||
|                 response_buffer = p + sizeof(http_header) - 1; | ||||
|  | ||||
|                 /* put content length and payload to buffer */ | ||||
|                 if(strncmp((const char *)in, "/api/get_browse", 15) == 0) | ||||
|                 if(mpd_conn_state != MPD_CONNECTED) {} | ||||
|                 else if(strncmp((const char *)in, "/api/get_browse", 15) == 0) | ||||
|                 { | ||||
|                     char *url; | ||||
|                     if(sscanf(in, "/api/get_browse/%m[^\t\n]", &url)) | ||||
|                     if(sscanf(in, "/api/get_browse/%m[^\t\n]", &url) == 1) | ||||
|                     { | ||||
|                         char *url_decoded = url_decode(url); | ||||
|                         printf("searching for %s", url_decoded); | ||||
|                         response_size = mpd_put_browse(response_buffer + 98, url_decoded); | ||||
|                         response_size = mpd_put_browse(response_buffer, url_decoded); | ||||
|                         free(url_decoded); | ||||
|                         free(url); | ||||
|                     } | ||||
|                     else | ||||
|                         response_size = mpd_put_browse(response_buffer + 98, "/"); | ||||
|                         response_size = mpd_put_browse(response_buffer, "/"); | ||||
|  | ||||
|                 } | ||||
|                 else if(strncmp((const char *)in, "/api/get_playlist", 17)  == 0) | ||||
|                     response_size = mpd_put_playlist(response_buffer + 98); | ||||
|                 else if(strncmp((const char *)in, "/api/version", 17)  == 0) | ||||
|                     response_size = mpd_put_playlist(response_buffer); | ||||
|                 else if(strncmp((const char *)in, "/api/get_version", 16)  == 0) | ||||
|                     response_size = snprintf(response_buffer, MAX_SIZE, | ||||
|                             "{\"type\":\"version\",\"data\":{" | ||||
|                             "\"ympd_version\":\"%d.%d.%d\"," | ||||
| @@ -106,24 +117,15 @@ int callback_http(struct libwebsocket_context *context, | ||||
|                             YMPD_VERSION_MAJOR, YMPD_VERSION_MINOR, YMPD_VERSION_PATCH, | ||||
|                             LIBMPDCLIENT_MAJOR_VERSION, LIBMPDCLIENT_MINOR_VERSION, | ||||
|                             LIBMPDCLIENT_PATCH_VERSION); | ||||
|                 else | ||||
|                 { | ||||
|                     /* invalid request, close connection */ | ||||
|                     free(response_buffer); | ||||
|                     return -1; | ||||
|                 } | ||||
|                 p += response_size + sprintf(p, "HTTP/1.0 200 OK\x0d\x0a" | ||||
|                         "Server: libwebsockets\x0d\x0a" | ||||
|                         "Content-Type: application/json\x0d\x0a" | ||||
|                         "Content-Length: %6lu\x0d\x0a\x0d\x0a",  | ||||
|                         response_size | ||||
|                         ); | ||||
|                 response_buffer[98] = '{'; | ||||
|  | ||||
|                 n = libwebsocket_write(wsi, (unsigned char *)response_buffer, | ||||
|                         p - response_buffer, LWS_WRITE_HTTP); | ||||
|                 /* Copy size to content-length field */ | ||||
|                 sprintf(buf, "%6lu", response_size); | ||||
|                 memcpy(p + sizeof(http_header) - 11, buf, 6); | ||||
|  | ||||
|                 free(response_buffer); | ||||
|                 n = libwebsocket_write(wsi, (unsigned char *)p, | ||||
|                         sizeof(http_header) - 1 + response_size, LWS_WRITE_HTTP); | ||||
|  | ||||
|                 free(p); | ||||
|                 /* | ||||
|                  * book us a LWS_CALLBACK_HTTP_WRITEABLE callback | ||||
|                  */ | ||||
|   | ||||
| @@ -41,12 +41,21 @@ int callback_ympd(struct libwebsocket_context *context, | ||||
|             } | ||||
|             p = &buf[LWS_SEND_BUFFER_PRE_PADDING]; | ||||
|  | ||||
|             if(mpd_conn_state != MPD_CONNECTED) { | ||||
|             if(pss->do_send & DO_SEND_ERROR) { | ||||
|                 n = snprintf(p, MAX_SIZE, "{\"type\":\"error\", \"data\": \"%s\"}",  | ||||
|                     mpd_connection_get_error_message(conn)); | ||||
|                 pss->do_send &= ~DO_SEND_ERROR; | ||||
|  | ||||
|                 /* Try to recover error */ | ||||
|                 if (!mpd_connection_clear_error(conn)) | ||||
|                     mpd_conn_state = MPD_FAILURE; | ||||
|             } | ||||
|             else if(mpd_conn_state != MPD_CONNECTED) { | ||||
|                 n = snprintf(p, MAX_SIZE, "{\"type\":\"disconnected\"}"); | ||||
|             } | ||||
|             //else if((pss->queue_version != queue_version) || (pss->do_send & DO_SEND_PLAYLIST)) { | ||||
|             else if(pss->do_send & DO_SEND_PLAYLIST) { | ||||
|                 n = mpd_put_playlist(p); | ||||
|             else if((pss->queue_version != queue_version) || (pss->do_send & DO_SEND_PLAYLIST)) { | ||||
|                 /*n = mpd_put_playlist(p);*/ | ||||
|                 n = snprintf(p, MAX_SIZE, "{\"type\":\"update_playlist\"}"); | ||||
|                 pss->queue_version = queue_version; | ||||
|                 pss->do_send &= ~DO_SEND_PLAYLIST; | ||||
|             } | ||||
| @@ -78,25 +87,20 @@ int callback_ympd(struct libwebsocket_context *context, | ||||
|                 pss->do_send |= DO_SEND_PLAYLIST; | ||||
|             else if(!strcmp((const char *)in, MPD_API_GET_TRACK_INFO)) | ||||
|                 pss->do_send |= DO_SEND_TRACK_INFO; | ||||
|             else if(!strcmp((const char *)in, MPD_API_UPDATE_DB)) { | ||||
|                 mpd_send_update(conn, NULL); | ||||
|                 mpd_response_finish(conn); | ||||
|             } | ||||
|             else if(!strcmp((const char *)in, MPD_API_SET_PAUSE)) { | ||||
|                 mpd_send_toggle_pause(conn); | ||||
|                 mpd_response_finish(conn); | ||||
|             } | ||||
|             else if(!strcmp((const char *)in, MPD_API_SET_PREV)) { | ||||
|                 mpd_send_previous(conn); | ||||
|                 mpd_response_finish(conn); | ||||
|             } | ||||
|             else if(!strcmp((const char *)in, MPD_API_SET_NEXT)) { | ||||
|                 mpd_send_next(conn); | ||||
|                 mpd_response_finish(conn); | ||||
|             } | ||||
|             else if(!strcmp((const char *)in, MPD_API_RM_ALL)) { | ||||
|             else if(!strcmp((const char *)in, MPD_API_UPDATE_DB)) | ||||
|                 mpd_run_update(conn, NULL); | ||||
|             else if(!strcmp((const char *)in, MPD_API_SET_PAUSE)) | ||||
|                 mpd_run_toggle_pause(conn); | ||||
|             else if(!strcmp((const char *)in, MPD_API_SET_PREV)) | ||||
|                 mpd_run_previous(conn); | ||||
|             else if(!strcmp((const char *)in, MPD_API_SET_NEXT)) | ||||
|                 mpd_run_next(conn); | ||||
|             else if(!strcmp((const char *)in, MPD_API_SET_PLAY)) | ||||
|                 mpd_run_play(conn); | ||||
|             else if(!strcmp((const char *)in, MPD_API_SET_STOP)) | ||||
|                 mpd_run_stop(conn); | ||||
|             else if(!strcmp((const char *)in, MPD_API_RM_ALL)) | ||||
|                 mpd_run_clear(conn); | ||||
|             } | ||||
|             else if(!strncmp((const char *)in, MPD_API_RM_TRACK, sizeof(MPD_API_RM_TRACK)-1)) { | ||||
|                 unsigned id; | ||||
|                 if(sscanf(in, "MPD_API_RM_TRACK,%u", &id)) | ||||
| @@ -129,9 +133,15 @@ int callback_ympd(struct libwebsocket_context *context, | ||||
|             } | ||||
|             else if(!strncmp((const char *)in, MPD_API_SET_VOLUME, sizeof(MPD_API_SET_VOLUME)-1)) { | ||||
|                 unsigned int volume; | ||||
|                 if(sscanf(in, "MPD_API_SET_VOLUME,%ud", &volume) && volume < 100) | ||||
|                 if(sscanf(in, "MPD_API_SET_VOLUME,%ud", &volume) && volume <= 100) | ||||
|                     mpd_run_set_volume(conn, volume); | ||||
|             } | ||||
|             else if(!strncmp((const char *)in, MPD_API_SET_SEEK, sizeof(MPD_API_SET_SEEK)-1)) { | ||||
|                 unsigned int seek, songid; | ||||
|                 if(sscanf(in, "MPD_API_SET_SEEK,%u,%u", &songid, &seek)) { | ||||
|                     mpd_run_seek_id(conn, songid, seek); | ||||
|                 } | ||||
|             } | ||||
|             else if(!strncmp((const char *)in, MPD_API_GET_BROWSE, sizeof(MPD_API_GET_BROWSE)-1)) { | ||||
|                 char *dir; | ||||
|                 if(sscanf(in, "MPD_API_GET_BROWSE,%m[^\t\n]", &dir) && dir != NULL) { | ||||
| @@ -146,6 +156,10 @@ int callback_ympd(struct libwebsocket_context *context, | ||||
|                     free(uri); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if(mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) | ||||
|                 pss->do_send |= DO_SEND_ERROR; | ||||
|  | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
| @@ -283,8 +297,12 @@ int mpd_put_playlist(char *buffer) | ||||
|  | ||||
|     if (!mpd_send_list_queue_meta(conn)) { | ||||
|         lwsl_err("MPD mpd_send_list_queue_meta: %s\n", mpd_connection_get_error_message(conn)); | ||||
|         cur += snprintf(cur, end  - cur, "{\"type\":\"error\",\"data\":\"%s\"}",  | ||||
|             mpd_connection_get_error_message(conn)); | ||||
|  | ||||
|         if (!mpd_connection_clear_error(conn)) | ||||
|             mpd_conn_state = MPD_FAILURE; | ||||
|         return 0; | ||||
|         return cur - buffer; | ||||
|     } | ||||
|  | ||||
|     cur += snprintf(cur, end  - cur, "{\"type\": \"playlist\", \"data\": [ "); | ||||
| @@ -319,8 +337,12 @@ int mpd_put_browse(char *buffer, char *path) | ||||
|  | ||||
|     if (!mpd_send_list_meta(conn, path)) { | ||||
|         lwsl_err("MPD mpd_send_list_meta: %s\n", mpd_connection_get_error_message(conn)); | ||||
|         cur += snprintf(cur, end  - cur, "{\"type\":\"error\",\"data\":\"%s\"}",  | ||||
|             mpd_connection_get_error_message(conn)); | ||||
|  | ||||
|         if (!mpd_connection_clear_error(conn)) | ||||
|             mpd_conn_state = MPD_FAILURE; | ||||
|         return 0; | ||||
|         return cur - buffer; | ||||
|     } | ||||
|     cur += snprintf(cur, end  - cur, "{\"type\":\"browse\",\"data\":[ "); | ||||
|  | ||||
|   | ||||
| @@ -9,6 +9,8 @@ | ||||
| #define DO_SEND_PLAYLIST   (1 << 1) | ||||
| #define DO_SEND_TRACK_INFO (1 << 2) | ||||
| #define DO_SEND_BROWSE     (1 << 3) | ||||
| #define DO_SEND_ERROR      (1 << 4) | ||||
|  | ||||
|  | ||||
| #define MPD_API_GET_SEEK         "MPD_API_GET_SEEK" | ||||
| #define MPD_API_GET_PLAYLIST     "MPD_API_GET_PLAYLIST" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Andrew Karpow
					Andrew Karpow