Re: [Musicpd-dev-team] [PATCH] idle command enhancement

2008-11-23 Thread Marc Pavot
Hi,


 Thanks, I have merged your patch.  Please write a patch which adds
 documentation for that feature to doc/protocol.xml.

Done.


I also attach a patch to libmpdclient that can be used as a basis for the
discussion on 'idle' implementation on client side.

Main points about this implementation:
- It is designed to be integrated into client main loop. This solution has
the advantage to avoid multithreading problems and to be well integrated
into client applications. The disadvantage is that we have to implement
something specific for each kind of loop. My patch comes with a generic
callback mechanism to allow different implementations and with an
implementation for GLib main loop.
- The client application starts by initializing the main loop integration
(mpd_glibInit)
- It can then start or stop the idle mode (mpd_startIdle and mpd_stopIdle).
In mpd_startIdle, the client specifies a callback to be called if a
notification is received.
- If the client application tries to send a command while it is in idle
mode, 'noidle' is sent and the callback is called (if needed) before the
real command.

Hope this helps.
Marc
diff --git a/doc/protocol.xml b/doc/protocol.xml
index 49f6d97..304b492 100644
--- a/doc/protocol.xml
+++ b/doc/protocol.xml
@@ -118,6 +118,7 @@
   term
 cmdsynopsis
   commandidle/command
+  arg choice=opt rep=repeatreplaceableSUBSYSTEMS/replaceable/arg
 /cmdsynopsis
   /term
   listitem
@@ -184,6 +185,11 @@
   commandidle/command mode and print results
   immediately; might be empty at this time.
 /para
+para
+  If the optional varnameSUBSYSTEMS/varname argument is used,
+  MPD will only send notifications when something changed in
+  one of the specified subsytems.
+/para
   /listitem
 /varlistentry
 varlistentry id=command_status
diff --git a/libmpdclient.c b/libmpdclient.c
index 1c19dd8..32ca719 100644
--- a/libmpdclient.c
+++ b/libmpdclient.c
@@ -81,6 +81,17 @@
 #  define WSACleanup()  do { /* nothing */ } while (0)
 #endif
 
+static const char *const idle_names[] = {
+	database,
+	stored_playlist,
+	playlist,
+	player,
+	mixer,
+	output,
+	options,
+	NULL
+};
+
 #ifdef WIN32
 static int winsock_dll_error(mpd_Connection *connection)
 {
@@ -367,6 +378,13 @@ mpd_Connection * mpd_newConnection(const char * host, int port, float timeout) {
 	connection-doneListOk = 0;
 	connection-returnElement = NULL;
 	connection-request = NULL;
+#ifdef MPD_GLIB
+	connection-source_id = 0;
+#endif
+	connection-idle = 0;
+	connection-startIdle = NULL;
+	connection-stopIdle = NULL;
+	connection-notify_cb = NULL;
 
 	if (winsock_dll_error(connection))
 		return connection;
@@ -446,6 +464,9 @@ static void mpd_executeCommand(mpd_Connection * connection, char * command) {
 	char * commandPtr = command;
 	int commandLen = strlen(command);
 
+	if (connection-idle)
+		mpd_stopIdle(connection);
+
 	if(!connection-doneProcessing  !connection-commandList) {
 		strcpy(connection-errorStr,not done processing current command);
 		connection-error = 1;
@@ -1965,3 +1986,100 @@ void mpd_sendPlaylistDeleteCommand(mpd_Connection *connection,
 	free(sPlaylist);
 	free(string);
 }
+
+static void mpd_readChanges(mpd_Connection *connection)
+{
+	unsigned i;
+	unsigned flags = 0;
+	mpd_ReturnElement *re;
+
+	if (!connection-returnElement) mpd_getNextReturnElement(connection);
+
+	while (connection-returnElement) {
+		re = connection-returnElement;
+		if (re-name !strncmp (re-name, changed, strlen (changed))) {
+			for (i = 0; idle_names[i]; ++i) {
+if (!strcmp (re-value, idle_names[i])) {
+	flags |= (1  i);
+}
+			}
+		}
+		mpd_getNextReturnElement(connection);
+	}
+
+	/* Notifiy application */
+	if (connection-notify_cb  flags)
+		connection-notify_cb (connection, flags);
+}
+
+void mpd_startIdle(mpd_Connection *connection, mpd_NotificationCb notify_cb)
+{
+	if (connection-startIdle)
+		connection-startIdle(connection);
+
+	mpd_executeCommand(connection, idle\n);
+	connection-idle = 1;
+	connection-notify_cb = notify_cb;
+}
+
+void mpd_stopIdle(mpd_Connection *connection)
+{
+	if (connection-stopIdle)
+		connection-stopIdle(connection);
+
+	connection-idle = 0;
+	connection-notify_cb = NULL;
+	connection-doneProcessing = 1;
+	mpd_executeCommand(connection, noidle\n);
+	mpd_readChanges(connection);
+}
+
+#ifdef MPD_GLIB
+static gboolean mpd_glibReadCb (GIOChannel *iochan, GIOCondition cond, gpointer data)
+{
+	mpd_Connection *connection = data;
+
+	if (!connection-idle) {
+		connection-source_id = 0;
+		return FALSE;
+	}
+
+	if ((cond  G_IO_IN)) {
+	 connection-idle = 0;
+	 if (connection-source_id) {
+		 g_source_remove (connection-source_id);
+		 connection-source_id = 0;
+	 }
+	 mpd_readChanges(connection);
+	}
+
+	return TRUE;
+}
+
+static void mpd_glibStartIdle(mpd_Connection *connection)
+{

[Musicpd-dev-team] MPD 0.14~beta1

2008-11-23 Thread Avuton Olrich
Greetings,

The MPD community is proud to announce the release MPD 0.14~beta1. The
changes for this release (from alpha 3) include the usual stability
fixes; support for non-unicode and non-latin1 file names; idle command
subscriptions; stream seeking optimizations; if changed, state saves
every 5 minutes; ffmpeg tag support and more. See the shortlog below
or the full git changelog in the usual places. As usual thanks to all
the developers from the community who made this release possible.
Everyone please test and file bugs at our bug tracker:
http://musicpd.org/mantis

Thanks and enjoy!



Avuton Olrich (1):
  MPD version 0.14~beta1

Konstantin Sobolev (3):
  path: fix g_convert() argument order
  mapper: use the utf8_to_fs_charset() result
  update: pass UTF-8 path to skip_symlink()

Laszlo Ashin (6):
  aac: don't try to free static buffer
  aac: fix compiler warnings on amd64
  wavpack: redo using audio_format_frame_size()
  aac: get rid of gcc warnings
  utils: introduce assert_static()
  wavpack: use assert_static()

Marc Pavot (2):
  command: allow clients to subscribe to specific idle events
  command: added documentation for idle subscriptions

Max Kellermann (31):
  decoder: check length==0 in decoder_read()
  aac: detect whether to pass uint32_t* to NeAACDecInit2()
  ffmpeg: fixed AVSEEK_SIZE
  input_stream: size==-1 means unknown size
  music_pipe: narrowed assertion on chunk index
  decoder: pass the correct buffer length to pcm_convert()
  doc: converted doc/COMMANDS to DocBook
  doc: fix Repeat typo in protocol.xml
  doc: process protocol.xml with xmlto
  input_curl: always set eof=true on CURLMSG_DONE
  curl: don't check running_handles for EOF
  input_curl: don't fail when seek to EOF is requested
  ogg: check the ov_read() return value before the vorbis_info evaluation
  ogg: moved the errorStr variable into the error handler
  decoder: ignore the SEEK command during startup
  input_curl: don't do temporary calculations with input_stream.offset
  input_curl: moved code to consume_buffer()
  input_curl: try to seek by fast-forwarding the buffer
  state_file: save state_file every 5 minutes
  log: print the log_domain
  aac: use GLib instead of utils.h/log.h
  audiofile: use GLib instead of log.h
  ffmpeg: use GLib instead of log.h
  flac, oggflac: use GLib instead of utils.h/log.h
  decoder: ignore decoder_data() calls with length==0
  audio_format: added audio_format_valid()
  decoder: check audio_format_valid() in all decoders
  command: format strerror() with %s
  autogen.sh: removed libtoolize
  update: fixed shadow warning on basename
  Makefile.am: include protocol.xml in source tarball

Monika Brinkert (3):
  doc: improved XML decorations
  doc: rephrase descriptions
  doc: merged protocol documentation from the wiki

Viliam Mateicka (3):
  audiofile: fixed misplaced if
  ffmpeg: read tags from AVFormatContext
  AUTHORS: added Viliam Mateicka

-- 
avuton
--
 I've got a fever. And the only prescription is more cowbell. --
Christopher Walken

-
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK  win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100url=/
___
Musicpd-dev-team mailing list
Musicpd-dev-team@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/musicpd-dev-team


[Musicpd-dev-team] [RFC-for-post-0.14] [PATCH] Support RVA2 Tags

2008-11-23 Thread Avuton Olrich
Hello,

This is the first in a series of patches I hope to do to update from
patches in from our bug tracker. I hope as well to get comments, and
the community gives these concepts and patches the big ACK or NACK. I
will try to keep these patches up to date until they're either
accepted or given the NACK, at which time I'll pop it off my guilt and
close the bug. Most of these patches I have neutral feelings about
acceptance. I may attempt to provide new better versions with
criticism though, please keep in mind that I am not a developer.

This patch works for me with the test mp3 at the bug link below,
though I don't notice or know the difference with before or after.

For more information about this particular patch, please see:
http://musicpd.org/mantis/view.php?id=562

Feel free to pull it from my git tree:
Using a mpd-mk tree as a reference to minimize bandwidth:
git clone --reference mpd-mk/ git://repo.or.cz/mpd-mk/avuton.git

or just plain old:
git clone git://repo.or.cz/mpd-mk/avuton.git

From: Avuton Olrich [EMAIL PROTECTED]
Date: Sun, 23 Nov 2008 23:37:28 + (-0800)
Subject: Add RVA2 tag support to MPD
X-Git-Url: 
http://repo.or.cz/w/mpd-mk/avuton.git?a=commitdiff_plain;h=ff66792aad6ba1ef888b0381577c93a27c8b76a7

Add RVA2 tag support to MPD

This patch adds RVA2 (relative volume adjustment) tag
support to mpd, as a fallback if no replaygain tags are
found. The code is almost directly from madplay (GPL).

RVA2 tags are generated for example by the normalize utility.

Originally by: Pauli Virtanen [EMAIL PROTECTED]  Wed, 22 Feb 2006 23:13:25 
+0200
Updated by: Avuton Olrich [EMAIL PROTECTED]
---

diff --git a/src/decoder/mp3_plugin.c b/src/decoder/mp3_plugin.c
index 69cc7d0..ebf1669 100644
--- a/src/decoder/mp3_plugin.c
+++ b/src/decoder/mp3_plugin.c
@@ -204,6 +204,95 @@ mp3_fill_buffer(struct mp3_data *data)
 }

 #ifdef HAVE_ID3TAG
+/* Parse mp3 RVA2 frame. Shamelessly stolen from madplay. */
+static int parse_rva2(struct id3_tag * tag, struct replay_gain_info *
replay_gain_info)
+{
+   struct id3_frame const * frame;
+
+   id3_latin1_t const *id;
+   id3_byte_t const *data;
+   id3_length_t length;
+   int found;
+
+   enum {
+   CHANNEL_OTHER = 0x00,
+   CHANNEL_MASTER_VOLUME = 0x01,
+   CHANNEL_FRONT_RIGHT   = 0x02,
+   CHANNEL_FRONT_LEFT= 0x03,
+   CHANNEL_BACK_RIGHT= 0x04,
+   CHANNEL_BACK_LEFT = 0x05,
+   CHANNEL_FRONT_CENTRE  = 0x06,
+   CHANNEL_BACK_CENTRE   = 0x07,
+   CHANNEL_SUBWOOFER = 0x08
+   };
+
+   found = 0;
+
+   /* relative volume adjustment information */
+
+   frame = id3_tag_findframe(tag, RVA2, 0);
+   if (!frame) return 0;
+
+   id   = id3_field_getlatin1(id3_frame_field(frame, 0));
+   data = id3_field_getbinarydata(id3_frame_field(frame, 1),
+   length);
+
+   if (!id || !data) return 0;
+
+   /*
+* The 'identification' string is used to identify the
+* situation and/or device where this adjustment should apply.
+* The following is then repeated for every channel
+*
+*   Type of channel $xx
+*   Volume adjustment   $xx xx
+*   Bits representing peak  $xx
+*   Peak volume $xx (xx ...)
+*/
+
+   while (length = 4) {
+   unsigned int peak_bytes;
+
+   peak_bytes = (data[3] + 7) / 8;
+   if (4 + peak_bytes  length)
+   break;
+
+   if (data[0] == CHANNEL_MASTER_VOLUME) {
+   signed int voladj_fixed;
+   double voladj_float;
+
+   /*
+* The volume adjustment is encoded as a fixed
+* point decibel value, 16 bit signed integer
+* representing (adjustment*512), giving +/- 64
+* dB with a precision of 0.001953125 dB.
+*/
+
+   voladj_fixed  = (data[1]  8) | (data[2]  0);
+   voladj_fixed |= -(voladj_fixed  0x8000);
+
+   voladj_float  = (double) voladj_fixed / 512;
+
+   replay_gain_info-tuples[REPLAY_GAIN_TRACK].peak = 
voladj_float;
+   replay_gain_info-tuples[REPLAY_GAIN_ALBUM].peak = 
voladj_float;
+
+   DEBUG(parseRVA2: Relative Volume 
+   %+.1f dB adjustment (%s)\n,
+   voladj_float, id);
+
+   found = 1;
+   break;
+   }
+
+   data   += 4 + peak_bytes;
+   length -= 4 + peak_bytes;
+   }
+
+   return found;
+}
+#endif
+
+#ifdef HAVE_ID3TAG
 static struct replay_gain_info *
 parse_id3_replay_gain_info(struct id3_tag *tag)
 {
@@ -245,6 +334,11 @@