|         |      1 diff -r fb5042644071 debian/patches/00list | 
|         |      2 --- a/debian/patches/00list	Mon May 19 00:17:05 2008 -0400 | 
|         |      3 +++ b/debian/patches/00list	Mon May 19 01:12:49 2008 -0400 | 
|         |      4 @@ -1,2 +1,4 @@ | 
|         |      5  01verbose-compilation | 
|         |      6  02compile-with-gcc-4.3 | 
|         |      7 +03mpd-client | 
|         |      8 +04mpd-client-config-init | 
|         |      9 diff -r fb5042644071 debian/patches/03mpd-client.dpatch | 
|         |     10 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000 | 
|         |     11 +++ b/debian/patches/03mpd-client.dpatch	Mon May 19 01:12:49 2008 -0400 | 
|         |     12 @@ -0,0 +1,3597 @@ | 
|         |     13 +#! /bin/sh /usr/share/dpatch/dpatch-run | 
|         |     14 +## mpd-client.dpatch by Fabien Niñoles <fabien@tzone.org> | 
|         |     15 +## | 
|         |     16 +## All lines beginning with `## DP:' are a description of the patch. | 
|         |     17 +## DP: Add mpd to imms clients. | 
|         |     18 + | 
|         |     19 +@DPATCH@ | 
|         |     20 + | 
|         |     21 +diff -r 171db9560cb5 clients/mpd/immsmpd.cc | 
|         |     22 +--- /dev/null	Thu Jan 01 00:00:00 1970 +0000 | 
|         |     23 ++++ b/clients/mpd/immsmpd.cc	Mon May 19 00:21:51 2008 -0400 | 
|         |     24 +@@ -0,0 +1,282 @@ | 
|         |     25 ++#include "immsutil.h" | 
|         |     26 ++#include "clientstub.h" | 
|         |     27 ++ | 
|         |     28 ++#include <glib.h> | 
|         |     29 ++#include <signal.h> | 
|         |     30 ++ | 
|         |     31 ++#include "mpdinterface.h" | 
|         |     32 ++#include <list> | 
|         |     33 ++ | 
|         |     34 ++ | 
|         |     35 ++using std::endl; | 
|         |     36 ++using std::list; | 
|         |     37 ++using namespace mpd_interface; | 
|         |     38 ++ | 
|         |     39 ++// interface for communication with IMMS server | 
|         |     40 ++// comes from clientstub.h | 
|         |     41 ++struct MPDOps; | 
|         |     42 ++typedef IMMSClient<MPDOps> MPDClient; | 
|         |     43 ++ | 
|         |     44 ++int poll_time = 250; // miliseconds | 
|         |     45 ++const double reconnect_interval = 1.0; // seconds | 
|         |     46 ++GMainLoop *loop = nullptr; | 
|         |     47 ++GSource* ts; | 
|         |     48 ++ | 
|         |     49 ++MPDClient imms; | 
|         |     50 ++Player mpd; | 
|         |     51 ++list<int> playqueue; | 
|         |     52 ++const list<int>::size_type pq_capacity = 1; | 
|         |     53 ++ | 
|         |     54 ++ | 
|         |     55 ++// that's the main function - it's called regularly and handles all the | 
|         |     56 ++// IMMS and MPD communication and decides what to do when anything happens | 
|         |     57 ++gboolean do_events(void *unused); | 
|         |     58 ++ | 
|         |     59 ++// determines whether the currently playing song has been selected | 
|         |     60 ++// specifically by the user | 
|         |     61 ++bool next_jumped();  | 
|         |     62 ++ | 
|         |     63 ++void notify_song_ended(const Song& song, double elapsed_time, bool jumped); | 
|         |     64 ++ | 
|         |     65 ++// resets the elapsed_timer and sets the jumped flag, too | 
|         |     66 ++void notify_song_started(const Song& song, double& elapsed_time, | 
|         |     67 ++    bool& jumped); | 
|         |     68 ++ | 
|         |     69 ++void update_playqueue(); | 
|         |     70 ++bool playqueue_contains(int song); | 
|         |     71 ++ | 
|         |     72 ++void quit(int signum); | 
|         |     73 ++ | 
|         |     74 ++ | 
|         |     75 ++struct MPDOps | 
|         |     76 ++{ | 
|         |     77 ++    // IMMS server's suggestion of the next song | 
|         |     78 ++    static void set_next(int next) | 
|         |     79 ++    { | 
|         |     80 ++      if(playqueue.size() < pq_capacity) { | 
|         |     81 ++	if(mpd.song(current).path() == mpd.song(next).path() || | 
|         |     82 ++	    mpd.song(previous).path() == mpd.song(next).path() || | 
|         |     83 ++	    playqueue_contains(next) || next >= mpd.playlist_length()) { | 
|         |     84 ++          update_playqueue(); | 
|         |     85 ++	} | 
|         |     86 ++	else { | 
|         |     87 ++	  playqueue.push_back(next); | 
|         |     88 ++	} | 
|         |     89 ++      } | 
|         |     90 ++    } | 
|         |     91 ++    // no idea, works just peach as it is | 
|         |     92 ++    // asked mag about it, waiting for an answer | 
|         |     93 ++    // TODO if he doesn't answer, dig it out | 
|         |     94 ++    static void reset_selection() { } | 
|         |     95 ++    // path of the song at the given pos for IMMS server | 
|         |     96 ++    static string get_item(int index) {return mpd.song(index).path(); } | 
|         |     97 ++    // size of the playlist for the IMMS server | 
|         |     98 ++    static int get_length() { return mpd.playlist_length(); } | 
|         |     99 ++};  | 
|         |    100 ++ | 
|         |    101 ++int main(int argc, char **argv) | 
|         |    102 ++{ | 
|         |    103 ++  // glib initialization | 
|         |    104 ++  loop = g_main_loop_new(nullptr, FALSE); | 
|         |    105 ++ | 
|         |    106 ++  signal(SIGINT,  quit); | 
|         |    107 ++  signal(SIGTERM, quit); | 
|         |    108 ++  signal(SIGPIPE, SIG_IGN); | 
|         |    109 ++ | 
|         |    110 ++  ts = g_timeout_source_new(poll_time); | 
|         |    111 ++  g_source_attach(ts, nullptr); | 
|         |    112 ++  g_source_set_callback(ts, (GSourceFunc)do_events, nullptr, nullptr); | 
|         |    113 ++  // end of glib init | 
|         |    114 ++ | 
|         |    115 ++  g_main_loop_run(loop); | 
|         |    116 ++ | 
|         |    117 ++  LOG(INFO) << "Exitting." << endl; | 
|         |    118 ++  return 0; | 
|         |    119 ++} | 
|         |    120 ++ | 
|         |    121 ++gboolean do_events(void *unused) | 
|         |    122 ++{ | 
|         |    123 ++  static const double time_inc = double(poll_time)/1000.0; | 
|         |    124 ++    // the time that ACTUALLY elapsed when playing the song (in seconds) | 
|         |    125 ++  static double elapsed_time = 0;  | 
|         |    126 ++  static bool jumped = false; | 
|         |    127 ++  static double reconnect_timeout = 0; | 
|         |    128 ++ | 
|         |    129 ++  try { | 
|         |    130 ++    if(!mpd.connected()) { | 
|         |    131 ++      if(reconnect_timeout < time_inc) { | 
|         |    132 ++	LOG(INFO) << "Not connected to MPD. Attempting to connect..." | 
|         |    133 ++	  << endl; | 
|         |    134 ++	reconnect_timeout = reconnect_interval; | 
|         |    135 ++	mpd.connect(); | 
|         |    136 ++	LOG(INFO) << "Connected to MPD." << endl; | 
|         |    137 ++	reconnect_timeout = 0; | 
|         |    138 ++      } | 
|         |    139 ++      else { | 
|         |    140 ++	reconnect_timeout -= time_inc; | 
|         |    141 ++	return TRUE; | 
|         |    142 ++      } | 
|         |    143 ++    } | 
|         |    144 ++    if(imms.check_connection()) imms.setup(0); | 
|         |    145 ++    if(!imms.isok()) return TRUE; | 
|         |    146 ++ | 
|         |    147 ++    mpd.refresh(); | 
|         |    148 ++ | 
|         |    149 ++    if(mpd.playlist_changed()) { | 
|         |    150 ++      imms.playlist_changed(mpd.playlist_length()); | 
|         |    151 ++      playqueue.clear(); | 
|         |    152 ++    } | 
|         |    153 ++    if(mpd.radnom()) update_playqueue(); | 
|         |    154 ++ | 
|         |    155 ++    if(mpd.status_changed()) { | 
|         |    156 ++      if(mpd.status(current) == stopped) { | 
|         |    157 ++	notify_song_ended(mpd.song(current), elapsed_time, jumped); | 
|         |    158 ++      } | 
|         |    159 ++      else if(mpd.status(previous) == stopped && | 
|         |    160 ++	  mpd.status(current)==playing) { | 
|         |    161 ++	notify_song_started(mpd.song(current), elapsed_time, jumped); | 
|         |    162 ++	 | 
|         |    163 ++	// clear the song_changed() flag | 
|         |    164 ++	if(mpd.song_changed()) mpd.refresh();  | 
|         |    165 ++      } | 
|         |    166 ++    } | 
|         |    167 ++    if(mpd.status(current) == playing) { | 
|         |    168 ++      elapsed_time += time_inc; | 
|         |    169 ++      if(mpd.song_changed()) { | 
|         |    170 ++	notify_song_ended(mpd.song(previous), elapsed_time, jumped); | 
|         |    171 ++ | 
|         |    172 ++	if(!mpd.radnom() || playqueue.empty()) { | 
|         |    173 ++	  notify_song_started(mpd.song(current), elapsed_time, jumped); | 
|         |    174 ++	} | 
|         |    175 ++	else { | 
|         |    176 ++	  mpd.play_song(playqueue.front()); | 
|         |    177 ++	  notify_song_started(mpd.song(playqueue.front()), elapsed_time, | 
|         |    178 ++	      jumped); | 
|         |    179 ++	  playqueue.erase(playqueue.begin()); | 
|         |    180 ++	  update_playqueue(); | 
|         |    181 ++	  // this could otherwise incorrectly set song_changed() flag | 
|         |    182 ++	  mpd.refresh();  | 
|         |    183 ++	} | 
|         |    184 ++      } | 
|         |    185 ++      else { | 
|         |    186 ++	// fix the real timer if it's inconsistent with what player | 
|         |    187 ++	// says is the elapsed time of the current song | 
|         |    188 ++	if(elapsed_time - double(mpd.song(current).elapsed()) >= 3.0) { | 
|         |    189 ++	  if(mpd.song(current).elapsed() == 0) { | 
|         |    190 ++	    Song tmp_ended = mpd.song(current); | 
|         |    191 ++	    tmp_ended.set_length(int(elapsed_time) * 2); | 
|         |    192 ++	    notify_song_ended(tmp_ended, elapsed_time, jumped); | 
|         |    193 ++	    notify_song_started(mpd.song(current), elapsed_time, jumped); | 
|         |    194 ++	    jumped = false; | 
|         |    195 ++	  } | 
|         |    196 ++	  elapsed_time = mpd.song(current).elapsed(); | 
|         |    197 ++	} | 
|         |    198 ++      } | 
|         |    199 ++    } | 
|         |    200 ++  } | 
|         |    201 ++  catch (connection_err) { | 
|         |    202 ++    if(reconnect_timeout >= reconnect_interval) { | 
|         |    203 ++	  LOG(INFO) << "Connecting to MPD was unsuccessful. " | 
|         |    204 ++	    "Next attempt in " << reconnect_interval << " second" | 
|         |    205 ++	    << (reconnect_interval == 1.0 ? "":"s") << "." << endl; | 
|         |    206 ++    } | 
|         |    207 ++    else { | 
|         |    208 ++      LOG(INFO) << "Disconnected from MPD." << endl; | 
|         |    209 ++    } | 
|         |    210 ++  } | 
|         |    211 ++  catch (mpd_err ex) { | 
|         |    212 ++    LOG(ERROR) << "Error: " << ex.message() << endl; | 
|         |    213 ++    g_main_quit(loop); | 
|         |    214 ++    loop = nullptr; | 
|         |    215 ++    exit(1); | 
|         |    216 ++  } | 
|         |    217 ++  return TRUE; | 
|         |    218 ++} | 
|         |    219 ++ | 
|         |    220 ++// determines whether the song has been played whole | 
|         |    221 ++bool played_whole(double elapsed_time, int length) | 
|         |    222 ++{ | 
|         |    223 ++  static const double abs_limit = 20.0; | 
|         |    224 ++  static const double coeficient = 0.08; | 
|         |    225 ++ | 
|         |    226 ++  double rel_limit = double(length) * coeficient; | 
|         |    227 ++ | 
|         |    228 ++  double limit = (abs_limit < rel_limit) ? abs_limit : rel_limit; | 
|         |    229 ++  return double(length)-elapsed_time < limit;  | 
|         |    230 ++} | 
|         |    231 ++// determines whether the song has been skipped early | 
|         |    232 ++// (thus being set as not a prefed one) | 
|         |    233 ++bool bad(double elapsed_time, int length) | 
|         |    234 ++{ | 
|         |    235 ++  static const double abs_limit = 30.0; | 
|         |    236 ++  static const double coeficient = 0.13; | 
|         |    237 ++ | 
|         |    238 ++  double rel_limit = double(length) * coeficient; | 
|         |    239 ++ | 
|         |    240 ++  double limit = (rel_limit < abs_limit) ? rel_limit : abs_limit; | 
|         |    241 ++  return elapsed_time < limit; | 
|         |    242 ++} | 
|         |    243 ++bool next_jumped() | 
|         |    244 ++{ | 
|         |    245 ++  if(mpd.radnom()) return false; | 
|         |    246 ++ | 
|         |    247 ++  if(mpd.song(current).pos() == mpd.song(previous).pos()+1) | 
|         |    248 ++    return false; | 
|         |    249 ++  if(mpd.song(current).pos() == 0 && | 
|         |    250 ++      mpd.song(previous).pos() == mpd.playlist_length()-1) | 
|         |    251 ++    return false; | 
|         |    252 ++ | 
|         |    253 ++  return true; | 
|         |    254 ++} | 
|         |    255 ++void notify_song_ended(const Song& song, double elapsed_time, bool jumped) | 
|         |    256 ++{ | 
|         |    257 ++  if(song.length() == Song::invalid_time) return; | 
|         |    258 ++ | 
|         |    259 ++  imms.end_song(played_whole(elapsed_time, song.length()), jumped, | 
|         |    260 ++      bad(elapsed_time, song.length()) ); | 
|         |    261 ++} | 
|         |    262 ++ | 
|         |    263 ++void notify_song_started(const Song& song, double& elapsed_timer, | 
|         |    264 ++    bool& jumped) | 
|         |    265 ++{ | 
|         |    266 ++  imms.start_song(song.pos(), song.path()); | 
|         |    267 ++  elapsed_timer = 0; | 
|         |    268 ++  jumped = next_jumped(); | 
|         |    269 ++  mpd.song_changed(); // clear the change notification | 
|         |    270 ++} | 
|         |    271 ++ | 
|         |    272 ++void update_playqueue() | 
|         |    273 ++{ | 
|         |    274 ++  static const int timeout_value = 3; | 
|         |    275 ++  static int timeout = 0; | 
|         |    276 ++ | 
|         |    277 ++  if(timeout == 0) | 
|         |    278 ++  { | 
|         |    279 ++    if(playqueue.size() < pq_capacity) { | 
|         |    280 ++      list<int>::size_type i; | 
|         |    281 ++      for(i = pq_capacity - playqueue.size(); i!=0; i--) { | 
|         |    282 ++	imms.select_next(); | 
|         |    283 ++      } | 
|         |    284 ++      timeout = timeout_value; | 
|         |    285 ++    } | 
|         |    286 ++  } | 
|         |    287 ++  else --timeout; | 
|         |    288 ++} | 
|         |    289 ++ | 
|         |    290 ++bool playqueue_contains(int song) | 
|         |    291 ++{ | 
|         |    292 ++  list<int>::const_iterator i; | 
|         |    293 ++  for(i = playqueue.begin(); i!= playqueue.end(); i++) { | 
|         |    294 ++    if (*i == song) return true; | 
|         |    295 ++  } | 
|         |    296 ++  return false; | 
|         |    297 ++} | 
|         |    298 ++ | 
|         |    299 ++void quit(int signum) | 
|         |    300 ++{ | 
|         |    301 ++  if (loop) g_main_quit(loop); | 
|         |    302 ++  loop = nullptr; | 
|         |    303 ++  signal(signum, SIG_DFL); | 
|         |    304 ++} | 
|         |    305 ++ | 
|         |    306 ++ | 
|         |    307 +diff -r 171db9560cb5 clients/mpd/libmpdclient.c | 
|         |    308 +--- /dev/null	Thu Jan 01 00:00:00 1970 +0000 | 
|         |    309 ++++ b/clients/mpd/libmpdclient.c	Mon May 19 00:21:51 2008 -0400 | 
|         |    310 +@@ -0,0 +1,1955 @@ | 
|         |    311 ++/* libmpdclient | 
|         |    312 ++   (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) | 
|         |    313 ++   This project's homepage is: http://www.musicpd.org | 
|         |    314 ++ | 
|         |    315 ++   Redistribution and use in source and binary forms, with or without | 
|         |    316 ++   modification, are permitted provided that the following conditions | 
|         |    317 ++   are met: | 
|         |    318 ++ | 
|         |    319 ++   - Redistributions of source code must retain the above copyright | 
|         |    320 ++   notice, this list of conditions and the following disclaimer. | 
|         |    321 ++ | 
|         |    322 ++   - Redistributions in binary form must reproduce the above copyright | 
|         |    323 ++   notice, this list of conditions and the following disclaimer in the | 
|         |    324 ++   documentation and/or other materials provided with the distribution. | 
|         |    325 ++ | 
|         |    326 ++   - Neither the name of the Music Player Daemon nor the names of its | 
|         |    327 ++   contributors may be used to endorse or promote products derived from | 
|         |    328 ++   this software without specific prior written permission. | 
|         |    329 ++ | 
|         |    330 ++   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
|         |    331 ++   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
|         |    332 ++   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
|         |    333 ++   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR | 
|         |    334 ++   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 
|         |    335 ++   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 
|         |    336 ++   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 
|         |    337 ++   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 
|         |    338 ++   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 
|         |    339 ++   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
|         |    340 ++   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|         |    341 ++*/ | 
|         |    342 ++ | 
|         |    343 ++#include "libmpdclient.h" | 
|         |    344 ++ | 
|         |    345 ++#include <errno.h> | 
|         |    346 ++#include <ctype.h> | 
|         |    347 ++#include <sys/types.h> | 
|         |    348 ++#include <stdio.h> | 
|         |    349 ++#include <sys/param.h> | 
|         |    350 ++#include <string.h> | 
|         |    351 ++#include <unistd.h> | 
|         |    352 ++#include <stdlib.h> | 
|         |    353 ++#include <fcntl.h> | 
|         |    354 ++#include <limits.h> | 
|         |    355 ++ | 
|         |    356 ++#ifdef WIN32 | 
|         |    357 ++#  include <ws2tcpip.h> | 
|         |    358 ++#  include <winsock.h> | 
|         |    359 ++#else | 
|         |    360 ++#  include <netinet/in.h> | 
|         |    361 ++#  include <arpa/inet.h> | 
|         |    362 ++#  include <sys/socket.h> | 
|         |    363 ++#  include <netdb.h> | 
|         |    364 ++#endif | 
|         |    365 ++ | 
|         |    366 ++/* (bits+1)/3 (plus the sign character) */ | 
|         |    367 ++#define INTLEN      ((sizeof(int)       * CHAR_BIT + 1) / 3 + 1) | 
|         |    368 ++#define LONGLONGLEN ((sizeof(long long) * CHAR_BIT + 1) / 3 + 1) | 
|         |    369 ++ | 
|         |    370 ++#define COMMAND_LIST    1 | 
|         |    371 ++#define COMMAND_LIST_OK 2 | 
|         |    372 ++ | 
|         |    373 ++#ifndef MPD_NO_GAI | 
|         |    374 ++#  ifdef AI_ADDRCONFIG | 
|         |    375 ++#    define MPD_HAVE_GAI | 
|         |    376 ++#  endif | 
|         |    377 ++#endif | 
|         |    378 ++ | 
|         |    379 ++#ifndef MSG_DONTWAIT | 
|         |    380 ++#  define MSG_DONTWAIT 0 | 
|         |    381 ++#endif | 
|         |    382 ++ | 
|         |    383 ++#ifdef WIN32 | 
|         |    384 ++#  define SELECT_ERRNO_IGNORE   (errno == WSAEINTR || errno == WSAEINPROGRESS) | 
|         |    385 ++#  define SENDRECV_ERRNO_IGNORE SELECT_ERRNO_IGNORE | 
|         |    386 ++#else | 
|         |    387 ++#  define SELECT_ERRNO_IGNORE   (errno == EINTR) | 
|         |    388 ++#  define SENDRECV_ERRNO_IGNORE (errno == EINTR || errno == EAGAIN) | 
|         |    389 ++#  define winsock_dll_error(c)  0 | 
|         |    390 ++#  define closesocket(s)        close(s) | 
|         |    391 ++#  define WSACleanup()          do { /* nothing */ } while (0) | 
|         |    392 ++#endif | 
|         |    393 ++ | 
|         |    394 ++#ifdef WIN32 | 
|         |    395 ++static int winsock_dll_error(mpd_Connection *connection) | 
|         |    396 ++{ | 
|         |    397 ++	WSADATA wsaData; | 
|         |    398 ++	if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0 || | 
|         |    399 ++			LOBYTE(wsaData.wVersion) != 2 || | 
|         |    400 ++			HIBYTE(wsaData.wVersion) != 2 ) { | 
|         |    401 ++		strcpy(connection->errorStr, | 
|         |    402 ++		       "Could not find usable WinSock DLL."); | 
|         |    403 ++		connection->error = MPD_ERROR_SYSTEM; | 
|         |    404 ++		return 1; | 
|         |    405 ++	} | 
|         |    406 ++	return 0; | 
|         |    407 ++} | 
|         |    408 ++ | 
|         |    409 ++static int do_connect_fail(mpd_Connection *connection, | 
|         |    410 ++                           const struct sockaddr *serv_addr, int addrlen) | 
|         |    411 ++{ | 
|         |    412 ++	int iMode = 1; /* 0 = blocking, else non-blocking */ | 
|         |    413 ++	ioctlsocket(connection->sock, FIONBIO, (u_long FAR*) &iMode); | 
|         |    414 ++	return (connect(connection->sock,serv_addr,addrlen) == SOCKET_ERROR | 
|         |    415 ++			&& WSAGetLastError() != WSAEWOULDBLOCK); | 
|         |    416 ++} | 
|         |    417 ++#else /* !WIN32 (sane operating systems) */ | 
|         |    418 ++static int do_connect_fail(mpd_Connection *connection, | 
|         |    419 ++                           const struct sockaddr *serv_addr, int addrlen) | 
|         |    420 ++{ | 
|         |    421 ++	int flags = fcntl(connection->sock, F_GETFL, 0); | 
|         |    422 ++	fcntl(connection->sock, F_SETFL, flags | O_NONBLOCK); | 
|         |    423 ++	return (connect(connection->sock,serv_addr,addrlen)<0 && | 
|         |    424 ++				errno!=EINPROGRESS); | 
|         |    425 ++} | 
|         |    426 ++#endif /* !WIN32 */ | 
|         |    427 ++ | 
|         |    428 ++#ifdef MPD_HAVE_GAI | 
|         |    429 ++static int mpd_connect(mpd_Connection * connection, const char * host, int port, | 
|         |    430 ++                       float timeout) | 
|         |    431 ++{ | 
|         |    432 ++	int error; | 
|         |    433 ++	char service[INTLEN+1]; | 
|         |    434 ++	struct addrinfo hints; | 
|         |    435 ++	struct addrinfo *res = NULL; | 
|         |    436 ++	struct addrinfo *addrinfo = NULL; | 
|         |    437 ++ | 
|         |    438 ++	/** | 
|         |    439 ++	 * Setup hints | 
|         |    440 ++	 */ | 
|         |    441 ++	hints.ai_flags     = AI_ADDRCONFIG; | 
|         |    442 ++	hints.ai_family    = PF_UNSPEC; | 
|         |    443 ++	hints.ai_socktype  = SOCK_STREAM; | 
|         |    444 ++	hints.ai_protocol  = IPPROTO_TCP; | 
|         |    445 ++	hints.ai_addrlen   = 0; | 
|         |    446 ++	hints.ai_addr      = NULL; | 
|         |    447 ++	hints.ai_canonname = NULL; | 
|         |    448 ++	hints.ai_next      = NULL; | 
|         |    449 ++ | 
|         |    450 ++	snprintf(service, sizeof(service), "%i", port); | 
|         |    451 ++ | 
|         |    452 ++	error = getaddrinfo(host, service, &hints, &addrinfo); | 
|         |    453 ++ | 
|         |    454 ++	if (error) { | 
|         |    455 ++		snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, | 
|         |    456 ++		         "host \"%s\" not found: %s", | 
|         |    457 ++		         host, gai_strerror(error)); | 
|         |    458 ++		connection->error = MPD_ERROR_UNKHOST; | 
|         |    459 ++		return -1; | 
|         |    460 ++	} | 
|         |    461 ++ | 
|         |    462 ++	for (res = addrinfo; res; res = res->ai_next) { | 
|         |    463 ++		/* create socket */ | 
|         |    464 ++		connection->sock = socket(res->ai_family, SOCK_STREAM, | 
|         |    465 ++		                          res->ai_protocol); | 
|         |    466 ++		if (connection->sock < 0) { | 
|         |    467 ++			snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, | 
|         |    468 ++			         "problems creating socket: %s", | 
|         |    469 ++			         strerror(errno)); | 
|         |    470 ++			connection->error = MPD_ERROR_SYSTEM; | 
|         |    471 ++			freeaddrinfo(addrinfo); | 
|         |    472 ++			return -1; | 
|         |    473 ++		} | 
|         |    474 ++ | 
|         |    475 ++		mpd_setConnectionTimeout(connection, timeout); | 
|         |    476 ++ | 
|         |    477 ++		/* connect stuff */ | 
|         |    478 ++ 		if (do_connect_fail(connection, | 
|         |    479 ++		                    res->ai_addr, res->ai_addrlen)) { | 
|         |    480 ++ 			/* try the next address family */ | 
|         |    481 ++ 			closesocket(connection->sock); | 
|         |    482 ++ 			connection->sock = -1; | 
|         |    483 ++ 			continue; | 
|         |    484 ++		} | 
|         |    485 ++	} | 
|         |    486 ++ | 
|         |    487 ++	freeaddrinfo(addrinfo); | 
|         |    488 ++ | 
|         |    489 ++	if (connection->sock < 0) { | 
|         |    490 ++		snprintf(connection->errorStr, MPD_ERRORSTR_MAX_LENGTH, | 
|         |    491 ++		         "problems connecting to \"%s\" on port %i: %s", | 
|         |    492 ++		         host, port, strerror(errno)); | 
|         |    493 ++		connection->error = MPD_ERROR_CONNPORT; | 
|         |    494 ++ | 
|         |    495 ++		return -1; | 
|         |    496 ++	} | 
|         |    497 ++ | 
|         |    498 ++	return 0; | 
|         |    499 ++} | 
|         |    500 ++#else /* !MPD_HAVE_GAI */ | 
|         |    501 ++static int mpd_connect(mpd_Connection * connection, const char * host, int port, | 
|         |    502 ++                       float timeout) | 
|         |    503 ++{ | 
|         |    504 ++	struct hostent * he; | 
|         |    505 ++	struct sockaddr * dest; | 
|         |    506 ++	int destlen; | 
|         |    507 ++	struct sockaddr_in sin; | 
|         |    508 ++ | 
|         |    509 ++	if(!(he=gethostbyname(host))) { | 
|         |    510 ++		snprintf(connection->errorStr,MPD_ERRORSTR_MAX_LENGTH, | 
|         |    511 ++				"host \"%s\" not found",host); | 
|         |    512 ++		connection->error = MPD_ERROR_UNKHOST; | 
|         |    513 ++		return -1; | 
|         |    514 ++	} | 
|         |    515 ++ | 
|         |    516 ++	memset(&sin,0,sizeof(struct sockaddr_in)); | 
|         |    517 ++	/*dest.sin_family = he->h_addrtype;*/ | 
|         |    518 ++	sin.sin_family = AF_INET; | 
|         |    519 ++	sin.sin_port = htons(port); | 
|         |    520 ++ | 
|         |    521 ++	switch(he->h_addrtype) { | 
|         |    522 ++	case AF_INET: | 
|         |    523 ++		memcpy((char *)&sin.sin_addr.s_addr,(char *)he->h_addr, | 
|         |    524 ++				he->h_length); | 
|         |    525 ++		dest = (struct sockaddr *)&sin; | 
|         |    526 ++		destlen = sizeof(struct sockaddr_in); | 
|         |    527 ++		break; | 
|         |    528 ++	default: | 
|         |    529 ++		strcpy(connection->errorStr,"address type is not IPv4"); | 
|         |    530 ++		connection->error = MPD_ERROR_SYSTEM; | 
|         |    531 ++		return -1; | 
|         |    532 ++		break; | 
|         |    533 ++	} | 
|         |    534 ++ | 
|         |    535 ++	if((connection->sock = socket(dest->sa_family,SOCK_STREAM,0))<0) { | 
|         |    536 ++		strcpy(connection->errorStr,"problems creating socket"); | 
|         |    537 ++		connection->error = MPD_ERROR_SYSTEM; | 
|         |    538 ++		return -1; | 
|         |    539 ++	} | 
|         |    540 ++ | 
|         |    541 ++	mpd_setConnectionTimeout(connection,timeout); | 
|         |    542 ++ | 
|         |    543 ++	/* connect stuff */ | 
|         |    544 ++	if (do_connect_fail(connection, dest, destlen)) { | 
|         |    545 ++		snprintf(connection->errorStr,MPD_ERRORSTR_MAX_LENGTH, | 
|         |    546 ++				"problems connecting to \"%s\" on port" | 
|         |    547 ++				" %i",host,port); | 
|         |    548 ++		connection->error = MPD_ERROR_CONNPORT; | 
|         |    549 ++		return -1; | 
|         |    550 ++	} | 
|         |    551 ++ | 
|         |    552 ++	return 0; | 
|         |    553 ++} | 
|         |    554 ++#endif /* !MPD_HAVE_GAI */ | 
|         |    555 ++ | 
|         |    556 ++char * mpdTagItemKeys[MPD_TAG_NUM_OF_ITEM_TYPES] = | 
|         |    557 ++{ | 
|         |    558 ++	"Artist", | 
|         |    559 ++	"Album", | 
|         |    560 ++	"Title", | 
|         |    561 ++	"Track", | 
|         |    562 ++	"Name", | 
|         |    563 ++	"Genre", | 
|         |    564 ++	"Date", | 
|         |    565 ++	"Composer", | 
|         |    566 ++	"Performer", | 
|         |    567 ++	"Comment", | 
|         |    568 ++	"Disc", | 
|         |    569 ++	"Filename", | 
|         |    570 ++	"Any" | 
|         |    571 ++}; | 
|         |    572 ++ | 
|         |    573 ++static char * mpd_sanitizeArg(const char * arg) { | 
|         |    574 ++	size_t i; | 
|         |    575 ++	char * ret; | 
|         |    576 ++	register const char *c; | 
|         |    577 ++	register char *rc; | 
|         |    578 ++ | 
|         |    579 ++	/* instead of counting in that loop above, just | 
|         |    580 ++	 * use a bit more memory and half running time | 
|         |    581 ++	 */ | 
|         |    582 ++	ret = (char *)malloc(strlen(arg) * 2 + 1); | 
|         |    583 ++ | 
|         |    584 ++	c = arg; | 
|         |    585 ++	rc = ret; | 
|         |    586 ++	for(i = strlen(arg)+1; i != 0; --i) { | 
|         |    587 ++		if(*c=='"' || *c=='\\') | 
|         |    588 ++			*rc++ = '\\'; | 
|         |    589 ++		*(rc++) = *(c++); | 
|         |    590 ++	} | 
|         |    591 ++ | 
|         |    592 ++	return ret; | 
|         |    593 ++} | 
|         |    594 ++ | 
|         |    595 ++static mpd_ReturnElement * mpd_newReturnElement(const char * name, const char * value) | 
|         |    596 ++{ | 
|         |    597 ++	mpd_ReturnElement * ret = (mpd_ReturnElement *)malloc(sizeof(mpd_ReturnElement)); | 
|         |    598 ++ | 
|         |    599 ++	ret->name = strdup(name); | 
|         |    600 ++	ret->value = strdup(value); | 
|         |    601 ++ | 
|         |    602 ++	return ret; | 
|         |    603 ++} | 
|         |    604 ++ | 
|         |    605 ++static void mpd_freeReturnElement(mpd_ReturnElement * re) { | 
|         |    606 ++	free(re->name); | 
|         |    607 ++	free(re->value); | 
|         |    608 ++	free(re); | 
|         |    609 ++} | 
|         |    610 ++ | 
|         |    611 ++void mpd_setConnectionTimeout(mpd_Connection * connection, float timeout) { | 
|         |    612 ++	connection->timeout.tv_sec = (int)timeout; | 
|         |    613 ++	connection->timeout.tv_usec = (int)(timeout*1e6 - | 
|         |    614 ++	                                    connection->timeout.tv_sec*1000000 + | 
|         |    615 ++					    0.5); | 
|         |    616 ++} | 
|         |    617 ++ | 
|         |    618 ++static int mpd_parseWelcome(mpd_Connection * connection, const char * host, int port, | 
|         |    619 ++                            char * rt, char * output) { | 
|         |    620 ++	char * tmp; | 
|         |    621 ++	char * test; | 
|         |    622 ++	int i; | 
|         |    623 ++ | 
|         |    624 ++	if(strncmp(output,MPD_WELCOME_MESSAGE,strlen(MPD_WELCOME_MESSAGE))) { | 
|         |    625 ++		snprintf(connection->errorStr,MPD_ERRORSTR_MAX_LENGTH, | 
|         |    626 ++				"mpd not running on port %i on host \"%s\"", | 
|         |    627 ++				port,host); | 
|         |    628 ++		connection->error = MPD_ERROR_NOTMPD; | 
|         |    629 ++		return 1; | 
|         |    630 ++	} | 
|         |    631 ++ | 
|         |    632 ++	tmp = &output[strlen(MPD_WELCOME_MESSAGE)]; | 
|         |    633 ++ | 
|         |    634 ++	for(i=0;i<3;i++) { | 
|         |    635 ++		if(tmp) connection->version[i] = strtol(tmp,&test,10); | 
|         |    636 ++ | 
|         |    637 ++		if (!tmp || (test[0] != '.' && test[0] != '\0')) { | 
|         |    638 ++			snprintf(connection->errorStr, | 
|         |    639 ++			         MPD_ERRORSTR_MAX_LENGTH, | 
|         |    640 ++			         "error parsing version number at " | 
|         |    641 ++			         "\"%s\"", | 
|         |    642 ++			         &output[strlen(MPD_WELCOME_MESSAGE)]); | 
|         |    643 ++			connection->error = MPD_ERROR_NOTMPD; | 
|         |    644 ++			return 1; | 
|         |    645 ++		} | 
|         |    646 ++		tmp = ++test; | 
|         |    647 ++	} | 
|         |    648 ++ | 
|         |    649 ++	return 0; | 
|         |    650 ++} | 
|         |    651 ++ | 
|         |    652 ++mpd_Connection * mpd_newConnection(const char * host, int port, float timeout) { | 
|         |    653 ++	int err; | 
|         |    654 ++	char * rt; | 
|         |    655 ++	char * output =  NULL; | 
|         |    656 ++	mpd_Connection * connection = (mpd_Connection *)malloc(sizeof(mpd_Connection)); | 
|         |    657 ++	struct timeval tv; | 
|         |    658 ++	fd_set fds; | 
|         |    659 ++	strcpy(connection->buffer,""); | 
|         |    660 ++	connection->buflen = 0; | 
|         |    661 ++	connection->bufstart = 0; | 
|         |    662 ++	strcpy(connection->errorStr,""); | 
|         |    663 ++	connection->error = 0; | 
|         |    664 ++	connection->doneProcessing = 0; | 
|         |    665 ++	connection->commandList = 0; | 
|         |    666 ++	connection->listOks = 0; | 
|         |    667 ++	connection->doneListOk = 0; | 
|         |    668 ++	connection->returnElement = NULL; | 
|         |    669 ++	connection->request = NULL; | 
|         |    670 ++ | 
|         |    671 ++	if (winsock_dll_error(connection)) | 
|         |    672 ++		return connection; | 
|         |    673 ++ | 
|         |    674 ++	if (mpd_connect(connection, host, port, timeout) < 0) | 
|         |    675 ++		return connection; | 
|         |    676 ++ | 
|         |    677 ++	while(!(rt = strstr(connection->buffer,"\n"))) { | 
|         |    678 ++		tv.tv_sec = connection->timeout.tv_sec; | 
|         |    679 ++		tv.tv_usec = connection->timeout.tv_usec; | 
|         |    680 ++		FD_ZERO(&fds); | 
|         |    681 ++		FD_SET(connection->sock,&fds); | 
|         |    682 ++		if((err = select(connection->sock+1,&fds,NULL,NULL,&tv)) == 1) { | 
|         |    683 ++			int readed; | 
|         |    684 ++			readed = recv(connection->sock, | 
|         |    685 ++					&(connection->buffer[connection->buflen]), | 
|         |    686 ++					MPD_BUFFER_MAX_LENGTH-connection->buflen,0); | 
|         |    687 ++			if(readed<=0) { | 
|         |    688 ++				snprintf(connection->errorStr,MPD_ERRORSTR_MAX_LENGTH, | 
|         |    689 ++						"problems getting a response from" | 
|         |    690 ++						" \"%s\" on port %i : %s",host, | 
|         |    691 ++						port, strerror(errno)); | 
|         |    692 ++				connection->error = MPD_ERROR_NORESPONSE; | 
|         |    693 ++				return connection; | 
|         |    694 ++			} | 
|         |    695 ++			connection->buflen+=readed; | 
|         |    696 ++			connection->buffer[connection->buflen] = '\0'; | 
|         |    697 ++		} | 
|         |    698 ++		else if(err<0) { | 
|         |    699 ++ 			if (SELECT_ERRNO_IGNORE) | 
|         |    700 ++				continue; | 
|         |    701 ++			snprintf(connection->errorStr, | 
|         |    702 ++					MPD_ERRORSTR_MAX_LENGTH, | 
|         |    703 ++					"problems connecting to \"%s\" on port" | 
|         |    704 ++					" %i",host,port); | 
|         |    705 ++			connection->error = MPD_ERROR_CONNPORT; | 
|         |    706 ++			return connection; | 
|         |    707 ++		} | 
|         |    708 ++		else { | 
|         |    709 ++			snprintf(connection->errorStr,MPD_ERRORSTR_MAX_LENGTH, | 
|         |    710 ++					"timeout in attempting to get a response from" | 
|         |    711 ++					" \"%s\" on port %i",host,port); | 
|         |    712 ++			connection->error = MPD_ERROR_NORESPONSE; | 
|         |    713 ++			return connection; | 
|         |    714 ++		} | 
|         |    715 ++	} | 
|         |    716 ++ | 
|         |    717 ++	*rt = '\0'; | 
|         |    718 ++	output = strdup(connection->buffer); | 
|         |    719 ++	strcpy(connection->buffer,rt+1); | 
|         |    720 ++	connection->buflen = strlen(connection->buffer); | 
|         |    721 ++ | 
|         |    722 ++	if(mpd_parseWelcome(connection,host,port,rt,output) == 0) connection->doneProcessing = 1; | 
|         |    723 ++ | 
|         |    724 ++	free(output); | 
|         |    725 ++ | 
|         |    726 ++	return connection; | 
|         |    727 ++} | 
|         |    728 ++ | 
|         |    729 ++void mpd_clearError(mpd_Connection * connection) { | 
|         |    730 ++	connection->error = 0; | 
|         |    731 ++	connection->errorStr[0] = '\0'; | 
|         |    732 ++} | 
|         |    733 ++ | 
|         |    734 ++void mpd_closeConnection(mpd_Connection * connection) { | 
|         |    735 ++	closesocket(connection->sock); | 
|         |    736 ++	if(connection->returnElement) free(connection->returnElement); | 
|         |    737 ++	if(connection->request) free(connection->request); | 
|         |    738 ++	free(connection); | 
|         |    739 ++	WSACleanup(); | 
|         |    740 ++} | 
|         |    741 ++ | 
|         |    742 ++static void mpd_executeCommand(mpd_Connection * connection, char * command) { | 
|         |    743 ++	int ret; | 
|         |    744 ++	struct timeval tv; | 
|         |    745 ++	fd_set fds; | 
|         |    746 ++	char * commandPtr = command; | 
|         |    747 ++	int commandLen = strlen(command); | 
|         |    748 ++ | 
|         |    749 ++	if(!connection->doneProcessing && !connection->commandList) { | 
|         |    750 ++		strcpy(connection->errorStr,"not done processing current command"); | 
|         |    751 ++		connection->error = 1; | 
|         |    752 ++		return; | 
|         |    753 ++	} | 
|         |    754 ++ | 
|         |    755 ++	mpd_clearError(connection); | 
|         |    756 ++ | 
|         |    757 ++	FD_ZERO(&fds); | 
|         |    758 ++	FD_SET(connection->sock,&fds); | 
|         |    759 ++	tv.tv_sec = connection->timeout.tv_sec; | 
|         |    760 ++	tv.tv_usec = connection->timeout.tv_usec; | 
|         |    761 ++ | 
|         |    762 ++	while((ret = select(connection->sock+1,NULL,&fds,NULL,&tv)==1) || | 
|         |    763 ++			(ret==-1 && SELECT_ERRNO_IGNORE)) { | 
|         |    764 ++		ret = send(connection->sock,commandPtr,commandLen,MSG_DONTWAIT); | 
|         |    765 ++		if(ret<=0) | 
|         |    766 ++		{ | 
|         |    767 ++			if (SENDRECV_ERRNO_IGNORE) continue; | 
|         |    768 ++			snprintf(connection->errorStr,MPD_ERRORSTR_MAX_LENGTH, | 
|         |    769 ++			         "problems giving command \"%s\"",command); | 
|         |    770 ++			connection->error = MPD_ERROR_SENDING; | 
|         |    771 ++			return; | 
|         |    772 ++		} | 
|         |    773 ++		else { | 
|         |    774 ++			commandPtr+=ret; | 
|         |    775 ++			commandLen-=ret; | 
|         |    776 ++		} | 
|         |    777 ++ | 
|         |    778 ++		if(commandLen<=0) break; | 
|         |    779 ++	} | 
|         |    780 ++ | 
|         |    781 ++	if(commandLen>0) { | 
|         |    782 ++		perror(""); | 
|         |    783 ++		snprintf(connection->errorStr,MPD_ERRORSTR_MAX_LENGTH, | 
|         |    784 ++		         "timeout sending command \"%s\"",command); | 
|         |    785 ++		connection->error = MPD_ERROR_TIMEOUT; | 
|         |    786 ++		return; | 
|         |    787 ++	} | 
|         |    788 ++ | 
|         |    789 ++	if(!connection->commandList) connection->doneProcessing = 0; | 
|         |    790 ++	else if(connection->commandList == COMMAND_LIST_OK) { | 
|         |    791 ++		connection->listOks++; | 
|         |    792 ++	} | 
|         |    793 ++} | 
|         |    794 ++ | 
|         |    795 ++static void mpd_getNextReturnElement(mpd_Connection * connection) { | 
|         |    796 ++	char * output = NULL; | 
|         |    797 ++	char * rt = NULL; | 
|         |    798 ++	char * name = NULL; | 
|         |    799 ++	char * value = NULL; | 
|         |    800 ++	fd_set fds; | 
|         |    801 ++	struct timeval tv; | 
|         |    802 ++	char * tok = NULL; | 
|         |    803 ++	int readed; | 
|         |    804 ++	char * bufferCheck = NULL; | 
|         |    805 ++	int err; | 
|         |    806 ++	int pos; | 
|         |    807 ++ | 
|         |    808 ++	if(connection->returnElement) mpd_freeReturnElement(connection->returnElement); | 
|         |    809 ++	connection->returnElement = NULL; | 
|         |    810 ++ | 
|         |    811 ++	if(connection->doneProcessing || (connection->listOks && | 
|         |    812 ++	   connection->doneListOk)) | 
|         |    813 ++	{ | 
|         |    814 ++		strcpy(connection->errorStr,"already done processing current command"); | 
|         |    815 ++		connection->error = 1; | 
|         |    816 ++		return; | 
|         |    817 ++	} | 
|         |    818 ++ | 
|         |    819 ++	bufferCheck = connection->buffer+connection->bufstart; | 
|         |    820 ++	while(connection->bufstart>=connection->buflen || | 
|         |    821 ++			!(rt = strchr(bufferCheck,'\n'))) { | 
|         |    822 ++		if(connection->buflen>=MPD_BUFFER_MAX_LENGTH) { | 
|         |    823 ++			memmove(connection->buffer, | 
|         |    824 ++					connection->buffer+ | 
|         |    825 ++					connection->bufstart, | 
|         |    826 ++					connection->buflen- | 
|         |    827 ++					connection->bufstart+1); | 
|         |    828 ++			connection->buflen-=connection->bufstart; | 
|         |    829 ++			connection->bufstart = 0; | 
|         |    830 ++		} | 
|         |    831 ++		if(connection->buflen>=MPD_BUFFER_MAX_LENGTH) { | 
|         |    832 ++			strcpy(connection->errorStr,"buffer overrun"); | 
|         |    833 ++			connection->error = MPD_ERROR_BUFFEROVERRUN; | 
|         |    834 ++			connection->doneProcessing = 1; | 
|         |    835 ++			connection->doneListOk = 0; | 
|         |    836 ++			return; | 
|         |    837 ++		} | 
|         |    838 ++		bufferCheck = connection->buffer+connection->buflen; | 
|         |    839 ++		tv.tv_sec = connection->timeout.tv_sec; | 
|         |    840 ++		tv.tv_usec = connection->timeout.tv_usec; | 
|         |    841 ++		FD_ZERO(&fds); | 
|         |    842 ++		FD_SET(connection->sock,&fds); | 
|         |    843 ++		if((err = select(connection->sock+1,&fds,NULL,NULL,&tv) == 1)) { | 
|         |    844 ++			readed = recv(connection->sock, | 
|         |    845 ++					connection->buffer+connection->buflen, | 
|         |    846 ++					MPD_BUFFER_MAX_LENGTH-connection->buflen, | 
|         |    847 ++					MSG_DONTWAIT); | 
|         |    848 ++			if(readed<0 && SENDRECV_ERRNO_IGNORE) { | 
|         |    849 ++				continue; | 
|         |    850 ++			} | 
|         |    851 ++			if(readed<=0) { | 
|         |    852 ++				strcpy(connection->errorStr,"connection" | 
|         |    853 ++				       " closed"); | 
|         |    854 ++				connection->error = MPD_ERROR_CONNCLOSED; | 
|         |    855 ++				connection->doneProcessing = 1; | 
|         |    856 ++				connection->doneListOk = 0; | 
|         |    857 ++				return; | 
|         |    858 ++			} | 
|         |    859 ++			connection->buflen+=readed; | 
|         |    860 ++			connection->buffer[connection->buflen] = '\0'; | 
|         |    861 ++		} | 
|         |    862 ++		else if(err<0 && SELECT_ERRNO_IGNORE) continue; | 
|         |    863 ++		else { | 
|         |    864 ++			strcpy(connection->errorStr,"connection timeout"); | 
|         |    865 ++			connection->error = MPD_ERROR_TIMEOUT; | 
|         |    866 ++			connection->doneProcessing = 1; | 
|         |    867 ++			connection->doneListOk = 0; | 
|         |    868 ++			return; | 
|         |    869 ++		} | 
|         |    870 ++	} | 
|         |    871 ++ | 
|         |    872 ++	*rt = '\0'; | 
|         |    873 ++	output = connection->buffer+connection->bufstart; | 
|         |    874 ++	connection->bufstart = rt - connection->buffer + 1; | 
|         |    875 ++ | 
|         |    876 ++	if(strcmp(output,"OK")==0) { | 
|         |    877 ++		if(connection->listOks > 0) { | 
|         |    878 ++			strcpy(connection->errorStr, "expected more list_OK's"); | 
|         |    879 ++			connection->error = 1; | 
|         |    880 ++		} | 
|         |    881 ++		connection->listOks = 0; | 
|         |    882 ++		connection->doneProcessing = 1; | 
|         |    883 ++		connection->doneListOk = 0; | 
|         |    884 ++		return; | 
|         |    885 ++	} | 
|         |    886 ++ | 
|         |    887 ++	if(strcmp(output, "list_OK") == 0) { | 
|         |    888 ++		if(!connection->listOks) { | 
|         |    889 ++			strcpy(connection->errorStr, | 
|         |    890 ++					"got an unexpected list_OK"); | 
|         |    891 ++			connection->error = 1; | 
|         |    892 ++		} | 
|         |    893 ++		else { | 
|         |    894 ++			connection->doneListOk = 1; | 
|         |    895 ++			connection->listOks--; | 
|         |    896 ++		} | 
|         |    897 ++		return; | 
|         |    898 ++	} | 
|         |    899 ++ | 
|         |    900 ++	if(strncmp(output,"ACK",strlen("ACK"))==0) { | 
|         |    901 ++		char * test; | 
|         |    902 ++		char * needle; | 
|         |    903 ++		int val; | 
|         |    904 ++ | 
|         |    905 ++		strcpy(connection->errorStr, output); | 
|         |    906 ++		connection->error = MPD_ERROR_ACK; | 
|         |    907 ++		connection->errorCode = MPD_ACK_ERROR_UNK; | 
|         |    908 ++		connection->errorAt = MPD_ERROR_AT_UNK; | 
|         |    909 ++		connection->doneProcessing = 1; | 
|         |    910 ++		connection->doneListOk = 0; | 
|         |    911 ++ | 
|         |    912 ++		needle = strchr(output, '['); | 
|         |    913 ++		if(!needle) return; | 
|         |    914 ++		val = strtol(needle+1, &test, 10); | 
|         |    915 ++		if(*test != '@') return; | 
|         |    916 ++		connection->errorCode = val; | 
|         |    917 ++		val = strtol(test+1, &test, 10); | 
|         |    918 ++		if(*test != ']') return; | 
|         |    919 ++		connection->errorAt = val; | 
|         |    920 ++		return; | 
|         |    921 ++	} | 
|         |    922 ++ | 
|         |    923 ++	tok = strchr(output, ':'); | 
|         |    924 ++	if (!tok) return; | 
|         |    925 ++	pos = tok - output; | 
|         |    926 ++	value = ++tok; | 
|         |    927 ++	name = output; | 
|         |    928 ++	name[pos] = '\0'; | 
|         |    929 ++ | 
|         |    930 ++	if(value[0]==' ') { | 
|         |    931 ++		connection->returnElement = mpd_newReturnElement(name,&(value[1])); | 
|         |    932 ++	} | 
|         |    933 ++	else { | 
|         |    934 ++		snprintf(connection->errorStr,MPD_ERRORSTR_MAX_LENGTH, | 
|         |    935 ++					"error parsing: %s:%s",name,value); | 
|         |    936 ++		connection->error = 1; | 
|         |    937 ++	} | 
|         |    938 ++} | 
|         |    939 ++ | 
|         |    940 ++void mpd_finishCommand(mpd_Connection * connection) { | 
|         |    941 ++	while(!connection->doneProcessing) { | 
|         |    942 ++		if(connection->doneListOk) connection->doneListOk = 0; | 
|         |    943 ++		mpd_getNextReturnElement(connection); | 
|         |    944 ++	} | 
|         |    945 ++} | 
|         |    946 ++ | 
|         |    947 ++static void mpd_finishListOkCommand(mpd_Connection * connection) { | 
|         |    948 ++	while(!connection->doneProcessing && connection->listOks && | 
|         |    949 ++			!connection->doneListOk) | 
|         |    950 ++	{ | 
|         |    951 ++		mpd_getNextReturnElement(connection); | 
|         |    952 ++	} | 
|         |    953 ++} | 
|         |    954 ++ | 
|         |    955 ++int mpd_nextListOkCommand(mpd_Connection * connection) { | 
|         |    956 ++	mpd_finishListOkCommand(connection); | 
|         |    957 ++	if(!connection->doneProcessing) connection->doneListOk = 0; | 
|         |    958 ++	if(connection->listOks == 0 || connection->doneProcessing) return -1; | 
|         |    959 ++	return 0; | 
|         |    960 ++} | 
|         |    961 ++ | 
|         |    962 ++void mpd_sendStatusCommand(mpd_Connection * connection) { | 
|         |    963 ++	mpd_executeCommand(connection,"status\n"); | 
|         |    964 ++} | 
|         |    965 ++ | 
|         |    966 ++mpd_Status * mpd_getStatus(mpd_Connection * connection) { | 
|         |    967 ++	mpd_Status * status; | 
|         |    968 ++ | 
|         |    969 ++	/*mpd_executeCommand(connection,"status\n"); | 
|         |    970 ++ | 
|         |    971 ++	if(connection->error) return NULL;*/ | 
|         |    972 ++ | 
|         |    973 ++	if(connection->doneProcessing || (connection->listOks && | 
|         |    974 ++	   connection->doneListOk)) | 
|         |    975 ++	{ | 
|         |    976 ++		return NULL; | 
|         |    977 ++	} | 
|         |    978 ++ | 
|         |    979 ++	if(!connection->returnElement) mpd_getNextReturnElement(connection); | 
|         |    980 ++ | 
|         |    981 ++	status = (mpd_Status *)malloc(sizeof(mpd_Status)); | 
|         |    982 ++	status->volume = -1; | 
|         |    983 ++	status->repeat = 0; | 
|         |    984 ++	status->random = 0; | 
|         |    985 ++	status->playlist = -1; | 
|         |    986 ++	status->playlistLength = -1; | 
|         |    987 ++	status->state = -1; | 
|         |    988 ++	status->song = 0; | 
|         |    989 ++	status->songid = 0; | 
|         |    990 ++	status->elapsedTime = 0; | 
|         |    991 ++	status->totalTime = 0; | 
|         |    992 ++	status->bitRate = 0; | 
|         |    993 ++	status->sampleRate = 0; | 
|         |    994 ++	status->bits = 0; | 
|         |    995 ++	status->channels = 0; | 
|         |    996 ++	status->crossfade = -1; | 
|         |    997 ++	status->error = NULL; | 
|         |    998 ++	status->updatingDb = 0; | 
|         |    999 ++ | 
|         |   1000 ++	if(connection->error) { | 
|         |   1001 ++		free(status); | 
|         |   1002 ++		return NULL; | 
|         |   1003 ++	} | 
|         |   1004 ++	while(connection->returnElement) { | 
|         |   1005 ++		mpd_ReturnElement * re = connection->returnElement; | 
|         |   1006 ++		if(strcmp(re->name,"volume")==0) { | 
|         |   1007 ++			status->volume = atoi(re->value); | 
|         |   1008 ++		} | 
|         |   1009 ++		else if(strcmp(re->name,"repeat")==0) { | 
|         |   1010 ++			status->repeat = atoi(re->value); | 
|         |   1011 ++		} | 
|         |   1012 ++		else if(strcmp(re->name,"random")==0) { | 
|         |   1013 ++			status->random = atoi(re->value); | 
|         |   1014 ++		} | 
|         |   1015 ++		else if(strcmp(re->name,"playlist")==0) { | 
|         |   1016 ++			status->playlist = strtol(re->value,NULL,10); | 
|         |   1017 ++		} | 
|         |   1018 ++		else if(strcmp(re->name,"playlistlength")==0) { | 
|         |   1019 ++			status->playlistLength = atoi(re->value); | 
|         |   1020 ++		} | 
|         |   1021 ++		else if(strcmp(re->name,"bitrate")==0) { | 
|         |   1022 ++			status->bitRate = atoi(re->value); | 
|         |   1023 ++		} | 
|         |   1024 ++		else if(strcmp(re->name,"state")==0) { | 
|         |   1025 ++			if(strcmp(re->value,"play")==0) { | 
|         |   1026 ++				status->state = MPD_STATUS_STATE_PLAY; | 
|         |   1027 ++			} | 
|         |   1028 ++			else if(strcmp(re->value,"stop")==0) { | 
|         |   1029 ++				status->state = MPD_STATUS_STATE_STOP; | 
|         |   1030 ++			} | 
|         |   1031 ++			else if(strcmp(re->value,"pause")==0) { | 
|         |   1032 ++				status->state = MPD_STATUS_STATE_PAUSE; | 
|         |   1033 ++			} | 
|         |   1034 ++			else { | 
|         |   1035 ++				status->state = MPD_STATUS_STATE_UNKNOWN; | 
|         |   1036 ++			} | 
|         |   1037 ++		} | 
|         |   1038 ++		else if(strcmp(re->name,"song")==0) { | 
|         |   1039 ++			status->song = atoi(re->value); | 
|         |   1040 ++		} | 
|         |   1041 ++		else if(strcmp(re->name,"songid")==0) { | 
|         |   1042 ++			status->songid = atoi(re->value); | 
|         |   1043 ++		} | 
|         |   1044 ++		else if(strcmp(re->name,"time")==0) { | 
|         |   1045 ++			char * tok = strchr(re->value,':'); | 
|         |   1046 ++			/* the second strchr below is a safety check */ | 
|         |   1047 ++			if (tok && (strchr(tok,0) > (tok+1))) { | 
|         |   1048 ++				/* atoi stops at the first non-[0-9] char: */ | 
|         |   1049 ++				status->elapsedTime = atoi(re->value); | 
|         |   1050 ++				status->totalTime = atoi(tok+1); | 
|         |   1051 ++			} | 
|         |   1052 ++		} | 
|         |   1053 ++		else if(strcmp(re->name,"error")==0) { | 
|         |   1054 ++			status->error = strdup(re->value); | 
|         |   1055 ++		} | 
|         |   1056 ++		else if(strcmp(re->name,"xfade")==0) { | 
|         |   1057 ++			status->crossfade = atoi(re->value); | 
|         |   1058 ++		} | 
|         |   1059 ++		else if(strcmp(re->name,"updating_db")==0) { | 
|         |   1060 ++			status->updatingDb = atoi(re->value); | 
|         |   1061 ++		} | 
|         |   1062 ++		else if(strcmp(re->name,"audio")==0) { | 
|         |   1063 ++			char * tok = strchr(re->value,':'); | 
|         |   1064 ++			if (tok && (strchr(tok,0) > (tok+1))) { | 
|         |   1065 ++				status->sampleRate = atoi(re->value); | 
|         |   1066 ++				status->bits = atoi(++tok); | 
|         |   1067 ++				tok = strchr(tok,':'); | 
|         |   1068 ++				if (tok && (strchr(tok,0) > (tok+1))) | 
|         |   1069 ++					status->channels = atoi(tok+1); | 
|         |   1070 ++			} | 
|         |   1071 ++		} | 
|         |   1072 ++ | 
|         |   1073 ++		mpd_getNextReturnElement(connection); | 
|         |   1074 ++		if(connection->error) { | 
|         |   1075 ++			free(status); | 
|         |   1076 ++			return NULL; | 
|         |   1077 ++		} | 
|         |   1078 ++	} | 
|         |   1079 ++ | 
|         |   1080 ++	if(connection->error) { | 
|         |   1081 ++		free(status); | 
|         |   1082 ++		return NULL; | 
|         |   1083 ++	} | 
|         |   1084 ++	else if(status->state<0) { | 
|         |   1085 ++		strcpy(connection->errorStr,"state not found"); | 
|         |   1086 ++		connection->error = 1; | 
|         |   1087 ++		free(status); | 
|         |   1088 ++		return NULL; | 
|         |   1089 ++	} | 
|         |   1090 ++ | 
|         |   1091 ++	return status; | 
|         |   1092 ++} | 
|         |   1093 ++ | 
|         |   1094 ++void mpd_freeStatus(mpd_Status * status) { | 
|         |   1095 ++	if(status->error) free(status->error); | 
|         |   1096 ++	free(status); | 
|         |   1097 ++} | 
|         |   1098 ++ | 
|         |   1099 ++void mpd_sendStatsCommand(mpd_Connection * connection) { | 
|         |   1100 ++	mpd_executeCommand(connection,"stats\n"); | 
|         |   1101 ++} | 
|         |   1102 ++ | 
|         |   1103 ++mpd_Stats * mpd_getStats(mpd_Connection * connection) { | 
|         |   1104 ++	mpd_Stats * stats; | 
|         |   1105 ++ | 
|         |   1106 ++	/*mpd_executeCommand(connection,"stats\n"); | 
|         |   1107 ++ | 
|         |   1108 ++	if(connection->error) return NULL;*/ | 
|         |   1109 ++ | 
|         |   1110 ++	if(connection->doneProcessing || (connection->listOks && | 
|         |   1111 ++	   connection->doneListOk)) | 
|         |   1112 ++	{ | 
|         |   1113 ++		return NULL; | 
|         |   1114 ++	} | 
|         |   1115 ++ | 
|         |   1116 ++	if(!connection->returnElement) mpd_getNextReturnElement(connection); | 
|         |   1117 ++ | 
|         |   1118 ++	stats = (mpd_Stats *)malloc(sizeof(mpd_Stats)); | 
|         |   1119 ++	stats->numberOfArtists = 0; | 
|         |   1120 ++	stats->numberOfAlbums = 0; | 
|         |   1121 ++	stats->numberOfSongs = 0; | 
|         |   1122 ++	stats->uptime = 0; | 
|         |   1123 ++	stats->dbUpdateTime = 0; | 
|         |   1124 ++	stats->playTime = 0; | 
|         |   1125 ++	stats->dbPlayTime = 0; | 
|         |   1126 ++ | 
|         |   1127 ++	if(connection->error) { | 
|         |   1128 ++		free(stats); | 
|         |   1129 ++		return NULL; | 
|         |   1130 ++	} | 
|         |   1131 ++	while(connection->returnElement) { | 
|         |   1132 ++		mpd_ReturnElement * re = connection->returnElement; | 
|         |   1133 ++		if(strcmp(re->name,"artists")==0) { | 
|         |   1134 ++			stats->numberOfArtists = atoi(re->value); | 
|         |   1135 ++		} | 
|         |   1136 ++		else if(strcmp(re->name,"albums")==0) { | 
|         |   1137 ++			stats->numberOfAlbums = atoi(re->value); | 
|         |   1138 ++		} | 
|         |   1139 ++		else if(strcmp(re->name,"songs")==0) { | 
|         |   1140 ++			stats->numberOfSongs = atoi(re->value); | 
|         |   1141 ++		} | 
|         |   1142 ++		else if(strcmp(re->name,"uptime")==0) { | 
|         |   1143 ++			stats->uptime = strtol(re->value,NULL,10); | 
|         |   1144 ++		} | 
|         |   1145 ++		else if(strcmp(re->name,"db_update")==0) { | 
|         |   1146 ++			stats->dbUpdateTime = strtol(re->value,NULL,10); | 
|         |   1147 ++		} | 
|         |   1148 ++		else if(strcmp(re->name,"playtime")==0) { | 
|         |   1149 ++			stats->playTime = strtol(re->value,NULL,10); | 
|         |   1150 ++		} | 
|         |   1151 ++		else if(strcmp(re->name,"db_playtime")==0) { | 
|         |   1152 ++			stats->dbPlayTime = strtol(re->value,NULL,10); | 
|         |   1153 ++		} | 
|         |   1154 ++ | 
|         |   1155 ++		mpd_getNextReturnElement(connection); | 
|         |   1156 ++		if(connection->error) { | 
|         |   1157 ++			free(stats); | 
|         |   1158 ++			return NULL; | 
|         |   1159 ++		} | 
|         |   1160 ++	} | 
|         |   1161 ++ | 
|         |   1162 ++	if(connection->error) { | 
|         |   1163 ++		free(stats); | 
|         |   1164 ++		return NULL; | 
|         |   1165 ++	} | 
|         |   1166 ++ | 
|         |   1167 ++	return stats; | 
|         |   1168 ++} | 
|         |   1169 ++ | 
|         |   1170 ++void mpd_freeStats(mpd_Stats * stats) { | 
|         |   1171 ++	free(stats); | 
|         |   1172 ++} | 
|         |   1173 ++ | 
|         |   1174 ++mpd_SearchStats * mpd_getSearchStats(mpd_Connection * connection) | 
|         |   1175 ++{ | 
|         |   1176 ++	mpd_SearchStats * stats; | 
|         |   1177 ++	mpd_ReturnElement * re; | 
|         |   1178 ++ | 
|         |   1179 ++	if (connection->doneProcessing || | 
|         |   1180 ++	    (connection->listOks && connection->doneListOk)) { | 
|         |   1181 ++		return NULL; | 
|         |   1182 ++	} | 
|         |   1183 ++ | 
|         |   1184 ++	if (!connection->returnElement) mpd_getNextReturnElement(connection); | 
|         |   1185 ++ | 
|         |   1186 ++	if (connection->error) | 
|         |   1187 ++		return NULL; | 
|         |   1188 ++ | 
|         |   1189 ++	stats = (mpd_SearchStats *)malloc(sizeof(mpd_SearchStats)); | 
|         |   1190 ++	stats->numberOfSongs = 0; | 
|         |   1191 ++	stats->playTime = 0; | 
|         |   1192 ++ | 
|         |   1193 ++	while (connection->returnElement) { | 
|         |   1194 ++		re = connection->returnElement; | 
|         |   1195 ++ | 
|         |   1196 ++		if (strcmp(re->name, "songs") == 0) { | 
|         |   1197 ++			stats->numberOfSongs = atoi(re->value); | 
|         |   1198 ++		} else if (strcmp(re->name, "playtime") == 0) { | 
|         |   1199 ++			stats->playTime = strtol(re->value, NULL, 10); | 
|         |   1200 ++		} | 
|         |   1201 ++ | 
|         |   1202 ++		mpd_getNextReturnElement(connection); | 
|         |   1203 ++		if (connection->error) { | 
|         |   1204 ++			free(stats); | 
|         |   1205 ++			return NULL; | 
|         |   1206 ++		} | 
|         |   1207 ++	} | 
|         |   1208 ++ | 
|         |   1209 ++	if (connection->error) { | 
|         |   1210 ++		free(stats); | 
|         |   1211 ++		return NULL; | 
|         |   1212 ++	} | 
|         |   1213 ++ | 
|         |   1214 ++	return stats; | 
|         |   1215 ++} | 
|         |   1216 ++ | 
|         |   1217 ++void mpd_freeSearchStats(mpd_SearchStats * stats) | 
|         |   1218 ++{ | 
|         |   1219 ++	free(stats); | 
|         |   1220 ++} | 
|         |   1221 ++ | 
|         |   1222 ++static void mpd_initSong(mpd_Song * song) { | 
|         |   1223 ++	song->file = NULL; | 
|         |   1224 ++	song->artist = NULL; | 
|         |   1225 ++	song->album = NULL; | 
|         |   1226 ++	song->track = NULL; | 
|         |   1227 ++	song->title = NULL; | 
|         |   1228 ++	song->name = NULL; | 
|         |   1229 ++	song->date = NULL; | 
|         |   1230 ++	/* added by Qball */ | 
|         |   1231 ++	song->genre = NULL; | 
|         |   1232 ++	song->composer = NULL; | 
|         |   1233 ++	song->performer = NULL; | 
|         |   1234 ++	song->disc = NULL; | 
|         |   1235 ++	song->comment = NULL; | 
|         |   1236 ++ | 
|         |   1237 ++	song->time = MPD_SONG_NO_TIME; | 
|         |   1238 ++	song->pos = MPD_SONG_NO_NUM; | 
|         |   1239 ++	song->id = MPD_SONG_NO_ID; | 
|         |   1240 ++} | 
|         |   1241 ++ | 
|         |   1242 ++static void mpd_finishSong(mpd_Song * song) { | 
|         |   1243 ++	if(song->file) free(song->file); | 
|         |   1244 ++	if(song->artist) free(song->artist); | 
|         |   1245 ++	if(song->album) free(song->album); | 
|         |   1246 ++	if(song->title) free(song->title); | 
|         |   1247 ++	if(song->track) free(song->track); | 
|         |   1248 ++	if(song->name) free(song->name); | 
|         |   1249 ++	if(song->date) free(song->date); | 
|         |   1250 ++	if(song->genre) free(song->genre); | 
|         |   1251 ++	if(song->composer) free(song->composer); | 
|         |   1252 ++	if(song->disc) free(song->disc); | 
|         |   1253 ++	if(song->comment) free(song->comment); | 
|         |   1254 ++} | 
|         |   1255 ++ | 
|         |   1256 ++mpd_Song * mpd_newSong(void) { | 
|         |   1257 ++	mpd_Song * ret = (mpd_Song *)malloc(sizeof(mpd_Song)); | 
|         |   1258 ++ | 
|         |   1259 ++	mpd_initSong(ret); | 
|         |   1260 ++ | 
|         |   1261 ++	return ret; | 
|         |   1262 ++} | 
|         |   1263 ++ | 
|         |   1264 ++void mpd_freeSong(mpd_Song * song) { | 
|         |   1265 ++	mpd_finishSong(song); | 
|         |   1266 ++	free(song); | 
|         |   1267 ++} | 
|         |   1268 ++ | 
|         |   1269 ++mpd_Song * mpd_songDup(mpd_Song * song) { | 
|         |   1270 ++	mpd_Song * ret = mpd_newSong(); | 
|         |   1271 ++ | 
|         |   1272 ++	if(song->file) ret->file = strdup(song->file); | 
|         |   1273 ++	if(song->artist) ret->artist = strdup(song->artist); | 
|         |   1274 ++	if(song->album) ret->album = strdup(song->album); | 
|         |   1275 ++	if(song->title) ret->title = strdup(song->title); | 
|         |   1276 ++	if(song->track) ret->track = strdup(song->track); | 
|         |   1277 ++	if(song->name) ret->name = strdup(song->name); | 
|         |   1278 ++	if(song->date) ret->date = strdup(song->date); | 
|         |   1279 ++	if(song->genre) ret->genre= strdup(song->genre); | 
|         |   1280 ++	if(song->composer) ret->composer= strdup(song->composer); | 
|         |   1281 ++	if(song->disc) ret->disc = strdup(song->disc); | 
|         |   1282 ++	if(song->comment) ret->comment = strdup(song->comment); | 
|         |   1283 ++	ret->time = song->time; | 
|         |   1284 ++	ret->pos = song->pos; | 
|         |   1285 ++	ret->id = song->id; | 
|         |   1286 ++ | 
|         |   1287 ++	return ret; | 
|         |   1288 ++} | 
|         |   1289 ++ | 
|         |   1290 ++static void mpd_initDirectory(mpd_Directory * directory) { | 
|         |   1291 ++	directory->path = NULL; | 
|         |   1292 ++} | 
|         |   1293 ++ | 
|         |   1294 ++static void mpd_finishDirectory(mpd_Directory * directory) { | 
|         |   1295 ++	if(directory->path) free(directory->path); | 
|         |   1296 ++} | 
|         |   1297 ++ | 
|         |   1298 ++mpd_Directory * mpd_newDirectory(void) { | 
|         |   1299 ++	mpd_Directory * directory = (mpd_Directory *)malloc(sizeof(mpd_Directory));; | 
|         |   1300 ++ | 
|         |   1301 ++	mpd_initDirectory(directory); | 
|         |   1302 ++ | 
|         |   1303 ++	return directory; | 
|         |   1304 ++} | 
|         |   1305 ++ | 
|         |   1306 ++void mpd_freeDirectory(mpd_Directory * directory) { | 
|         |   1307 ++	mpd_finishDirectory(directory); | 
|         |   1308 ++ | 
|         |   1309 ++	free(directory); | 
|         |   1310 ++} | 
|         |   1311 ++ | 
|         |   1312 ++mpd_Directory * mpd_directoryDup(mpd_Directory * directory) { | 
|         |   1313 ++	mpd_Directory * ret = mpd_newDirectory(); | 
|         |   1314 ++ | 
|         |   1315 ++	if(directory->path) ret->path = strdup(directory->path); | 
|         |   1316 ++ | 
|         |   1317 ++	return ret; | 
|         |   1318 ++} | 
|         |   1319 ++ | 
|         |   1320 ++static void mpd_initPlaylistFile(mpd_PlaylistFile * playlist) { | 
|         |   1321 ++	playlist->path = NULL; | 
|         |   1322 ++} | 
|         |   1323 ++ | 
|         |   1324 ++static void mpd_finishPlaylistFile(mpd_PlaylistFile * playlist) { | 
|         |   1325 ++	if(playlist->path) free(playlist->path); | 
|         |   1326 ++} | 
|         |   1327 ++ | 
|         |   1328 ++mpd_PlaylistFile * mpd_newPlaylistFile(void) { | 
|         |   1329 ++	mpd_PlaylistFile * playlist = (mpd_PlaylistFile *)malloc(sizeof(mpd_PlaylistFile)); | 
|         |   1330 ++ | 
|         |   1331 ++	mpd_initPlaylistFile(playlist); | 
|         |   1332 ++ | 
|         |   1333 ++	return playlist; | 
|         |   1334 ++} | 
|         |   1335 ++ | 
|         |   1336 ++void mpd_freePlaylistFile(mpd_PlaylistFile * playlist) { | 
|         |   1337 ++	mpd_finishPlaylistFile(playlist); | 
|         |   1338 ++	free(playlist); | 
|         |   1339 ++} | 
|         |   1340 ++ | 
|         |   1341 ++mpd_PlaylistFile * mpd_playlistFileDup(mpd_PlaylistFile * playlist) { | 
|         |   1342 ++	mpd_PlaylistFile * ret = mpd_newPlaylistFile(); | 
|         |   1343 ++ | 
|         |   1344 ++	if(playlist->path) ret->path = strdup(playlist->path); | 
|         |   1345 ++ | 
|         |   1346 ++	return ret; | 
|         |   1347 ++} | 
|         |   1348 ++ | 
|         |   1349 ++static void mpd_initInfoEntity(mpd_InfoEntity * entity) { | 
|         |   1350 ++	entity->info.directory = NULL; | 
|         |   1351 ++} | 
|         |   1352 ++ | 
|         |   1353 ++static void mpd_finishInfoEntity(mpd_InfoEntity * entity) { | 
|         |   1354 ++	if(entity->info.directory) { | 
|         |   1355 ++		if(entity->type == MPD_INFO_ENTITY_TYPE_DIRECTORY) { | 
|         |   1356 ++			mpd_freeDirectory(entity->info.directory); | 
|         |   1357 ++		} | 
|         |   1358 ++		else if(entity->type == MPD_INFO_ENTITY_TYPE_SONG) { | 
|         |   1359 ++			mpd_freeSong(entity->info.song); | 
|         |   1360 ++		} | 
|         |   1361 ++		else if(entity->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE) { | 
|         |   1362 ++			mpd_freePlaylistFile(entity->info.playlistFile); | 
|         |   1363 ++		} | 
|         |   1364 ++	} | 
|         |   1365 ++} | 
|         |   1366 ++ | 
|         |   1367 ++mpd_InfoEntity * mpd_newInfoEntity(void) { | 
|         |   1368 ++	mpd_InfoEntity * entity = (mpd_InfoEntity *)malloc(sizeof(mpd_InfoEntity)); | 
|         |   1369 ++ | 
|         |   1370 ++	mpd_initInfoEntity(entity); | 
|         |   1371 ++ | 
|         |   1372 ++	return entity; | 
|         |   1373 ++} | 
|         |   1374 ++ | 
|         |   1375 ++void mpd_freeInfoEntity(mpd_InfoEntity * entity) { | 
|         |   1376 ++	mpd_finishInfoEntity(entity); | 
|         |   1377 ++	free(entity); | 
|         |   1378 ++} | 
|         |   1379 ++ | 
|         |   1380 ++static void mpd_sendInfoCommand(mpd_Connection * connection, char * command) { | 
|         |   1381 ++	mpd_executeCommand(connection,command); | 
|         |   1382 ++} | 
|         |   1383 ++ | 
|         |   1384 ++mpd_InfoEntity * mpd_getNextInfoEntity(mpd_Connection * connection) { | 
|         |   1385 ++	mpd_InfoEntity * entity = NULL; | 
|         |   1386 ++ | 
|         |   1387 ++	if(connection->doneProcessing || (connection->listOks && | 
|         |   1388 ++	   connection->doneListOk)) | 
|         |   1389 ++	{ | 
|         |   1390 ++		return NULL; | 
|         |   1391 ++	} | 
|         |   1392 ++ | 
|         |   1393 ++	if(!connection->returnElement) mpd_getNextReturnElement(connection); | 
|         |   1394 ++ | 
|         |   1395 ++	if(connection->returnElement) { | 
|         |   1396 ++		if(strcmp(connection->returnElement->name,"file")==0) { | 
|         |   1397 ++			entity = mpd_newInfoEntity(); | 
|         |   1398 ++			entity->type = MPD_INFO_ENTITY_TYPE_SONG; | 
|         |   1399 ++			entity->info.song = mpd_newSong(); | 
|         |   1400 ++			entity->info.song->file = | 
|         |   1401 ++				strdup(connection->returnElement->value); | 
|         |   1402 ++		} | 
|         |   1403 ++		else if(strcmp(connection->returnElement->name, | 
|         |   1404 ++					"directory")==0) { | 
|         |   1405 ++			entity = mpd_newInfoEntity(); | 
|         |   1406 ++			entity->type = MPD_INFO_ENTITY_TYPE_DIRECTORY; | 
|         |   1407 ++			entity->info.directory = mpd_newDirectory(); | 
|         |   1408 ++			entity->info.directory->path = | 
|         |   1409 ++				strdup(connection->returnElement->value); | 
|         |   1410 ++		} | 
|         |   1411 ++		else if(strcmp(connection->returnElement->name,"playlist")==0) { | 
|         |   1412 ++			entity = mpd_newInfoEntity(); | 
|         |   1413 ++			entity->type = MPD_INFO_ENTITY_TYPE_PLAYLISTFILE; | 
|         |   1414 ++			entity->info.playlistFile = mpd_newPlaylistFile(); | 
|         |   1415 ++			entity->info.playlistFile->path = | 
|         |   1416 ++				strdup(connection->returnElement->value); | 
|         |   1417 ++		} | 
|         |   1418 ++		else if(strcmp(connection->returnElement->name, "cpos") == 0){ | 
|         |   1419 ++			entity = mpd_newInfoEntity(); | 
|         |   1420 ++			entity->type = MPD_INFO_ENTITY_TYPE_SONG; | 
|         |   1421 ++			entity->info.song = mpd_newSong(); | 
|         |   1422 ++			entity->info.song->pos = atoi(connection->returnElement->value); | 
|         |   1423 ++		} | 
|         |   1424 ++		else { | 
|         |   1425 ++			connection->error = 1; | 
|         |   1426 ++			strcpy(connection->errorStr,"problem parsing song info"); | 
|         |   1427 ++			return NULL; | 
|         |   1428 ++		} | 
|         |   1429 ++	} | 
|         |   1430 ++	else return NULL; | 
|         |   1431 ++ | 
|         |   1432 ++	mpd_getNextReturnElement(connection); | 
|         |   1433 ++	while(connection->returnElement) { | 
|         |   1434 ++		mpd_ReturnElement * re = connection->returnElement; | 
|         |   1435 ++ | 
|         |   1436 ++		if(strcmp(re->name,"file")==0) return entity; | 
|         |   1437 ++		else if(strcmp(re->name,"directory")==0) return entity; | 
|         |   1438 ++		else if(strcmp(re->name,"playlist")==0) return entity; | 
|         |   1439 ++		else if(strcmp(re->name,"cpos")==0) return entity; | 
|         |   1440 ++ | 
|         |   1441 ++		if(entity->type == MPD_INFO_ENTITY_TYPE_SONG && | 
|         |   1442 ++				strlen(re->value)) { | 
|         |   1443 ++			if(!entity->info.song->artist && | 
|         |   1444 ++					strcmp(re->name,"Artist")==0) { | 
|         |   1445 ++				entity->info.song->artist = strdup(re->value); | 
|         |   1446 ++			} | 
|         |   1447 ++			else if(!entity->info.song->album && | 
|         |   1448 ++					strcmp(re->name,"Album")==0) { | 
|         |   1449 ++				entity->info.song->album = strdup(re->value); | 
|         |   1450 ++			} | 
|         |   1451 ++			else if(!entity->info.song->title && | 
|         |   1452 ++					strcmp(re->name,"Title")==0) { | 
|         |   1453 ++				entity->info.song->title = strdup(re->value); | 
|         |   1454 ++			} | 
|         |   1455 ++			else if(!entity->info.song->track && | 
|         |   1456 ++					strcmp(re->name,"Track")==0) { | 
|         |   1457 ++				entity->info.song->track = strdup(re->value); | 
|         |   1458 ++			} | 
|         |   1459 ++			else if(!entity->info.song->name && | 
|         |   1460 ++					strcmp(re->name,"Name")==0) { | 
|         |   1461 ++				entity->info.song->name = strdup(re->value); | 
|         |   1462 ++			} | 
|         |   1463 ++			else if(entity->info.song->time==MPD_SONG_NO_TIME && | 
|         |   1464 ++					strcmp(re->name,"Time")==0) { | 
|         |   1465 ++				entity->info.song->time = atoi(re->value); | 
|         |   1466 ++			} | 
|         |   1467 ++			else if(entity->info.song->pos==MPD_SONG_NO_NUM && | 
|         |   1468 ++					strcmp(re->name,"Pos")==0) { | 
|         |   1469 ++				entity->info.song->pos = atoi(re->value); | 
|         |   1470 ++			} | 
|         |   1471 ++			else if(entity->info.song->id==MPD_SONG_NO_ID && | 
|         |   1472 ++					strcmp(re->name,"Id")==0) { | 
|         |   1473 ++				entity->info.song->id = atoi(re->value); | 
|         |   1474 ++			} | 
|         |   1475 ++			else if(!entity->info.song->date && | 
|         |   1476 ++					strcmp(re->name, "Date") == 0) { | 
|         |   1477 ++				entity->info.song->date = strdup(re->value); | 
|         |   1478 ++			} | 
|         |   1479 ++			else if(!entity->info.song->genre && | 
|         |   1480 ++					strcmp(re->name, "Genre") == 0) { | 
|         |   1481 ++				entity->info.song->genre = strdup(re->value); | 
|         |   1482 ++			} | 
|         |   1483 ++			else if(!entity->info.song->composer && | 
|         |   1484 ++					strcmp(re->name, "Composer") == 0) { | 
|         |   1485 ++				entity->info.song->composer = strdup(re->value); | 
|         |   1486 ++			} | 
|         |   1487 ++			else if(!entity->info.song->performer && | 
|         |   1488 ++					strcmp(re->name, "Performer") == 0) { | 
|         |   1489 ++				entity->info.song->performer = strdup(re->value); | 
|         |   1490 ++			} | 
|         |   1491 ++			else if(!entity->info.song->disc && | 
|         |   1492 ++					strcmp(re->name, "Disc") == 0) { | 
|         |   1493 ++				entity->info.song->disc = strdup(re->value); | 
|         |   1494 ++			} | 
|         |   1495 ++			else if(!entity->info.song->comment && | 
|         |   1496 ++					strcmp(re->name, "Comment") == 0) { | 
|         |   1497 ++				entity->info.song->comment = strdup(re->value); | 
|         |   1498 ++			} | 
|         |   1499 ++		} | 
|         |   1500 ++		else if(entity->type == MPD_INFO_ENTITY_TYPE_DIRECTORY) { | 
|         |   1501 ++		} | 
|         |   1502 ++		else if(entity->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE) { | 
|         |   1503 ++		} | 
|         |   1504 ++ | 
|         |   1505 ++		mpd_getNextReturnElement(connection); | 
|         |   1506 ++	} | 
|         |   1507 ++ | 
|         |   1508 ++	return entity; | 
|         |   1509 ++} | 
|         |   1510 ++ | 
|         |   1511 ++static char * mpd_getNextReturnElementNamed(mpd_Connection * connection, | 
|         |   1512 ++		const char * name) | 
|         |   1513 ++{ | 
|         |   1514 ++	if(connection->doneProcessing || (connection->listOks && | 
|         |   1515 ++				connection->doneListOk)) | 
|         |   1516 ++	{ | 
|         |   1517 ++		return NULL; | 
|         |   1518 ++	} | 
|         |   1519 ++ | 
|         |   1520 ++	mpd_getNextReturnElement(connection); | 
|         |   1521 ++	while(connection->returnElement) { | 
|         |   1522 ++		mpd_ReturnElement * re = connection->returnElement; | 
|         |   1523 ++ | 
|         |   1524 ++		if(strcmp(re->name,name)==0) return strdup(re->value); | 
|         |   1525 ++		mpd_getNextReturnElement(connection); | 
|         |   1526 ++	} | 
|         |   1527 ++ | 
|         |   1528 ++	return NULL; | 
|         |   1529 ++} | 
|         |   1530 ++ | 
|         |   1531 ++char *mpd_getNextTag(mpd_Connection *connection, int type) | 
|         |   1532 ++{ | 
|         |   1533 ++	if (type < 0 || type >= MPD_TAG_NUM_OF_ITEM_TYPES || | 
|         |   1534 ++	    type == MPD_TAG_ITEM_ANY) | 
|         |   1535 ++		return NULL; | 
|         |   1536 ++	if (type == MPD_TAG_ITEM_FILENAME) | 
|         |   1537 ++		return mpd_getNextReturnElementNamed(connection, "file"); | 
|         |   1538 ++	return mpd_getNextReturnElementNamed(connection, mpdTagItemKeys[type]); | 
|         |   1539 ++} | 
|         |   1540 ++ | 
|         |   1541 ++char * mpd_getNextArtist(mpd_Connection * connection) { | 
|         |   1542 ++	return mpd_getNextReturnElementNamed(connection,"Artist"); | 
|         |   1543 ++} | 
|         |   1544 ++ | 
|         |   1545 ++char * mpd_getNextAlbum(mpd_Connection * connection) { | 
|         |   1546 ++	return mpd_getNextReturnElementNamed(connection,"Album"); | 
|         |   1547 ++} | 
|         |   1548 ++ | 
|         |   1549 ++void mpd_sendPlaylistInfoCommand(mpd_Connection * connection, int songPos) { | 
|         |   1550 ++	int len = strlen("playlistinfo")+2+INTLEN+3; | 
|         |   1551 ++	char *string = (char *)malloc(len); | 
|         |   1552 ++	snprintf(string, len, "playlistinfo \"%i\"\n", songPos); | 
|         |   1553 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1554 ++	free(string); | 
|         |   1555 ++} | 
|         |   1556 ++ | 
|         |   1557 ++void mpd_sendPlaylistIdCommand(mpd_Connection * connection, int id) { | 
|         |   1558 ++	int len = strlen("playlistid")+2+INTLEN+3; | 
|         |   1559 ++	char *string = (char *)malloc(len); | 
|         |   1560 ++	snprintf(string, len, "playlistid \"%i\"\n", id); | 
|         |   1561 ++	mpd_sendInfoCommand(connection, string); | 
|         |   1562 ++	free(string); | 
|         |   1563 ++} | 
|         |   1564 ++ | 
|         |   1565 ++void mpd_sendPlChangesCommand(mpd_Connection * connection, long long playlist) { | 
|         |   1566 ++	int len = strlen("plchanges")+2+LONGLONGLEN+3; | 
|         |   1567 ++	char *string = (char *)malloc(len); | 
|         |   1568 ++	snprintf(string, len, "plchanges \"%lld\"\n", playlist); | 
|         |   1569 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1570 ++	free(string); | 
|         |   1571 ++} | 
|         |   1572 ++ | 
|         |   1573 ++void mpd_sendPlChangesPosIdCommand(mpd_Connection * connection, long long playlist) { | 
|         |   1574 ++	int len = strlen("plchangesposid")+2+LONGLONGLEN+3; | 
|         |   1575 ++	char *string = (char *)malloc(len); | 
|         |   1576 ++	snprintf(string, len, "plchangesposid \"%lld\"\n", playlist); | 
|         |   1577 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1578 ++	free(string); | 
|         |   1579 ++} | 
|         |   1580 ++ | 
|         |   1581 ++void mpd_sendListallCommand(mpd_Connection * connection, const char * dir) { | 
|         |   1582 ++	char * sDir = mpd_sanitizeArg(dir); | 
|         |   1583 ++	int len = strlen("listall")+2+strlen(sDir)+3; | 
|         |   1584 ++	char *string = (char *)malloc(len); | 
|         |   1585 ++	snprintf(string, len, "listall \"%s\"\n", sDir); | 
|         |   1586 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1587 ++	free(string); | 
|         |   1588 ++	free(sDir); | 
|         |   1589 ++} | 
|         |   1590 ++ | 
|         |   1591 ++void mpd_sendListallInfoCommand(mpd_Connection * connection, const char * dir) { | 
|         |   1592 ++	char * sDir = mpd_sanitizeArg(dir); | 
|         |   1593 ++	int len = strlen("listallinfo")+2+strlen(sDir)+3; | 
|         |   1594 ++	char *string = (char *)malloc(len); | 
|         |   1595 ++	snprintf(string, len, "listallinfo \"%s\"\n", sDir); | 
|         |   1596 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1597 ++	free(string); | 
|         |   1598 ++	free(sDir); | 
|         |   1599 ++} | 
|         |   1600 ++ | 
|         |   1601 ++void mpd_sendLsInfoCommand(mpd_Connection * connection, const char * dir) { | 
|         |   1602 ++	char * sDir = mpd_sanitizeArg(dir); | 
|         |   1603 ++	int len = strlen("lsinfo")+2+strlen(sDir)+3; | 
|         |   1604 ++	char *string = (char *)malloc(len); | 
|         |   1605 ++	snprintf(string, len, "lsinfo \"%s\"\n", sDir); | 
|         |   1606 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1607 ++	free(string); | 
|         |   1608 ++	free(sDir); | 
|         |   1609 ++} | 
|         |   1610 ++ | 
|         |   1611 ++void mpd_sendCurrentSongCommand(mpd_Connection * connection) { | 
|         |   1612 ++	mpd_executeCommand(connection,"currentsong\n"); | 
|         |   1613 ++} | 
|         |   1614 ++ | 
|         |   1615 ++void mpd_sendSearchCommand(mpd_Connection * connection, int table, | 
|         |   1616 ++		const char * str) | 
|         |   1617 ++{ | 
|         |   1618 ++	mpd_startSearch(connection, 0); | 
|         |   1619 ++	mpd_addConstraintSearch(connection, table, str); | 
|         |   1620 ++	mpd_commitSearch(connection); | 
|         |   1621 ++} | 
|         |   1622 ++ | 
|         |   1623 ++void mpd_sendFindCommand(mpd_Connection * connection, int table, | 
|         |   1624 ++		const char * str) | 
|         |   1625 ++{ | 
|         |   1626 ++	mpd_startSearch(connection, 1); | 
|         |   1627 ++	mpd_addConstraintSearch(connection, table, str); | 
|         |   1628 ++	mpd_commitSearch(connection); | 
|         |   1629 ++} | 
|         |   1630 ++ | 
|         |   1631 ++void mpd_sendListCommand(mpd_Connection * connection, int table, | 
|         |   1632 ++		const char * arg1) | 
|         |   1633 ++{ | 
|         |   1634 ++	char st[10]; | 
|         |   1635 ++	int len; | 
|         |   1636 ++	char *string; | 
|         |   1637 ++	if(table == MPD_TABLE_ARTIST) strcpy(st,"artist"); | 
|         |   1638 ++	else if(table == MPD_TABLE_ALBUM) strcpy(st,"album"); | 
|         |   1639 ++	else { | 
|         |   1640 ++		connection->error = 1; | 
|         |   1641 ++		strcpy(connection->errorStr,"unknown table for list"); | 
|         |   1642 ++		return; | 
|         |   1643 ++	} | 
|         |   1644 ++	if(arg1) { | 
|         |   1645 ++		char * sanitArg1 = mpd_sanitizeArg(arg1); | 
|         |   1646 ++		len = strlen("list")+1+strlen(sanitArg1)+2+strlen(st)+3; | 
|         |   1647 ++		string = (char *)malloc(len); | 
|         |   1648 ++		snprintf(string, len, "list %s \"%s\"\n", st, sanitArg1); | 
|         |   1649 ++		free(sanitArg1); | 
|         |   1650 ++	} | 
|         |   1651 ++	else { | 
|         |   1652 ++		len = strlen("list")+1+strlen(st)+2; | 
|         |   1653 ++		string = (char *)malloc(len); | 
|         |   1654 ++		snprintf(string, len, "list %s\n", st); | 
|         |   1655 ++	} | 
|         |   1656 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1657 ++	free(string); | 
|         |   1658 ++} | 
|         |   1659 ++ | 
|         |   1660 ++void mpd_sendAddCommand(mpd_Connection * connection, const char * file) { | 
|         |   1661 ++	char * sFile = mpd_sanitizeArg(file); | 
|         |   1662 ++	int len = strlen("add")+2+strlen(sFile)+3; | 
|         |   1663 ++	char *string = (char *)malloc(len); | 
|         |   1664 ++	snprintf(string, len, "add \"%s\"\n", sFile); | 
|         |   1665 ++	mpd_executeCommand(connection,string); | 
|         |   1666 ++	free(string); | 
|         |   1667 ++	free(sFile); | 
|         |   1668 ++} | 
|         |   1669 ++ | 
|         |   1670 ++int mpd_sendAddIdCommand(mpd_Connection *connection, const char *file) | 
|         |   1671 ++{ | 
|         |   1672 ++	int retval = -1; | 
|         |   1673 ++	char *sFile = mpd_sanitizeArg(file); | 
|         |   1674 ++	int len = strlen("addid")+2+strlen(sFile)+3; | 
|         |   1675 ++	char *string = (char *)malloc(len); | 
|         |   1676 ++ | 
|         |   1677 ++	snprintf(string, len, "addid \"%s\"\n", sFile); | 
|         |   1678 ++	mpd_sendInfoCommand(connection, string); | 
|         |   1679 ++	free(string); | 
|         |   1680 ++	free(sFile); | 
|         |   1681 ++ | 
|         |   1682 ++	string = mpd_getNextReturnElementNamed(connection, "Id"); | 
|         |   1683 ++	if (string) { | 
|         |   1684 ++		retval = atoi(string); | 
|         |   1685 ++		free(string); | 
|         |   1686 ++	} | 
|         |   1687 ++	 | 
|         |   1688 ++	return retval; | 
|         |   1689 ++} | 
|         |   1690 ++ | 
|         |   1691 ++void mpd_sendDeleteCommand(mpd_Connection * connection, int songPos) { | 
|         |   1692 ++	int len = strlen("delete")+2+INTLEN+3; | 
|         |   1693 ++	char *string = (char *)malloc(len); | 
|         |   1694 ++	snprintf(string, len, "delete \"%i\"\n", songPos); | 
|         |   1695 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1696 ++	free(string); | 
|         |   1697 ++} | 
|         |   1698 ++ | 
|         |   1699 ++void mpd_sendDeleteIdCommand(mpd_Connection * connection, int id) { | 
|         |   1700 ++	int len = strlen("deleteid")+2+INTLEN+3; | 
|         |   1701 ++	char *string = (char *)malloc(len); | 
|         |   1702 ++	snprintf(string, len, "deleteid \"%i\"\n", id); | 
|         |   1703 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1704 ++	free(string); | 
|         |   1705 ++} | 
|         |   1706 ++ | 
|         |   1707 ++void mpd_sendSaveCommand(mpd_Connection * connection, const char * name) { | 
|         |   1708 ++	char * sName = mpd_sanitizeArg(name); | 
|         |   1709 ++	int len = strlen("save")+2+strlen(sName)+3; | 
|         |   1710 ++	char *string = (char *)malloc(len); | 
|         |   1711 ++	snprintf(string, len, "save \"%s\"\n", sName); | 
|         |   1712 ++	mpd_executeCommand(connection,string); | 
|         |   1713 ++	free(string); | 
|         |   1714 ++	free(sName); | 
|         |   1715 ++} | 
|         |   1716 ++ | 
|         |   1717 ++void mpd_sendLoadCommand(mpd_Connection * connection, const char * name) { | 
|         |   1718 ++	char * sName = mpd_sanitizeArg(name); | 
|         |   1719 ++	int len = strlen("load")+2+strlen(sName)+3; | 
|         |   1720 ++	char *string = (char *)malloc(len); | 
|         |   1721 ++	snprintf(string, len, "load \"%s\"\n", sName); | 
|         |   1722 ++	mpd_executeCommand(connection,string); | 
|         |   1723 ++	free(string); | 
|         |   1724 ++	free(sName); | 
|         |   1725 ++} | 
|         |   1726 ++ | 
|         |   1727 ++void mpd_sendRmCommand(mpd_Connection * connection, const char * name) { | 
|         |   1728 ++	char * sName = mpd_sanitizeArg(name); | 
|         |   1729 ++	int len = strlen("rm")+2+strlen(sName)+3; | 
|         |   1730 ++	char *string = (char *)malloc(len); | 
|         |   1731 ++	snprintf(string, len, "rm \"%s\"\n", sName); | 
|         |   1732 ++	mpd_executeCommand(connection,string); | 
|         |   1733 ++	free(string); | 
|         |   1734 ++	free(sName); | 
|         |   1735 ++} | 
|         |   1736 ++ | 
|         |   1737 ++void mpd_sendRenameCommand(mpd_Connection *connection, const char *from, | 
|         |   1738 ++                           const char *to) | 
|         |   1739 ++{ | 
|         |   1740 ++	char *sFrom = mpd_sanitizeArg(from); | 
|         |   1741 ++	char *sTo = mpd_sanitizeArg(to); | 
|         |   1742 ++	int len = strlen("rename")+2+strlen(sFrom)+3+strlen(sTo)+3; | 
|         |   1743 ++	char *string = (char *)malloc(len); | 
|         |   1744 ++	snprintf(string, len, "rename \"%s\" \"%s\"\n", sFrom, sTo); | 
|         |   1745 ++	mpd_executeCommand(connection, string); | 
|         |   1746 ++	free(string); | 
|         |   1747 ++	free(sFrom); | 
|         |   1748 ++	free(sTo); | 
|         |   1749 ++} | 
|         |   1750 ++ | 
|         |   1751 ++void mpd_sendShuffleCommand(mpd_Connection * connection) { | 
|         |   1752 ++	mpd_executeCommand(connection,"shuffle\n"); | 
|         |   1753 ++} | 
|         |   1754 ++ | 
|         |   1755 ++void mpd_sendClearCommand(mpd_Connection * connection) { | 
|         |   1756 ++	mpd_executeCommand(connection,"clear\n"); | 
|         |   1757 ++} | 
|         |   1758 ++ | 
|         |   1759 ++void mpd_sendPlayCommand(mpd_Connection * connection, int songPos) { | 
|         |   1760 ++	int len = strlen("play")+2+INTLEN+3; | 
|         |   1761 ++	char *string = (char *)malloc(len); | 
|         |   1762 ++	snprintf(string, len, "play \"%i\"\n", songPos); | 
|         |   1763 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1764 ++	free(string); | 
|         |   1765 ++} | 
|         |   1766 ++ | 
|         |   1767 ++void mpd_sendPlayIdCommand(mpd_Connection * connection, int id) { | 
|         |   1768 ++	int len = strlen("playid")+2+INTLEN+3; | 
|         |   1769 ++	char *string = (char *)malloc(len); | 
|         |   1770 ++	snprintf(string, len, "playid \"%i\"\n", id); | 
|         |   1771 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1772 ++	free(string); | 
|         |   1773 ++} | 
|         |   1774 ++ | 
|         |   1775 ++void mpd_sendStopCommand(mpd_Connection * connection) { | 
|         |   1776 ++	mpd_executeCommand(connection,"stop\n"); | 
|         |   1777 ++} | 
|         |   1778 ++ | 
|         |   1779 ++void mpd_sendPauseCommand(mpd_Connection * connection, int pauseMode) { | 
|         |   1780 ++	int len = strlen("pause")+2+INTLEN+3; | 
|         |   1781 ++	char *string = (char *)malloc(len); | 
|         |   1782 ++	snprintf(string, len, "pause \"%i\"\n", pauseMode); | 
|         |   1783 ++	mpd_executeCommand(connection,string); | 
|         |   1784 ++	free(string); | 
|         |   1785 ++} | 
|         |   1786 ++ | 
|         |   1787 ++void mpd_sendNextCommand(mpd_Connection * connection) { | 
|         |   1788 ++	mpd_executeCommand(connection,"next\n"); | 
|         |   1789 ++} | 
|         |   1790 ++ | 
|         |   1791 ++void mpd_sendMoveCommand(mpd_Connection * connection, int from, int to) { | 
|         |   1792 ++	int len = strlen("move")+2+INTLEN+3+INTLEN+3; | 
|         |   1793 ++	char *string = (char *)malloc(len); | 
|         |   1794 ++	snprintf(string, len, "move \"%i\" \"%i\"\n", from, to); | 
|         |   1795 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1796 ++	free(string); | 
|         |   1797 ++} | 
|         |   1798 ++ | 
|         |   1799 ++void mpd_sendMoveIdCommand(mpd_Connection * connection, int id, int to) { | 
|         |   1800 ++	int len = strlen("moveid")+2+INTLEN+3+INTLEN+3; | 
|         |   1801 ++	char *string = (char *)malloc(len); | 
|         |   1802 ++	snprintf(string, len, "moveid \"%i\" \"%i\"\n", id, to); | 
|         |   1803 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1804 ++	free(string); | 
|         |   1805 ++} | 
|         |   1806 ++ | 
|         |   1807 ++void mpd_sendSwapCommand(mpd_Connection * connection, int song1, int song2) { | 
|         |   1808 ++	int len = strlen("swap")+2+INTLEN+3+INTLEN+3; | 
|         |   1809 ++	char *string = (char *)malloc(len); | 
|         |   1810 ++	snprintf(string, len, "swap \"%i\" \"%i\"\n", song1, song2); | 
|         |   1811 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1812 ++	free(string); | 
|         |   1813 ++} | 
|         |   1814 ++ | 
|         |   1815 ++void mpd_sendSwapIdCommand(mpd_Connection * connection, int id1, int id2) { | 
|         |   1816 ++	int len = strlen("swapid")+2+INTLEN+3+INTLEN+3; | 
|         |   1817 ++	char *string = (char *)malloc(len); | 
|         |   1818 ++	snprintf(string, len, "swapid \"%i\" \"%i\"\n", id1, id2); | 
|         |   1819 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1820 ++	free(string); | 
|         |   1821 ++} | 
|         |   1822 ++ | 
|         |   1823 ++void mpd_sendSeekCommand(mpd_Connection * connection, int song, int time) { | 
|         |   1824 ++	int len = strlen("seek")+2+INTLEN+3+INTLEN+3; | 
|         |   1825 ++	char *string = (char *)malloc(len); | 
|         |   1826 ++	snprintf(string, len, "seek \"%i\" \"%i\"\n", song, time); | 
|         |   1827 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1828 ++	free(string); | 
|         |   1829 ++} | 
|         |   1830 ++ | 
|         |   1831 ++void mpd_sendSeekIdCommand(mpd_Connection * connection, int id, int time) { | 
|         |   1832 ++	int len = strlen("seekid")+2+INTLEN+3+INTLEN+3; | 
|         |   1833 ++	char *string = (char *)malloc(len); | 
|         |   1834 ++	snprintf(string, len, "seekid \"%i\" \"%i\"\n", id, time); | 
|         |   1835 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1836 ++	free(string); | 
|         |   1837 ++} | 
|         |   1838 ++ | 
|         |   1839 ++void mpd_sendUpdateCommand(mpd_Connection * connection, char * path) { | 
|         |   1840 ++	char * sPath = mpd_sanitizeArg(path); | 
|         |   1841 ++	int len = strlen("update")+2+strlen(sPath)+3; | 
|         |   1842 ++	char *string = (char *)malloc(len); | 
|         |   1843 ++	snprintf(string, len, "update \"%s\"\n", sPath); | 
|         |   1844 ++	mpd_sendInfoCommand(connection,string); | 
|         |   1845 ++	free(string); | 
|         |   1846 ++	free(sPath); | 
|         |   1847 ++} | 
|         |   1848 ++ | 
|         |   1849 ++int mpd_getUpdateId(mpd_Connection * connection) { | 
|         |   1850 ++	char * jobid; | 
|         |   1851 ++	int ret = 0; | 
|         |   1852 ++ | 
|         |   1853 ++	jobid = mpd_getNextReturnElementNamed(connection,"updating_db"); | 
|         |   1854 ++	if(jobid) { | 
|         |   1855 ++		ret = atoi(jobid); | 
|         |   1856 ++		free(jobid); | 
|         |   1857 ++	} | 
|         |   1858 ++ | 
|         |   1859 ++	return ret; | 
|         |   1860 ++} | 
|         |   1861 ++ | 
|         |   1862 ++void mpd_sendPrevCommand(mpd_Connection * connection) { | 
|         |   1863 ++	mpd_executeCommand(connection,"previous\n"); | 
|         |   1864 ++} | 
|         |   1865 ++ | 
|         |   1866 ++void mpd_sendRepeatCommand(mpd_Connection * connection, int repeatMode) { | 
|         |   1867 ++	int len = strlen("repeat")+2+INTLEN+3; | 
|         |   1868 ++	char *string = (char *)malloc(len); | 
|         |   1869 ++	snprintf(string, len, "repeat \"%i\"\n", repeatMode); | 
|         |   1870 ++	mpd_executeCommand(connection,string); | 
|         |   1871 ++	free(string); | 
|         |   1872 ++} | 
|         |   1873 ++ | 
|         |   1874 ++void mpd_sendRandomCommand(mpd_Connection * connection, int randomMode) { | 
|         |   1875 ++	int len = strlen("random")+2+INTLEN+3; | 
|         |   1876 ++	char *string = (char *)malloc(len); | 
|         |   1877 ++	snprintf(string, len, "random \"%i\"\n", randomMode); | 
|         |   1878 ++	mpd_executeCommand(connection,string); | 
|         |   1879 ++	free(string); | 
|         |   1880 ++} | 
|         |   1881 ++ | 
|         |   1882 ++void mpd_sendSetvolCommand(mpd_Connection * connection, int volumeChange) { | 
|         |   1883 ++	int len = strlen("setvol")+2+INTLEN+3; | 
|         |   1884 ++	char *string = (char *)malloc(len); | 
|         |   1885 ++	snprintf(string, len, "setvol \"%i\"\n", volumeChange); | 
|         |   1886 ++	mpd_executeCommand(connection,string); | 
|         |   1887 ++	free(string); | 
|         |   1888 ++} | 
|         |   1889 ++ | 
|         |   1890 ++void mpd_sendVolumeCommand(mpd_Connection * connection, int volumeChange) { | 
|         |   1891 ++	int len = strlen("volume")+2+INTLEN+3; | 
|         |   1892 ++	char *string = (char *)malloc(len); | 
|         |   1893 ++	snprintf(string, len, "volume \"%i\"\n", volumeChange); | 
|         |   1894 ++	mpd_executeCommand(connection,string); | 
|         |   1895 ++	free(string); | 
|         |   1896 ++} | 
|         |   1897 ++ | 
|         |   1898 ++void mpd_sendCrossfadeCommand(mpd_Connection * connection, int seconds) { | 
|         |   1899 ++	int len = strlen("crossfade")+2+INTLEN+3; | 
|         |   1900 ++	char *string = (char *)malloc(len); | 
|         |   1901 ++	snprintf(string, len, "crossfade \"%i\"\n", seconds); | 
|         |   1902 ++	mpd_executeCommand(connection,string); | 
|         |   1903 ++	free(string); | 
|         |   1904 ++} | 
|         |   1905 ++ | 
|         |   1906 ++void mpd_sendPasswordCommand(mpd_Connection * connection, const char * pass) { | 
|         |   1907 ++	char * sPass = mpd_sanitizeArg(pass); | 
|         |   1908 ++	int len = strlen("password")+2+strlen(sPass)+3; | 
|         |   1909 ++	char *string = (char *)malloc(len); | 
|         |   1910 ++	snprintf(string, len, "password \"%s\"\n", sPass); | 
|         |   1911 ++	mpd_executeCommand(connection,string); | 
|         |   1912 ++	free(string); | 
|         |   1913 ++	free(sPass); | 
|         |   1914 ++} | 
|         |   1915 ++ | 
|         |   1916 ++void mpd_sendCommandListBegin(mpd_Connection * connection) { | 
|         |   1917 ++	if(connection->commandList) { | 
|         |   1918 ++		strcpy(connection->errorStr,"already in command list mode"); | 
|         |   1919 ++		connection->error = 1; | 
|         |   1920 ++		return; | 
|         |   1921 ++	} | 
|         |   1922 ++	connection->commandList = COMMAND_LIST; | 
|         |   1923 ++	mpd_executeCommand(connection,"command_list_begin\n"); | 
|         |   1924 ++} | 
|         |   1925 ++ | 
|         |   1926 ++void mpd_sendCommandListOkBegin(mpd_Connection * connection) { | 
|         |   1927 ++	if(connection->commandList) { | 
|         |   1928 ++		strcpy(connection->errorStr,"already in command list mode"); | 
|         |   1929 ++		connection->error = 1; | 
|         |   1930 ++		return; | 
|         |   1931 ++	} | 
|         |   1932 ++	connection->commandList = COMMAND_LIST_OK; | 
|         |   1933 ++	mpd_executeCommand(connection,"command_list_ok_begin\n"); | 
|         |   1934 ++	connection->listOks = 0; | 
|         |   1935 ++} | 
|         |   1936 ++ | 
|         |   1937 ++void mpd_sendCommandListEnd(mpd_Connection * connection) { | 
|         |   1938 ++	if(!connection->commandList) { | 
|         |   1939 ++		strcpy(connection->errorStr,"not in command list mode"); | 
|         |   1940 ++		connection->error = 1; | 
|         |   1941 ++		return; | 
|         |   1942 ++	} | 
|         |   1943 ++	connection->commandList = 0; | 
|         |   1944 ++	mpd_executeCommand(connection,"command_list_end\n"); | 
|         |   1945 ++} | 
|         |   1946 ++ | 
|         |   1947 ++void mpd_sendOutputsCommand(mpd_Connection * connection) { | 
|         |   1948 ++	mpd_executeCommand(connection,"outputs\n"); | 
|         |   1949 ++} | 
|         |   1950 ++ | 
|         |   1951 ++mpd_OutputEntity * mpd_getNextOutput(mpd_Connection * connection) { | 
|         |   1952 ++	mpd_OutputEntity * output = NULL; | 
|         |   1953 ++ | 
|         |   1954 ++	if(connection->doneProcessing || (connection->listOks && | 
|         |   1955 ++				connection->doneListOk)) | 
|         |   1956 ++	{ | 
|         |   1957 ++		return NULL; | 
|         |   1958 ++	} | 
|         |   1959 ++ | 
|         |   1960 ++	if(connection->error) return NULL; | 
|         |   1961 ++ | 
|         |   1962 ++	output = (mpd_OutputEntity *)malloc(sizeof(mpd_OutputEntity)); | 
|         |   1963 ++	output->id = -10; | 
|         |   1964 ++	output->name = NULL; | 
|         |   1965 ++	output->enabled = 0; | 
|         |   1966 ++ | 
|         |   1967 ++	if(!connection->returnElement) mpd_getNextReturnElement(connection); | 
|         |   1968 ++ | 
|         |   1969 ++	while(connection->returnElement) { | 
|         |   1970 ++		mpd_ReturnElement * re = connection->returnElement; | 
|         |   1971 ++		if(strcmp(re->name,"outputid")==0) { | 
|         |   1972 ++			if(output!=NULL && output->id>=0) return output; | 
|         |   1973 ++			output->id = atoi(re->value); | 
|         |   1974 ++		} | 
|         |   1975 ++		else if(strcmp(re->name,"outputname")==0) { | 
|         |   1976 ++			output->name = strdup(re->value); | 
|         |   1977 ++		} | 
|         |   1978 ++		else if(strcmp(re->name,"outputenabled")==0) { | 
|         |   1979 ++			output->enabled = atoi(re->value); | 
|         |   1980 ++		} | 
|         |   1981 ++ | 
|         |   1982 ++		mpd_getNextReturnElement(connection); | 
|         |   1983 ++		if(connection->error) { | 
|         |   1984 ++			free(output); | 
|         |   1985 ++			return NULL; | 
|         |   1986 ++		} | 
|         |   1987 ++ | 
|         |   1988 ++	} | 
|         |   1989 ++ | 
|         |   1990 ++	return output; | 
|         |   1991 ++} | 
|         |   1992 ++ | 
|         |   1993 ++void mpd_sendEnableOutputCommand(mpd_Connection * connection, int outputId) { | 
|         |   1994 ++	int len = strlen("enableoutput")+2+INTLEN+3; | 
|         |   1995 ++	char *string = (char *)malloc(len); | 
|         |   1996 ++	snprintf(string, len, "enableoutput \"%i\"\n", outputId); | 
|         |   1997 ++	mpd_executeCommand(connection,string); | 
|         |   1998 ++	free(string); | 
|         |   1999 ++} | 
|         |   2000 ++ | 
|         |   2001 ++void mpd_sendDisableOutputCommand(mpd_Connection * connection, int outputId) { | 
|         |   2002 ++	int len = strlen("disableoutput")+2+INTLEN+3; | 
|         |   2003 ++	char *string = (char *)malloc(len); | 
|         |   2004 ++	snprintf(string, len, "disableoutput \"%i\"\n", outputId); | 
|         |   2005 ++	mpd_executeCommand(connection,string); | 
|         |   2006 ++	free(string); | 
|         |   2007 ++} | 
|         |   2008 ++ | 
|         |   2009 ++void mpd_freeOutputElement(mpd_OutputEntity * output) { | 
|         |   2010 ++	free(output->name); | 
|         |   2011 ++	free(output); | 
|         |   2012 ++} | 
|         |   2013 ++ | 
|         |   2014 ++/** | 
|         |   2015 ++ * mpd_sendNotCommandsCommand | 
|         |   2016 ++ * odd naming, but it gets the not allowed commands | 
|         |   2017 ++ */ | 
|         |   2018 ++ | 
|         |   2019 ++void mpd_sendNotCommandsCommand(mpd_Connection * connection) | 
|         |   2020 ++{ | 
|         |   2021 ++	mpd_executeCommand(connection, "notcommands\n"); | 
|         |   2022 ++} | 
|         |   2023 ++ | 
|         |   2024 ++/** | 
|         |   2025 ++ * mpd_sendCommandsCommand | 
|         |   2026 ++ * odd naming, but it gets the allowed commands | 
|         |   2027 ++ */ | 
|         |   2028 ++void mpd_sendCommandsCommand(mpd_Connection * connection) | 
|         |   2029 ++{ | 
|         |   2030 ++	mpd_executeCommand(connection, "commands\n"); | 
|         |   2031 ++} | 
|         |   2032 ++ | 
|         |   2033 ++/** | 
|         |   2034 ++ * Get the next returned command | 
|         |   2035 ++ */ | 
|         |   2036 ++char * mpd_getNextCommand(mpd_Connection * connection) | 
|         |   2037 ++{ | 
|         |   2038 ++	return mpd_getNextReturnElementNamed(connection, "command"); | 
|         |   2039 ++} | 
|         |   2040 ++ | 
|         |   2041 ++void mpd_sendUrlHandlersCommand(mpd_Connection * connection) | 
|         |   2042 ++{ | 
|         |   2043 ++	mpd_executeCommand(connection, "urlhandlers\n"); | 
|         |   2044 ++} | 
|         |   2045 ++ | 
|         |   2046 ++char * mpd_getNextHandler(mpd_Connection * connection) | 
|         |   2047 ++{ | 
|         |   2048 ++	return mpd_getNextReturnElementNamed(connection, "handler"); | 
|         |   2049 ++} | 
|         |   2050 ++ | 
|         |   2051 ++void mpd_sendTagTypesCommand(mpd_Connection * connection) | 
|         |   2052 ++{ | 
|         |   2053 ++	mpd_executeCommand(connection, "tagtypes\n"); | 
|         |   2054 ++} | 
|         |   2055 ++ | 
|         |   2056 ++char * mpd_getNextTagType(mpd_Connection * connection) | 
|         |   2057 ++{ | 
|         |   2058 ++	return mpd_getNextReturnElementNamed(connection, "tagtype"); | 
|         |   2059 ++} | 
|         |   2060 ++ | 
|         |   2061 ++void mpd_startSearch(mpd_Connection *connection, int exact) | 
|         |   2062 ++{ | 
|         |   2063 ++	if (connection->request) { | 
|         |   2064 ++		strcpy(connection->errorStr, "search already in progress"); | 
|         |   2065 ++		connection->error = 1; | 
|         |   2066 ++		return; | 
|         |   2067 ++	} | 
|         |   2068 ++ | 
|         |   2069 ++	if (exact) connection->request = strdup("find"); | 
|         |   2070 ++	else connection->request = strdup("search"); | 
|         |   2071 ++} | 
|         |   2072 ++ | 
|         |   2073 ++void mpd_startStatsSearch(mpd_Connection *connection) | 
|         |   2074 ++{ | 
|         |   2075 ++	if (connection->request) { | 
|         |   2076 ++		strcpy(connection->errorStr, "search already in progress"); | 
|         |   2077 ++		connection->error = 1; | 
|         |   2078 ++		return; | 
|         |   2079 ++	} | 
|         |   2080 ++ | 
|         |   2081 ++	connection->request = strdup("count"); | 
|         |   2082 ++} | 
|         |   2083 ++ | 
|         |   2084 ++void mpd_startPlaylistSearch(mpd_Connection *connection, int exact) | 
|         |   2085 ++{ | 
|         |   2086 ++	if (connection->request) { | 
|         |   2087 ++		strcpy(connection->errorStr, "search already in progress"); | 
|         |   2088 ++		connection->error = 1; | 
|         |   2089 ++		return; | 
|         |   2090 ++	} | 
|         |   2091 ++ | 
|         |   2092 ++	if (exact) connection->request = strdup("playlistfind"); | 
|         |   2093 ++	else connection->request = strdup("playlistsearch"); | 
|         |   2094 ++} | 
|         |   2095 ++ | 
|         |   2096 ++void mpd_startFieldSearch(mpd_Connection *connection, int type) | 
|         |   2097 ++{ | 
|         |   2098 ++	char *strtype; | 
|         |   2099 ++	int len; | 
|         |   2100 ++ | 
|         |   2101 ++	if (connection->request) { | 
|         |   2102 ++		strcpy(connection->errorStr, "search already in progress"); | 
|         |   2103 ++		connection->error = 1; | 
|         |   2104 ++		return; | 
|         |   2105 ++	} | 
|         |   2106 ++ | 
|         |   2107 ++	if (type < 0 || type >= MPD_TAG_NUM_OF_ITEM_TYPES) { | 
|         |   2108 ++		strcpy(connection->errorStr, "invalid type specified"); | 
|         |   2109 ++		connection->error = 1; | 
|         |   2110 ++		return; | 
|         |   2111 ++	} | 
|         |   2112 ++ | 
|         |   2113 ++	strtype = mpdTagItemKeys[type]; | 
|         |   2114 ++ | 
|         |   2115 ++	len = 5+strlen(strtype)+1; | 
|         |   2116 ++	connection->request = (char *)malloc(len); | 
|         |   2117 ++ | 
|         |   2118 ++	snprintf(connection->request, len, "list %c%s", | 
|         |   2119 ++	         tolower(strtype[0]), strtype+1); | 
|         |   2120 ++} | 
|         |   2121 ++ | 
|         |   2122 ++void mpd_addConstraintSearch(mpd_Connection *connection, int type, const char *name) | 
|         |   2123 ++{ | 
|         |   2124 ++	char *strtype; | 
|         |   2125 ++	char *arg; | 
|         |   2126 ++	int len; | 
|         |   2127 ++	char *string; | 
|         |   2128 ++ | 
|         |   2129 ++	if (!connection->request) { | 
|         |   2130 ++		strcpy(connection->errorStr, "no search in progress"); | 
|         |   2131 ++		connection->error = 1; | 
|         |   2132 ++		return; | 
|         |   2133 ++	} | 
|         |   2134 ++ | 
|         |   2135 ++	if (type < 0 || type >= MPD_TAG_NUM_OF_ITEM_TYPES) { | 
|         |   2136 ++		strcpy(connection->errorStr, "invalid type specified"); | 
|         |   2137 ++		connection->error = 1; | 
|         |   2138 ++		return; | 
|         |   2139 ++	} | 
|         |   2140 ++ | 
|         |   2141 ++	if (name == NULL) { | 
|         |   2142 ++		strcpy(connection->errorStr, "no name specified"); | 
|         |   2143 ++		connection->error = 1; | 
|         |   2144 ++		return; | 
|         |   2145 ++	} | 
|         |   2146 ++ | 
|         |   2147 ++	string = strdup(connection->request); | 
|         |   2148 ++	strtype = mpdTagItemKeys[type]; | 
|         |   2149 ++	arg = mpd_sanitizeArg(name); | 
|         |   2150 ++ | 
|         |   2151 ++	len = strlen(string)+1+strlen(strtype)+2+strlen(arg)+2; | 
|         |   2152 ++	connection->request = (char *)realloc(connection->request, len); | 
|         |   2153 ++	snprintf(connection->request, len, "%s %c%s \"%s\"", | 
|         |   2154 ++	         string, tolower(strtype[0]), strtype+1, arg); | 
|         |   2155 ++ | 
|         |   2156 ++	free(string); | 
|         |   2157 ++	free(arg); | 
|         |   2158 ++} | 
|         |   2159 ++ | 
|         |   2160 ++void mpd_commitSearch(mpd_Connection *connection) | 
|         |   2161 ++{ | 
|         |   2162 ++	int len; | 
|         |   2163 ++ | 
|         |   2164 ++	if (!connection->request) { | 
|         |   2165 ++		strcpy(connection->errorStr, "no search in progress"); | 
|         |   2166 ++		connection->error = 1; | 
|         |   2167 ++		return; | 
|         |   2168 ++	} | 
|         |   2169 ++ | 
|         |   2170 ++	len = strlen(connection->request)+2; | 
|         |   2171 ++	connection->request = (char *)realloc(connection->request, len); | 
|         |   2172 ++	connection->request[len-2] = '\n'; | 
|         |   2173 ++	connection->request[len-1] = '\0'; | 
|         |   2174 ++	mpd_sendInfoCommand(connection, connection->request); | 
|         |   2175 ++ | 
|         |   2176 ++	free(connection->request); | 
|         |   2177 ++	connection->request = NULL; | 
|         |   2178 ++} | 
|         |   2179 ++ | 
|         |   2180 ++/** | 
|         |   2181 ++ * @param connection a MpdConnection | 
|         |   2182 ++ * @param path	the path to the playlist. | 
|         |   2183 ++ * | 
|         |   2184 ++ * List the content, with full metadata, of a stored playlist. | 
|         |   2185 ++ * | 
|         |   2186 ++ */ | 
|         |   2187 ++void mpd_sendListPlaylistInfoCommand(mpd_Connection *connection, char *path) | 
|         |   2188 ++{ | 
|         |   2189 ++	char *arg = mpd_sanitizeArg(path); | 
|         |   2190 ++	int len = strlen("listplaylistinfo")+2+strlen(arg)+3; | 
|         |   2191 ++	char *query = (char *)malloc(len); | 
|         |   2192 ++	snprintf(query, len, "listplaylistinfo \"%s\"\n", arg); | 
|         |   2193 ++	mpd_sendInfoCommand(connection, query); | 
|         |   2194 ++	free(arg); | 
|         |   2195 ++	free(query); | 
|         |   2196 ++} | 
|         |   2197 ++ | 
|         |   2198 ++/** | 
|         |   2199 ++ * @param connection a MpdConnection | 
|         |   2200 ++ * @param path	the path to the playlist. | 
|         |   2201 ++ * | 
|         |   2202 ++ * List the content of a stored playlist. | 
|         |   2203 ++ * | 
|         |   2204 ++ */ | 
|         |   2205 ++void mpd_sendListPlaylistCommand(mpd_Connection *connection, char *path) | 
|         |   2206 ++{ | 
|         |   2207 ++	char *arg = mpd_sanitizeArg(path); | 
|         |   2208 ++	int len = strlen("listplaylist")+2+strlen(arg)+3; | 
|         |   2209 ++	char *query = (char *)malloc(len); | 
|         |   2210 ++	snprintf(query, len, "listplaylist \"%s\"\n", arg); | 
|         |   2211 ++	mpd_sendInfoCommand(connection, query); | 
|         |   2212 ++	free(arg); | 
|         |   2213 ++	free(query); | 
|         |   2214 ++} | 
|         |   2215 ++ | 
|         |   2216 ++void mpd_sendPlaylistClearCommand(mpd_Connection *connection, char *path) | 
|         |   2217 ++{ | 
|         |   2218 ++	char *sPath = mpd_sanitizeArg(path); | 
|         |   2219 ++	int len = strlen("playlistclear")+2+strlen(sPath)+3; | 
|         |   2220 ++	char *string = (char *)malloc(len); | 
|         |   2221 ++	snprintf(string, len, "playlistclear \"%s\"\n", sPath); | 
|         |   2222 ++	mpd_executeCommand(connection, string); | 
|         |   2223 ++	free(sPath); | 
|         |   2224 ++	free(string); | 
|         |   2225 ++} | 
|         |   2226 ++ | 
|         |   2227 ++void mpd_sendPlaylistAddCommand(mpd_Connection *connection, | 
|         |   2228 ++                                char *playlist, char *path) | 
|         |   2229 ++{ | 
|         |   2230 ++	char *sPlaylist = mpd_sanitizeArg(playlist); | 
|         |   2231 ++	char *sPath = mpd_sanitizeArg(path); | 
|         |   2232 ++	int len = strlen("playlistadd")+2+strlen(sPlaylist)+3+strlen(sPath)+3; | 
|         |   2233 ++	char *string = (char *)malloc(len); | 
|         |   2234 ++	snprintf(string, len, "playlistadd \"%s\" \"%s\"\n", sPlaylist, sPath); | 
|         |   2235 ++	mpd_executeCommand(connection, string); | 
|         |   2236 ++	free(sPlaylist); | 
|         |   2237 ++	free(sPath); | 
|         |   2238 ++	free(string); | 
|         |   2239 ++} | 
|         |   2240 ++ | 
|         |   2241 ++void mpd_sendPlaylistMoveCommand(mpd_Connection *connection, | 
|         |   2242 ++                                 char *playlist, int from, int to) | 
|         |   2243 ++{ | 
|         |   2244 ++	char *sPlaylist = mpd_sanitizeArg(playlist); | 
|         |   2245 ++	int len = strlen("playlistmove")+ | 
|         |   2246 ++	          2+strlen(sPlaylist)+3+INTLEN+3+INTLEN+3; | 
|         |   2247 ++	char *string = (char *)malloc(len); | 
|         |   2248 ++	snprintf(string, len, "playlistmove \"%s\" \"%i\" \"%i\"\n", | 
|         |   2249 ++	         sPlaylist, from, to); | 
|         |   2250 ++	mpd_executeCommand(connection, string); | 
|         |   2251 ++	free(sPlaylist); | 
|         |   2252 ++	free(string); | 
|         |   2253 ++} | 
|         |   2254 ++ | 
|         |   2255 ++void mpd_sendPlaylistDeleteCommand(mpd_Connection *connection, | 
|         |   2256 ++                                   char *playlist, int pos) | 
|         |   2257 ++{ | 
|         |   2258 ++	char *sPlaylist = mpd_sanitizeArg(playlist); | 
|         |   2259 ++	int len = strlen("playlistdelete")+2+strlen(sPlaylist)+3+INTLEN+3; | 
|         |   2260 ++	char *string = (char *)malloc(len); | 
|         |   2261 ++	snprintf(string, len, "playlistdelete \"%s\" \"%i\"\n", sPlaylist, pos); | 
|         |   2262 ++	mpd_executeCommand(connection, string); | 
|         |   2263 ++	free(sPlaylist); | 
|         |   2264 ++	free(string); | 
|         |   2265 ++} | 
|         |   2266 +diff -r 171db9560cb5 clients/mpd/libmpdclient.h | 
|         |   2267 +--- /dev/null	Thu Jan 01 00:00:00 1970 +0000 | 
|         |   2268 ++++ b/clients/mpd/libmpdclient.h	Mon May 19 00:21:51 2008 -0400 | 
|         |   2269 +@@ -0,0 +1,670 @@ | 
|         |   2270 ++/* libmpdclient | 
|         |   2271 ++   (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com) | 
|         |   2272 ++   This project's homepage is: http://www.musicpd.org | 
|         |   2273 ++ | 
|         |   2274 ++   Redistribution and use in source and binary forms, with or without | 
|         |   2275 ++   modification, are permitted provided that the following conditions | 
|         |   2276 ++   are met: | 
|         |   2277 ++ | 
|         |   2278 ++   - Redistributions of source code must retain the above copyright | 
|         |   2279 ++   notice, this list of conditions and the following disclaimer. | 
|         |   2280 ++ | 
|         |   2281 ++   - Redistributions in binary form must reproduce the above copyright | 
|         |   2282 ++   notice, this list of conditions and the following disclaimer in the | 
|         |   2283 ++   documentation and/or other materials provided with the distribution. | 
|         |   2284 ++ | 
|         |   2285 ++   - Neither the name of the Music Player Daemon nor the names of its | 
|         |   2286 ++   contributors may be used to endorse or promote products derived from | 
|         |   2287 ++   this software without specific prior written permission. | 
|         |   2288 ++ | 
|         |   2289 ++   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
|         |   2290 ++   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
|         |   2291 ++   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
|         |   2292 ++   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR | 
|         |   2293 ++   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 
|         |   2294 ++   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 
|         |   2295 ++   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 
|         |   2296 ++   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 
|         |   2297 ++   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 
|         |   2298 ++   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
|         |   2299 ++   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|         |   2300 ++*/ | 
|         |   2301 ++ | 
|         |   2302 ++#ifndef LIBMPDCLIENT_H | 
|         |   2303 ++#define LIBMPDCLIENT_H | 
|         |   2304 ++ | 
|         |   2305 ++#ifdef WIN32 | 
|         |   2306 ++#  define __W32API_USE_DLLIMPORT__ 1 | 
|         |   2307 ++#endif | 
|         |   2308 ++ | 
|         |   2309 ++#include <sys/time.h> | 
|         |   2310 ++#include <stdarg.h> | 
|         |   2311 ++#define MPD_BUFFER_MAX_LENGTH	50000 | 
|         |   2312 ++#define MPD_ERRORSTR_MAX_LENGTH	1000 | 
|         |   2313 ++#define MPD_WELCOME_MESSAGE	"OK MPD " | 
|         |   2314 ++ | 
|         |   2315 ++#define MPD_ERROR_TIMEOUT	10 /* timeout trying to talk to mpd */ | 
|         |   2316 ++#define MPD_ERROR_SYSTEM	11 /* system error */ | 
|         |   2317 ++#define MPD_ERROR_UNKHOST	12 /* unknown host */ | 
|         |   2318 ++#define MPD_ERROR_CONNPORT	13 /* problems connecting to port on host */ | 
|         |   2319 ++#define MPD_ERROR_NOTMPD	14 /* mpd not running on port at host */ | 
|         |   2320 ++#define MPD_ERROR_NORESPONSE	15 /* no response on attempting to connect */ | 
|         |   2321 ++#define MPD_ERROR_SENDING	16 /* error sending command */ | 
|         |   2322 ++#define MPD_ERROR_CONNCLOSED	17 /* connection closed by mpd */ | 
|         |   2323 ++#define MPD_ERROR_ACK		18 /* ACK returned! */ | 
|         |   2324 ++#define MPD_ERROR_BUFFEROVERRUN	19 /* Buffer was overrun! */ | 
|         |   2325 ++ | 
|         |   2326 ++#define MPD_ACK_ERROR_UNK	-1 | 
|         |   2327 ++#define MPD_ERROR_AT_UNK	-1 | 
|         |   2328 ++ | 
|         |   2329 ++#define MPD_ACK_ERROR_NOT_LIST			1 | 
|         |   2330 ++#define MPD_ACK_ERROR_ARG			2 | 
|         |   2331 ++#define MPD_ACK_ERROR_PASSWORD			3 | 
|         |   2332 ++#define MPD_ACK_ERROR_PERMISSION		4 | 
|         |   2333 ++#define MPD_ACK_ERROR_UNKNOWN_CMD		5 | 
|         |   2334 ++ | 
|         |   2335 ++#define MPD_ACK_ERROR_NO_EXIST			50 | 
|         |   2336 ++#define MPD_ACK_ERROR_PLAYLIST_MAX		51 | 
|         |   2337 ++#define MPD_ACK_ERROR_SYSTEM			52 | 
|         |   2338 ++#define MPD_ACK_ERROR_PLAYLIST_LOAD		53 | 
|         |   2339 ++#define MPD_ACK_ERROR_UPDATE_ALREADY		54 | 
|         |   2340 ++#define MPD_ACK_ERROR_PLAYER_SYNC		55 | 
|         |   2341 ++#define MPD_ACK_ERROR_EXIST			56 | 
|         |   2342 ++ | 
|         |   2343 ++#ifdef __cplusplus | 
|         |   2344 ++extern "C" { | 
|         |   2345 ++#endif | 
|         |   2346 ++ | 
|         |   2347 ++typedef enum mpd_TagItems | 
|         |   2348 ++{ | 
|         |   2349 ++	MPD_TAG_ITEM_ARTIST, | 
|         |   2350 ++	MPD_TAG_ITEM_ALBUM, | 
|         |   2351 ++	MPD_TAG_ITEM_TITLE, | 
|         |   2352 ++	MPD_TAG_ITEM_TRACK, | 
|         |   2353 ++	MPD_TAG_ITEM_NAME, | 
|         |   2354 ++	MPD_TAG_ITEM_GENRE, | 
|         |   2355 ++	MPD_TAG_ITEM_DATE, | 
|         |   2356 ++	MPD_TAG_ITEM_COMPOSER, | 
|         |   2357 ++	MPD_TAG_ITEM_PERFORMER, | 
|         |   2358 ++	MPD_TAG_ITEM_COMMENT, | 
|         |   2359 ++	MPD_TAG_ITEM_DISC, | 
|         |   2360 ++	MPD_TAG_ITEM_FILENAME, | 
|         |   2361 ++	MPD_TAG_ITEM_ANY, | 
|         |   2362 ++	MPD_TAG_NUM_OF_ITEM_TYPES | 
|         |   2363 ++} mpd_TagItems; | 
|         |   2364 ++ | 
|         |   2365 ++extern char * mpdTagItemKeys[MPD_TAG_NUM_OF_ITEM_TYPES]; | 
|         |   2366 ++ | 
|         |   2367 ++/* internal stuff don't touch this struct */ | 
|         |   2368 ++typedef struct _mpd_ReturnElement { | 
|         |   2369 ++	char * name; | 
|         |   2370 ++	char * value; | 
|         |   2371 ++} mpd_ReturnElement; | 
|         |   2372 ++ | 
|         |   2373 ++/* mpd_Connection | 
|         |   2374 ++ * holds info about connection to mpd | 
|         |   2375 ++ * use error, and errorStr to detect errors | 
|         |   2376 ++ */ | 
|         |   2377 ++typedef struct _mpd_Connection { | 
|         |   2378 ++	/* use this to check the version of mpd */ | 
|         |   2379 ++	int version[3]; | 
|         |   2380 ++	/* IMPORTANT, you want to get the error messages from here */ | 
|         |   2381 ++	char errorStr[MPD_ERRORSTR_MAX_LENGTH+1]; | 
|         |   2382 ++	int errorCode; | 
|         |   2383 ++	int errorAt; | 
|         |   2384 ++	/* this will be set to MPD_ERROR_* if there is an error, 0 if not */ | 
|         |   2385 ++	int error; | 
|         |   2386 ++	/* DON'T TOUCH any of the rest of this stuff */ | 
|         |   2387 ++	int sock; | 
|         |   2388 ++	char buffer[MPD_BUFFER_MAX_LENGTH+1]; | 
|         |   2389 ++	int buflen; | 
|         |   2390 ++	int bufstart; | 
|         |   2391 ++	int doneProcessing; | 
|         |   2392 ++	int listOks; | 
|         |   2393 ++	int doneListOk; | 
|         |   2394 ++	int commandList; | 
|         |   2395 ++	mpd_ReturnElement * returnElement; | 
|         |   2396 ++	struct timeval timeout; | 
|         |   2397 ++	char *request; | 
|         |   2398 ++} mpd_Connection; | 
|         |   2399 ++ | 
|         |   2400 ++/* mpd_newConnection | 
|         |   2401 ++ * use this to open a new connection | 
|         |   2402 ++ * you should use mpd_closeConnection, when your done with the connection, | 
|         |   2403 ++ * even if an error has occurred | 
|         |   2404 ++ * _timeout_ is the connection timeout period in seconds | 
|         |   2405 ++ */ | 
|         |   2406 ++mpd_Connection * mpd_newConnection(const char * host, int port, float timeout); | 
|         |   2407 ++ | 
|         |   2408 ++void mpd_setConnectionTimeout(mpd_Connection * connection, float timeout); | 
|         |   2409 ++ | 
|         |   2410 ++/* mpd_closeConnection | 
|         |   2411 ++ * use this to close a connection and free'ing subsequent memory | 
|         |   2412 ++ */ | 
|         |   2413 ++void mpd_closeConnection(mpd_Connection * connection); | 
|         |   2414 ++ | 
|         |   2415 ++/* mpd_clearError | 
|         |   2416 ++ * clears error | 
|         |   2417 ++ */ | 
|         |   2418 ++void mpd_clearError(mpd_Connection * connection); | 
|         |   2419 ++ | 
|         |   2420 ++/* STATUS STUFF */ | 
|         |   2421 ++ | 
|         |   2422 ++/* use these with status.state to determine what state the player is in */ | 
|         |   2423 ++#define MPD_STATUS_STATE_UNKNOWN	0 | 
|         |   2424 ++#define MPD_STATUS_STATE_STOP		1 | 
|         |   2425 ++#define MPD_STATUS_STATE_PLAY		2 | 
|         |   2426 ++#define MPD_STATUS_STATE_PAUSE		3 | 
|         |   2427 ++ | 
|         |   2428 ++/* us this with status.volume to determine if mpd has volume support */ | 
|         |   2429 ++#define MPD_STATUS_NO_VOLUME		-1 | 
|         |   2430 ++ | 
|         |   2431 ++/* mpd_Status | 
|         |   2432 ++ * holds info return from status command | 
|         |   2433 ++ */ | 
|         |   2434 ++typedef struct mpd_Status { | 
|         |   2435 ++	/* 0-100, or MPD_STATUS_NO_VOLUME when there is no volume support */ | 
|         |   2436 ++	int volume; | 
|         |   2437 ++	/* 1 if repeat is on, 0 otherwise */ | 
|         |   2438 ++	int repeat; | 
|         |   2439 ++	/* 1 if random is on, 0 otherwise */ | 
|         |   2440 ++	int random; | 
|         |   2441 ++	/* playlist length */ | 
|         |   2442 ++	int playlistLength; | 
|         |   2443 ++	/* playlist, use this to determine when the playlist has changed */ | 
|         |   2444 ++	long long playlist; | 
|         |   2445 ++	/* use with MPD_STATUS_STATE_* to determine state of player */ | 
|         |   2446 ++	int state; | 
|         |   2447 ++	/* crossfade setting in seconds */ | 
|         |   2448 ++	int crossfade; | 
|         |   2449 ++	/* if a song is currently selected (always the case when state is | 
|         |   2450 ++	 * PLAY or PAUSE), this is the position of the currently | 
|         |   2451 ++	 * playing song in the playlist, beginning with 0 | 
|         |   2452 ++	 */ | 
|         |   2453 ++	int song; | 
|         |   2454 ++	/* Song ID of the currently selected song */ | 
|         |   2455 ++	int songid; | 
|         |   2456 ++	/* time in seconds that have elapsed in the currently playing/paused | 
|         |   2457 ++	 * song | 
|         |   2458 ++	 */ | 
|         |   2459 ++	int elapsedTime; | 
|         |   2460 ++	/* length in seconds of the currently playing/paused song */ | 
|         |   2461 ++	int totalTime; | 
|         |   2462 ++	/* current bit rate in kbs */ | 
|         |   2463 ++	int bitRate; | 
|         |   2464 ++	/* audio sample rate */ | 
|         |   2465 ++	unsigned int sampleRate; | 
|         |   2466 ++	/* audio bits */ | 
|         |   2467 ++	int bits; | 
|         |   2468 ++	/* audio channels */ | 
|         |   2469 ++	int channels; | 
|         |   2470 ++	/* 1 if mpd is updating, 0 otherwise */ | 
|         |   2471 ++	int updatingDb; | 
|         |   2472 ++	/* error */ | 
|         |   2473 ++	char * error; | 
|         |   2474 ++} mpd_Status; | 
|         |   2475 ++ | 
|         |   2476 ++void mpd_sendStatusCommand(mpd_Connection * connection); | 
|         |   2477 ++ | 
|         |   2478 ++/* mpd_getStatus | 
|         |   2479 ++ * returns status info, be sure to free it with mpd_freeStatus() | 
|         |   2480 ++ * call this after mpd_sendStatusCommand() | 
|         |   2481 ++ */ | 
|         |   2482 ++mpd_Status * mpd_getStatus(mpd_Connection * connection); | 
|         |   2483 ++ | 
|         |   2484 ++/* mpd_freeStatus | 
|         |   2485 ++ * free's status info malloc'd and returned by mpd_getStatus | 
|         |   2486 ++ */ | 
|         |   2487 ++void mpd_freeStatus(mpd_Status * status); | 
|         |   2488 ++ | 
|         |   2489 ++typedef struct _mpd_Stats { | 
|         |   2490 ++	int numberOfArtists; | 
|         |   2491 ++	int numberOfAlbums; | 
|         |   2492 ++	int numberOfSongs; | 
|         |   2493 ++	unsigned long uptime; | 
|         |   2494 ++	unsigned long dbUpdateTime; | 
|         |   2495 ++	unsigned long playTime; | 
|         |   2496 ++	unsigned long dbPlayTime; | 
|         |   2497 ++} mpd_Stats; | 
|         |   2498 ++ | 
|         |   2499 ++typedef struct _mpd_SearchStats { | 
|         |   2500 ++	int numberOfSongs; | 
|         |   2501 ++	unsigned long playTime; | 
|         |   2502 ++} mpd_SearchStats; | 
|         |   2503 ++ | 
|         |   2504 ++void mpd_sendStatsCommand(mpd_Connection * connection); | 
|         |   2505 ++ | 
|         |   2506 ++mpd_Stats * mpd_getStats(mpd_Connection * connection); | 
|         |   2507 ++ | 
|         |   2508 ++void mpd_freeStats(mpd_Stats * stats); | 
|         |   2509 ++ | 
|         |   2510 ++mpd_SearchStats * mpd_getSearchStats(mpd_Connection * connection); | 
|         |   2511 ++ | 
|         |   2512 ++void mpd_freeSearchStats(mpd_SearchStats * stats); | 
|         |   2513 ++ | 
|         |   2514 ++/* SONG STUFF */ | 
|         |   2515 ++ | 
|         |   2516 ++#define MPD_SONG_NO_TIME	-1 | 
|         |   2517 ++#define MPD_SONG_NO_NUM		-1 | 
|         |   2518 ++#define MPD_SONG_NO_ID		-1 | 
|         |   2519 ++ | 
|         |   2520 ++/* mpd_Song | 
|         |   2521 ++ * for storing song info returned by mpd | 
|         |   2522 ++ */ | 
|         |   2523 ++typedef struct _mpd_Song { | 
|         |   2524 ++	/* filename of song */ | 
|         |   2525 ++	char * file; | 
|         |   2526 ++	/* artist, maybe NULL if there is no tag */ | 
|         |   2527 ++	char * artist; | 
|         |   2528 ++	/* title, maybe NULL if there is no tag */ | 
|         |   2529 ++	char * title; | 
|         |   2530 ++	/* album, maybe NULL if there is no tag */ | 
|         |   2531 ++	char * album; | 
|         |   2532 ++	/* track, maybe NULL if there is no tag */ | 
|         |   2533 ++	char * track; | 
|         |   2534 ++	/* name, maybe NULL if there is no tag; it's the name of the current | 
|         |   2535 ++	 * song, f.e. the icyName of the stream */ | 
|         |   2536 ++	char * name; | 
|         |   2537 ++	/* date */ | 
|         |   2538 ++	char *date; | 
|         |   2539 ++ | 
|         |   2540 ++	/* added by qball */ | 
|         |   2541 ++	/* Genre */ | 
|         |   2542 ++	char *genre; | 
|         |   2543 ++	/* Composer */ | 
|         |   2544 ++	char *composer; | 
|         |   2545 ++	/* Performer */ | 
|         |   2546 ++	char *performer; | 
|         |   2547 ++	/* Disc */ | 
|         |   2548 ++	char *disc; | 
|         |   2549 ++	/* Comment */ | 
|         |   2550 ++	char *comment; | 
|         |   2551 ++ | 
|         |   2552 ++	/* length of song in seconds, check that it is not MPD_SONG_NO_TIME  */ | 
|         |   2553 ++	int time; | 
|         |   2554 ++	/* if plchanges/playlistinfo/playlistid used, is the position of the | 
|         |   2555 ++	 * song in the playlist */ | 
|         |   2556 ++	int pos; | 
|         |   2557 ++	/* song id for a song in the playlist */ | 
|         |   2558 ++	int id; | 
|         |   2559 ++} mpd_Song; | 
|         |   2560 ++ | 
|         |   2561 ++/* mpd_newSong | 
|         |   2562 ++ * use to allocate memory for a new mpd_Song | 
|         |   2563 ++ * file, artist, etc all initialized to NULL | 
|         |   2564 ++ * if your going to assign values to file, artist, etc | 
|         |   2565 ++ * be sure to malloc or strdup the memory | 
|         |   2566 ++ * use mpd_freeSong to free the memory for the mpd_Song, it will also | 
|         |   2567 ++ * free memory for file, artist, etc, so don't do it yourself | 
|         |   2568 ++ */ | 
|         |   2569 ++mpd_Song * mpd_newSong(void); | 
|         |   2570 ++ | 
|         |   2571 ++/* mpd_freeSong | 
|         |   2572 ++ * use to free memory allocated by mpd_newSong | 
|         |   2573 ++ * also it will free memory pointed to by file, artist, etc, so be careful | 
|         |   2574 ++ */ | 
|         |   2575 ++void mpd_freeSong(mpd_Song * song); | 
|         |   2576 ++ | 
|         |   2577 ++/* mpd_songDup | 
|         |   2578 ++ * works like strDup, but for a mpd_Song | 
|         |   2579 ++ */ | 
|         |   2580 ++mpd_Song * mpd_songDup(mpd_Song * song); | 
|         |   2581 ++ | 
|         |   2582 ++/* DIRECTORY STUFF */ | 
|         |   2583 ++ | 
|         |   2584 ++/* mpd_Directory | 
|         |   2585 ++ * used to store info fro directory (right now that just the path) | 
|         |   2586 ++ */ | 
|         |   2587 ++typedef struct _mpd_Directory { | 
|         |   2588 ++	char * path; | 
|         |   2589 ++} mpd_Directory; | 
|         |   2590 ++ | 
|         |   2591 ++/* mpd_newDirectory | 
|         |   2592 ++ * allocates memory for a new directory | 
|         |   2593 ++ * use mpd_freeDirectory to free this memory | 
|         |   2594 ++ */ | 
|         |   2595 ++mpd_Directory * mpd_newDirectory(void); | 
|         |   2596 ++ | 
|         |   2597 ++/* mpd_freeDirectory | 
|         |   2598 ++ * used to free memory allocated with mpd_newDirectory, and it frees | 
|         |   2599 ++ * path of mpd_Directory, so be careful | 
|         |   2600 ++ */ | 
|         |   2601 ++void mpd_freeDirectory(mpd_Directory * directory); | 
|         |   2602 ++ | 
|         |   2603 ++/* mpd_directoryDup | 
|         |   2604 ++ * works like strdup, but for mpd_Directory | 
|         |   2605 ++ */ | 
|         |   2606 ++mpd_Directory * mpd_directoryDup(mpd_Directory * directory); | 
|         |   2607 ++ | 
|         |   2608 ++/* PLAYLISTFILE STUFF */ | 
|         |   2609 ++ | 
|         |   2610 ++/* mpd_PlaylistFile | 
|         |   2611 ++ * stores info about playlist file returned by lsinfo | 
|         |   2612 ++ */ | 
|         |   2613 ++typedef struct _mpd_PlaylistFile { | 
|         |   2614 ++	char * path; | 
|         |   2615 ++} mpd_PlaylistFile; | 
|         |   2616 ++ | 
|         |   2617 ++/* mpd_newPlaylistFile | 
|         |   2618 ++ * allocates memory for new mpd_PlaylistFile, path is set to NULL | 
|         |   2619 ++ * free this memory with mpd_freePlaylistFile | 
|         |   2620 ++ */ | 
|         |   2621 ++mpd_PlaylistFile * mpd_newPlaylistFile(void); | 
|         |   2622 ++ | 
|         |   2623 ++/* mpd_freePlaylist | 
|         |   2624 ++ * free memory allocated for freePlaylistFile, will also free | 
|         |   2625 ++ * path, so be careful | 
|         |   2626 ++ */ | 
|         |   2627 ++void mpd_freePlaylistFile(mpd_PlaylistFile * playlist); | 
|         |   2628 ++ | 
|         |   2629 ++/* mpd_playlistFileDup | 
|         |   2630 ++ * works like strdup, but for mpd_PlaylistFile | 
|         |   2631 ++ */ | 
|         |   2632 ++mpd_PlaylistFile * mpd_playlistFileDup(mpd_PlaylistFile * playlist); | 
|         |   2633 ++ | 
|         |   2634 ++/* INFO ENTITY STUFF */ | 
|         |   2635 ++ | 
|         |   2636 ++/* the type of entity returned from one of the commands that generates info | 
|         |   2637 ++ * use in conjunction with mpd_InfoEntity.type | 
|         |   2638 ++ */ | 
|         |   2639 ++#define MPD_INFO_ENTITY_TYPE_DIRECTORY		0 | 
|         |   2640 ++#define MPD_INFO_ENTITY_TYPE_SONG		1 | 
|         |   2641 ++#define MPD_INFO_ENTITY_TYPE_PLAYLISTFILE	2 | 
|         |   2642 ++ | 
|         |   2643 ++/* mpd_InfoEntity | 
|         |   2644 ++ * stores info on stuff returned info commands | 
|         |   2645 ++ */ | 
|         |   2646 ++typedef struct mpd_InfoEntity { | 
|         |   2647 ++	/* the type of entity, use with MPD_INFO_ENTITY_TYPE_* to determine | 
|         |   2648 ++	 * what this entity is (song, directory, etc...) | 
|         |   2649 ++	 */ | 
|         |   2650 ++	int type; | 
|         |   2651 ++	/* the actual data you want, mpd_Song, mpd_Directory, etc */ | 
|         |   2652 ++	union { | 
|         |   2653 ++		mpd_Directory * directory; | 
|         |   2654 ++		mpd_Song * song; | 
|         |   2655 ++		mpd_PlaylistFile * playlistFile; | 
|         |   2656 ++	} info; | 
|         |   2657 ++} mpd_InfoEntity; | 
|         |   2658 ++ | 
|         |   2659 ++mpd_InfoEntity * mpd_newInfoEntity(void); | 
|         |   2660 ++ | 
|         |   2661 ++void mpd_freeInfoEntity(mpd_InfoEntity * entity); | 
|         |   2662 ++ | 
|         |   2663 ++/* INFO COMMANDS AND STUFF */ | 
|         |   2664 ++ | 
|         |   2665 ++/* use this function to loop over after calling Info/Listall functions */ | 
|         |   2666 ++mpd_InfoEntity * mpd_getNextInfoEntity(mpd_Connection * connection); | 
|         |   2667 ++ | 
|         |   2668 ++/* fetches the currently seeletect song (the song referenced by status->song | 
|         |   2669 ++ * and status->songid*/ | 
|         |   2670 ++void mpd_sendCurrentSongCommand(mpd_Connection * connection); | 
|         |   2671 ++ | 
|         |   2672 ++/* songNum of -1, means to display the whole list */ | 
|         |   2673 ++void mpd_sendPlaylistInfoCommand(mpd_Connection * connection, int songNum); | 
|         |   2674 ++ | 
|         |   2675 ++/* songId of -1, means to display the whole list */ | 
|         |   2676 ++void mpd_sendPlaylistIdCommand(mpd_Connection * connection, int songId); | 
|         |   2677 ++ | 
|         |   2678 ++/* use this to get the changes in the playlist since version _playlist_ */ | 
|         |   2679 ++void mpd_sendPlChangesCommand(mpd_Connection * connection, long long playlist); | 
|         |   2680 ++ | 
|         |   2681 ++/** | 
|         |   2682 ++ * @param connection: A valid and connected mpd_Connection. | 
|         |   2683 ++ * @param playlist: The playlist version you want the diff with. | 
|         |   2684 ++ * A more bandwidth efficient version of the mpd_sendPlChangesCommand. | 
|         |   2685 ++ * It only returns the pos+id of the changes song. | 
|         |   2686 ++ */ | 
|         |   2687 ++void mpd_sendPlChangesPosIdCommand(mpd_Connection * connection, long long playlist); | 
|         |   2688 ++ | 
|         |   2689 ++/* recursivel fetches all songs/dir/playlists in "dir* (no metadata is | 
|         |   2690 ++ * returned) */ | 
|         |   2691 ++void mpd_sendListallCommand(mpd_Connection * connection, const char * dir); | 
|         |   2692 ++ | 
|         |   2693 ++/* same as sendListallCommand, but also metadata is returned */ | 
|         |   2694 ++void mpd_sendListallInfoCommand(mpd_Connection * connection, const char * dir); | 
|         |   2695 ++ | 
|         |   2696 ++/* non-recursive version of ListallInfo */ | 
|         |   2697 ++void mpd_sendLsInfoCommand(mpd_Connection * connection, const char * dir); | 
|         |   2698 ++ | 
|         |   2699 ++#define MPD_TABLE_ARTIST	MPD_TAG_ITEM_ARTIST | 
|         |   2700 ++#define MPD_TABLE_ALBUM		MPD_TAG_ITEM_ALBUM | 
|         |   2701 ++#define MPD_TABLE_TITLE		MPD_TAG_ITEM_TITLE | 
|         |   2702 ++#define MPD_TABLE_FILENAME	MPD_TAG_ITEM_FILENAME | 
|         |   2703 ++ | 
|         |   2704 ++void mpd_sendSearchCommand(mpd_Connection * connection, int table, | 
|         |   2705 ++		const char * str); | 
|         |   2706 ++ | 
|         |   2707 ++void mpd_sendFindCommand(mpd_Connection * connection, int table, | 
|         |   2708 ++		const char * str); | 
|         |   2709 ++ | 
|         |   2710 ++/* LIST TAG COMMANDS */ | 
|         |   2711 ++ | 
|         |   2712 ++/* use this function fetch next artist entry, be sure to free the returned | 
|         |   2713 ++ * string.  NULL means there are no more.  Best used with sendListArtists | 
|         |   2714 ++ */ | 
|         |   2715 ++char * mpd_getNextArtist(mpd_Connection * connection); | 
|         |   2716 ++ | 
|         |   2717 ++char * mpd_getNextAlbum(mpd_Connection * connection); | 
|         |   2718 ++ | 
|         |   2719 ++char * mpd_getNextTag(mpd_Connection *connection, int type); | 
|         |   2720 ++ | 
|         |   2721 ++/* list artist or albums by artist, arg1 should be set to the artist if | 
|         |   2722 ++ * listing albums by a artist, otherwise NULL for listing all artists or albums | 
|         |   2723 ++ */ | 
|         |   2724 ++void mpd_sendListCommand(mpd_Connection * connection, int table, | 
|         |   2725 ++		const char * arg1); | 
|         |   2726 ++ | 
|         |   2727 ++/* SIMPLE COMMANDS */ | 
|         |   2728 ++ | 
|         |   2729 ++void mpd_sendAddCommand(mpd_Connection * connection, const char * file); | 
|         |   2730 ++ | 
|         |   2731 ++int mpd_sendAddIdCommand(mpd_Connection *connection, const char *file); | 
|         |   2732 ++ | 
|         |   2733 ++void mpd_sendDeleteCommand(mpd_Connection * connection, int songNum); | 
|         |   2734 ++ | 
|         |   2735 ++void mpd_sendDeleteIdCommand(mpd_Connection * connection, int songNum); | 
|         |   2736 ++ | 
|         |   2737 ++void mpd_sendSaveCommand(mpd_Connection * connection, const char * name); | 
|         |   2738 ++ | 
|         |   2739 ++void mpd_sendLoadCommand(mpd_Connection * connection, const char * name); | 
|         |   2740 ++ | 
|         |   2741 ++void mpd_sendRmCommand(mpd_Connection * connection, const char * name); | 
|         |   2742 ++ | 
|         |   2743 ++void mpd_sendRenameCommand(mpd_Connection *connection, const char *from, | 
|         |   2744 ++                           const char *to); | 
|         |   2745 ++ | 
|         |   2746 ++void mpd_sendShuffleCommand(mpd_Connection * connection); | 
|         |   2747 ++ | 
|         |   2748 ++void mpd_sendClearCommand(mpd_Connection * connection); | 
|         |   2749 ++ | 
|         |   2750 ++/* use this to start playing at the beginning, useful when in random mode */ | 
|         |   2751 ++#define MPD_PLAY_AT_BEGINNING	-1 | 
|         |   2752 ++ | 
|         |   2753 ++void mpd_sendPlayCommand(mpd_Connection * connection, int songNum); | 
|         |   2754 ++ | 
|         |   2755 ++void mpd_sendPlayIdCommand(mpd_Connection * connection, int songNum); | 
|         |   2756 ++ | 
|         |   2757 ++void mpd_sendStopCommand(mpd_Connection * connection); | 
|         |   2758 ++ | 
|         |   2759 ++void mpd_sendPauseCommand(mpd_Connection * connection, int pauseMode); | 
|         |   2760 ++ | 
|         |   2761 ++void mpd_sendNextCommand(mpd_Connection * connection); | 
|         |   2762 ++ | 
|         |   2763 ++void mpd_sendPrevCommand(mpd_Connection * connection); | 
|         |   2764 ++ | 
|         |   2765 ++void mpd_sendMoveCommand(mpd_Connection * connection, int from, int to); | 
|         |   2766 ++ | 
|         |   2767 ++void mpd_sendMoveIdCommand(mpd_Connection * connection, int from, int to); | 
|         |   2768 ++ | 
|         |   2769 ++void mpd_sendSwapCommand(mpd_Connection * connection, int song1, int song2); | 
|         |   2770 ++ | 
|         |   2771 ++void mpd_sendSwapIdCommand(mpd_Connection * connection, int song1, int song2); | 
|         |   2772 ++ | 
|         |   2773 ++void mpd_sendSeekCommand(mpd_Connection * connection, int song, int time); | 
|         |   2774 ++ | 
|         |   2775 ++void mpd_sendSeekIdCommand(mpd_Connection * connection, int song, int time); | 
|         |   2776 ++ | 
|         |   2777 ++void mpd_sendRepeatCommand(mpd_Connection * connection, int repeatMode); | 
|         |   2778 ++ | 
|         |   2779 ++void mpd_sendRandomCommand(mpd_Connection * connection, int randomMode); | 
|         |   2780 ++ | 
|         |   2781 ++void mpd_sendSetvolCommand(mpd_Connection * connection, int volumeChange); | 
|         |   2782 ++ | 
|         |   2783 ++/* WARNING: don't use volume command, its depreacted */ | 
|         |   2784 ++void mpd_sendVolumeCommand(mpd_Connection * connection, int volumeChange); | 
|         |   2785 ++ | 
|         |   2786 ++void mpd_sendCrossfadeCommand(mpd_Connection * connection, int seconds); | 
|         |   2787 ++ | 
|         |   2788 ++void mpd_sendUpdateCommand(mpd_Connection * connection, char * path); | 
|         |   2789 ++ | 
|         |   2790 ++/* returns the update job id, call this after a update command*/ | 
|         |   2791 ++int mpd_getUpdateId(mpd_Connection * connection); | 
|         |   2792 ++ | 
|         |   2793 ++void mpd_sendPasswordCommand(mpd_Connection * connection, const char * pass); | 
|         |   2794 ++ | 
|         |   2795 ++/* after executing a command, when your done with it to get its status | 
|         |   2796 ++ * (you want to check connection->error for an error) | 
|         |   2797 ++ */ | 
|         |   2798 ++void mpd_finishCommand(mpd_Connection * connection); | 
|         |   2799 ++ | 
|         |   2800 ++/* command list stuff, use this to do things like add files very quickly */ | 
|         |   2801 ++void mpd_sendCommandListBegin(mpd_Connection * connection); | 
|         |   2802 ++ | 
|         |   2803 ++void mpd_sendCommandListOkBegin(mpd_Connection * connection); | 
|         |   2804 ++ | 
|         |   2805 ++void mpd_sendCommandListEnd(mpd_Connection * connection); | 
|         |   2806 ++ | 
|         |   2807 ++/* advance to the next listOk | 
|         |   2808 ++ * returns 0 if advanced to the next list_OK, | 
|         |   2809 ++ * returns -1 if it advanced to an OK or ACK */ | 
|         |   2810 ++int mpd_nextListOkCommand(mpd_Connection * connection); | 
|         |   2811 ++ | 
|         |   2812 ++typedef struct _mpd_OutputEntity { | 
|         |   2813 ++	int id; | 
|         |   2814 ++	char * name; | 
|         |   2815 ++	int enabled; | 
|         |   2816 ++} mpd_OutputEntity; | 
|         |   2817 ++ | 
|         |   2818 ++void mpd_sendOutputsCommand(mpd_Connection * connection); | 
|         |   2819 ++ | 
|         |   2820 ++mpd_OutputEntity * mpd_getNextOutput(mpd_Connection * connection); | 
|         |   2821 ++ | 
|         |   2822 ++void mpd_sendEnableOutputCommand(mpd_Connection * connection, int outputId); | 
|         |   2823 ++ | 
|         |   2824 ++void mpd_sendDisableOutputCommand(mpd_Connection * connection, int outputId); | 
|         |   2825 ++ | 
|         |   2826 ++void mpd_freeOutputElement(mpd_OutputEntity * output); | 
|         |   2827 ++ | 
|         |   2828 ++/** | 
|         |   2829 ++ * @param connection a #mpd_Connection | 
|         |   2830 ++ * | 
|         |   2831 ++ * Queries mpd for the allowed commands | 
|         |   2832 ++ */ | 
|         |   2833 ++void mpd_sendCommandsCommand(mpd_Connection * connection); | 
|         |   2834 ++ | 
|         |   2835 ++/** | 
|         |   2836 ++ * @param connection a #mpd_Connection | 
|         |   2837 ++ * | 
|         |   2838 ++ * Queries mpd for the not allowed commands | 
|         |   2839 ++ */ | 
|         |   2840 ++void mpd_sendNotCommandsCommand(mpd_Connection * connection); | 
|         |   2841 ++ | 
|         |   2842 ++/** | 
|         |   2843 ++ * @param connection a #mpd_Connection | 
|         |   2844 ++ * | 
|         |   2845 ++ * returns the next supported command. | 
|         |   2846 ++ * | 
|         |   2847 ++ * @returns a string, needs to be free'ed | 
|         |   2848 ++ */ | 
|         |   2849 ++char *mpd_getNextCommand(mpd_Connection *connection); | 
|         |   2850 ++ | 
|         |   2851 ++void mpd_sendUrlHandlersCommand(mpd_Connection * connection); | 
|         |   2852 ++ | 
|         |   2853 ++char *mpd_getNextHandler(mpd_Connection * connection); | 
|         |   2854 ++ | 
|         |   2855 ++void mpd_sendTagTypesCommand(mpd_Connection * connection); | 
|         |   2856 ++ | 
|         |   2857 ++char *mpd_getNextTagType(mpd_Connection * connection); | 
|         |   2858 ++ | 
|         |   2859 ++/** | 
|         |   2860 ++ * @param connection a MpdConnection | 
|         |   2861 ++ * @param path	the path to the playlist. | 
|         |   2862 ++ * | 
|         |   2863 ++ * List the content, with full metadata, of a stored playlist. | 
|         |   2864 ++ * | 
|         |   2865 ++ */ | 
|         |   2866 ++void mpd_sendListPlaylistInfoCommand(mpd_Connection *connection, char *path); | 
|         |   2867 ++ | 
|         |   2868 ++/** | 
|         |   2869 ++ * @param connection a MpdConnection | 
|         |   2870 ++ * @param path	the path to the playlist. | 
|         |   2871 ++ * | 
|         |   2872 ++ * List the content of a stored playlist. | 
|         |   2873 ++ * | 
|         |   2874 ++ */ | 
|         |   2875 ++void mpd_sendListPlaylistCommand(mpd_Connection *connection, char *path); | 
|         |   2876 ++ | 
|         |   2877 ++/** | 
|         |   2878 ++ * @param connection a #mpd_Connection | 
|         |   2879 ++ * @param exact if to match exact | 
|         |   2880 ++ * | 
|         |   2881 ++ * starts a search, use mpd_addConstraintSearch to add | 
|         |   2882 ++ * a constraint to the search, and mpd_commitSearch to do the actual search | 
|         |   2883 ++ */ | 
|         |   2884 ++void mpd_startSearch(mpd_Connection *connection, int exact); | 
|         |   2885 ++ | 
|         |   2886 ++/** | 
|         |   2887 ++ * @param connection a #mpd_Connection | 
|         |   2888 ++ * @param type | 
|         |   2889 ++ * @param name | 
|         |   2890 ++ */ | 
|         |   2891 ++void mpd_addConstraintSearch(mpd_Connection *connection, int type, const char *name); | 
|         |   2892 ++ | 
|         |   2893 ++/** | 
|         |   2894 ++ * @param connection a #mpd_Connection | 
|         |   2895 ++ */ | 
|         |   2896 ++void mpd_commitSearch(mpd_Connection *connection); | 
|         |   2897 ++ | 
|         |   2898 ++/** | 
|         |   2899 ++ * @param connection a #mpd_Connection | 
|         |   2900 ++ * @param type The type to search for | 
|         |   2901 ++ * | 
|         |   2902 ++ * starts a search for fields... f.e. get a list of artists would be: | 
|         |   2903 ++ * @code | 
|         |   2904 ++ * mpd_startFieldSearch(connection, MPD_TAG_ITEM_ARTIST); | 
|         |   2905 ++ * mpd_commitSearch(connection); | 
|         |   2906 ++ * @endcode | 
|         |   2907 ++ * | 
|         |   2908 ++ * or get a list of artist in genre "jazz" would be: | 
|         |   2909 ++ * @code | 
|         |   2910 ++ * mpd_startFieldSearch(connection, MPD_TAG_ITEM_ARTIST); | 
|         |   2911 ++ * mpd_addConstraintSearch(connection, MPD_TAG_ITEM_GENRE, "jazz") | 
|         |   2912 ++ * mpd_commitSearch(connection); | 
|         |   2913 ++ * @endcode | 
|         |   2914 ++ * | 
|         |   2915 ++ * mpd_startSearch will return  a list of songs (and you need mpd_getNextInfoEntity) | 
|         |   2916 ++ * this one will return a list of only one field (the one specified with type) and you need | 
|         |   2917 ++ * mpd_getNextTag to get the results | 
|         |   2918 ++ */ | 
|         |   2919 ++void mpd_startFieldSearch(mpd_Connection *connection, int type); | 
|         |   2920 ++ | 
|         |   2921 ++void mpd_startPlaylistSearch(mpd_Connection *connection, int exact); | 
|         |   2922 ++ | 
|         |   2923 ++void mpd_startStatsSearch(mpd_Connection *connection); | 
|         |   2924 ++ | 
|         |   2925 ++void mpd_sendPlaylistClearCommand(mpd_Connection *connection, char *path); | 
|         |   2926 ++ | 
|         |   2927 ++void mpd_sendPlaylistAddCommand(mpd_Connection *connection, | 
|         |   2928 ++                                char *playlist, char *path); | 
|         |   2929 ++ | 
|         |   2930 ++void mpd_sendPlaylistMoveCommand(mpd_Connection *connection, | 
|         |   2931 ++                                 char *playlist, int from, int to); | 
|         |   2932 ++ | 
|         |   2933 ++void mpd_sendPlaylistDeleteCommand(mpd_Connection *connection, | 
|         |   2934 ++                                   char *playlist, int pos); | 
|         |   2935 ++#ifdef __cplusplus | 
|         |   2936 ++} | 
|         |   2937 ++#endif | 
|         |   2938 ++ | 
|         |   2939 ++#endif | 
|         |   2940 +diff -r 171db9560cb5 clients/mpd/mpdinterface.cc | 
|         |   2941 +--- /dev/null	Thu Jan 01 00:00:00 1970 +0000 | 
|         |   2942 ++++ b/clients/mpd/mpdinterface.cc	Mon May 19 00:21:51 2008 -0400 | 
|         |   2943 +@@ -0,0 +1,404 @@ | 
|         |   2944 ++#include "mpdinterface.h" | 
|         |   2945 ++#include "immsutil.h" | 
|         |   2946 ++#include <cctype> | 
|         |   2947 ++#include <fstream> | 
|         |   2948 ++#include <sstream> | 
|         |   2949 ++ | 
|         |   2950 ++namespace mpd_interface | 
|         |   2951 ++{ | 
|         |   2952 ++  position_err::position_err(int position, int playlist_length) | 
|         |   2953 ++  { | 
|         |   2954 ++    std::ostringstream s; | 
|         |   2955 ++    s << "Attempted to access song of invalid position in playlist. " | 
|         |   2956 ++      "Used position: " << position << ", playlist size: " | 
|         |   2957 ++      << playlist_length; | 
|         |   2958 ++    msg = s.str(); | 
|         |   2959 ++  } | 
|         |   2960 ++ | 
|         |   2961 ++  std::string Song::music_directory = ""; | 
|         |   2962 ++ | 
|         |   2963 ++  void Song::set_default_dir(std::string path) | 
|         |   2964 ++  { | 
|         |   2965 ++    music_directory = path; | 
|         |   2966 ++    if(!path.empty() && path[path.length()-1]!='/') { | 
|         |   2967 ++      music_directory.append("/"); | 
|         |   2968 ++    } | 
|         |   2969 ++  } | 
|         |   2970 ++ | 
|         |   2971 ++  bool operator==(const Song& first, const Song& second) | 
|         |   2972 ++  { | 
|         |   2973 ++    return (first.song_path == second.song_path) && | 
|         |   2974 ++      (first.pl_pos == second.pl_pos) && | 
|         |   2975 ++      (first.song_length == second.song_length); | 
|         |   2976 ++  } | 
|         |   2977 ++  bool operator!=(const Song& first, const Song& second) | 
|         |   2978 ++  { | 
|         |   2979 ++    return !(first == second); | 
|         |   2980 ++  } | 
|         |   2981 ++ | 
|         |   2982 ++  // determines whether the line contains the given parameter in the | 
|         |   2983 ++  // mpd.conf fashion | 
|         |   2984 ++  bool contains_parameter(const std::string& line, const std::string& parameter) | 
|         |   2985 ++  { | 
|         |   2986 ++    if(line.empty() || line[0]=='#') return false; | 
|         |   2987 ++     | 
|         |   2988 ++    std::string::size_type pos = line.find(parameter); | 
|         |   2989 ++    if(pos == std::string::npos) return false; | 
|         |   2990 ++ | 
|         |   2991 ++    while(pos>0) { | 
|         |   2992 ++      if(!isspace(line[pos-1])) return false; | 
|         |   2993 ++      --pos; | 
|         |   2994 ++    } | 
|         |   2995 ++    return true; | 
|         |   2996 ++  } | 
|         |   2997 ++ | 
|         |   2998 ++  // returns the value of the given parameter from an mpd.config line | 
|         |   2999 ++  std::string get_value(const std::string& line, | 
|         |   3000 ++      const std::string& parameter) | 
|         |   3001 ++  { | 
|         |   3002 ++    if(!contains_parameter(line, parameter)) return ""; | 
|         |   3003 ++ | 
|         |   3004 ++    std::string::size_type start = line.find_first_of("\""); | 
|         |   3005 ++    ++start; // position of the first non-quote char | 
|         |   3006 ++    if(start == std::string::npos || start>=line.size()) return ""; | 
|         |   3007 ++ | 
|         |   3008 ++    std::string::size_type end = line.find_last_of("\""); | 
|         |   3009 ++    if(end == std::string::npos) return ""; | 
|         |   3010 ++ | 
|         |   3011 ++    std::string result = line.substr(start, end-start); | 
|         |   3012 ++    return result; | 
|         |   3013 ++  } | 
|         |   3014 ++ | 
|         |   3015 ++  config read_configuration(std::string conf_path) throw(config_err) | 
|         |   3016 ++  { | 
|         |   3017 ++    static const std::string address_param = "bind_to_address"; | 
|         |   3018 ++    static const std::string port_param = "port"; | 
|         |   3019 ++    static const std::string dir_param = "music_directory"; | 
|         |   3020 ++ | 
|         |   3021 ++    if(conf_path == "") | 
|         |   3022 ++    { | 
|         |   3023 ++      std::string user_path = getenv("HOME"); | 
|         |   3024 ++      if(user_path[user_path.size()-1] != '/') user_path.append("/"); | 
|         |   3025 ++      user_path.append(".mpdconf"); | 
|         |   3026 ++ | 
|         |   3027 ++      try { | 
|         |   3028 ++	// read the "~/.mpdconf" file | 
|         |   3029 ++	return read_configuration(user_path); | 
|         |   3030 ++      } | 
|         |   3031 ++      catch (config_err) { // "~/.mpdconf" not found | 
|         |   3032 ++	  // read the "/etc/mpd.conf" instead | 
|         |   3033 ++	  return read_configuration("/etc/mpd.conf"); | 
|         |   3034 ++      } | 
|         |   3035 ++    } | 
|         |   3036 ++    else | 
|         |   3037 ++    { | 
|         |   3038 ++      std::ifstream con_f(conf_path.c_str()); | 
|         |   3039 ++      if(!con_f) { | 
|         |   3040 ++	throw config_err("cannot open the MPD config file \"" + | 
|         |   3041 ++	    conf_path + "\""); | 
|         |   3042 ++      } | 
|         |   3043 ++ | 
|         |   3044 ++      config result; | 
|         |   3045 ++      std::string line; | 
|         |   3046 ++      while(getline(con_f, line)) { | 
|         |   3047 ++	if(contains_parameter(line, address_param)) { | 
|         |   3048 ++	  result.hostname = get_value(line, address_param); | 
|         |   3049 ++	  if(result.hostname.empty()) result.hostname = "localhost"; | 
|         |   3050 ++	} | 
|         |   3051 ++	else if(contains_parameter(line, port_param)) { | 
|         |   3052 ++	  std::stringstream s; | 
|         |   3053 ++	  s << get_value(line, port_param); | 
|         |   3054 ++	  if(!(s >> result.port)) result.port = 6600; | 
|         |   3055 ++	} | 
|         |   3056 ++	else if(contains_parameter(line, dir_param)) { | 
|         |   3057 ++	  result.music_dir = get_value(line, dir_param); | 
|         |   3058 ++	} | 
|         |   3059 ++      } | 
|         |   3060 ++      con_f.close(); | 
|         |   3061 ++      if(result.music_dir.empty()) { | 
|         |   3062 ++	throw config_err("infalid format of the MPD config file \"" +  | 
|         |   3063 ++	    conf_path + "\""); | 
|         |   3064 ++      } | 
|         |   3065 ++ | 
|         |   3066 ++      return result; | 
|         |   3067 ++    } | 
|         |   3068 ++  } | 
|         |   3069 ++ | 
|         |   3070 ++   | 
|         |   3071 ++  bool Server::connect(const std::string& hostname, int port) | 
|         |   3072 ++    throw(connection_err) | 
|         |   3073 ++  { | 
|         |   3074 ++    if(connected()) disconnect(); | 
|         |   3075 ++ | 
|         |   3076 ++    try { | 
|         |   3077 ++      connection = mpd_newConnection(hostname.c_str(), port, 10); | 
|         |   3078 ++      if(mpd_error()) throw connection_err(connection->errorStr); | 
|         |   3079 ++    } | 
|         |   3080 ++    catch(connection_err) { | 
|         |   3081 ++      disconnect(); | 
|         |   3082 ++      throw; | 
|         |   3083 ++    } | 
|         |   3084 ++     | 
|         |   3085 ++    if(connected()) { | 
|         |   3086 ++    } | 
|         |   3087 ++    return connected(); | 
|         |   3088 ++  } | 
|         |   3089 ++ | 
|         |   3090 ++  void Server::disconnect() | 
|         |   3091 ++  { | 
|         |   3092 ++    if(connection!=nullptr) { | 
|         |   3093 ++      mpd_closeConnection(connection); | 
|         |   3094 ++    } | 
|         |   3095 ++    connection = nullptr; | 
|         |   3096 ++  } | 
|         |   3097 ++ | 
|         |   3098 ++  bool Server::ack_error() const throw(connection_err) | 
|         |   3099 ++  { | 
|         |   3100 ++    if(!connected()) throw connection_err(); | 
|         |   3101 ++    return connection->error == MPD_ERROR_ACK; | 
|         |   3102 ++  } | 
|         |   3103 ++  // determines whether the MPD is in error state which is not the ACK error | 
|         |   3104 ++  bool Server::mpd_error() const throw(connection_err) | 
|         |   3105 ++  { | 
|         |   3106 ++    if(!connected()) throw connection_err(); | 
|         |   3107 ++    return connection->error!=0 && !ack_error(); | 
|         |   3108 ++  } | 
|         |   3109 ++ | 
|         |   3110 ++  // changes the mpd internal status to the playback_status type | 
|         |   3111 ++  playback_status resolve_state(int mpd_state) | 
|         |   3112 ++  { | 
|         |   3113 ++    switch(mpd_state) | 
|         |   3114 ++    { | 
|         |   3115 ++      case MPD_STATUS_STATE_PLAY: | 
|         |   3116 ++	return playing; | 
|         |   3117 ++      case MPD_STATUS_STATE_STOP: | 
|         |   3118 ++	return stopped; | 
|         |   3119 ++      case MPD_STATUS_STATE_PAUSE: | 
|         |   3120 ++	return paused; | 
|         |   3121 ++      default: | 
|         |   3122 ++	return playing; | 
|         |   3123 ++    } | 
|         |   3124 ++  } | 
|         |   3125 ++ | 
|         |   3126 ++  void Server::refresh() throw(connection_err) | 
|         |   3127 ++  { | 
|         |   3128 ++    if(!connected()) throw connection_err(); | 
|         |   3129 ++    try { | 
|         |   3130 ++       | 
|         |   3131 ++// the mess below is here because otherwise the results in nasty problems | 
|         |   3132 ++// when MPD connection times out | 
|         |   3133 ++//TODO prolly doesn't have to be everywhere, though. Weed it out | 
|         |   3134 ++if(mpd_error()) throw connection_err(connection->errorStr); | 
|         |   3135 ++      mpd_sendCommandListOkBegin(connection); | 
|         |   3136 ++if(mpd_error()) throw connection_err(connection->errorStr); | 
|         |   3137 ++      mpd_sendStatusCommand(connection); | 
|         |   3138 ++if(mpd_error()) throw connection_err(connection->errorStr); | 
|         |   3139 ++      mpd_sendCurrentSongCommand(connection); | 
|         |   3140 ++if(mpd_error()) throw connection_err(connection->errorStr); | 
|         |   3141 ++      mpd_sendCommandListEnd(connection); | 
|         |   3142 ++if(mpd_error()) throw connection_err(connection->errorStr); | 
|         |   3143 ++ | 
|         |   3144 ++      mpd_Status * status = mpd_getStatus(connection); | 
|         |   3145 ++      if(status!=nullptr) { | 
|         |   3146 ++ | 
|         |   3147 ++      pl_length = status->playlistLength; | 
|         |   3148 ++      pl_version = status->playlist; | 
|         |   3149 ++      pb_status = resolve_state(status->state); | 
|         |   3150 ++      current_song.set_elapsed(status->elapsedTime); | 
|         |   3151 ++      random = status->random; | 
|         |   3152 ++ | 
|         |   3153 ++      mpd_freeStatus(status); | 
|         |   3154 ++      } | 
|         |   3155 ++ | 
|         |   3156 ++      if(mpd_error()) throw connection_err(connection->errorStr); | 
|         |   3157 ++ | 
|         |   3158 ++      mpd_nextListOkCommand(connection); | 
|         |   3159 ++      mpd_InfoEntity *entity; | 
|         |   3160 ++      while((entity = mpd_getNextInfoEntity(connection))) { | 
|         |   3161 ++	mpd_Song *song = entity->info.song; | 
|         |   3162 ++ | 
|         |   3163 ++	if(entity->type!=MPD_INFO_ENTITY_TYPE_SONG) { | 
|         |   3164 ++	  mpd_freeInfoEntity(entity); | 
|         |   3165 ++	  continue; | 
|         |   3166 ++	} | 
|         |   3167 ++	 | 
|         |   3168 ++	current_song.set_path(song->file); | 
|         |   3169 ++	current_song.set_pos(song->pos); | 
|         |   3170 ++	current_song.set_length(song->time); | 
|         |   3171 ++	mpd_freeInfoEntity(entity); | 
|         |   3172 ++      } | 
|         |   3173 ++      if(mpd_error()) throw connection_err(connection->errorStr); | 
|         |   3174 ++ | 
|         |   3175 ++      mpd_finishCommand(connection); | 
|         |   3176 ++      if(mpd_error()) throw connection_err(connection->errorStr); | 
|         |   3177 ++    } | 
|         |   3178 ++    catch(connection_err) { | 
|         |   3179 ++      disconnect(); | 
|         |   3180 ++      throw; | 
|         |   3181 ++    } | 
|         |   3182 ++  } | 
|         |   3183 ++ | 
|         |   3184 ++  Song Server::get_song_info(int pl_pos) | 
|         |   3185 ++    throw(connection_err, position_err)    | 
|         |   3186 ++  { | 
|         |   3187 ++    if(!connected()) throw connection_err(); | 
|         |   3188 ++    if(pl_pos < 0 || pl_pos >= get_playlist_length()) { | 
|         |   3189 ++      throw position_err(pl_pos, get_playlist_length()); | 
|         |   3190 ++    } | 
|         |   3191 ++ | 
|         |   3192 ++    Song result; | 
|         |   3193 ++    try { | 
|         |   3194 ++      mpd_sendPlaylistInfoCommand(connection, pl_pos); | 
|         |   3195 ++      if(mpd_error()) throw connection_err(connection->errorStr); | 
|         |   3196 ++ | 
|         |   3197 ++      mpd_InfoEntity *entity; | 
|         |   3198 ++      while((entity = mpd_getNextInfoEntity(connection))) | 
|         |   3199 ++      { | 
|         |   3200 ++	mpd_Song *song = entity->info.song; | 
|         |   3201 ++ | 
|         |   3202 ++	if(entity->type!=MPD_INFO_ENTITY_TYPE_SONG) | 
|         |   3203 ++	{ | 
|         |   3204 ++	  mpd_freeInfoEntity(entity); | 
|         |   3205 ++	  continue; | 
|         |   3206 ++	} | 
|         |   3207 ++	 | 
|         |   3208 ++	result = Song(song->file,song->pos,song->time); | 
|         |   3209 ++ | 
|         |   3210 ++	mpd_freeInfoEntity(entity); | 
|         |   3211 ++      } | 
|         |   3212 ++      if(mpd_error()) throw connection_err(connection->errorStr); | 
|         |   3213 ++ | 
|         |   3214 ++      mpd_finishCommand(connection); | 
|         |   3215 ++      if(mpd_error()) throw connection_err(connection->errorStr); | 
|         |   3216 ++      // shouldn't happen, but just in case | 
|         |   3217 ++      if(ack_error())  { | 
|         |   3218 ++	refresh(); | 
|         |   3219 ++	throw position_err(pl_pos, get_playlist_length()); | 
|         |   3220 ++      } | 
|         |   3221 ++    } | 
|         |   3222 ++    catch(connection_err) | 
|         |   3223 ++    { | 
|         |   3224 ++      disconnect(); | 
|         |   3225 ++      throw; | 
|         |   3226 ++    } | 
|         |   3227 ++ | 
|         |   3228 ++    return result; | 
|         |   3229 ++  } | 
|         |   3230 ++ | 
|         |   3231 ++  void Server::play_song(int pl_pos) throw(connection_err, position_err) | 
|         |   3232 ++  { | 
|         |   3233 ++    if(!connected()) throw connection_err(); | 
|         |   3234 ++    if(pl_pos < 0 || pl_pos >= pl_length) { | 
|         |   3235 ++      throw position_err(pl_pos, get_playlist_length()); | 
|         |   3236 ++    } | 
|         |   3237 ++ | 
|         |   3238 ++    try { | 
|         |   3239 ++      mpd_sendPlayCommand(connection, pl_pos); | 
|         |   3240 ++      mpd_finishCommand(connection); | 
|         |   3241 ++      if(mpd_error()) throw connection_err(connection->errorStr); | 
|         |   3242 ++      if(ack_error()) throw position_err(pl_pos, get_playlist_length()); | 
|         |   3243 ++    } | 
|         |   3244 ++    catch(connection_err) { | 
|         |   3245 ++      disconnect(); | 
|         |   3246 ++      throw; | 
|         |   3247 ++    } | 
|         |   3248 ++  } | 
|         |   3249 ++  // end of SERVER section | 
|         |   3250 ++ | 
|         |   3251 ++ | 
|         |   3252 ++  // Player class | 
|         |   3253 ++  Player::Player(): previous_status(stopped), current_status(stopped), | 
|         |   3254 ++  previous_song_pos(Song::invalid_pos), current_song_pos(Song::invalid_pos), | 
|         |   3255 ++  null_song() | 
|         |   3256 ++  { | 
|         |   3257 ++  } | 
|         |   3258 ++ | 
|         |   3259 ++  bool Player::connect() throw(config_err, connection_err) | 
|         |   3260 ++  { | 
|         |   3261 ++    config conf = read_configuration(); | 
|         |   3262 ++    Song::set_default_dir(conf.music_dir); | 
|         |   3263 ++    return mpd.connect(conf.hostname, conf.port); | 
|         |   3264 ++  } | 
|         |   3265 ++ | 
|         |   3266 ++  void Player::disconnect() | 
|         |   3267 ++  { | 
|         |   3268 ++    mpd.disconnect(); | 
|         |   3269 ++  } | 
|         |   3270 ++ | 
|         |   3271 ++  void Player::refresh() | 
|         |   3272 ++  { | 
|         |   3273 ++    mpd.refresh(); | 
|         |   3274 ++ | 
|         |   3275 ++    playlist__changed = pl_ver != mpd.get_playlist_version(); | 
|         |   3276 ++    if(playlist__changed) { | 
|         |   3277 ++      pl_ver = mpd.get_playlist_version(); | 
|         |   3278 ++ | 
|         |   3279 ++      // update the internal playlist | 
|         |   3280 ++      playlist.clear(); | 
|         |   3281 ++      playlist.reserve(mpd.get_playlist_length()); | 
|         |   3282 ++      for(int i = 0; i<mpd.get_playlist_length(); i++) { | 
|         |   3283 ++	playlist.push_back(mpd.get_song_info(i)); | 
|         |   3284 ++      } | 
|         |   3285 ++    } | 
|         |   3286 ++ | 
|         |   3287 ++    song__changed = mpd.get_current_song() != song(current); | 
|         |   3288 ++    if(song__changed) { | 
|         |   3289 ++      previous_song_pos = current_song_pos; | 
|         |   3290 ++      current_song_pos = mpd.get_current_song().pos(); | 
|         |   3291 ++    } | 
|         |   3292 ++    else if(!playlist.empty() && current_song_pos != Song::invalid_pos) { | 
|         |   3293 ++      playlist[current_song_pos].set_elapsed(mpd.get_current_song(). | 
|         |   3294 ++	  elapsed()); | 
|         |   3295 ++    } | 
|         |   3296 ++ | 
|         |   3297 ++    status__changed = current_status != mpd.get_playback_status(); | 
|         |   3298 ++    if(status__changed) { | 
|         |   3299 ++      previous_status = current_status; | 
|         |   3300 ++      current_status = mpd.get_playback_status(); | 
|         |   3301 ++    } | 
|         |   3302 ++  } | 
|         |   3303 ++ | 
|         |   3304 ++  const Song& Player::song(recent value) const | 
|         |   3305 ++  { | 
|         |   3306 ++    if(playlist.empty()) return null_song; | 
|         |   3307 ++ | 
|         |   3308 ++    switch(value) { | 
|         |   3309 ++      case previous: | 
|         |   3310 ++	return previous_song_pos == Song::invalid_pos ? | 
|         |   3311 ++	  null_song : song(previous_song_pos); | 
|         |   3312 ++ | 
|         |   3313 ++      case current: | 
|         |   3314 ++      default: | 
|         |   3315 ++	return current_song_pos == Song::invalid_pos ? | 
|         |   3316 ++	  null_song : song(current_song_pos); | 
|         |   3317 ++    } | 
|         |   3318 ++  } | 
|         |   3319 ++  const Song& Player::song(int position) const throw(position_err) | 
|         |   3320 ++  { | 
|         |   3321 ++    try { | 
|         |   3322 ++      return playlist.at(position); | 
|         |   3323 ++    } | 
|         |   3324 ++    catch (...) { | 
|         |   3325 ++      throw position_err(position, playlist.size()); | 
|         |   3326 ++    } | 
|         |   3327 ++  } | 
|         |   3328 ++ | 
|         |   3329 ++  playback_status Player::status(recent value) const | 
|         |   3330 ++  { | 
|         |   3331 ++    switch (value) { | 
|         |   3332 ++      case previous: return previous_status; | 
|         |   3333 ++      case current: | 
|         |   3334 ++      default: return current_status; | 
|         |   3335 ++    } | 
|         |   3336 ++  } | 
|         |   3337 ++ | 
|         |   3338 ++  void Player::play_song(int pl_pos) | 
|         |   3339 ++  { | 
|         |   3340 ++    mpd.play_song(pl_pos); | 
|         |   3341 ++  } | 
|         |   3342 ++  // end of Player class | 
|         |   3343 ++ | 
|         |   3344 ++ | 
|         |   3345 ++} // namespace end | 
|         |   3346 ++ | 
|         |   3347 ++ | 
|         |   3348 +diff -r 171db9560cb5 clients/mpd/mpdinterface.h | 
|         |   3349 +--- /dev/null	Thu Jan 01 00:00:00 1970 +0000 | 
|         |   3350 ++++ b/clients/mpd/mpdinterface.h	Mon May 19 00:21:51 2008 -0400 | 
|         |   3351 +@@ -0,0 +1,209 @@ | 
|         |   3352 ++#ifndef MPDINTERFACE_H | 
|         |   3353 ++#define MPDINTERFACE_H | 
|         |   3354 ++ | 
|         |   3355 ++#include "libmpdclient.h" | 
|         |   3356 ++#include <string> | 
|         |   3357 ++#include <vector> | 
|         |   3358 ++ | 
|         |   3359 ++namespace mpd_interface | 
|         |   3360 ++{ | 
|         |   3361 ++const int nullptr = 0;  | 
|         |   3362 ++ | 
|         |   3363 ++/* list of thrown exceptions */ | 
|         |   3364 ++ | 
|         |   3365 ++  // generic exception that can be thrown by MPD | 
|         |   3366 ++  class mpd_err | 
|         |   3367 ++  { | 
|         |   3368 ++  protected: | 
|         |   3369 ++    std::string msg; | 
|         |   3370 ++  public: | 
|         |   3371 ++    mpd_err(const std::string& message = "unknown error"): msg(message) { } | 
|         |   3372 ++    std::string message() const { return msg; } | 
|         |   3373 ++  }; | 
|         |   3374 ++ | 
|         |   3375 ++  // thrown when for whatever reason the connection cannot be maintained | 
|         |   3376 ++  // the Player is always set to the disconnected state when this is thrown | 
|         |   3377 ++  class connection_err: public mpd_err | 
|         |   3378 ++  { | 
|         |   3379 ++  public: | 
|         |   3380 ++    connection_err(const std::string& message = "not connected"): | 
|         |   3381 ++      mpd_err(message) { } | 
|         |   3382 ++  }; | 
|         |   3383 ++ | 
|         |   3384 ++  class config_err: public mpd_err | 
|         |   3385 ++  { | 
|         |   3386 ++  public: | 
|         |   3387 ++    config_err(const std::string& message = "") : mpd_err(message) { } | 
|         |   3388 ++  }; | 
|         |   3389 ++ | 
|         |   3390 ++  // thrown when trying to access element out of the playlist range | 
|         |   3391 ++  // contains information about the length of the playlist | 
|         |   3392 ++  // and the invalid position | 
|         |   3393 ++  class position_err: public mpd_err | 
|         |   3394 ++  { | 
|         |   3395 ++    int invalid_position; | 
|         |   3396 ++    int pl_length; | 
|         |   3397 ++  public: | 
|         |   3398 ++    position_err(int position, int playlist_length); | 
|         |   3399 ++    int pos() const { return invalid_position; } | 
|         |   3400 ++    int playlist_length() const {return pl_length; } | 
|         |   3401 ++  }; | 
|         |   3402 ++/* end of the exception list */ | 
|         |   3403 ++ | 
|         |   3404 ++ | 
|         |   3405 ++  // information about the configuration of MPD | 
|         |   3406 ++  // it's the relevant info read from the mpd.config file | 
|         |   3407 ++  struct config | 
|         |   3408 ++  { | 
|         |   3409 ++    std::string hostname; | 
|         |   3410 ++    int port; | 
|         |   3411 ++    std::string music_dir; | 
|         |   3412 ++  }; | 
|         |   3413 ++ | 
|         |   3414 ++  // attempts to read the configuration file | 
|         |   3415 ++  // if no path is specified following actions are taken: | 
|         |   3416 ++  // first, the ~/.mpdconf file is looked for | 
|         |   3417 ++  // then, the /etc/mpd.conf file is tried. | 
|         |   3418 ++  config read_configuration(std::string conf_path="") throw(config_err); | 
|         |   3419 ++ | 
|         |   3420 ++ | 
|         |   3421 ++  // Represents one song in playlist. | 
|         |   3422 ++  // Note that when one song is twice in a playlist (their positions differ) | 
|         |   3423 ++  // they are two different songs from this class' point of view. | 
|         |   3424 ++  class Song | 
|         |   3425 ++  { | 
|         |   3426 ++    static std::string music_directory; // directory in which the songs are | 
|         |   3427 ++ | 
|         |   3428 ++    std::string song_path;  | 
|         |   3429 ++    int pl_pos;  | 
|         |   3430 ++    int song_length; // time - in seconds | 
|         |   3431 ++    int song_elapsed; // time - in seconds | 
|         |   3432 ++ | 
|         |   3433 ++  public: | 
|         |   3434 ++    static const int invalid_pos = MPD_SONG_NO_NUM; | 
|         |   3435 ++    static const int invalid_time = MPD_SONG_NO_TIME; | 
|         |   3436 ++ | 
|         |   3437 ++    static void set_default_dir(std::string path); // set the music directory | 
|         |   3438 ++ | 
|         |   3439 ++    Song(std::string path = "", int position = invalid_pos, | 
|         |   3440 ++	int length = invalid_time, int elapsed = invalid_time): | 
|         |   3441 ++      song_path(music_directory+path), pl_pos(position), | 
|         |   3442 ++      song_length(length), song_elapsed(elapsed) { } | 
|         |   3443 ++ | 
|         |   3444 ++    friend bool operator==(const Song& first, const Song& second); | 
|         |   3445 ++    friend bool operator!=(const Song& first, const Song& second); | 
|         |   3446 ++ | 
|         |   3447 ++    std::string path() const { return song_path; } | 
|         |   3448 ++    void set_path(std::string path) { song_path = music_directory+path; } | 
|         |   3449 ++    int pos() const { return pl_pos; } | 
|         |   3450 ++    void set_pos(int position) { pl_pos = position; } | 
|         |   3451 ++    int length() const { return song_length; } | 
|         |   3452 ++    void set_length(int length) { song_length = length; } | 
|         |   3453 ++    int elapsed() const {return song_elapsed; } | 
|         |   3454 ++    void set_elapsed(int elapsed) { song_elapsed = elapsed; } | 
|         |   3455 ++  }; | 
|         |   3456 ++ | 
|         |   3457 ++ | 
|         |   3458 ++ | 
|         |   3459 ++  // the status of the playback - whether it's stopped, paused | 
|         |   3460 ++  // or is playing a song right now | 
|         |   3461 ++  enum playback_status {playing, stopped, paused} ; | 
|         |   3462 ++ | 
|         |   3463 ++  // represents the communication with the MPD server | 
|         |   3464 ++  // It's a confortable wrapper around the libmpdclient library | 
|         |   3465 ++  // When its refresh() method is called it gets all information from server | 
|         |   3466 ++  // and stores them so as not to flood the MPD with commands | 
|         |   3467 ++  class Server | 
|         |   3468 ++  { | 
|         |   3469 ++  public: | 
|         |   3470 ++    Server(): connection(nullptr) {}; | 
|         |   3471 ++    ~Server() { disconnect(); } | 
|         |   3472 ++ | 
|         |   3473 ++    bool connect(const std::string& hostname="localhost", int port = 6600) | 
|         |   3474 ++      throw(connection_err); | 
|         |   3475 ++    void disconnect(); | 
|         |   3476 ++    bool connected() const {return connection!=nullptr; } | 
|         |   3477 ++ | 
|         |   3478 ++ | 
|         |   3479 ++    void refresh() throw(connection_err); // the Server asks MPD for new values | 
|         |   3480 ++    int get_playlist_length() const { return pl_length; } | 
|         |   3481 ++    long long get_playlist_version() { return pl_version; } | 
|         |   3482 ++    playback_status get_playback_status() { return pb_status; } | 
|         |   3483 ++    bool get_random() const {return random; } | 
|         |   3484 ++ | 
|         |   3485 ++    Song get_song_info(int pl_pos) throw(connection_err,position_err); | 
|         |   3486 ++    Song get_current_song() const { return current_song; } | 
|         |   3487 ++ | 
|         |   3488 ++    // plays the song at the specified position | 
|         |   3489 ++    void play_song(int pl_pos) throw(connection_err, position_err); | 
|         |   3490 ++ | 
|         |   3491 ++  private: | 
|         |   3492 ++    Server& operator=(const Server&); | 
|         |   3493 ++    Server(const Server&); | 
|         |   3494 ++ | 
|         |   3495 ++    mpd_Connection *connection; | 
|         |   3496 ++    int pl_length; | 
|         |   3497 ++    long long pl_version; | 
|         |   3498 ++    playback_status pb_status; | 
|         |   3499 ++    Song current_song; | 
|         |   3500 ++    bool random; | 
|         |   3501 ++ | 
|         |   3502 ++ | 
|         |   3503 ++    // determines whether the actual MPD error state is the ACK error | 
|         |   3504 ++    bool ack_error() const throw(connection_err); | 
|         |   3505 ++ | 
|         |   3506 ++    // determines whether the MPD is in error state which is not the ACK error | 
|         |   3507 ++    bool mpd_error() const throw(connection_err); | 
|         |   3508 ++  }; | 
|         |   3509 ++ | 
|         |   3510 ++ | 
|         |   3511 ++ | 
|         |   3512 ++  enum recent {previous, current}; | 
|         |   3513 ++ | 
|         |   3514 ++  class Player | 
|         |   3515 ++  { | 
|         |   3516 ++  public: | 
|         |   3517 ++ | 
|         |   3518 ++    Player(); | 
|         |   3519 ++ | 
|         |   3520 ++    bool connect() throw(config_err, connection_err); | 
|         |   3521 ++    void disconnect(); | 
|         |   3522 ++    bool connected() const { return mpd.connected(); } | 
|         |   3523 ++ | 
|         |   3524 ++    void refresh(); | 
|         |   3525 ++     | 
|         |   3526 ++    bool song_changed() {return song__changed; } | 
|         |   3527 ++    bool playlist_changed() { return playlist__changed; } | 
|         |   3528 ++    bool status_changed() { return status__changed; } | 
|         |   3529 ++ | 
|         |   3530 ++    // gets the current or the previously played song | 
|         |   3531 ++    // song(current) returns currently played song | 
|         |   3532 ++    // song(previous) returns the previously played song | 
|         |   3533 ++    const Song& song(recent) const; | 
|         |   3534 ++    const Song& song(int position) const throw(position_err); | 
|         |   3535 ++    int playlist_length() const { return mpd.get_playlist_length(); } | 
|         |   3536 ++    bool radnom() const { return mpd.get_random(); } | 
|         |   3537 ++    void play_song(int pl_pos); | 
|         |   3538 ++ | 
|         |   3539 ++    // gets the current or the previous playback status | 
|         |   3540 ++    playback_status status(recent) const; | 
|         |   3541 ++ | 
|         |   3542 ++ | 
|         |   3543 ++  private: | 
|         |   3544 ++    Player& operator=(const Player&); | 
|         |   3545 ++    Player(const Player&); | 
|         |   3546 ++ | 
|         |   3547 ++    Server mpd; | 
|         |   3548 ++    long long pl_ver; | 
|         |   3549 ++    playback_status previous_status, current_status; | 
|         |   3550 ++    int previous_song_pos, current_song_pos; | 
|         |   3551 ++    const Song null_song; | 
|         |   3552 ++    std::vector<Song> playlist; | 
|         |   3553 ++ | 
|         |   3554 ++    bool song__changed, playlist__changed, status__changed; | 
|         |   3555 ++  }; | 
|         |   3556 ++ | 
|         |   3557 ++} | 
|         |   3558 ++ | 
|         |   3559 ++#endif | 
|         |   3560 ++ | 
|         |   3561 +diff -r 171db9560cb5 clients/mpd/rules.mk | 
|         |   3562 +--- /dev/null	Thu Jan 01 00:00:00 1970 +0000 | 
|         |   3563 ++++ b/clients/mpd/rules.mk	Mon May 19 00:21:51 2008 -0400 | 
|         |   3564 +@@ -0,0 +1,16 @@ | 
|         |   3565 ++MDPCPPFLAGS= $(GLIB2CPPFLAGS) | 
|         |   3566 ++MPDLDFLAGS= $(GLIB2LDFLAGS) | 
|         |   3567 ++MPDCOMMON= mpdinterface.o libmpdclient.o clientstubbase.o libimmscore.a libmodel.a | 
|         |   3568 ++ | 
|         |   3569 ++ | 
|         |   3570 ++immsmpd: immsmpd.o $(MPDCOMMON) | 
|         |   3571 ++immsmpd: $(call objects,../clients/mpd) | 
|         |   3572 ++immsmpd-CPPFLAGS=$(MDPCPPFLAGS) | 
|         |   3573 ++immsmpd-LIBS=$(MPDLDFLAGS) | 
|         |   3574 ++ | 
|         |   3575 ++ | 
|         |   3576 ++MPDDESTDIR=/usr/bin | 
|         |   3577 ++ | 
|         |   3578 ++immsmpd_install: immsmpd | 
|         |   3579 ++	${INSTALL} -D $^ $(MPDDESTDIR) | 
|         |   3580 ++ | 
|         |   3581 +diff -r 171db9560cb5 configure.ac | 
|         |   3582 +--- a/configure.ac	Mon May 19 00:16:56 2008 -0400 | 
|         |   3583 ++++ b/configure.ac	Mon May 19 00:21:51 2008 -0400 | 
|         |   3584 +@@ -260,6 +260,13 @@ | 
|         |   3585 + saved_libs="$LIBS" | 
|         |   3586 +  | 
|         |   3587 + PLUGINS="" | 
|         |   3588 ++ | 
|         |   3589 ++AC_CHECK_PROG(with_mdp, mpd --help, "yes", "no") | 
|         |   3590 ++if test "$with_mpd" != "no"; then | 
|         |   3591 ++    AC_APPEND(PLUGINS, immsmpd) | 
|         |   3592 ++fi | 
|         |   3593 ++ | 
|         |   3594 ++ | 
|         |   3595 + AC_CHECK_PROG(with_xmms, xmms-config, "yes", "no") | 
|         |   3596 + if test "$with_xmms" != "no"; then | 
|         |   3597 +     CPPFLAGS=`xmms-config --cflags` | 
|         |   3598 +diff -r 171db9560cb5 vars.mk.in | 
|         |   3599 +--- a/vars.mk.in	Mon May 19 00:16:56 2008 -0400 | 
|         |   3600 ++++ b/vars.mk.in	Mon May 19 00:21:51 2008 -0400 | 
|         |   3601 +@@ -10,7 +10,7 @@ | 
|         |   3602 + bindir = @bindir@ | 
|         |   3603 + datadir = @datadir@ | 
|         |   3604 +  | 
|         |   3605 +-VPATH = ../immscore:../analyzer:../model:../autotag:../immsremote:../utils:../clients:../immsd:../data:../clients/xmms:../clients/bmp:../clients/audacious | 
|         |   3606 ++VPATH = ../immscore:../analyzer:../model:../autotag:../immsremote:../utils:../clients:../immsd:../data:../clients/xmms:../clients/bmp:../clients/audacious:../clients/mpd | 
|         |   3607 + ARFLAGS = rs | 
|         |   3608 +  | 
|         |   3609 + SHELL = bash | 
|         |   3610 diff -r fb5042644071 debian/patches/04mpd-client-config-init.dpatch | 
|         |   3611 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000 | 
|         |   3612 +++ b/debian/patches/04mpd-client-config-init.dpatch	Mon May 19 01:12:49 2008 -0400 | 
|         |   3613 @@ -0,0 +1,20 @@ | 
|         |   3614 +#! /bin/sh /usr/share/dpatch/dpatch-run | 
|         |   3615 +## mpd-client-config-init.dpatch by Fabien Niñoles <fabien@tzone.org> | 
|         |   3616 +## | 
|         |   3617 +## All lines beginning with `## DP:' are a description of the patch. | 
|         |   3618 +## DP: Initialize default configuration. | 
|         |   3619 + | 
|         |   3620 +@DPATCH@ | 
|         |   3621 + | 
|         |   3622 +diff -r 019508c19157 clients/mpd/mpdinterface.cc | 
|         |   3623 +--- a/clients/mpd/mpdinterface.cc	Mon May 19 00:21:51 2008 -0400 | 
|         |   3624 ++++ b/clients/mpd/mpdinterface.cc	Mon May 19 00:51:06 2008 -0400 | 
|         |   3625 +@@ -98,7 +98,7 @@ | 
|         |   3626 + 	    conf_path + "\""); | 
|         |   3627 +       } | 
|         |   3628 +  | 
|         |   3629 +-      config result; | 
|         |   3630 ++      config result = { "localhost", 6600, "" }; | 
|         |   3631 +       std::string line; | 
|         |   3632 +       while(getline(con_f, line)) { | 
|         |   3633 + 	if(contains_parameter(line, address_param)) { |