fix buttons, added auto-reconnect, code cleanup
authorAndrew Karpow <andy@ndyk.de>
Tue, 5 Nov 2013 13:59:12 +0000 (14:59 +0100)
committerAndrew Karpow <andy@ndyk.de>
Tue, 5 Nov 2013 13:59:12 +0000 (14:59 +0100)
htdocs/css/starter-template.css
htdocs/index.html
htdocs/js/mpd.js
src/Makefile
src/http_server.c
src/main.c
src/mpd_client.c
src/mpd_client.h

index f68b959..a61fb1c 100644 (file)
@@ -1,7 +1,22 @@
 body {
   padding-top: 50px;
+  padding-bottom: 50px;
 }
+
 .starter-template {
   padding: 40px 15px;
-  max-width: 800px;
+}
+
+.slider.slider-horizontal {
+  height: 15px;
+}
+
+.slider.slider-horizontal .slider-track {
+  height: 10px;
+  margin-top: -6px;
+}
+
+.progress {
+  margin-top: 0px;
+  margin-bottom: 0px;
 }
index 4edddc4..331eb14 100644 (file)
   <link href="css/bootstrap.css" rel="stylesheet">
 
   <!-- Custom styles for this template -->
-  <link href="css/starter-template.css" rel="stylesheet">
   <link href="css/slider.css" rel="stylesheet">
+  <link href="css/starter-template.css" rel="stylesheet">
 
   <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
   <!--[if lt IE 9]>
-    <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
-    <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
-    <![endif]-->
-  </head>
-  <body>
-
-    <div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
-      <div class="container">
-        <div class="navbar-header">
-          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
-            <span class="icon-bar"></span>
-            <span class="icon-bar"></span>
-            <span class="icon-bar"></span>
-          </button>
-          <a class="navbar-brand" href="#">ympd</a>
-        </div>
-        <div class="collapse navbar-collapse">
+  <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
+  <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
+  <![endif]-->
+</head>
+<body>
 
-          <ul class="nav navbar-nav">
-            <li class="active"><a href="#">Playlist</a></li>
-            <li><a href="#about">Browse</a></li>
-            <li><a href="#contact">About</a></li>
-          </ul>
+  <div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
+    <div class="container">
+      <div class="navbar-header">
+        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
+          <span class="icon-bar"></span>
+          <span class="icon-bar"></span>
+          <span class="icon-bar"></span>
+        </button>
+        <a class="navbar-brand" href="#">ympd</a>
+      </div>
+      <div class="collapse navbar-collapse">
 
-          <form class="navbar-form navbar-right" role="search">
-            <div class="form-group">
-              <input type="text" class="form-control" placeholder="Search">
-            </div>
-            <button type="submit" class="btn btn-default">
+        <ul class="nav navbar-nav">
+          <li class="active"><a href="#">Playlist</a></li>
+          <li><a href="#about">Browse</a></li>
+          <li><a href="#contact">About</a></li>
+        </ul>
+
+        <form class="navbar-form navbar-right" role="search">
+          <div class="form-group">
+            <input type="text" class="form-control" placeholder="Search">
+          </div>
+          <button type="submit" class="btn btn-default">
             <span class="glyphicon glyphicon-search"></span>
+          </button>
+        </form>
+
+        <div class="btn-toolbar navbar-btn navbar-right" role="toolbar">
+          <div class="btn-group">
+            <button type="button" class="btn btn-default">
+              <span class="glyphicon glyphicon-backward" onclick="socket.send('MPD_API_SET_NEXT')"></span>
+            </button>
+            <button type="button" class="btn btn-default" onclick="socket.send('MPD_API_SET_PAUSE')">
+              <span id="play-icon" class="glyphicon glyphicon-pause"></span>
+            </button>
+            <button type="button" class="btn btn-default" onclick="socket.send('MPD_API_SET_PREV')">
+              <span class="glyphicon glyphicon-forward"></span>
             </button>
-          </form>
-
-          <div class="btn-toolbar navbar-btn navbar-right" role="toolbar">
-            <div class="btn-group">
-              <button type="button" class="btn btn-default">
-                <span class="glyphicon glyphicon-backward" onclick="socket.send('MPD_API_SET_NEXT')"></span>
-              </button>
-              <button type="button" class="btn btn-default" onclick="socket.send('MPD_API_SET_PAUSE')">
-                <span id="play-icon" class="glyphicon glyphicon-pause"></span>
-              </button>
-              <button type="button" class="btn btn-default" onclick="socket.send('MPD_API_SET_PREV')">
-                <span class="glyphicon glyphicon-forward"></span>
-              </button>
-            </div>
-            <div class="btn-group">
-              <button type="button" class="btn btn-toolbar btn-default">
-                <span id="volume-icon" class="glyphicon glyphicon-volume-up"></span>
-                <input type="text" class="span2" value="0" data-slider-min="0" data-slider-max="100" data-slider-step="5" id="volumeslider" data-slider-tooltip="hide">
-              </button>
-            </div>
           </div>
-
-        </div><!--/.nav-collapse -->
-      </div>
+          <div class="btn-group">
+            <button type="button" class="btn btn-toolbar btn-default">
+              <span id="volume-icon" class="glyphicon glyphicon-volume-up"></span>
+              &nbsp;&nbsp;
+              <input type="text" class="span2" value="0" data-slider-min="0" data-slider-max="100" data-slider-step="5" id="volumeslider" data-slider-tooltip="hide">
+            </button>
+          </div>
+        </div>
+      </div><!--/.nav-collapse -->
     </div>
+  </div>
 
-    <div class="progress progress-striped active">
-      <div id="progressbar" class="progress-bar"  role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 45%">
-        <span class="sr-only">60% Complete</span>
-      </div>
-    </div>
+  <div class="container starter-template">
+    <div class="row">
 
-    <div class="container">
-      <div class="starter-template">
-        <div class="panel panel-default">
+      <div class="col-md-10">
+        <div id="alert" class="alert hide"></div>
+        <div class="panel panel-primary">
           <!-- Default panel contents -->
           <div class="panel-heading">Playlist</div>
+          <div class="panel-body">
+            <h2><span id="track-icon" class="glyphicon glyphicon-play"></span> Playing track xyz</h2>
+            <p class="text pull-right">&nbsp;&nbsp;2:13/4:12</p>
+
+            <div class="progress progress-striped active">
+              <div id="progressbar" class="progress-bar navbar-left"  role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100">
+              </div>
+            </div>
+          </div>
 
           <!-- Table -->
           <table id="salamisandwich" class="table">
             </tbody>
           </table>
         </div>
-
       </div>
-    </div><!-- /.container -->
-
-
-    <!-- Bootstrap core JavaScript
-    ================================================== -->
-    <!-- Placed at the end of the document so the pages load faster -->
-    <script src="js/jquery-1.10.2.min.js"></script>
-    <script src="js/bootstrap.min.js"></script>
-    <script src="js/bootstrap-slider.js"></script>
-    <script src="js/mpd.js"></script>
-  </body>
-  </html>
+
+      <div class="col-md-2" >
+        <div data-spy="affix">
+          <div class="btn-group-vertical btn-block btn-group-lg" data-toggle="buttons">
+            <button id="btnrandom" type="button" class="btn btn-default" onclick="toggleButton(this.id)">
+              <span class="glyphicon glyphicon-random"></span> Random
+            </button>
+            <button id="btnconsume" type="button" class="btn btn-default" onclick="toggleButton(this.id)">
+              <span class="glyphicon glyphicon-fire"></span> Consume
+            </button>
+            <button id="btnsingle" type="button" class="btn btn-default" onclick="toggleButton(this.id)">
+              <span class="glyphicon glyphicon-star"></span> Single
+            </button>
+            <button id="btnrepeat" type="button" class="btn btn-default" onclick="toggleButton(this.id)">
+              <span class="glyphicon glyphicon-repeat"></span> Repeat
+            </button>
+          </div>
+
+          <button type="button" class="btn btn-block btn-default btn-lg dropdown-toggle" data-toggle="dropdown">
+            <span class="glyphicon glyphicon-wrench"></span> Options <span class="caret"></span>
+          </button>
+          <ul class="dropdown-menu">
+            <li><a href="#" onclick="updateDB()"><span class="glyphicon glyphicon-refresh"></span> Update Database</a></li>
+          </ul>
+        </div>
+      </div><!-- /.col-md-2 -->
+
+    </div><!-- /.row -->
+  </div><!-- /.container -->
+
+
+
+  <!-- Bootstrap core JavaScript
+  ================================================== -->
+  <!-- Placed at the end of the document so the pages load faster -->
+  <script src="js/jquery-1.10.2.min.js"></script>
+  <script src="js/bootstrap.min.js"></script>
+  <script src="js/bootstrap-slider.js"></script>
+  <script src="js/mpd.js"></script>
+</body>
+</html>
index 176ea63..4e35a64 100644 (file)
 var socket;
+var last_state;
 
-if (typeof MozWebSocket != "undefined") {
-       socket = new MozWebSocket(get_appropriate_ws_url(), "ympd-client");
-} else {
-       socket = new WebSocket(get_appropriate_ws_url(), "ympd-client");
-}
+$('#volumeslider').slider().on('slide', function(event) {
+       socket.send("MPD_API_SET_VOLUME,"+event.value);
+});
 
-try {
-       socket.onopen = function() {
-               console.log("Connected");
-               init();
-       } 
-
-       socket.onmessage =function got_packet(msg) {
-               console.log(msg.data);
-               var obj = JSON.parse(msg.data);
-               switch (obj.type) {
-                 case "playlist":
-                       for (var song in obj.data) {
-                               var minutes = Math.floor(obj.data[song].duration / 60);
-                               var seconds = obj.data[song].duration - minutes * 60;
-
-                               $('#salamisandwich tr:last').after(
-                                       "<tr id=\"playlist_" + obj.data[song].id + "\"><td>" + obj.data[song].id + "</td>" +
-                                       "<td>"+ obj.data[song].uri +"</td>" +
-                                       "<td>"+ obj.data[song].title.replace(/%07/g, '"') +"</td>" + 
-                                       "<td>"+ minutes + ":" + (seconds < 10 ? '0' : '') + seconds +"</td></tr>");
-                       }
-                   break;
-                 case "state":
-                       $('#volumeslider').slider('setValue', obj.data.volume)
-                       var progress = Math.floor(100*obj.data.elapsedTime/obj.data.totalTime) + "%";
-                       $('#progressbar').width(progress);
-                       $('#playlist_'+obj.data.currentsongid).addClass('active');
-                       updatePlayIcon(obj.data.state);
-                       updateVolumeIcon(obj.data.volume);
-
-                       break;
-                 default:
-                   alert("Sie bleiben leider dumm");
-                   break;
-               }
+webSocketConnect();
+
+function webSocketConnect() {
+
+       if (typeof MozWebSocket != "undefined") {
+               socket = new MozWebSocket(get_appropriate_ws_url(), "ympd-client");
+       } else {
+               socket = new WebSocket(get_appropriate_ws_url(), "ympd-client");
        }
-       socket.onclose = function(){
-               console.log("Disconnected");
 
+       try {
+               socket.onopen = function() {
+                       console.log("Connected");
+                       socket.send("MPD_API_GET_PLAYLIST");
+                       socket.send("MPD_API_GET_STATE");
+               }
+
+               socket.onmessage =function got_packet(msg) {
+                       console.log(msg.data);
+                       if(msg.data === last_state)
+                               return;
+
+                       var obj = JSON.parse(msg.data);
+                       switch (obj.type) {
+                               case "playlist":
+                                       for (var song in obj.data) {
+                                               var minutes = Math.floor(obj.data[song].duration / 60);
+                                               var seconds = obj.data[song].duration - minutes * 60;
+
+                                               $('#salamisandwich tr:last').after(
+                                                       "<tr id=\"playlist_" + obj.data[song].id + "\"><td>" + obj.data[song].id + "</td>" +
+                                                       "<td>"+ obj.data[song].uri +"</td>" +
+                                                       "<td>"+ obj.data[song].title.replace(/%07/g, '"') +"</td>" + 
+                                                       "<td>"+ minutes + ":" + (seconds < 10 ? '0' : '') + seconds +"</td></tr>");
+                                       }
+                                       break;
+                               case "state":
+                                       if(JSON.stringify(obj) === JSON.stringify(last_state))
+                                               break;
+
+                                       $('#volumeslider').slider('setValue', obj.data.volume);
+                                       var progress = Math.floor(100*obj.data.elapsedTime/obj.data.totalTime) + "%";
+                                       $('#progressbar').width(progress);
+                                       $('#playlist_'+obj.data.currentsongid).addClass('success');
+                                       if(obj.data.random)
+                                               $('#btnrandom').addClass("active")
+                                       else
+                                               $('#btnrandom').removeClass("active");
+
+                                       if(obj.data.consume)
+                                               $('#btnconsume').addClass("active")
+                                       else
+                                               $('#btnconsume').removeClass("active");
+
+                                       if(obj.data.single)
+                                               $('#btnsingle').addClass("active")
+                                       else
+                                               $('#btnsingle').removeClass("active");
+
+                                       if(obj.data.repeat)
+                                               $('#btnrepeat').addClass("active")
+                                       else
+                                               $('#btnrepeat').removeClass("active");
+
+                                       if(last_state && (obj.data.state !== last_state.data.state))
+                                               updatePlayIcon(obj.data.state);
+                                       if(last_state && (obj.data.volume !== last_state.data.volume))
+                                               updateVolumeIcon(obj.data.volume);
+                                       break;
+                               case "disconnected":
+                                       $('#alert').text("Error: Connection to MPD failed.");
+                                       $('#alert').removeClass("hide alert-info").addclass("alert-danger");
+                                       break;
+
+                               default:
+                                       break;
+                       }
+
+                       last_state = obj;
+
+               }
+               socket.onclose = function(){
+                       console.log("Disconnected");
+
+                       var seconds = 5;
+                       var tm = setInterval(disconnectAlert,1000);
+
+                       function disconnectAlert() {
+                               $('#alert')
+                               .text("Connection to MPD lost, retrying in " + seconds + " seconds")
+                               .removeClass("hide alert-info")
+                               .addClass("alert-danger");
+
+                               if(seconds-- <= 0) {
+                                       webSocketConnect();
+                                       seconds = 5;
+                                       $('#alert').addClass("hide");
+                                       clearInterval(tm);
+                               }
+                       }
+                       
+               }
+
+       } catch(exception) {
+               alert('<p>Error' + exception);
        }
-} catch(exception) {
-       alert('<p>Error' + exception);  
-}
 
-$('#volumeslider').slider().on('slide', function(event) {
-    socket.send("MPD_API_SET_VOLUME,"+event.value);
-});
+}
 
 function get_appropriate_ws_url()
 {
@@ -60,9 +120,9 @@ function get_appropriate_ws_url()
        var u = document.URL;
 
        /*
-        * We open the websocket encrypted if this page came on an
-        * https:// url itself, otherwise unencrypted
-        */
+       /* We open the websocket encrypted if this page came on an
+       /* https:// url itself, otherwise unencrypted
+       /*/
 
        if (u.substring(0, 5) == "https") {
                pcol = "wss://";
@@ -95,26 +155,54 @@ var updateVolumeIcon = function(volume)
 
 var updatePlayIcon = function(state)
 {
-       $("#play-icon").removeClass("glyphicon-play");
-       $("#play-icon").removeClass("glyphicon-pause");
-       $("#play-icon").removeClass("glyphicon-stop");
-
+       $("#play-icon").removeClass("glyphicon-play")
+       .removeClass("glyphicon-pause")
+       .removeClass("glyphicon-stop");
+       $('#track-icon').removeClass("glyphicon-play")
+       .removeClass("glyphicon-pause")
+       .removeClass("glyphicon-stop");
+       
        if(state == 1) {
                $("#play-icon").addClass("glyphicon-stop");
+               $('#track-icon').addClass("glyphicon-stop");
        } else if(state == 2) {
                $("#play-icon").addClass("glyphicon-pause");
+               $('#track-icon').addClass("glyphicon-play");
        } else {
                $("#play-icon").addClass("glyphicon-play");
+               $('#track-icon').addClass("glyphicon-pause");
        }
 }
 
+function updateDB()
+{
+       socket.send('MPD_API_UPDATE_DB');
 
-function init() {
-       socket.send("MPD_API_GET_PLAYLIST");
-       socket.send("MPD_API_GET_STATE");
-}
+       $('#alert')
+       .text("Updating MPD Database...")
+       .removeClass("hide alert-danger")
+       .addClass("alert-info");
 
-function test() {
-       socket.send("MPD_API_GET_PLAYLIST");
+       setTimeout(function() {
+               $('#alert').addClass("hide");
+       }, 5000);
 }
 
+function toggleButton(id) {
+       switch (obj.type) {
+               case "btnrandom":
+                       socket.send("MPD_API_TOGGLE_RANDOM");
+                       break;
+               case "btnconsume":
+                       socket.send("MPD_API_TOGGLE_CONSUME");
+                       break;
+               case "btnsingle":
+                       socket.send("MPD_API_TOGGLE_SINGLE");
+                       break;
+               case "btnrepeat":
+                       socket.send("MPD_API_TOGGLE_REPEAT");
+                       break;
+               default:
+                       break;
+       }
+}
index 6ca9499..5fd83b4 100644 (file)
@@ -1,4 +1,4 @@
-CFLAGS = -ggdb
+CFLAGS = -ggdb -Wall
 LFLAGS = `pkg-config --libs libwebsockets libmpdclient`
 
 .PHONY: clean
index 3e27426..638653f 100644 (file)
@@ -1,5 +1,6 @@
 #include <libwebsockets.h>
 #include <stdio.h>
+#include <string.h>
 #include "http_server.h"
 
 #define INSTALL_DATADIR "/home/andy/workspace/ympd"
@@ -36,9 +37,7 @@ int callback_http(struct libwebsocket_context *context,
        void *in, size_t len)
 {
        char buf[256];
-       char leaf_path[1024];
-       int n, m;
-       unsigned char *p;
+       int n;
 
        switch (reason) {
                case LWS_CALLBACK_HTTP:
@@ -56,7 +55,9 @@ int callback_http(struct libwebsocket_context *context,
 
                case LWS_CALLBACK_HTTP_FILE_COMPLETION:
                        /* kill the connection after we sent one file */
-               return -1;
+                       return -1;
+               default:
+                       break;
        }
 
        return 0;
index b017ee6..d378291 100644 (file)
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
+#include <sys/time.h>
 
 #include "http_server.h"
 #include "mpd_client.h"
@@ -95,7 +96,7 @@ int main(int argc, char **argv)
                 * as soon as it can take more packets (usually immediately)
                 */
 
-               if (((unsigned int)tv.tv_usec - oldus) > 500000) {
+               if (((unsigned int)tv.tv_usec - oldus) > 1000 * 500) {
                        mpd_loop();
                        libwebsocket_callback_on_writable_all_protocol(&protocols[1]);
                        oldus = tv.tv_usec;
@@ -105,4 +106,5 @@ int main(int argc, char **argv)
        }
 
        libwebsocket_context_destroy(context);
-}
\ No newline at end of file
+       return 0;
+}
index 5f5218a..e7c13f7 100644 (file)
 struct mpd_connection *conn = NULL;
 enum mpd_conn_states mpd_conn_state = MPD_DISCONNECTED;
 enum mpd_state mpd_play_state = MPD_STATE_UNKNOWN;
-static int global_send;
 
-callback_ympd(struct libwebsocket_context *context,
+int callback_ympd(struct libwebsocket_context *context,
        struct libwebsocket *wsi,
        enum libwebsocket_callback_reasons reason,
        void *user, void *in, size_t len)
 {
-       int n, m;
+       size_t n;
+       int m;
        char *buf = NULL, *p;
        struct per_session_data__ympd *pss = (struct per_session_data__ympd *)user;
 
-       //if(global_send || (pss != NULL && pss->do_send))
-       //{
-               buf = (char *)malloc(MAX_SIZE + LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING);
-
-               if(buf == NULL)
-                       return -1;
-
-               p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
-       //}
-
        switch (reason) {
                case LWS_CALLBACK_ESTABLISHED:
-                       lwsl_info("callback_dumb_increment: "
+                       lwsl_info("mpd_client: "
                                "LWS_CALLBACK_ESTABLISHED\n");
                        break;
 
                case LWS_CALLBACK_SERVER_WRITEABLE:
-                       if(pss->do_send & DO_SEND_STATE)
-                       {
+                       buf = (char *)malloc(MAX_SIZE + LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING);
+                       if(buf == NULL) {
+                               lwsl_err("ERROR Failed allocating memory\n");
+                               return -1;
+                       }
+                       p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
+
+                       if(mpd_conn_state != MPD_CONNECTED) {
+                               n = snprintf(p, MAX_SIZE, "{\"type\":\"disconnected\"}");
+                       }
+                       else if(pss->do_send & DO_SEND_STATE) {
                                n = mpd_put_state(p);
                                pss->do_send &= ~DO_SEND_STATE;
                        }
-                       else if(pss->do_send & DO_SEND_PLAYLIST)
-                       {
+                       else if(pss->do_send & DO_SEND_PLAYLIST) {
                                n = mpd_put_playlist(p);
                                pss->do_send &= ~DO_SEND_PLAYLIST;
                        }
                        else if(pss->do_send & DO_SEND_TRACK_INFO)
                                n = mpd_put_current_song(p);
-                       else
-                       {
+                       else {
                                n = mpd_put_state(p);
                        }
 
-                       m = libwebsocket_write(wsi, p, n, LWS_WRITE_TEXT);
+                       if(n > 0)
+                               m = libwebsocket_write(wsi, (unsigned char*)p, n, LWS_WRITE_TEXT);
+
                        if (m < n) {
-                               lwsl_err("ERROR %d writing to socket\n", n);
+                               lwsl_err("ERROR %d writing to socket\n", n, m);
+                               free(buf);
                                return -1;
                        }
+                       free(buf);
                        break;
 
                case LWS_CALLBACK_RECEIVE:
@@ -77,47 +78,33 @@ callback_ympd(struct libwebsocket_context *context,
                                pss->do_send |= DO_SEND_STATE;
                        else if(!strcmp((const char *)in, MPD_API_GET_PLAYLIST))
                                pss->do_send |= DO_SEND_PLAYLIST;
-                       else if(!strcmp((const char *)in, MPD_API_SET_PAUSE))
-                       {
+                       else if(!strcmp((const char *)in, MPD_API_GET_TRACK_INFO))
+                               pss->do_send |= DO_SEND_TRACK_INFO;
+                       else if(!strcmp((const char *)in, MPD_API_UPDATE_DB)) {
+                               mpd_send_update(conn, NULL);
+                               mpd_response_finish(conn);
+                       }
+                       else if(!strcmp((const char *)in, MPD_API_SET_PAUSE)) {
                                mpd_send_toggle_pause(conn);
                                mpd_response_finish(conn);
                        }
-                       else if(!strcmp((const char *)in, MPD_API_SET_PREV))
-                       {
+                       else if(!strcmp((const char *)in, MPD_API_SET_PREV)) {
                                mpd_send_previous(conn);
                                mpd_response_finish(conn);
                        }
-                       else if(!strcmp((const char *)in, MPD_API_SET_NEXT))
-                       {
+                       else if(!strcmp((const char *)in, MPD_API_SET_NEXT)) {
                                mpd_send_next(conn);
                                mpd_response_finish(conn);
                        }
-                       else if(!strncmp((const char *)in, MPD_API_SET_VOLUME, sizeof(MPD_API_SET_VOLUME)-1))
-                       {
+                       else if(!strncmp((const char *)in, MPD_API_SET_VOLUME, sizeof(MPD_API_SET_VOLUME)-1)) {
                                unsigned int volume;
                                if(sscanf(in, "MPD_API_SET_VOLUME,%ud", &volume) && volume < 100)
-                               {
-                                       printf("Setting volume to %d\n", volume);
                                        mpd_run_set_volume(conn, volume);
-
-                               }
                        }
+                       break;
 
-
-
-               break;
-       /*
-        * this just demonstrates how to use the protocol filter. If you won't
-        * study and reject connections based on header content, you don't need
-        * to handle this callback
-        */
-
-        case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
-               /* you could return non-zero here and kill the connection */
-        break;
-
-        default:
-        break;
+               default:
+                       break;
        }
 
        return 0;
@@ -128,40 +115,44 @@ void mpd_loop()
        switch (mpd_conn_state) {
                case MPD_DISCONNECTED:
                        /* Try to connect */
+                       conn = mpd_connection_new("127.0.0.1", 6600, 3000);
+                       if (conn == NULL) {
+                               lwsl_err("Out of memory.");
+                               mpd_conn_state = MPD_FAILURE;
+                               return;
+                       }
 
-               conn = mpd_connection_new("10.23.44.2", 6600, 3000);
-               if (conn == NULL) {
-                       lwsl_err("%s", "Out of memory");
-                       mpd_conn_state = MPD_FAILURE;
-                       return;
-               }
-
-               if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) {
-                       lwsl_notice("MPD Connection: %s", mpd_connection_get_error_message(conn));
-                       mpd_conn_state = MPD_FAILURE;
-                       return;
-               }
+                       if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) {
+                               lwsl_notice("MPD connection: %s\n", mpd_connection_get_error_message(conn));
+                               mpd_conn_state = MPD_FAILURE;
+                               return;
+                       }
 
-               mpd_conn_state = MPD_CONNECTED;
-               break;
+                       lwsl_notice("MPD connected.\n");
+                       mpd_conn_state = MPD_CONNECTED;
+                       break;
 
                case MPD_FAILURE:
-               if(conn != NULL)
-                       mpd_connection_free(conn);
-               conn = NULL;
-               mpd_conn_state = MPD_DISCONNECTED;
-               break;
+                       lwsl_notice("MPD connection failed.\n");
+
+                       if(conn != NULL)
+                               mpd_connection_free(conn);
+                       conn = NULL;
+                       mpd_conn_state = MPD_DISCONNECTED;
+                       break;
 
                case MPD_CONNECTED:
-                       printf("mpd connected\n");
+                       /* Nothing to do */
+                       break;
        }
-
-
 }
 
 const char* encode_string(const char *str)
 {
        char *ptr = (char *)str;
+       if(str == NULL)
+               return NULL;
+
        while(*ptr++ != '\0')
                if(*ptr=='"')
                        *ptr=' ';
@@ -175,9 +166,9 @@ int mpd_put_state(char* buffer)
 
        status = mpd_run_status(conn);
        if (!status) {
-               lwsl_notice("MPD Status: %s", mpd_connection_get_error_message(conn));
+               lwsl_err("MPD status: %s\n", mpd_connection_get_error_message(conn));
                mpd_conn_state = MPD_FAILURE;
-               return;
+               return 0;
        }
 
        len = snprintf(buffer, MAX_SIZE,
@@ -200,25 +191,28 @@ int mpd_put_state(char* buffer)
 
        printf("buffer: %s\n", buffer);
        mpd_status_free(status);
-       //printf("status: %d\n", mpd_response_finish(conn));
        return len;
 }
 
 int mpd_put_current_song(char* buffer)
 {
        struct mpd_song *song;
+    int len;
 
        song = mpd_run_current_song(conn);
        if (song != NULL) {
-               sprintf(buffer, 
-                       "{\"type\": \"current_song\", \"data\": {"
-                       " \"uri\":%s"
-                   "}}", 
-                       mpd_song_get_uri(song)
+               len = snprintf(buffer, MAX_SIZE, "{\"type\": \"current_song\", \"data\": {"
+                       "{\"id\":%d, \"uri\":\"%s\", \"duration\":%d, \"title\":\"%s\"},",
+                       mpd_song_get_id(song),
+                       mpd_song_get_uri(song),
+                       mpd_song_get_duration(song),
+                       encode_string(mpd_song_get_tag(song, MPD_TAG_TITLE, 0))
                );
                mpd_song_free(song);
        }
        mpd_response_finish(conn);
+
+       return len;
 }
 
 int mpd_put_playlist(char* buffer)
@@ -247,11 +241,10 @@ int mpd_put_playlist(char* buffer)
 
                mpd_entity_free(entity);
        }
-       //printf("status: %d\n", mpd_response_finish(conn));
 
        /* remove last ',' */
        cur--;
        cur += snprintf(cur, end  - cur, "] }");
        printf("buffer: %s\n", buffer);
        return cur - buffer;
-}
\ No newline at end of file
+}
index 673961f..5af5128 100644 (file)
@@ -13,8 +13,7 @@ struct per_session_data__ympd {
 enum mpd_conn_states {
        MPD_FAILURE,
        MPD_DISCONNECTED,
-       MPD_CONNECTED,
-       MPD_PLAYING
+       MPD_CONNECTED
 };
 
 #define MPD_API_GET_STATE        "MPD_API_GET_STATE"
@@ -29,6 +28,7 @@ enum mpd_conn_states {
 #define MPD_API_SET_SEEK         "MPD_API_SET_SEEK"
 #define MPD_API_SET_NEXT         "MPD_API_SET_PREV"
 #define MPD_API_SET_PREV         "MPD_API_SET_NEXT"
+#define MPD_API_UPDATE_DB        "MPD_API_UPDATE_DB"
 
 
 
@@ -37,7 +37,7 @@ int callback_ympd(struct libwebsocket_context *context,
                        enum libwebsocket_callback_reasons reason,
                        void *user, void *in, size_t len);
 
-void mpd_connect();
+void mpd_loop();
 int mpd_put_state(char* buffer);
 int mpd_put_current_song(char* buffer);
 int mpd_put_playlist(char* buffer);