mirror of
				https://github.com/SuperBFG7/ympd
				synced 2025-10-31 22:03:01 +00:00 
			
		
		
		
	Removed not working dirble support
Removed jquery sorttable dependency Reworked html template Reworked notifications Repaired search
This commit is contained in:
		| @@ -11,6 +11,7 @@ UI Components | |||||||
| ------------- | ------------- | ||||||
|  - Bootstrap 4: https://getbootstrap.com/ |  - Bootstrap 4: https://getbootstrap.com/ | ||||||
|  - Bootstrap Notify: http://bootstrap-notify.remabledesigns.com/ |  - Bootstrap Notify: http://bootstrap-notify.remabledesigns.com/ | ||||||
|  |  - Bootstrap Slider: https://github.com/seiyria/bootstrap-slider | ||||||
|  - Material Design Icons: https://material.io/tools/icons/?style=baseline |  - Material Design Icons: https://material.io/tools/icons/?style=baseline | ||||||
|  - Sammy.js: http://sammyjs.org/ |  - Sammy.js: http://sammyjs.org/ | ||||||
|  |  | ||||||
| @@ -40,7 +41,6 @@ Usage: ./ympd [OPTION]... | |||||||
|  -h, --host <host>             connect to mpd at host [localhost] |  -h, --host <host>             connect to mpd at host [localhost] | ||||||
|  -p, --port <port>             connect to mpd at port [6600] |  -p, --port <port>             connect to mpd at port [6600] | ||||||
|  -w, --webport [ip:]<port>     listen interface/port for webserver [8080] |  -w, --webport [ip:]<port>     listen interface/port for webserver [8080] | ||||||
|  -d, --dirbletoken <apitoken>  Dirble API token |  | ||||||
|  -u, --user <username>         drop priviliges to user after socket bind |  -u, --user <username>         drop priviliges to user after socket bind | ||||||
|  -V, --version                 get version |  -V, --version                 get version | ||||||
|  --help                        this help |  --help                        this help | ||||||
| @@ -60,12 +60,6 @@ To run ympd with SSL support: | |||||||
| # ./ympd -w "ssl://8081:/path/to/ssl.pem" | # ./ympd -w "ssl://8081:/path/to/ssl.pem" | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| Dirble support |  | ||||||
| -------------- |  | ||||||
|  |  | ||||||
| 1. Get an API-key from http://dirble.com |  | ||||||
| 2. Add the key at ```var TOKEN = "";```, in ```mpd.js```. |  | ||||||
|  |  | ||||||
| Copyright | Copyright | ||||||
| --------- | --------- | ||||||
| ympd: 2013-2014 <andy@ndyk.de> | ympd: 2013-2014 <andy@ndyk.de> | ||||||
|   | |||||||
| @@ -3,6 +3,5 @@ MPD_PORT=6600 | |||||||
| MPD_PASSWORD= | MPD_PASSWORD= | ||||||
| WEB_PORT=8080 | WEB_PORT=8080 | ||||||
| YMPD_USER=nobody | YMPD_USER=nobody | ||||||
| DIRBLE_API_TOKEN=2e223c9909593b94fc6577361a |  | ||||||
| #DIGEST=--digest /path/to/htdigest | #DIGEST=--digest /path/to/htdigest | ||||||
| #LOCALPORT=--localport 8080 | #LOCALPORT=--localport 8080 | ||||||
|   | |||||||
| @@ -8,11 +8,10 @@ Environment=MPD_PORT=6600 | |||||||
| Environment=MPD_PASSWORD= | Environment=MPD_PASSWORD= | ||||||
| Environment=WEB_PORT=8080 | Environment=WEB_PORT=8080 | ||||||
| Environment=YMPD_USER=nobody | Environment=YMPD_USER=nobody | ||||||
| Environment=DIRBLE_API_TOKEN=2e223c9909593b94fc6577361a |  | ||||||
| Environment=DIGEST= | Environment=DIGEST= | ||||||
| Environment=LOCALPORT= | Environment=LOCALPORT= | ||||||
| EnvironmentFile=/etc/default/ympd | EnvironmentFile=/etc/default/ympd | ||||||
| ExecStart=/usr/bin/ympd --user $YMPD_USER --webport $WEB_PORT --host $MPD_HOST --port $MPD_PORT --dirbletoken $DIRBLE_API_TOKEN $DIGEST $LOCALPORT | ExecStart=/usr/bin/ympd --user $YMPD_USER --webport $WEB_PORT --host $MPD_HOST --port $MPD_PORT $DIGEST $LOCALPORT | ||||||
| Type=simple | Type=simple | ||||||
|  |  | ||||||
| [Install] | [Install] | ||||||
|   | |||||||
| @@ -21,34 +21,24 @@ body { | |||||||
|   width: 104px; |   width: 104px; | ||||||
| } | } | ||||||
|  |  | ||||||
| #volumeslider .progress { |  | ||||||
|   margin-bottom: 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| button { | button { | ||||||
|   overflow: hidden; |   overflow: hidden; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| #volume-icon { | #browseBreadcrumb { | ||||||
|   float: left; |  | ||||||
|   margin-right: 10px; |  | ||||||
|   margin-top: 2px; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #breadcrumb { |  | ||||||
|   overflow: auto; |   overflow: auto; | ||||||
|   white-space: nowrap; |   white-space: nowrap; | ||||||
| } | } | ||||||
|  |  | ||||||
| #breadcrumb > li > a{ | #browseBreadcrumb > li > a { | ||||||
|   cursor: pointer; |   cursor: pointer; | ||||||
| } | } | ||||||
|  |  | ||||||
| #counter { | #counter { | ||||||
|   font-size: 24px; |   font-size: 24px; | ||||||
|   margin-top: -6px; |   margin-top: -2px; | ||||||
|   margin-left: 10px; |   margin-left: 10px; | ||||||
|   min-width: 50px; |   min-width: 50px; | ||||||
| } | } | ||||||
| @@ -75,14 +65,6 @@ td:nth-last-child(2), th:nth-last-child(2) { | |||||||
|   width: 4em; |   width: 4em; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* |  | ||||||
| #salamisandwich td:nth-child(4) span { |  | ||||||
|   font-style: italic; |  | ||||||
|   font-size: 90%; |  | ||||||
|   display: block; |  | ||||||
| } |  | ||||||
| */ |  | ||||||
|  |  | ||||||
| td:nth-child(2), td:nth-child(3) { | td:nth-child(2), td:nth-child(3) { | ||||||
|   min-width: 25%; |   min-width: 25%; | ||||||
|   max-width: 10em; |   max-width: 10em; | ||||||
| @@ -103,6 +85,9 @@ td:nth-child(2), td:nth-child(3) { | |||||||
|   .tbllength, .tblnum { |   .tbllength, .tblnum { | ||||||
|     visibility:collapse; |     visibility:collapse; | ||||||
|   } |   } | ||||||
|  |   .header-logo { | ||||||
|  |     display:none !important; | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| tbody { | tbody { | ||||||
| @@ -113,24 +98,6 @@ td:last-child, td:first-child { | |||||||
|   width: 30px; |   width: 30px; | ||||||
| } | } | ||||||
|  |  | ||||||
| .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; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #album-cover { | #album-cover { | ||||||
|   background-size:cover; |   background-size:cover; | ||||||
|   border:1px solid black; |   border:1px solid black; | ||||||
| @@ -207,6 +174,10 @@ main { | |||||||
|  color:#6c757d; |  color:#6c757d; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .color-darkgrey:hover { | ||||||
|  |  color:#6c757d !important; | ||||||
|  | } | ||||||
|  |  | ||||||
| #filter-toolbar { | #filter-toolbar { | ||||||
|  margin-bottom:10px; |  margin-bottom:10px; | ||||||
| } | } | ||||||
| @@ -222,18 +193,11 @@ main { | |||||||
|  overflow-x:hidden; |  overflow-x:hidden; | ||||||
| } | } | ||||||
|  |  | ||||||
| .slider-handle.custom { |  | ||||||
|   background: transparent none; |  | ||||||
| } |  | ||||||
| .slider-handle.custom::before { |  | ||||||
|   content: ''; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .slider-selection { | .slider-selection { | ||||||
|  background:#28a745 !important; |  background:#28a745 !important; | ||||||
| } | } | ||||||
|  |  | ||||||
| #progressbar .slider-track, #volumebar .slider-track { | #progressbar .slider-track { | ||||||
|  height: 20px !important; |  height: 20px !important; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -247,4 +211,14 @@ main { | |||||||
|  |  | ||||||
| .slider-handle { | .slider-handle { | ||||||
|  visibility:hidden !important; |  visibility:hidden !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | [data-notify="title"] { | ||||||
|  |  font-size:120%;  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .header-logo { | ||||||
|  |  font-size:2rem; | ||||||
|  |  float:left; | ||||||
|  |  margin-right:5px; | ||||||
| } | } | ||||||
| @@ -22,15 +22,13 @@ | |||||||
|   <header> |   <header> | ||||||
|     <nav class="navbar navbar-expand navbar-dark fixed-top bg-dark"> |     <nav class="navbar navbar-expand navbar-dark fixed-top bg-dark"> | ||||||
|         <div class="dropdown col-auto mr-auto"> |         <div class="dropdown col-auto mr-auto"> | ||||||
|           <a class="navbar-brand dropdown-toggle" data-toggle="dropdown" href="/#/playing/"><span style="font-size:24px;float:left;margin-right:5px;" class="material-icons">play_circle_outline</span>myMPD</a> |           <a class="dropdown-toggle navbar-brand" data-toggle="dropdown" href="#"> | ||||||
|  |             <span class="material-icons header-logo">play_circle_outline</span>myMPD</a> | ||||||
|           <div class="dropdown-menu bg-dark"> |           <div class="dropdown-menu bg-dark"> | ||||||
|             <h1 class="dropdown-header text-light">myMPD</h1> |  | ||||||
|             <div class="dropdown-divider"></div> |  | ||||||
|             <form id="search" class="px-4 py-3" role="search"> |             <form id="search" class="px-4 py-3" role="search"> | ||||||
|               <input type="text" class="form-control" placeholder="Search"> |               <input type="text" class="form-control" placeholder="Search"> | ||||||
|             </form> |             </form> | ||||||
|             <div class="dropdown-divider"></div> |             <div class="dropdown-divider"></div> | ||||||
|             <a id="nav-dirble" class="dropdown-item" href="#/dirble/">Dirble</a> |  | ||||||
|             <a id="nav-addstream" class="dropdown-item text-light bg-dark" href="#" data-toggle="modal" data-target="#addstream">Add Stream</a> |             <a id="nav-addstream" class="dropdown-item text-light bg-dark" href="#" data-toggle="modal" data-target="#addstream">Add Stream</a> | ||||||
|             <a id="nav-settings" class="dropdown-item text-light bg-dark" href="#" data-toggle="modal" data-target="#settings" onclick="getHost();">Settings</a> |             <a id="nav-settings" class="dropdown-item text-light bg-dark" href="#" data-toggle="modal" data-target="#settings" onclick="getHost();">Settings</a> | ||||||
|             <a id="nav-updatedb" class="dropdown-item text-light bg-dark" href="#" onclick="updateDB();">Update Database</a> |             <a id="nav-updatedb" class="dropdown-item text-light bg-dark" href="#" onclick="updateDB();">Update Database</a> | ||||||
| @@ -41,11 +39,6 @@ | |||||||
|             <button type="button" class="btn btn-secondary" onclick="socket.send('MPD_API_SET_PREV');"> |             <button type="button" class="btn btn-secondary" onclick="socket.send('MPD_API_SET_PREV');"> | ||||||
|               <span class="material-icons">skip_previous</span> |               <span class="material-icons">skip_previous</span> | ||||||
|             </button> |             </button> | ||||||
|             <!-- |  | ||||||
|             <button type="button" class="btn btn-secondary" onclick="socket.send('MPD_API_SET_STOP');"> |  | ||||||
|               <span id="stop-icon" class="material-icons">stop</span> |  | ||||||
|             </button> |  | ||||||
|             --> |  | ||||||
|             <button type="button" class="btn btn-secondary" onclick="clickPlay();"> |             <button type="button" class="btn btn-secondary" onclick="clickPlay();"> | ||||||
|               <span id="play-icon" class="material-icons">pause</span> |               <span id="play-icon" class="material-icons">pause</span> | ||||||
|             </button> |             </button> | ||||||
| @@ -60,9 +53,11 @@ | |||||||
|             <div class="dropdown-menu dropdown-menu-right bg-dark"> |             <div class="dropdown-menu dropdown-menu-right bg-dark"> | ||||||
|               <h1 class="dropdown-header text-light">Volume: <span id="volumePrct"></span></h1> |               <h1 class="dropdown-header text-light">Volume: <span id="volumePrct"></span></h1> | ||||||
|               <form class="px-4 py-3" style="padding-top:0px !important;"> |               <form class="px-4 py-3" style="padding-top:0px !important;"> | ||||||
|               <div class="btn-group btn-secondary" role="group" style="border-radius:0.25rem"> |               <div class="btn-group" role="group"> | ||||||
|                 <input type="button" class="btn btn-secondary" value="−" onclick="chVolume(-5)"/> |                 <input type="button" class="btn btn-secondary" value="−" onclick="chVolume(-5)"/> | ||||||
|                 <input id="volumebar" data-slider-id="volumebar" data-slider-handle="custom" type="text" data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="0"/> |                 <div class="btn btn-secondary"> | ||||||
|  |                  <input id="volumebar" data-slider-id="volumebar" data-slider-handle="custom" type="text" data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="0"/> | ||||||
|  |                 </div> | ||||||
|                 <input type="button" class="btn btn-secondary" value="+" onclick="chVolume(5)"/> |                 <input type="button" class="btn btn-secondary" value="+" onclick="chVolume(5)"/> | ||||||
|                 </div> |                 </div> | ||||||
|               </form> |               </form> | ||||||
| @@ -85,13 +80,33 @@ | |||||||
|     </nav> |     </nav> | ||||||
|   </header> |   </header> | ||||||
|   <main role="main" class="container"> |   <main role="main" class="container"> | ||||||
|     <div class="card"> |  | ||||||
|  |     <div class="card" id="cardPlayback"> | ||||||
|  |       <div class="card-header">Now playing</div> | ||||||
|  |       <div class="card-body"> | ||||||
|  |         <div id="album-cover"></div> | ||||||
|  |         <h1 id="currenttrack"></h1> | ||||||
|  |         <h3 id="artist"></h3> | ||||||
|  |         <h4 id="album"></h4> | ||||||
|  |         <div class="row"> | ||||||
|  |           <div class="col-8"> | ||||||
|  |             <input id="progressbar" data-slider-id='progressbar' data-slider-handle='custom' type="text" data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="0"/> | ||||||
|  |           </div> | ||||||
|  |           <div class="col-4"> | ||||||
|  |             <p id="counter" class="text">  </p> | ||||||
|  |           </div> | ||||||
|  |         </div>           | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     <div class="card hide" id="cardQueue"> | ||||||
|       <div class="card-header"> |       <div class="card-header"> | ||||||
|         <span id="panel-heading">Now playing</span> |         <span>Queue</span> | ||||||
|         <span id="panel-heading-info" class="text pull-right"></span> |         <span id="panel-heading-queue" class="text pull-right"></span> | ||||||
|       </div> |       </div> | ||||||
|       <div class="card-body"> |       <div class="card-body"> | ||||||
|         <div class="btn-toolbar hide" id="queue-buttons" role="toolbar"> |         <div class="btn-toolbar" id="queue-buttons" role="toolbar"> | ||||||
|           <div id="trashmode" class="btn-group mr-2" data-toggle="radio"> |           <div id="trashmode" class="btn-group mr-2" data-toggle="radio"> | ||||||
|             <button id="btntrashmodeup" type="button" class="btn btn-secondary" title="Delete upward"> |             <button id="btntrashmodeup" type="button" class="btn btn-secondary" title="Delete upward"> | ||||||
|               <span class="material-icons">vertical_align_top</span> |               <span class="material-icons">vertical_align_top</span> | ||||||
| @@ -115,32 +130,7 @@ | |||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|            |            | ||||||
|         <div id="nowplaying"> |         <table id="queueList" class="table table-hover"> | ||||||
|           <div id="album-cover"></div> |  | ||||||
|           <h1 id="currenttrack"></h1> |  | ||||||
|           <h3 id="artist"></h3> |  | ||||||
|           <h4 id="album"></h4> |  | ||||||
|           <div class="row"> |  | ||||||
|             <div class="col-8"> |  | ||||||
|               <input id="progressbar" data-slider-id='progressbar' data-slider-handle='custom' type="text" data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="0"/> |  | ||||||
|             </div> |  | ||||||
|             <div class="col-4"> |  | ||||||
|               <p id="counter" class="text">  </p> |  | ||||||
|             </div> |  | ||||||
|           </div>           |  | ||||||
|         </div> |  | ||||||
|  |  | ||||||
|         <ol id="breadcrumb" class="breadcrumb hide"> |  | ||||||
|         </ol> |  | ||||||
|  |  | ||||||
|         <div class="btn-toolbar hide" id="filter-toolbar"> |  | ||||||
|           <div class="btn-group mr-2 flex-wrap" data-toggle="radio" id="filter"></div> |  | ||||||
|           <div class="btn-group mr-2 pull-right"> |  | ||||||
|             <button id="add-all-songs" class="btn btn-secondary">Add all</button> |  | ||||||
|           </div> |  | ||||||
|         </div> |  | ||||||
|  |  | ||||||
|         <table id="salamisandwich" class="table table-hover hide"> |  | ||||||
|           <col class="tblnum"/> |           <col class="tblnum"/> | ||||||
|           <col class="tblartist"/> |           <col class="tblartist"/> | ||||||
|           <col class="tblalbum"/> |           <col class="tblalbum"/> | ||||||
| @@ -161,42 +151,86 @@ | |||||||
|           </tbody> |           </tbody> | ||||||
|         </table> |         </table> | ||||||
|  |  | ||||||
|         <div id="dirble_panel" class="hide"> |  | ||||||
|           <p id="dirble_loading" style="font-size:16px;font-weight:bold;margin-left:4em;">Loading...</p> |  | ||||||
|           <table style="float:right; width:44%; margin-right:4%;" id="dirble_right" class="table table-hover"> |  | ||||||
|             <thead> |  | ||||||
|               <tr> |  | ||||||
|                 <th></th> |  | ||||||
|               </tr> |  | ||||||
|             </thead> |  | ||||||
|             <tbody> |  | ||||||
|             </tbody> |  | ||||||
|           </table> |  | ||||||
|           <table style="width:44%; margin-left:4%;" id="dirble_left" class="table table-hover"> |  | ||||||
|             <thead> |  | ||||||
|               <tr> |  | ||||||
|                 <th></th> |  | ||||||
|               </tr> |  | ||||||
|             </thead> |  | ||||||
|             <tbody> |  | ||||||
|             </tbody> |  | ||||||
|           </table> |  | ||||||
|         </div> |  | ||||||
|  |  | ||||||
|         <ul class="pagination justify-content-center"> |         <ul class="pagination justify-content-center"> | ||||||
|           <li id="prev" class="page-item hide"><a class="page-link" href="">Previous</a></li> |           <li id="queuePrev" class="page-item hide"><a class="page-link text-secondary" href="">Previous</a></li> | ||||||
|           <li id="next" class="page-item hide"><a class="page-link" href="">Next</a></li> |           <li id="queueNext" class="page-item hide"><a class="page-link text-secondary" href="">Next</a></li> | ||||||
|         </ul> |         </ul> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|   </main> |      | ||||||
|  |     <div class="card hide" id="cardBrowse"> | ||||||
|  |       <div class="card-header" id="panel-heading-browse">Browse</div> | ||||||
|  |       <div class="card-body"> | ||||||
|  |         <ol id="browseBreadcrumb" class="breadcrumb"> | ||||||
|  |         </ol> | ||||||
|  |  | ||||||
|  |         <div class="btn-toolbar" id="filter-toolbar"> | ||||||
|  |           <div class="btn-group mr-2 flex-wrap" data-toggle="radio" id="filter"></div> | ||||||
|  |           <div class="btn-group mr-2 pull-right"> | ||||||
|  |             <button id="add-all-songs" class="btn btn-secondary">Add all</button> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <table id="browseList" class="table table-hover"> | ||||||
|  |           <col class="tblnum"/> | ||||||
|  |           <col class="tblartist"/> | ||||||
|  |           <col class="tblalbum"/> | ||||||
|  |           <col class="tbltitle"/> | ||||||
|  |           <col class="tbllength"/> | ||||||
|  |           <col class="tblaction"/> | ||||||
|  |           <thead> | ||||||
|  |             <tr> | ||||||
|  |               <th></th> | ||||||
|  |               <th>Artist</th> | ||||||
|  |               <th>Album</th> | ||||||
|  |               <th>Title</th> | ||||||
|  |               <th>Length</th> | ||||||
|  |               <th></th> | ||||||
|  |             </tr> | ||||||
|  |           </thead> | ||||||
|  |           <tbody> | ||||||
|  |           </tbody> | ||||||
|  |         </table> | ||||||
|  |  | ||||||
|  |         <ul class="pagination justify-content-center"> | ||||||
|  |           <li id="browsePrev" class="page-item hide"><a class="page-link text-secondary" href="">Previous</a></li> | ||||||
|  |           <li id="browseNext" class="page-item hide"><a class="page-link text-secondary" href="">Next</a></li> | ||||||
|  |         </ul> | ||||||
|  |       </div> | ||||||
|  |     </div>         | ||||||
|  |  | ||||||
|  |     <div class="card hide" id="cardSearch"> | ||||||
|  |       <div class="card-header" id="pnael-heading-search">Search</div> | ||||||
|  |       <div class="card-body"> | ||||||
|  |         <table id="searchList" class="table table-hover"> | ||||||
|  |           <col class="tblnum"/> | ||||||
|  |           <col class="tblartist"/> | ||||||
|  |           <col class="tblalbum"/> | ||||||
|  |           <col class="tbltitle"/> | ||||||
|  |           <col class="tbllength"/> | ||||||
|  |           <col class="tblaction"/> | ||||||
|  |           <thead> | ||||||
|  |             <tr> | ||||||
|  |               <th></th> | ||||||
|  |               <th>Artist</th> | ||||||
|  |               <th>Album</th> | ||||||
|  |               <th>Title</th> | ||||||
|  |               <th>Length</th> | ||||||
|  |               <th></th> | ||||||
|  |             </tr> | ||||||
|  |           </thead> | ||||||
|  |           <tbody> | ||||||
|  |           </tbody> | ||||||
|  |         </table> | ||||||
|  |       </div> | ||||||
|  |     </div>     | ||||||
|  |      | ||||||
|   <footer class="footer"> |   <footer class="footer"> | ||||||
|     <nav class="navbar navbar-expand navbar-dark fixed-bottom bg-dark"> |     <nav class="navbar navbar-expand navbar-dark fixed-bottom bg-dark"> | ||||||
|       <div class="d-flex flex-fill navbar-nav" id="navbar-bottom"> |       <div class="d-flex flex-fill navbar-nav" id="navbar-bottom"> | ||||||
|         <div class="nav-item flex-fill text-center" id="nav-playing"><a class="nav-link" href="#/playing/">Playback</a></div> |         <div class="nav-item flex-fill text-center" id="navPlayback"><a class="nav-link" href="#/playing/">Playback</a></div> | ||||||
|         <div class="nav-item flex-fill text-center" id="nav-queue"><a class="nav-link" href="#/queue/0">Queue</a></div> |         <div class="nav-item flex-fill text-center" id="navQueue"><a class="nav-link" href="#/queue/0">Queue</a></div> | ||||||
|         <div class="nav-item flex-fill text-center" id="nav-browse"><a class="nav-link" href="#/browse/0/">Browse</a></div> |         <div class="nav-item flex-fill text-center" id="navBrowse"><a class="nav-link" href="#/browse/0/">Browse</a></div> | ||||||
|       </div> |       </div> | ||||||
|     </nav> |     </nav> | ||||||
|   </footer> |   </footer> | ||||||
| @@ -244,12 +278,20 @@ | |||||||
|               <button id="btnrepeat" type="button" class="btn btn-secondary btn-block" title="Repeat"> |               <button id="btnrepeat" type="button" class="btn btn-secondary btn-block" title="Repeat"> | ||||||
|                 <span class="glyphicon glyphicon-repeat"></span> Repeat |                 <span class="glyphicon glyphicon-repeat"></span> Repeat | ||||||
|               </button> |               </button> | ||||||
|             </div>           |             </div> | ||||||
|  |           </div> | ||||||
|  |           <hr/> | ||||||
|  |           <div class="row"> | ||||||
|             <div class="form-group col-md-6" data-toggle="buttons"> |             <div class="form-group col-md-6" data-toggle="buttons"> | ||||||
|               <button type="button" class="btn btn-secondary btn-block" id="btnnotify"> |               <button type="button" class="btn btn-secondary btn-block" id="btnnotifyPage"> | ||||||
|                 <span class="glyphicon glyphicon-comment"></span> Enable Notifications |                 <span class="glyphicon glyphicon-comment"></span> Page Notifications | ||||||
|               </button> |               </button> | ||||||
|             </div>             |             </div> | ||||||
|  |             <div class="form-group col-md-6" data-toggle="buttons"> | ||||||
|  |               <button type="button" class="btn btn-secondary btn-block" id="btnnotifyWeb"> | ||||||
|  |                 <span class="glyphicon glyphicon-comment"></span> Web Notifications | ||||||
|  |               </button> | ||||||
|  |             </div> | ||||||
|           </div> |           </div> | ||||||
|           <hr/> |           <hr/> | ||||||
|           <form role="form"> |           <form role="form"> | ||||||
| @@ -352,21 +394,6 @@ | |||||||
|     </div><!-- /.modal-dialog --> |     </div><!-- /.modal-dialog --> | ||||||
|   </div><!-- /.modal --> |   </div><!-- /.modal --> | ||||||
|  |  | ||||||
|   <div class="modal fade bs-example-modal-sm" id="wait" tabindex="-1" role="dialog" data-backdrop="static" data-keyboard="false" aria-hidden="true"> |  | ||||||
|     <div class="modal-dialog"> |  | ||||||
|       <div class="modal-content"> |  | ||||||
|         <div class="modal-header"> |  | ||||||
|           <h5>Searching...</h5> |  | ||||||
|         </div> |  | ||||||
|         <div class="modal-body"> |  | ||||||
|           <div class="progress"> |  | ||||||
|             <div class="progress-bar progress-bar-striped progress-bar-animated bg-success" role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width:100%;"></div> |  | ||||||
|           </div> |  | ||||||
|         </div> |  | ||||||
|       </div><!-- /.modal-content --> |  | ||||||
|     </div><!-- /.modal-dialog --> |  | ||||||
|   </div><!-- /.modal --> |  | ||||||
|  |  | ||||||
|   <!-- Bootstrap core JavaScript |   <!-- Bootstrap core JavaScript | ||||||
|   ================================================== --> |   ================================================== --> | ||||||
|   <!-- Placed at the end of the document so the pages load faster --> |   <!-- Placed at the end of the document so the pages load faster --> | ||||||
| @@ -376,7 +403,6 @@ | |||||||
|   <script src="js/bootstrap-slider.min.js"></script> |   <script src="js/bootstrap-slider.min.js"></script> | ||||||
|   <script src="js/bootstrap-notify.min.js"></script> |   <script src="js/bootstrap-notify.min.js"></script> | ||||||
|   <script src="js/sammy.js"></script> |   <script src="js/sammy.js"></script> | ||||||
|   <script src="js/jquery-ui-sortable.min.js"></script> |  | ||||||
|   <script src="js/mpd.js"></script> |   <script src="js/mpd.js"></script> | ||||||
|   <script src="js/custom.js"></script></body> |   <script src="js/custom.js"></script></body> | ||||||
| </html> | </html> | ||||||
|   | |||||||
| @@ -1,3 +1,2 @@ | |||||||
| //Remove some buttons | //Remove some buttons | ||||||
| //document.getElementById('btnlove').parentNode.style.display='none'; |  | ||||||
| document.getElementById('player').parentNode.style.display='none'; | document.getElementById('player').parentNode.style.display='none'; | ||||||
|   | |||||||
							
								
								
									
										589
									
								
								htdocs/js/mpd.js
									
									
									
									
									
								
							
							
						
						
									
										589
									
								
								htdocs/js/mpd.js
									
									
									
									
									
								
							| @@ -22,8 +22,6 @@ | |||||||
|    Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |    Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||||
| */ | */ | ||||||
|  |  | ||||||
| var TOKEN = ""; |  | ||||||
|  |  | ||||||
| var socket; | var socket; | ||||||
| var last_state; | var last_state; | ||||||
| var last_outputs; | var last_outputs; | ||||||
| @@ -33,39 +31,21 @@ var browsepath = ""; | |||||||
| var lastSongTitle = ""; | var lastSongTitle = ""; | ||||||
| var current_song = new Object(); | var current_song = new Object(); | ||||||
| var MAX_ELEMENTS_PER_PAGE = 100; | var MAX_ELEMENTS_PER_PAGE = 100; | ||||||
| var dirble_selected_cat = ""; |  | ||||||
| var dirble_catid = ""; |  | ||||||
| var dirble_page = 1; |  | ||||||
| var isTouch = Modernizr.touch ? 1 : 0; | var isTouch = Modernizr.touch ? 1 : 0; | ||||||
| var filter = ""; | var filter = ""; | ||||||
| var dirble_api_token = ""; |  | ||||||
| var dirble_stations = false; |  | ||||||
| var playstate = ""; | var playstate = ""; | ||||||
| var progressBar; | var progressBar; | ||||||
| var volumeBar; | var volumeBar; | ||||||
|  |  | ||||||
| var app = $.sammy(function() { | var app = $.sammy(function() { | ||||||
|  |  | ||||||
|     function runBrowse() { |  | ||||||
|         current_app = 'queue'; |  | ||||||
|         $('#nowplaying').addClass('hide'); |  | ||||||
|         $('#breadcrumb').addClass('hide'); |  | ||||||
|         $('#filter-toolbar').addClass('hide'); |  | ||||||
|         $('#salamisandwich').removeClass('hide').find("tr:gt(0)").remove(); |  | ||||||
|         $('#dirble_panel').addClass('hide'); |  | ||||||
|         socket.send('MPD_API_GET_QUEUE,'+pagination); |  | ||||||
|  |  | ||||||
|         $('#panel-heading').text("Queue"); |  | ||||||
|         $('#panel-heading-info').empty(); |  | ||||||
|         $('#queue-buttons').removeClass('hide'); |  | ||||||
|  |  | ||||||
|         $('#nav-queue').addClass('active'); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     function prepare() { |     function prepare() { | ||||||
|         $('#navbar-bottom > div').removeClass('active'); |         $('#navbar-bottom > div').removeClass('active'); | ||||||
|  |         $('#cardPlayback').addClass('hide'); | ||||||
|  |         $('#cardQueue').addClass('hide'); | ||||||
|  |         $('#cardBrowse').addClass('hide'); | ||||||
|  |         $('#cardSearch').addClass('hide'); | ||||||
|         $('.page-item').addClass('hide'); |         $('.page-item').addClass('hide'); | ||||||
|         $('#add-all-songs').addClass('hide'); |  | ||||||
|         pagination = 0; |         pagination = 0; | ||||||
|         browsepath = ''; |         browsepath = ''; | ||||||
|     } |     } | ||||||
| @@ -73,21 +53,19 @@ var app = $.sammy(function() { | |||||||
|     this.get (/\#\/playing\//, function() { |     this.get (/\#\/playing\//, function() { | ||||||
|         prepare(); |         prepare(); | ||||||
|         current_app = 'nowplaying'; |         current_app = 'nowplaying'; | ||||||
|         $('#breadcrumb').addClass('hide'); |         $('#cardPlayback').removeClass('hide'); | ||||||
|         $('#salamisandwich').addClass('hide'); |         $('#navPlayback').addClass('active'); | ||||||
|         $('#filter-toolbar').addClass('hide'); |  | ||||||
|         $('#dirble_panel').addClass('hide'); |  | ||||||
|         $('#queue-buttons').addClass('hide'); |  | ||||||
|         $('#panel-heading').text("Now playing"); |  | ||||||
|         $('#panel-heading-info').empty(); |  | ||||||
|         $('#nowplaying').removeClass('hide'); |  | ||||||
|         $('#nav-playing').addClass('active'); |  | ||||||
|     });     |     });     | ||||||
|  |  | ||||||
|     this.get(/\#\/queue\/(\d+)/, function() { |     this.get(/\#\/queue\/(\d+)/, function() { | ||||||
|         prepare(); |         prepare(); | ||||||
|  |         current_app = 'queue'; | ||||||
|  |         $('#navQueue').addClass('active'); | ||||||
|  |         $('#cardQueue').removeClass('hide'); | ||||||
|  |         $('#panel-heading-queue').empty(); | ||||||
|         pagination = parseInt(this.params['splat'][0]); |         pagination = parseInt(this.params['splat'][0]); | ||||||
|         runBrowse(); |         $('#queueList').find("tr:gt(0)").remove(); | ||||||
|  |         socket.send('MPD_API_GET_QUEUE,'+pagination);         | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     this.get(/\#\/browse\/(\d+)\/(.*)/, function() { |     this.get(/\#\/browse\/(\d+)\/(.*)/, function() { | ||||||
| @@ -95,110 +73,57 @@ var app = $.sammy(function() { | |||||||
|         browsepath = this.params['splat'][1]; |         browsepath = this.params['splat'][1]; | ||||||
|         pagination = parseInt(this.params['splat'][0]); |         pagination = parseInt(this.params['splat'][0]); | ||||||
|         current_app = 'browse'; |         current_app = 'browse'; | ||||||
|         $('#breadcrumb').removeClass('hide').empty().append("<li class=\"breadcrumb-item\"><a uri=\"\" onclick=\"set_filter('')\">root</a></li>"); |         $('#navBrowse').addClass('active'); | ||||||
|         $('#filter-toolbar').removeClass('hide'); |         $('#cardBrowse').removeClass('hide'); | ||||||
|         $('#salamisandwich').removeClass('hide').find("tr:gt(0)").remove(); |         $('#browseList').find("tr:gt(0)").remove(); | ||||||
|         $('#dirble_panel').addClass('hide'); |         $('#browseBreadcrumb').empty().append("<li class=\"breadcrumb-item\"><a uri=\"\" onclick=\"set_filter('')\">root</a></li>"); | ||||||
|         $('#queue-buttons').addClass('hide'); |  | ||||||
|         $('#nowplaying').addClass('hide'); |  | ||||||
|         $('#nav-browse').addClass('active'); |  | ||||||
|         socket.send('MPD_API_GET_BROWSE,'+pagination+','+(browsepath ? browsepath : "/")); |         socket.send('MPD_API_GET_BROWSE,'+pagination+','+(browsepath ? browsepath : "/")); | ||||||
|         // Don't add all songs from root |         // Don't add all songs from root | ||||||
|  |         var add_all_songs = $('#add-all-songs'); | ||||||
|         if (browsepath) { |         if (browsepath) { | ||||||
|             var add_all_songs = $('#add-all-songs'); |  | ||||||
|             add_all_songs.off(); // remove previous binds |             add_all_songs.off(); // remove previous binds | ||||||
|             add_all_songs.on('click', function() { |             add_all_songs.on('click', function() { | ||||||
|                 socket.send('MPD_API_ADD_TRACK,'+browsepath); |                 socket.send('MPD_API_ADD_TRACK,'+browsepath); | ||||||
|             }); |             }); | ||||||
|             add_all_songs.removeClass('hide'); |             add_all_songs.removeClass('hide'); | ||||||
|  |         } else { | ||||||
|  |             add_all_songs.addClass('hide'); | ||||||
|         } |         } | ||||||
|         $('#panel-heading').text("Browse database: /"+browsepath); |         $('#panel-heading-browse').text("Browse database: /"+browsepath); | ||||||
|         $('#panel-heading-info').empty(); |  | ||||||
|  |  | ||||||
|         var path_array = browsepath.split('/'); |         var path_array = browsepath.split('/'); | ||||||
|         var full_path = ""; |         var full_path = ""; | ||||||
|         $.each(path_array, function(index, chunk) { |         $.each(path_array, function(index, chunk) { | ||||||
|             if(path_array.length - 1 == index) { |             if(path_array.length - 1 == index) { | ||||||
|                 $('#breadcrumb').append("<li class=\"breadcrumb-item active\">"+ chunk + "</li>"); |                 $('#browseBreadcrumb').append("<li class=\"breadcrumb-item active\">"+ chunk + "</li>"); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             full_path = full_path + chunk; |             full_path = full_path + chunk; | ||||||
|             $('#breadcrumb').append("<li class=\"breadcrumb-item\"><a uri=\"" + full_path + "\">"+chunk+"</a></li>"); |             $('#browseBreadcrumb').append("<li class=\"breadcrumb-item\"><a uri=\"" + full_path + "\">"+chunk+"</a></li>"); | ||||||
|             full_path += "/"; |             full_path += "/"; | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     this.get(/\#\/search\/(.*)/, function() { |     this.get(/\#\/search\/(.*)/, function() { | ||||||
|  |  | ||||||
|  |         prepare(); | ||||||
|         current_app = 'search'; |         current_app = 'search'; | ||||||
|         $('#salamisandwich').removeClass('hide').find("tr:gt(0)").remove(); |         $('#cardSearch').removeClass('hide'); | ||||||
|         $('#nowplaying').addClass('hide'); |  | ||||||
|         $('#dirble_panel').addClass('hide'); |  | ||||||
|         $('#filter-toolbar').addClass('hide'); |  | ||||||
|         var searchstr = this.params['splat'][0]; |         var searchstr = this.params['splat'][0]; | ||||||
|  |  | ||||||
|         $('#search > input').val(searchstr); |         $('#search > input').val(searchstr); | ||||||
|         socket.send('MPD_API_SEARCH,' + searchstr); |         socket.send('MPD_API_SEARCH,' + searchstr); | ||||||
|  |         $('#searchList').find("tr:gt(0)").remove(); | ||||||
|         $('#panel-heading').text("Search: "+searchstr); |         $('#searchList > tbody').append( | ||||||
|     }); |             "<tr><td><span class=\"material-icons\">search</span></td>" + | ||||||
|  |             "<td colspan=\"3\">Searching</td>" + | ||||||
|     this.get(/\#\/dirble\/(\d+)\/(\d+)/, function() { |             "<td></td><td></td></tr>"); | ||||||
|          |         $('#panel-heading-search').text("Search: "+searchstr); | ||||||
|         if (TOKEN === "") context.redirect("#/0"); |  | ||||||
|          |  | ||||||
|         prepare(); |  | ||||||
|         current_app = 'dirble'; |  | ||||||
|         $('#breadcrumb').removeClass('hide').empty().append("<li><a href=\"#/dirble/\">Categories</a></li><li>"+dirble_selected_cat+"</li>"); |  | ||||||
|         $('#salamisandwich').addClass('hide'); |  | ||||||
|         $('#dirble_panel').removeClass('hide'); |  | ||||||
|         $('#dirble_loading').removeClass('hide'); |  | ||||||
|         $('#dirble_left').find("tr:gt(0)").remove(); |  | ||||||
|         $('#dirble_right').find("tr:gt(0)").remove(); |  | ||||||
|  |  | ||||||
|         $('#panel-heading').text("Dirble"); |  | ||||||
|         $('#panel-heading-info').empty(); |  | ||||||
|  |  | ||||||
|         $('#dirble-nav').addClass('active'); |  | ||||||
|  |  | ||||||
|         $('#next').addClass('hide'); |  | ||||||
|  |  | ||||||
|         if (this.params['splat'][1] > 1) $('#prev').removeClass('hide'); |  | ||||||
|         else $('#prev').addClass('hide'); |  | ||||||
|  |  | ||||||
|         dirble_catid = this.params['splat'][0]; |  | ||||||
|         dirble_page = this.params['splat'][1]; |  | ||||||
|  |  | ||||||
|         dirble_stations = true; |  | ||||||
|  |  | ||||||
|         if (dirble_api_token) { dirble_load_stations(); } |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     this.get(/\#\/dirble\//, function() { |  | ||||||
|          |  | ||||||
|         if (TOKEN === "") context.redirect("#/0"); |  | ||||||
|          |  | ||||||
|         prepare(); |  | ||||||
|         current_app = 'dirble'; |  | ||||||
|         $('#breadcrumb').removeClass('hide').empty().append("<li>Categories</li>"); |  | ||||||
|         $('#salamisandwich').addClass('hide'); |  | ||||||
|         $('#dirble_panel').removeClass('hide'); |  | ||||||
|         $('#dirble_loading').removeClass('hide'); |  | ||||||
|         $('#dirble_left').find("tr:gt(0)").remove(); |  | ||||||
|         $('#dirble_right').find("tr:gt(0)").remove(); |  | ||||||
|  |  | ||||||
|         $('#panel-heading').text("Dirble"); |  | ||||||
|         $('#panel-heading-info').empty(); |  | ||||||
|  |  | ||||||
|         $('#dirble').addClass('active'); |  | ||||||
|  |  | ||||||
|         dirble_stations = false; |  | ||||||
|  |  | ||||||
|         if (dirble_api_token) { dirble_load_categories(); } |  | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     this.get("/", function(context) { |     this.get("/", function(context) { | ||||||
|         context.redirect("#\/playing/"); |         context.redirect("#/playing/"); | ||||||
|     }); |     }); | ||||||
|      |      | ||||||
| }); | }); | ||||||
| @@ -230,10 +155,13 @@ $(document).ready(function(){ | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     if(!notificationsSupported()) |     if(!notificationsSupported()) | ||||||
|         $('#btnnotify').addClass("disabled"); |         $('#btnnotifyWeb').addClass("disabled"); | ||||||
|     else |     else | ||||||
|         if ($.cookie("notification") === "true") |         if ($.cookie("notificationWeb") === "true") | ||||||
|             $('#btnnotify').removeClass('btn-secondary').addClass("btn-success") |             $('#btnnotifyWeb').removeClass('btn-secondary').addClass("btn-success") | ||||||
|  |      | ||||||
|  |     if ($.cookie("notificationPage") === "true") | ||||||
|  |         $('#btnnotifyPage').removeClass('btn-secondary').addClass("btn-success") | ||||||
|  |  | ||||||
|     add_filter(); |     add_filter(); | ||||||
| 	 | 	 | ||||||
| @@ -296,7 +224,6 @@ $(document).ready(function(){ | |||||||
| 		} | 		} | ||||||
| 	}, true); | 	}, true); | ||||||
|              |              | ||||||
|     if (TOKEN === "") $('#nav-dirble').addClass('hide'); |  | ||||||
| }); | }); | ||||||
|  |  | ||||||
| function webSocketConnect() { | function webSocketConnect() { | ||||||
| @@ -309,14 +236,11 @@ function webSocketConnect() { | |||||||
|     try { |     try { | ||||||
|         socket.onopen = function() { |         socket.onopen = function() { | ||||||
|             console.log("connected"); |             console.log("connected"); | ||||||
|              |             showNotification('Connected to myMPD','','','success'); | ||||||
|             $.notify({message:"Connected to myMPD" },{ type: "success", offset: { y: 60, x:20 }}); |  | ||||||
|                  |                  | ||||||
|             app.run(); |             app.run(); | ||||||
|             /* emit initial request for output names */ |             /* emit initial request for output names */ | ||||||
|             socket.send('MPD_API_GET_OUTPUTS'); |             socket.send('MPD_API_GET_OUTPUTS'); | ||||||
|             /* emit initial request for dirble api token */ |  | ||||||
|             socket.send('MPD_API_GET_DIRBLEAPITOKEN'); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         socket.onmessage = function got_packet(msg) { |         socket.onmessage = function got_packet(msg) { | ||||||
| @@ -325,7 +249,7 @@ function webSocketConnect() { | |||||||
|             try { |             try { | ||||||
|               var obj = JSON.parse(msg.data); |               var obj = JSON.parse(msg.data); | ||||||
|             } catch(e) { |             } catch(e) { | ||||||
|               $.notify({ title: "Invalid JSON Data received", message: msg.data},{ type: "success", offset: { y: 60, x:20 }}); |               showNotification('Invalid JSON data received', msg.data, msg.data,'success'); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             switch (obj.type) { |             switch (obj.type) { | ||||||
| @@ -339,20 +263,20 @@ function webSocketConnect() { | |||||||
|                         var minutes = Math.floor(obj.totalTime / 60) - hours * 60 - days * 1440; |                         var minutes = Math.floor(obj.totalTime / 60) - hours * 60 - days * 1440; | ||||||
|                         var seconds = obj.totalTime - days * 86400 - hours * 3600 - minutes * 60; |                         var seconds = obj.totalTime - days * 86400 - hours * 3600 - minutes * 60; | ||||||
|  |  | ||||||
|                         $('#panel-heading-info').text(obj.totalSongs+' Songs – ' + |                         $('#panel-heading-queue').text(obj.totalSongs+' Songs – ' + | ||||||
|                             (days > 0 ? days + '\u2009d ' : '') + |                             (days > 0 ? days + '\u2009d ' : '') + | ||||||
|                             (hours > 0 ? hours + '\u2009h ' + (minutes < 10 ? '0' : '') : '') + |                             (hours > 0 ? hours + '\u2009h ' + (minutes < 10 ? '0' : '') : '') + | ||||||
|                             minutes + '\u2009m ' + (seconds < 10 ? '0' : '') + seconds + '\u2009s'); |                             minutes + '\u2009m ' + (seconds < 10 ? '0' : '') + seconds + '\u2009s'); | ||||||
|                     } else { |                     } else { | ||||||
|                         $('#panel-heading-info').empty(); |                         $('#panel-heading-queue').empty(); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     $('#salamisandwich > tbody').empty(); |                     $('#queueList > tbody').empty(); | ||||||
|                     for (var song in obj.data) { |                     for (var song in obj.data) { | ||||||
|                         var minutes = Math.floor(obj.data[song].duration / 60); |                         var minutes = Math.floor(obj.data[song].duration / 60); | ||||||
|                         var seconds = obj.data[song].duration - minutes * 60; |                         var seconds = obj.data[song].duration - minutes * 60; | ||||||
|  |  | ||||||
|                         $('#salamisandwich > tbody').append( |                         $('#queueList > tbody').append( | ||||||
|                             "<tr trackid=\"" + obj.data[song].id + "\"><td>" + (obj.data[song].pos + 1) + "</td>" + |                             "<tr trackid=\"" + obj.data[song].id + "\"><td>" + (obj.data[song].pos + 1) + "</td>" + | ||||||
|                                 "<td>"+ obj.data[song].artist +"</td>" +  |                                 "<td>"+ obj.data[song].artist +"</td>" +  | ||||||
|                                 "<td>"+ obj.data[song].album +"</td>" + |                                 "<td>"+ obj.data[song].album +"</td>" + | ||||||
| @@ -362,22 +286,22 @@ function webSocketConnect() { | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if(obj.data.length && obj.data[obj.data.length-1].pos + 1 >= pagination + MAX_ELEMENTS_PER_PAGE) |                     if(obj.data.length && obj.data[obj.data.length-1].pos + 1 >= pagination + MAX_ELEMENTS_PER_PAGE) | ||||||
|                         $('#next').removeClass('hide'); |                         $('#queueNext').removeClass('hide'); | ||||||
|                     if(pagination > 0) |                     if(pagination > 0) | ||||||
|                         $('#prev').removeClass('hide'); |                         $('#queuePrev').removeClass('hide'); | ||||||
|                     if ( isTouch ) { |                     if ( isTouch ) { | ||||||
|                         $('#salamisandwich > tbody > tr > td:last-child').append( |                         $('#queueList > tbody > tr > td:last-child').append( | ||||||
|                                     "<a class=\"pull-right btn-group-hover color-darkgrey\" href=\"#/\" " + |                                     "<a class=\"pull-right btn-group-hover color-darkgrey\" href=\"#/\" " + | ||||||
|                                         "onclick=\"trash($(this).parents('tr'));\">" + |                                         "onclick=\"trash($(this).parents('tr'));\">" + | ||||||
|                                 "<span class=\"material-icons\">delete</span></a>"); |                                 "<span class=\"material-icons\">delete</span></a>"); | ||||||
|                     } else { |                     } else { | ||||||
|                         $('#salamisandwich > tbody > tr').on({ |                         $('#queueList > tbody > tr').on({ | ||||||
|                             mouseover: function(){ |                             mouseover: function(){ | ||||||
|                                 var doomed = $(this); |                                 var doomed = $(this); | ||||||
|                                 if ( $('#btntrashmodeup').hasClass('btn-success') ) |                                 if ( $('#btntrashmodeup').hasClass('btn-success') ) | ||||||
|                                     doomed = $("#salamisandwich > tbody > tr:lt(" + ($(this).index() + 1) + ")"); |                                     doomed = $("#queueList > tbody > tr:lt(" + ($(this).index() + 1) + ")"); | ||||||
|                                 if ( $('#btntrashmodedown').hasClass('btn-success') ) |                                 if ( $('#btntrashmodedown').hasClass('btn-success') ) | ||||||
|                                     doomed = $("#salamisandwich > tbody > tr:gt(" + ($(this).index() - 1) + ")"); |                                     doomed = $("#queueList > tbody > tr:gt(" + ($(this).index() - 1) + ")"); | ||||||
|                                 $.each(doomed, function(){ |                                 $.each(doomed, function(){ | ||||||
|                                 if($(this).children().last().has("a").length == 0) |                                 if($(this).children().last().has("a").length == 0) | ||||||
|                                     $(this).children().last().append( |                                     $(this).children().last().append( | ||||||
| @@ -390,52 +314,35 @@ function webSocketConnect() { | |||||||
|                             mouseleave: function(){ |                             mouseleave: function(){ | ||||||
|                                 var doomed = $(this); |                                 var doomed = $(this); | ||||||
|                                 if ( $('#btntrashmodeup').hasClass('btn-success') ) |                                 if ( $('#btntrashmodeup').hasClass('btn-success') ) | ||||||
|                                     doomed = $("#salamisandwich > tbody > tr:lt(" + ($(this).index() + 1) + ")"); |                                     doomed = $("#queueList > tbody > tr:lt(" + ($(this).index() + 1) + ")"); | ||||||
|                                 if ( $('#btntrashmodedown').hasClass('btn-success') ) |                                 if ( $('#btntrashmodedown').hasClass('btn-success') ) | ||||||
|                                     doomed = $("#salamisandwich > tbody > tr:gt(" + ($(this).index() - 1) + ")"); |                                     doomed = $("#queueList > tbody > tr:gt(" + ($(this).index() - 1) + ")"); | ||||||
|                                 $.each(doomed, function(){$(this).children().last().find("a").stop().remove();}); |                                 $.each(doomed, function(){$(this).children().last().find("a").stop().remove();}); | ||||||
|                             } |                             } | ||||||
|                         }); |                         }); | ||||||
|                     }; |                     }; | ||||||
|  |  | ||||||
|                     $('#salamisandwich > tbody > tr').on({ |                     $('#queueList > tbody > tr').on({ | ||||||
|                         click: function() { |                         click: function() { | ||||||
|                             $('#salamisandwich > tbody > tr').removeClass('active'); |                             $('#queueList > tbody > tr').removeClass('active'); | ||||||
|                             socket.send('MPD_API_PLAY_TRACK,'+$(this).attr('trackid')); |                             socket.send('MPD_API_PLAY_TRACK,'+$(this).attr('trackid')); | ||||||
|                             $(this).addClass('active'); |                             $(this).addClass('active'); | ||||||
|                         }, |                         }, | ||||||
|                     }); |                     }); | ||||||
|                     //Helper function to keep table row from collapsing when being sorted |  | ||||||
|                     var fixHelperModified = function(e, tr) { |  | ||||||
|                       var $originals = tr.children(); |  | ||||||
|                       var $helper = tr.clone(); |  | ||||||
|                       $helper.children().each(function(index) |  | ||||||
|                       { |  | ||||||
|                         $(this).width($originals.eq(index).width()) |  | ||||||
|                       }); |  | ||||||
|                       return $helper; |  | ||||||
|                     }; |  | ||||||
|                      |  | ||||||
|                     //Make queue table sortable |  | ||||||
|                     $('#salamisandwich > tbody').sortable({ |  | ||||||
|                       helper: fixHelperModified, |  | ||||||
|                       stop: function(event,ui) {renumber_table('#salamisandwich',ui.item)} |  | ||||||
|                     }).disableSelection(); |  | ||||||
|                     break; |                     break; | ||||||
|                 case 'search': |                 case 'search': | ||||||
|                     $('#wait').modal('hide'); |                     $('#searchList').find("tr:gt(0)").remove(); | ||||||
|                 case 'browse': |                 case 'browse': | ||||||
|                     if(current_app !== 'browse' && current_app !== 'search') |                     if(current_app !== 'browse' && current_app !== 'search') | ||||||
|                         break; |                         break; | ||||||
|  |                      | ||||||
|                     /* The use of encodeURI() below might seem useless, but it's not. It prevents |                     /* The use of encodeURI() below might seem useless, but it's not. It prevents | ||||||
|                      * some browsers, such as Safari, from changing the normalization form of the |                      * some browsers, such as Safari, from changing the normalization form of the | ||||||
|                      * URI from NFD to NFC, breaking our link with MPD. |                      * URI from NFD to NFC, breaking our link with MPD. | ||||||
|                      */ |                      */ | ||||||
|                     if ($('#salamisandwich > tbody').is(':ui-sortable')) { |                     var nrItems=0; | ||||||
|                         $('#salamisandwich > tbody').sortable('destroy'); |  | ||||||
|                     } |  | ||||||
|                     for (var item in obj.data) { |                     for (var item in obj.data) { | ||||||
|  |                         nrItems++; | ||||||
|                         switch(obj.data[item].type) { |                         switch(obj.data[item].type) { | ||||||
|                             case 'directory': |                             case 'directory': | ||||||
|                                 var clazz = 'dir'; |                                 var clazz = 'dir'; | ||||||
| @@ -449,7 +356,7 @@ function webSocketConnect() { | |||||||
|                                         clazz += ' hide'; |                                         clazz += ' hide'; | ||||||
|                                     } |                                     } | ||||||
|                                 } |                                 } | ||||||
|                                 $('#salamisandwich > tbody').append( |                                 $('#'+current_app+'List > tbody').append( | ||||||
|                                     "<tr uri=\"" + encodeURI(obj.data[item].dir) + "\" class=\"" + clazz + "\">" + |                                     "<tr uri=\"" + encodeURI(obj.data[item].dir) + "\" class=\"" + clazz + "\">" + | ||||||
|                                     "<td><span class=\"material-icons\">folder_open</span></td>" + |                                     "<td><span class=\"material-icons\">folder_open</span></td>" + | ||||||
|                                     "<td colspan=\"3\"><a>" + basename(obj.data[item].dir) + "</a></td>" + |                                     "<td colspan=\"3\"><a>" + basename(obj.data[item].dir) + "</a></td>" + | ||||||
| @@ -461,7 +368,7 @@ function webSocketConnect() { | |||||||
|                                 if ( (filter !== "") && (filter !== "plist") ) { |                                 if ( (filter !== "") && (filter !== "plist") ) { | ||||||
|                                     clazz += ' hide'; |                                     clazz += ' hide'; | ||||||
|                                 } |                                 } | ||||||
|                                 $('#salamisandwich > tbody').append( |                                 $('#'+current_app+'List > tbody').append( | ||||||
|                                     "<tr uri=\"" + encodeURI(obj.data[item].plist) + "\" class=\"" + clazz + "\">" + |                                     "<tr uri=\"" + encodeURI(obj.data[item].plist) + "\" class=\"" + clazz + "\">" + | ||||||
|                                     "<td><span class=\"material-icons\">list</span></td>" + |                                     "<td><span class=\"material-icons\">list</span></td>" + | ||||||
|                                     "<td colspan=\"3\"><a>" + basename(obj.data[item].plist) + "</a></td>" + |                                     "<td colspan=\"3\"><a>" + basename(obj.data[item].plist) + "</a></td>" + | ||||||
| @@ -479,7 +386,7 @@ function webSocketConnect() { | |||||||
|                                                      "<span>" + obj.data[item].album + "</span></td><td>"; |                                                      "<span>" + obj.data[item].album + "</span></td><td>"; | ||||||
|                                 } |                                 } | ||||||
|  |  | ||||||
|                                 $('#salamisandwich > tbody').append( |                                 $('#'+current_app+'List > tbody').append( | ||||||
|                                     "<tr uri=\"" + encodeURI(obj.data[item].uri) + "\" class=\"song\">" + |                                     "<tr uri=\"" + encodeURI(obj.data[item].uri) + "\" class=\"song\">" + | ||||||
|                                     "<td><span class=\"material-icons\">music_note</span></td>" +  |                                     "<td><span class=\"material-icons\">music_note</span></td>" +  | ||||||
|                                     "<td>" + obj.data[item].artist + "</td>" +  |                                     "<td>" + obj.data[item].artist + "</td>" +  | ||||||
| @@ -491,9 +398,9 @@ function webSocketConnect() { | |||||||
|                                 break; |                                 break; | ||||||
|                             case 'wrap': |                             case 'wrap': | ||||||
|                                 if(current_app == 'browse') { |                                 if(current_app == 'browse') { | ||||||
|                                     $('#next').removeClass('hide'); |                                     $('#browseNext').removeClass('hide'); | ||||||
|                                 } else { |                                 } else { | ||||||
|                                     $('#salamisandwich > tbody').append( |                                     $('#'+current_app+'List > tbody').append( | ||||||
|                                         "<tr><td><span class=\"material-icons\">error_outline</span></td>" + |                                         "<tr><td><span class=\"material-icons\">error_outline</span></td>" + | ||||||
|                                         "<td colspan=\"3\">Too many results, please refine your search!</td>" + |                                         "<td colspan=\"3\">Too many results, please refine your search!</td>" + | ||||||
|                                         "<td></td><td></td></tr>" |                                         "<td></td><td></td></tr>" | ||||||
| @@ -503,9 +410,18 @@ function webSocketConnect() { | |||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         if(pagination > 0) |                         if(pagination > 0) | ||||||
|                             $('#prev').removeClass('hide'); |                             $('#browsePrev').removeClass('hide'); | ||||||
|  |  | ||||||
|                     } |                     } | ||||||
|  |                      | ||||||
|  |                     if (current_app == 'search') | ||||||
|  |                        if (nrItems == 0) { | ||||||
|  |                            $('#'+current_app+'List > tbody').append( | ||||||
|  |                                "<tr><td><span class=\"material-icons\">error_outline</span></td>" + | ||||||
|  |                                "<td colspan=\"3\">No results, please refine your search!</td>" + | ||||||
|  |                                "<td></td><td></td></tr>" | ||||||
|  |                            ); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|                     function appendClickableIcon(appendTo, onClickAction, glyphicon) { |                     function appendClickableIcon(appendTo, onClickAction, glyphicon) { | ||||||
|                         $(appendTo).append( |                         $(appendTo).append( | ||||||
| @@ -514,15 +430,15 @@ function webSocketConnect() { | |||||||
|                             .find('a').click(function(e) { |                             .find('a').click(function(e) { | ||||||
|                                 e.stopPropagation(); |                                 e.stopPropagation(); | ||||||
|                                 socket.send(onClickAction + "," + decodeURI($(this).parents("tr").attr("uri"))); |                                 socket.send(onClickAction + "," + decodeURI($(this).parents("tr").attr("uri"))); | ||||||
|                             $.notify({message: "\"" + $('td:nth-last-child(3)', $(this).parents("tr")).text() + "\" added"},{ type: "success", offset: { y: 60, x:20 }}); |                                 showNotification('"' + $('td:nth-last-child(3)', $(this).parents('tr')).text() + '" added','','','success'); | ||||||
|                             }); |                             }); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if ( isTouch ) { |                     if ( isTouch ) { | ||||||
|                         appendClickableIcon($("#salamisandwich > tbody > tr.dir > td:last-child"), 'MPD_API_ADD_TRACK', 'playlist_add'); |                         appendClickableIcon($('#'+current_app+'List > tbody > tr.dir > td:last-child'), 'MPD_API_ADD_TRACK', 'playlist_add'); | ||||||
|                         appendClickableIcon($("#salamisandwich > tbody > tr.song > td:last-child"), 'MPD_API_ADD_TRACK', 'playlist_add'); |                         appendClickableIcon($('#'+current_app+'List > tbody > tr.song > td:last-child'), 'MPD_API_ADD_TRACK', 'playlist_add'); | ||||||
|                     } else { |                     } else { | ||||||
|                         $('#salamisandwich > tbody > tr').on({ |                         $('#'+current_app+'List > tbody > tr').on({ | ||||||
|                             mouseenter: function() { |                             mouseenter: function() { | ||||||
|                                 if($(this).is(".dir"))  |                                 if($(this).is(".dir"))  | ||||||
|                                     appendClickableIcon($(this).children().last(), 'MPD_API_ADD_TRACK', 'playlist_add'); |                                     appendClickableIcon($(this).children().last(), 'MPD_API_ADD_TRACK', 'playlist_add'); | ||||||
| @@ -534,7 +450,7 @@ function webSocketConnect() { | |||||||
|                             } |                             } | ||||||
|                         }); |                         }); | ||||||
|                     }; |                     }; | ||||||
|                     $('#salamisandwich > tbody > tr').on({ |                     $('#'+current_app+'List > tbody > tr').on({ | ||||||
|                         click: function() { |                         click: function() { | ||||||
|                             switch($(this).attr('class')) { |                             switch($(this).attr('class')) { | ||||||
|                                 case 'dir': |                                 case 'dir': | ||||||
| @@ -547,27 +463,26 @@ function webSocketConnect() { | |||||||
|                                     break; |                                     break; | ||||||
|                                 case 'song': |                                 case 'song': | ||||||
|                                     socket.send("MPD_API_ADD_TRACK," + decodeURI($(this).attr("uri"))); |                                     socket.send("MPD_API_ADD_TRACK," + decodeURI($(this).attr("uri"))); | ||||||
|                                      |                                     showNotification('"' + $('td:nth-last-child(3)', this).text() + '" added','','','success'); | ||||||
|                                     $.notify({message: "\"" + $('td:nth-last-child(3)', this).text() + "\" added"},{ type: "success", offset: { y: 60, x:20 }}); |  | ||||||
|                                     break; |                                     break; | ||||||
|                                 case 'plist': |                                 case 'plist': | ||||||
|                                     socket.send("MPD_API_ADD_PLAYLIST," + decodeURI($(this).attr("uri"))); |                                     socket.send("MPD_API_ADD_PLAYLIST," + decodeURI($(this).attr("uri"))); | ||||||
|                                     $.notify({message: "\"" + $('td:nth-last-child(3)', this).text() + "\" added"},{ type: "success", offset: { y: 60, x:20 }}); |                                     showNotification('"' + $('td:nth-last-child(3)', this).text() + '" added','','','success'); | ||||||
|                                     break; |                                     break; | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     }); |                     }); | ||||||
|  |  | ||||||
| 					$('#breadcrumb > li > a').on({ |                     $('#browseBreadcrumb > li > a').on({ | ||||||
| 						click: function() { | 			click: function() { | ||||||
| 							pagination = 0; | 		        	pagination = 0; | ||||||
| 							browsepath = $(this).attr("uri"); | 				browsepath = $(this).attr("uri"); | ||||||
| 							$("#browse > a").attr("href", '#/browse/'+pagination+'/'+browsepath); | 				$("#browse > a").attr("href", '#/browse/'+pagination+'/'+browsepath); | ||||||
| 							$('#filter > a').attr("href", '#/browse/'+pagination+'/'+browsepath); | 				$('#filter > a').attr("href", '#/browse/'+pagination+'/'+browsepath); | ||||||
| 							app.setLocation('#/browse/'+pagination+'/'+browsepath); | 				app.setLocation('#/browse/'+pagination+'/'+browsepath); | ||||||
| 							set_filter(''); | 				set_filter(''); | ||||||
| 						} | 			} | ||||||
| 					}); |                     }); | ||||||
|  |  | ||||||
|                     break; |                     break; | ||||||
|                 case 'state': |                 case 'state': | ||||||
| @@ -650,37 +565,28 @@ function webSocketConnect() { | |||||||
|                     last_outputs = obj; |                     last_outputs = obj; | ||||||
|                     break; |                     break; | ||||||
|                 case 'disconnected': |                 case 'disconnected': | ||||||
|                     $.notify({message: "myMPD lost connection to MPD "},{ type: "danger", offset: { y: 60, x:20 }}); |                     showNotification('myMPD lost connection to MPD','','','danger'); | ||||||
|                     break; |                     break; | ||||||
|                 case 'update_queue': |                 case 'update_queue': | ||||||
|                     if(current_app === 'queue') |                     if(current_app === 'queue') | ||||||
|                         socket.send('MPD_API_GET_QUEUE,'+pagination); |                         socket.send('MPD_API_GET_QUEUE,'+pagination); | ||||||
|                     break; |                     break; | ||||||
|               case "song_change": |               case "song_change": | ||||||
|                     var coverImg='/library/'+obj.data.uri.replace(/\/[^\/]+$/,'\/folder.jpg'); |                     if (obj.data.uri) { | ||||||
|                     $('#album-cover').css('backgroundImage','url("'+coverImg+'")'); |                       var coverImg='/library/'+obj.data.uri.replace(/\/[^\/]+$/,'\/folder.jpg'); | ||||||
|                     updatePageTitle(obj.data); |                       $('#album-cover').css('backgroundImage','url("'+coverImg+'")'); | ||||||
|                     $('#album').text(""); |  | ||||||
|                     $('#artist').text(""); |  | ||||||
|  |  | ||||||
|                     $('#currenttrack').text(" " + obj.data.title); |  | ||||||
|                     var notification = "<strong><h4>" + obj.data.title + "</h4></strong>"; |  | ||||||
|  |  | ||||||
|                     if(obj.data.artist) { |  | ||||||
|                         $('#artist').text(obj.data.artist); |  | ||||||
|                         notification += obj.data.artist + "<br />"; |  | ||||||
|                     } |  | ||||||
|                     if(obj.data.album) { |  | ||||||
|                         $('#album').text(obj.data.album); |  | ||||||
|                         notification += obj.data.album + "<br />"; |  | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if ($.cookie("notification") === "true") |                     if (obj.data.title) { $('#currenttrack').text(obj.data.title); } | ||||||
|                         songNotify(obj.data.title, obj.data.artist, obj.data.album ); |                     else { $('#currenttrack').text(''); } | ||||||
|                     else |  | ||||||
|                         if (current_app != 'nowplaying') { |                     if(obj.data.artist) { $('#artist').text(obj.data.artist); } | ||||||
|                             $.notify({message: notification },{ type: "success", offset: { y: 60, x:20 }}); |                     else { $('#artist').text(''); } | ||||||
|                         } |  | ||||||
|  |                     if(obj.data.album) { $('#album').text(obj.data.album); } | ||||||
|  |                     else { $('#album').text(''); } | ||||||
|  |                      | ||||||
|  |                     songNotify(obj.data.title, obj.data.artist, obj.data.album); | ||||||
|                     break; |                     break; | ||||||
|                 case 'mpdhost': |                 case 'mpdhost': | ||||||
|                     $('#mpdhost').val(obj.data.host); |                     $('#mpdhost').val(obj.data.host); | ||||||
| @@ -689,21 +595,8 @@ function webSocketConnect() { | |||||||
|                     if(obj.data.passwort_set) |                     if(obj.data.passwort_set) | ||||||
|                         $('#mpd_password_set').removeClass('hide'); |                         $('#mpd_password_set').removeClass('hide'); | ||||||
|                     break; |                     break; | ||||||
|                 case 'dirbleapitoken': |  | ||||||
|                     dirble_api_token = obj.data; |  | ||||||
|                      |  | ||||||
| 		    if (dirble_api_token) { |  | ||||||
| 		        $('#dirble-nav').removeClass('hide'); |  | ||||||
|  |  | ||||||
|                         if (dirble_stations) { dirble_load_stations();   } |  | ||||||
|                         else {                 dirble_load_categories(); } |  | ||||||
|  |  | ||||||
|                     } else { |  | ||||||
|                         $('#dirble-nav').addClass('hide'); |  | ||||||
| 		    } |  | ||||||
|                     break; |  | ||||||
|                 case 'error': |                 case 'error': | ||||||
|                     $.notify({message: obj.data },{ type: "danger", offset: { y: 60, x:20 }}); |                     showNotification(obj.data,'','','danger'); | ||||||
|                 default: |                 default: | ||||||
|                     break; |                     break; | ||||||
|             } |             } | ||||||
| @@ -711,7 +604,7 @@ function webSocketConnect() { | |||||||
|  |  | ||||||
|         socket.onclose = function(){ |         socket.onclose = function(){ | ||||||
|             console.log("disconnected"); |             console.log("disconnected"); | ||||||
|             $.notify({message:"Connection to myMPD lost, retrying in 3 seconds " },{ type: "danger", offset: { y: 60, x:20 }}); |             showNotification('Connection to myMPD lost, retrying in 3 seconds','','','danger'); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     } catch(exception) { |     } catch(exception) { | ||||||
| @@ -781,23 +674,11 @@ var updatePlayIcon = function(state) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| var updatePageTitle = function(songInfo) { |  | ||||||
|     if(!songInfo || (!songInfo.artist && !songInfo.title)) { |  | ||||||
|         document.title = 'myMPD'; |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|     if(songInfo.artist) { |  | ||||||
|         if(songInfo.title) { |  | ||||||
|             document.title = 'myMPD: '+songInfo.artist + ' - ' + songInfo.title; |  | ||||||
|         } |  | ||||||
|     } else { |  | ||||||
|         document.title = 'myMPD: '+songInfo.title; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function updateDB() { | function updateDB() { | ||||||
|     socket.send('MPD_API_UPDATE_DB'); |     socket.send('MPD_API_UPDATE_DB'); | ||||||
|     $.notify({message:"Updating MPD Database..." },{ type: "success", offset: { y: 60, x:20 }}); |     showNotification('Updating MPD Database...','','','success'); | ||||||
| } | } | ||||||
|  |  | ||||||
| function clickPlay() { | function clickPlay() { | ||||||
| @@ -866,16 +747,6 @@ function trash(tr) { | |||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
| function renumber_table(tableID,item) { |  | ||||||
|     was = item.children("td").first().text();//Check if first item exists! |  | ||||||
|     is = item.index() + 1;//maybe add pagination |  | ||||||
|  |  | ||||||
|     if (was != is) { |  | ||||||
|         socket.send("MPD_API_MOVE_TRACK," + was + "," + is); |  | ||||||
|         socket.send('MPD_API_GET_QUEUE,'+pagination); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function basename(path) { | function basename(path) { | ||||||
|     return path.split('/').reverse()[0]; |     return path.split('/').reverse()[0]; | ||||||
| } | } | ||||||
| @@ -907,24 +778,34 @@ $('#trashmode').children("button").on('click', function(e) { | |||||||
|     $(this).removeClass("btn-secondary").addClass("btn-success"); |     $(this).removeClass("btn-secondary").addClass("btn-success"); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| $('#btnnotify').on('click', function (e) { | $('#btnnotifyWeb').on('click', function (e) { | ||||||
|     if($.cookie("notification") === "true") { |     if($.cookie('notificationWeb') === 'true') { | ||||||
|         $.cookie("notification", false); |         $.cookie('notificationWeb', false); | ||||||
|         $('#btnnotify').removeClass("btn-success").addClass("btn-secondary"); |         $('#btnnotify').removeClass('btn-success').addClass('btn-secondary'); | ||||||
|     } else { |     } else { | ||||||
|         Notification.requestPermission(function (permission) { |         Notification.requestPermission(function (permission) { | ||||||
|             if(!('permission' in Notification)) { |             if(!('permission' in Notification)) { | ||||||
|                 Notification.permission = permission; |                 Notification.permission = permission; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (permission === "granted") { |             if (permission === 'granted') { | ||||||
|                 $.cookie("notification", true, { expires: 424242 }); |                 $.cookie('notificationWeb', true, { expires: 424242 }); | ||||||
|                 $('#btnnotify').removeClass("btn-secondary").addClass("btn-success"); |                 $('#btnnotifyWeb').removeClass('btn-secondary').addClass('btn-success'); | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | $('#btnnotifyPage').on('click', function (e) { | ||||||
|  |     if($.cookie("notificationPage") === 'true') { | ||||||
|  |         $.cookie("notificationPage", false); | ||||||
|  |         $('#btnnotifyPage').removeClass('btn-success').addClass('btn-secondary'); | ||||||
|  |     } else { | ||||||
|  |         $.cookie('notificationPage', true, { expires: 424242 }); | ||||||
|  |         $('#btnnotifyPage').removeClass('btn-secondary').addClass('btn-success'); | ||||||
|  |     } | ||||||
|  | }); | ||||||
|  |  | ||||||
| function getHost() { | function getHost() { | ||||||
|     socket.send('MPD_API_GET_MPDHOST'); |     socket.send('MPD_API_GET_MPDHOST'); | ||||||
|  |  | ||||||
| @@ -942,11 +823,8 @@ function getHost() { | |||||||
| } | } | ||||||
|  |  | ||||||
| $('#search').submit(function () { | $('#search').submit(function () { | ||||||
|  |      | ||||||
|     app.setLocation("#/search/"+$('#search > input').val()); |     app.setLocation("#/search/"+$('#search > input').val()); | ||||||
|     $('#wait').modal('show'); |  | ||||||
|     setTimeout(function() { |  | ||||||
|         $('#wait').modal('hide'); |  | ||||||
|     }, 10000); |  | ||||||
|     return false; |     return false; | ||||||
| }); | }); | ||||||
|  |  | ||||||
| @@ -954,16 +832,12 @@ $('.page-link').on('click', function (e) { | |||||||
|  |  | ||||||
|     switch ($(this).text()) { |     switch ($(this).text()) { | ||||||
|         case "Next": |         case "Next": | ||||||
|             if (current_app == "dirble") dirble_page++; |             pagination += MAX_ELEMENTS_PER_PAGE; | ||||||
|             else pagination += MAX_ELEMENTS_PER_PAGE; |  | ||||||
|             break; |             break; | ||||||
|         case "Previous": |         case "Previous": | ||||||
|             if (current_app == "dirble") dirble_page-- |             pagination -= MAX_ELEMENTS_PER_PAGE; | ||||||
|             else { |             if(pagination <= 0) | ||||||
|                 pagination -= MAX_ELEMENTS_PER_PAGE; |                pagination = 0; | ||||||
|                 if(pagination <= 0) |  | ||||||
|                     pagination = 0; |  | ||||||
|             } |  | ||||||
|             break; |             break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -974,9 +848,6 @@ $('.page-link').on('click', function (e) { | |||||||
|         case "browse": |         case "browse": | ||||||
|             app.setLocation('#/browse/'+pagination+'/'+browsepath); |             app.setLocation('#/browse/'+pagination+'/'+browsepath); | ||||||
|             break; |             break; | ||||||
|         case "dirble": |  | ||||||
|             app.setLocation("#/dirble/"+dirble_catid+"/"+dirble_page); |  | ||||||
|             break; |  | ||||||
|     } |     } | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
| }); | }); | ||||||
| @@ -1020,23 +891,54 @@ $('#mpd_password_set > button').on('click', function (e) { | |||||||
|     $('#mpd_password_set').addClass('hide'); |     $('#mpd_password_set').addClass('hide'); | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  | function showNotification(notificationTitle,notificationText,notificationHtml,notificationType) { | ||||||
|  |     if ($.cookie('notificationWeb') === 'true') { | ||||||
|  |       var notification = new Notification(notificationTitle, {icon: 'assets/favicon.ico', body: notificationText}); | ||||||
|  |       setTimeout(function(notification) { | ||||||
|  |         notification.close(); | ||||||
|  |       }, 3000, notification);     | ||||||
|  |     }  | ||||||
|  |     if ($.cookie('notificationPage') === 'true') { | ||||||
|  |       $.notify({ title: notificationTitle, message: notificationHtml},{ type: notificationType, offset: { y: 60, x:20 }, | ||||||
|  |         template: '<div data-notify="container" class="col-xs-11 col-sm-3 alert alert-{0}" role="alert">' + | ||||||
|  | 		'<button type="button" aria-hidden="true" class="close" data-notify="dismiss">×</button>' + | ||||||
|  | 		'<span data-notify="icon"></span> ' + | ||||||
|  | 		'<span data-notify="title">{1}</span> ' + | ||||||
|  | 		'<span data-notify="message">{2}</span>' + | ||||||
|  | 		'<div class="progress" data-notify="progressbar">' + | ||||||
|  | 			'<div class="progress-bar progress-bar-{0}" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div>' + | ||||||
|  | 		'</div>' + | ||||||
|  | 		'<a href="{3}" target="{4}" data-notify="url"></a>' + | ||||||
|  | 		'</div>'  | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| function notificationsSupported() { | function notificationsSupported() { | ||||||
|     return "Notification" in window; |     return "Notification" in window; | ||||||
| } | } | ||||||
|  |  | ||||||
| function songNotify(title, artist, album) { | function songNotify(title, artist, album) { | ||||||
|     var textNotification = ""; |     var textNotification = ''; | ||||||
|     if(typeof artist != 'undefined' && artist.length > 0) |     var htmlNotification = ''; | ||||||
|         textNotification += " " + artist; |     var pageTitle = 'myMPD: '; | ||||||
|     if(typeof album != 'undefined' && album.length > 0) |     if(typeof artist != 'undefined' && artist.length > 0) { | ||||||
|         textNotification += "\n " + album; |         textNotification += artist; | ||||||
|  |         htmlNotification += '<br/>' + artist; | ||||||
|     var notification = new Notification(title, {icon: 'assets/favicon.ico', body: textNotification}); |         pageTitle += artist + ' - '; | ||||||
|     setTimeout(function(notification) { |     } | ||||||
|         notification.close(); |     if(typeof album != 'undefined' && album.length > 0) { | ||||||
|     }, 3000, notification); |         textNotification += ' - ' + album; | ||||||
|  |         htmlNotification += '<br/>' + album; | ||||||
|  |     } | ||||||
|  |     if(typeof title != 'undefined' && title.length > 0) { | ||||||
|  |         pageTitle += title; | ||||||
|  |     } | ||||||
|  |     document.title = pageTitle; | ||||||
|  |     showNotification(title,textNotification,htmlNotification,'success'); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |          | ||||||
| $(document).keydown(function(e){ | $(document).keydown(function(e){ | ||||||
|     if (e.target.tagName == 'INPUT') { |     if (e.target.tagName == 'INPUT') { | ||||||
|         return; |         return; | ||||||
| @@ -1057,158 +959,19 @@ $(document).keydown(function(e){ | |||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| function dirble_load_categories() { |  | ||||||
|  |  | ||||||
|     dirble_page = 1; |  | ||||||
|  |  | ||||||
|     $.getJSON( "https://api.dirble.com/v2/categories?token=" + dirble_api_token, function( data ) { |  | ||||||
|  |  | ||||||
|         $('#dirble_loading').addClass('hide'); |  | ||||||
|  |  | ||||||
|         data = data.sort(function(a, b) { |  | ||||||
|             return (a.title > b.title) ? 1 : 0; |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         var max = data.length - data.length%2; |  | ||||||
|  |  | ||||||
|         for(i = 0; i < max; i+=2) { |  | ||||||
|  |  | ||||||
|             $('#dirble_left > tbody').append( |  | ||||||
|                 "<tr><td catid=\""+data[i].id+"\">"+data[i].title+"</td></tr>" |  | ||||||
|             ); |  | ||||||
|  |  | ||||||
|             $('#dirble_right > tbody').append( |  | ||||||
|                 "<tr><td catid=\""+data[i+1].id+"\">"+data[i+1].title+"</td></tr>" |  | ||||||
|             ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (max != data.length) { |  | ||||||
|             $('#dirble_left > tbody').append( |  | ||||||
|                 "<tr><td catid=\""+data[max].id+"\">"+data[max].title+"</td></tr>" |  | ||||||
|             ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         $('#dirble_left > tbody > tr > td').on({ |  | ||||||
|             click: function() { |  | ||||||
|                 dirble_selected_cat = $(this).text(); |  | ||||||
|                 dirble_catid = $(this).attr("catid"); |  | ||||||
|                 app.setLocation("#/dirble/"+dirble_catid+"/"+dirble_page); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         $('#dirble_right > tbody > tr > td').on({ |  | ||||||
|             click: function() { |  | ||||||
|                 dirble_selected_cat = $(this).text(); |  | ||||||
|                 dirble_catid = $(this).attr("catid"); |  | ||||||
|                 app.setLocation("#/dirble/"+dirble_catid+"/"+dirble_page); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| function dirble_load_stations() { |  | ||||||
|  |  | ||||||
|     $.getJSON( "https://api.dirble.com/v2/category/"+dirble_catid+"/stations?page="+dirble_page+"&per_page=20&token=" + dirble_api_token, function( data ) { |  | ||||||
|  |  | ||||||
|         $('#dirble_loading').addClass('hide'); |  | ||||||
|         if (data.length == 20) $('#next').removeClass('hide'); |  | ||||||
|  |  | ||||||
|         var max = data.length - data.length%2; |  | ||||||
|  |  | ||||||
|         for(i = 0; i < max; i+=2) { |  | ||||||
|  |  | ||||||
|             $('#dirble_left > tbody').append( |  | ||||||
|                 "<tr><td radioid=\""+data[i].id+"\">"+data[i].name+"</td></tr>" |  | ||||||
|             ); |  | ||||||
|             $('#dirble_right > tbody').append( |  | ||||||
|                 "<tr><td radioid=\""+data[i+1].id+"\">"+data[i+1].name+"</td></tr>" |  | ||||||
|             ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (max != data.length) { |  | ||||||
|             $('#dirble_left > tbody').append( |  | ||||||
|                 "<tr><td radioid=\""+data[max].id+"\">"+data[max].name+"</td></tr>" |  | ||||||
|             ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         $('#dirble_left > tbody > tr > td').on({ |  | ||||||
|             click: function() { |  | ||||||
|                 var _this = $(this); |  | ||||||
|  |  | ||||||
|                 $.getJSON( "https://api.dirble.com/v2/station/"+$(this).attr("radioid")+"?token=" + dirble_api_token, function( data ) { |  | ||||||
|  |  | ||||||
|                     socket.send("MPD_API_ADD_TRACK," + data.streams[0].stream); |  | ||||||
|                     $.notify({message: _this.text() + " added"},{ type: "success", offset: { y: 60, x:20 }}); |  | ||||||
|                 }); |  | ||||||
|             }, |  | ||||||
|             mouseenter: function() { |  | ||||||
|                 var _this = $(this); |  | ||||||
|  |  | ||||||
|                 $(this).last().append( |  | ||||||
|                 "<a role=\"button\" class=\"pull-right btn-group-hover\">" + |  | ||||||
|                 "<span class=\"glyphicon glyphicon-play\"></span></a>").find('a').click(function(e) { |  | ||||||
|                     e.stopPropagation(); |  | ||||||
|  |  | ||||||
|                     $.getJSON( "https://api.dirble.com/v2/station/"+_this.attr("radioid")+"?token=" + dirble_api_token, function( data ) { |  | ||||||
|  |  | ||||||
|                         socket.send("MPD_API_ADD_PLAY_TRACK," + data.streams[0].stream); |  | ||||||
|                         $.notify({message: _this.text() + " added" },{ type: "success", offset: { y: 60, x:20 }}); |  | ||||||
|                     }); |  | ||||||
|                 }).fadeTo('fast',1); |  | ||||||
|             }, |  | ||||||
|  |  | ||||||
|             mouseleave: function(){ |  | ||||||
|                 $(this).last().find("a").stop().remove(); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         $('#dirble_right> tbody > tr > td').on({ |  | ||||||
|             click: function() { |  | ||||||
|                 var _this = $(this); |  | ||||||
|  |  | ||||||
|                 $.getJSON( "https://api.dirble.com/v2/station/"+$(this).attr("radioid")+"?token=" + dirble_api_token, function( data ) { |  | ||||||
|  |  | ||||||
|                     socket.send("MPD_API_ADD_TRACK," + data.streams[0].stream); |  | ||||||
|                     $.notify({message: _this.text() + " added"},{ type: "success", offset: { y: 60, x:20 }}); |  | ||||||
|                 }); |  | ||||||
|             }, |  | ||||||
|             mouseenter: function() { |  | ||||||
|                 var _this = $(this); |  | ||||||
|  |  | ||||||
|                 $(this).last().append( |  | ||||||
|                 "<a role=\"button\" class=\"pull-right btn-group-hover\">" + |  | ||||||
|                 "<span class=\"glyphicon glyphicon-play\"></span></a>").find('a').click(function(e) { |  | ||||||
|                     e.stopPropagation(); |  | ||||||
|  |  | ||||||
|                     $.getJSON( "https://api.dirble.com/v2/station/"+_this.attr("radioid")+"?token=" + dirble_api_token, function( data ) { |  | ||||||
|  |  | ||||||
|                         socket.send("MPD_API_ADD_PLAY_TRACK," + data.streams[0].stream); |  | ||||||
|                         $.notify({message: _this.text() + " added"},{ type: "success", offset: { y: 60, x:20 }}); |  | ||||||
|                     }); |  | ||||||
|                 }).fadeTo('fast',1); |  | ||||||
|             }, |  | ||||||
|  |  | ||||||
|             mouseleave: function(){ |  | ||||||
|                 $(this).last().find("a").stop().remove(); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function set_filter (c) { | function set_filter (c) { | ||||||
|     filter = c; |     filter = c; | ||||||
| 	$('#filter > a').removeClass('btn-success'); | 	$('#filter > a').removeClass('btn-success'); | ||||||
| 	$('#f' + c).addClass('btn-success'); | 	$('#f' + c).addClass('btn-success'); | ||||||
|  |  | ||||||
|     if (filter === "") { |     if (filter === "") { | ||||||
|     	$('#salamisandwich > tbody > tr').removeClass('hide'); |     	$('#'+current_app+'List > tbody > tr').removeClass('hide'); | ||||||
| 	} else if (filter === "plist") { | 	} else if (filter === "plist") { | ||||||
|     	$('#salamisandwich > tbody > tr.dir').addClass('hide'); |     	$('#'+current_app+'List > tbody > tr.dir').addClass('hide'); | ||||||
|     	$('#salamisandwich > tbody > tr.song').addClass('hide'); |     	$('#'+current_app+'List > tbody > tr.song').addClass('hide'); | ||||||
|     	$('#salamisandwich > tbody > tr.plist').removeClass('hide'); |     	$('#'+current_app+'List > tbody > tr.plist').removeClass('hide'); | ||||||
|     } else { |     } else { | ||||||
| 		$.each($('#salamisandwich > tbody > tr'), function(i, line) { | 		$.each($('#'+current_app+'List > tbody > tr'), function(i, line) { | ||||||
| 			var first = basename($(line).attr('uri'))[0]; | 			var first = basename($(line).attr('uri'))[0]; | ||||||
| 			if ( $(line).hasClass('song') ) { | 			if ( $(line).hasClass('song') ) { | ||||||
| 				first = $(line).children().eq(3).text()[0]; | 				first = $(line).children().eq(3).text()[0]; | ||||||
|   | |||||||
| @@ -64,8 +64,7 @@ int callback_mpd(struct mg_connection *c) | |||||||
|         return MG_TRUE; |         return MG_TRUE; | ||||||
|  |  | ||||||
|     if(mpd.conn_state != MPD_CONNECTED && cmd_id != MPD_API_SET_MPDHOST && |     if(mpd.conn_state != MPD_CONNECTED && cmd_id != MPD_API_SET_MPDHOST && | ||||||
|         cmd_id != MPD_API_GET_MPDHOST && cmd_id != MPD_API_SET_MPDPASS && |         cmd_id != MPD_API_GET_MPDHOST && cmd_id != MPD_API_SET_MPDPASS) | ||||||
|         cmd_id != MPD_API_GET_DIRBLEAPITOKEN) |  | ||||||
|         return MG_TRUE; |         return MG_TRUE; | ||||||
|  |  | ||||||
|     switch(cmd_id) |     switch(cmd_id) | ||||||
| @@ -291,10 +290,6 @@ out_host_change: | |||||||
|                 "{\"host\" : \"%s\", \"port\": \"%d\", \"passwort_set\": %s}" |                 "{\"host\" : \"%s\", \"port\": \"%d\", \"passwort_set\": %s}" | ||||||
|                 "}", mpd.host, mpd.port, mpd.password ? "true" : "false"); |                 "}", mpd.host, mpd.port, mpd.password ? "true" : "false"); | ||||||
|             break; |             break; | ||||||
|         case MPD_API_GET_DIRBLEAPITOKEN: |  | ||||||
|             n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"dirbleapitoken\", \"" |  | ||||||
|                 "data\": \"%s\"}", dirble_api_token); |  | ||||||
|             break; |  | ||||||
|         case MPD_API_SET_MPDPASS: |         case MPD_API_SET_MPDPASS: | ||||||
|             p_charbuf = strdup(c->content); |             p_charbuf = strdup(c->content); | ||||||
|             if(strcmp(strtok(p_charbuf, ","), "MPD_API_SET_MPDPASS")) |             if(strcmp(strtok(p_charbuf, ","), "MPD_API_SET_MPDPASS")) | ||||||
|   | |||||||
| @@ -40,7 +40,6 @@ | |||||||
|     X(MPD_API_GET_QUEUE) \ |     X(MPD_API_GET_QUEUE) \ | ||||||
|     X(MPD_API_GET_BROWSE) \ |     X(MPD_API_GET_BROWSE) \ | ||||||
|     X(MPD_API_GET_MPDHOST) \ |     X(MPD_API_GET_MPDHOST) \ | ||||||
|     X(MPD_API_GET_DIRBLEAPITOKEN) \ |  | ||||||
|     X(MPD_API_ADD_TRACK) \ |     X(MPD_API_ADD_TRACK) \ | ||||||
|     X(MPD_API_ADD_PLAY_TRACK) \ |     X(MPD_API_ADD_PLAY_TRACK) \ | ||||||
|     X(MPD_API_ADD_PLAYLIST) \ |     X(MPD_API_ADD_PLAYLIST) \ | ||||||
| @@ -100,8 +99,6 @@ struct t_mpd { | |||||||
|     unsigned queue_version; |     unsigned queue_version; | ||||||
| } mpd; | } mpd; | ||||||
|  |  | ||||||
| char dirble_api_token[28]; |  | ||||||
|  |  | ||||||
| struct t_mpd_client_session { | struct t_mpd_client_session { | ||||||
|     int song_id; |     int song_id; | ||||||
|     unsigned queue_version; |     unsigned queue_version; | ||||||
|   | |||||||
| @@ -101,7 +101,6 @@ int main(int argc, char **argv) | |||||||
|         {"port",         required_argument, 0, 'p'}, |         {"port",         required_argument, 0, 'p'}, | ||||||
|         {"localport",    required_argument, 0, 'l'}, |         {"localport",    required_argument, 0, 'l'}, | ||||||
|         {"webport",      required_argument, 0, 'w'}, |         {"webport",      required_argument, 0, 'w'}, | ||||||
|         {"dirbletoken",  required_argument, 0, 'd'}, |  | ||||||
|         {"user",         required_argument, 0, 'u'}, |         {"user",         required_argument, 0, 'u'}, | ||||||
|         {"version",      no_argument,       0, 'v'}, |         {"version",      no_argument,       0, 'v'}, | ||||||
|         {"help",         no_argument,       0,  0 }, |         {"help",         no_argument,       0,  0 }, | ||||||
| @@ -127,9 +126,6 @@ int main(int argc, char **argv) | |||||||
|             case 'w': |             case 'w': | ||||||
|                 webport = strdup(optarg); |                 webport = strdup(optarg); | ||||||
|                 break; |                 break; | ||||||
|             case 'd': |  | ||||||
|                 strncpy(dirble_api_token, optarg, sizeof(dirble_api_token)); |  | ||||||
|                 break; |  | ||||||
|             case 'u': |             case 'u': | ||||||
|                 run_as_user = strdup(optarg); |                 run_as_user = strdup(optarg); | ||||||
|                 break; |                 break; | ||||||
| @@ -153,7 +149,6 @@ int main(int argc, char **argv) | |||||||
|                         " -l, --localport <port>\t\tskip authorization for local port\n" |                         " -l, --localport <port>\t\tskip authorization for local port\n" | ||||||
|                         " -w, --webport [ip:]<port>\tlisten interface/port for webserver [8080]\n" |                         " -w, --webport [ip:]<port>\tlisten interface/port for webserver [8080]\n" | ||||||
|                         " -u, --user <username>\t\tdrop priviliges to user after socket bind\n" |                         " -u, --user <username>\t\tdrop priviliges to user after socket bind\n" | ||||||
|                         " -d, --dirbletoken <apitoken>\tDirble API token\n" |  | ||||||
|                         " -v, --version\t\t\tget version\n" |                         " -v, --version\t\t\tget version\n" | ||||||
|                         " -m, --mpdpass <password>\tspecifies the password to use when connecting to mpd\n" |                         " -m, --mpdpass <password>\tspecifies the password to use when connecting to mpd\n" | ||||||
|                         " --help\t\t\t\tthis help\n" |                         " --help\t\t\t\tthis help\n" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 jcorporation
					jcorporation