Re: [Musicpd-dev-team] Empty fields

2009-03-06 Thread Marc Pavot
Hi,

This behavior has been introduced in MPD 0.14: When MPD returns an empty
value, it doesn't mean that the tag is empty but that the tag is unknown
(not set in the music file). As a client developer I find this behavior very
useful for example if you want to build a tree like this:
The Doors
L.A. Woman
Strange Days
Unknown Album

It's also useful if some of your music files are badly tagged.

Marc

2009/3/6 Jerome Quelin jque...@gmail.com

 On 09/03/06 10:30 +0100, Max Kellermann wrote:
  On 2009/03/06 10:24, Jerome Quelin jque...@gmail.com wrote:
   definitely sure: i had to update the test-suite of the perl modules
   audio::mpd and poe::component::client::mpd to take this into account.
  
   i'm not saying it's right or wrong, but it has definitely changed
 
  Ok, so let's talk about whether it's right or wrong.  Does it make any
  sense to have an empty string in a tag value?  Should MPD discard the
  whole tag item in this case?
 
  My opinion: kill empty values.

 that's also my opinion, but then i can understand people wanting to have
 empty values. indeed, they would not be able to say whether all songs
 have an album, or if some don't have an album.

 in the end, i don't really care. just pick a behaviour and stick with
 it. i would hate to have to update the test suite every mpd version! :-)

 jérôme
 --
 jque...@gmail.com


 --
 Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco,
 CA
 -OSBC tackles the biggest issue in open source: Open Sourcing the
 Enterprise
 -Strategies to boost innovation and cut costs with open source
 participation
 -Receive a $600 discount off the registration fee with the source code:
 SFAD
 http://p.sf.net/sfu/XcvMzF8H
 ___
 Musicpd-dev-team mailing list
 Musicpd-dev-team@lists.sourceforge.net
 https://lists.sourceforge.net/lists/listinfo/musicpd-dev-team

--
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H___
Musicpd-dev-team mailing list
Musicpd-dev-team@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/musicpd-dev-team


Re: [Musicpd-dev-team] The libmpdclient v2.0 project

2008-11-30 Thread Marc Pavot
11 other patches available on my repository:
  Add unit tests to libmpclient
  Fix glib include
  Change include guards
  Convert MPD_INFO_ENTITY_ to enum
  Fix currentsong test
  Cosmetic
  Improve calls to mpd_executeCommand
  Small performance improvements
  Split libmpdclient: entity
  Bug fix
  Split connection into connection  ipc

What do you mean by ''libmpdclient should be stateless regarding its caller
program'? Do you plan to remove the getNext* commands and to make the send*
commands return data? In this case, how do you want to implement
CommandList'?

Marc
-
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


Re: [Musicpd-dev-team] The libmpdclient v2.0 project

2008-11-27 Thread Marc Pavot

 - I saw that your idle patch introduced inconsistent indentation
  (e.g. mpd_glibStartIdle); please configure your editor to indent
  with tabs.

I don't want to start a 'religion war' on this point but don't you think it
would be better to use spaces everywhere instead of tabs?
This discussion has already been done thousands of times by other people so
I won't say more but you can find a lot of projects using spaces instead of
tabs because tabs are always a nightmare for projects involving different
developers and for developers contributing to several projects. (spaces
indent makes you sure that the files will appear identically in any text
editor).



 - A commit should include a brief one-line description, followed by an
  empty line, and a longer description following.  This way, stuff
  like git shortlog works properly.  Don't write another description
  in the email - a well-documented patch doesn't need further
  explanation.

Ok. It's my first time using git but I will remember it.


- set local includes first, to test if the include file has
  specified its own dependencies properly, i.e. include idle.h
  before stdio.h and string.h in idle.c.  In return_element.c you
  did this very well: return_element.h before str_pool.h
  (str_pool.h was already checked by str_pool.c).

Ok.
-
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


Re: [Musicpd-dev-team] The libmpdclient v2.0 project

2008-11-27 Thread Marc Pavot
Hi,

There are some commits on my repository that you may find interesting to
integrate.

Marc Pavot:
  Use tabs instead of spaces
  Split libmpdclient: status
  Set local includes first for idle.c
  Split libmpdclient: stats
  Merge branch 'master' of git://git.musicpd.org/cirrus/libmpdclient
  Merge branch 'master' of git://git.musicpd.org/cirrus/libmpdclient
  Remove useless malloc/free
  changed typedef mpd_Status to struct
  changed typedef mpd_Stats and mpd_SearchStats to struct
  New disconnect event
  W32 support of idle mode

Marc
-
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


Re: [Musicpd-dev-team] The libmpdclient v2.0 project

2008-11-26 Thread Marc Pavot
 - portability - even Windows?  There's no good C99 compiler on
  Windows..  mingw32?

Just a quick remark about this point: I compile Ario and libmpdclient on
windows with mingw32 and it works fine. (I distribute .exe files for Ario).
-
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


Re: [Musicpd-dev-team] The libmpdclient v2.0 project

2008-11-26 Thread Marc Pavot
 Some of you already promised to help me with that.  From now on, I
 will accept patches (git pull requests preferred).  Please keep your
 git repository rebased on mine.


I have created a git repository to help you on this project:
http://repo.or.cz/w/libmpdclient/marc.git

It is based on your repository and I have done one commit to continue the
split of libmpdclient.
It creates three new files: connection, idle and return_element. The
separation is not perfect (for example some structures and methods in
connection will have to become private in the future) but it's a first
brick.

Marc
-
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


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

2008-11-24 Thread Marc Pavot
I attach a new patch that integrates some fixes and ideas proposed by Qball.
This patch replaces the previous one.

I have added the support of idle command in Ario (
http://ario-player.sourceforge.net/) and I have found something that looks
like a bug in MPD:
- When a song is finished, the next one is played and the 'player' event is
emitted.
- When the client sends the status command just after this event, the songid
is the new one but the 'elapsed' time is not reseted to 0.

This is problem because I have implemented the solution using a timer on
client side to compute the elapsed time but with this bug the elapsed time
continues to be incremented on a new song.

I propose a patch to MPD to fix this issue but I don't really know this part
of MPD so it may not be the best solution.

Marc


2008/11/23 Marc Pavot [EMAIL PROTECTED]

 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/libmpdclient.c b/libmpdclient.c
index 1c19dd8..2071af6 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,105 @@ 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, connection-userdata);
+}
+
+void mpd_startIdle(mpd_Connection *connection, mpd_NotificationCb notify_cb, void *userdata)
+{
+if (connection-idle)
+return;
+
+	if (connection-startIdle)
+		connection-startIdle(connection);
+
+	mpd_executeCommand(connection, idle\n);
+	connection-idle = 1;
+	connection-notify_cb = notify_cb;
+	connection-userdata = userdata;
+}
+
+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

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)
+{

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

2008-11-21 Thread Marc Pavot
Hi,

 - It adds the possibility to choose which notification you want to
 receive.
  The idle command can now take no argument (same behavior as before) or
  several arguments.
  For example if a client uses command 'idle mixer elapsed', it will only
  receive notifications when the volume changed or when the elapsed time
  changed.

 Good idea.

 Someone proposed that idle 10 would make MPD respond after 10
 seconds, disregarding whether an event has really happened, and
 probably returns with an empty event set.

 Can you make a separate patch of that?  And maybe implement the
 timeout thing if you have time...

I attach a separate patch. What would be the advantage of this timeout
thing? I don't see in which use case it can be useful.


  - And last, with this patch MPD doesn't leave idle mode anymore when a
  notification has been done. It means that idle mode will continue until
  'noidle' command is sent. I think this will easy client implementation of
  idle command and reduce a lot the amount of useless traffic. Please tell
 me
  if you see a major drawback with this behavior.

 No, I think the disadvantages of this solution will prevail here.
 Events aren't that often (unless we really implement your 'elapsed'
 event), and after most events, the client has to query the server
 anyway.

Could you list these disadvantages? In fact I don't see any



  flags = ~0;

Thanks, it's much better like this ;-)

Marc
diff --git a/src/client.c b/src/client.c
index ee98464..fd55b31 100644
--- a/src/client.c
+++ b/src/client.c
@@ -91,6 +91,9 @@ struct client {
 	/** idle flags pending on this client, to be sent as soon as
 	the client enters idle */
 	unsigned idle_flags;
+
+	/** idle flags that the client wants to receive */
+	unsigned idle_subscriptions;
 };
 
 static LIST_HEAD(clients);
@@ -766,16 +769,6 @@ mpd_fprintf void client_printf(struct client *client, const char *fmt, ...)
 	va_end(args);
 }
 
-static const char *const idle_names[] = {
-	database,
-	stored_playlist,
-	playlist,
-	player,
-	mixer,
-	output,
-	options,
-};
-
 /**
  * Send idle response to this client.
  */
@@ -783,6 +776,7 @@ static void
 client_idle_notify(struct client *client)
 {
 	unsigned flags, i;
+	const char *const* idle_names;
 
 	assert(client-idle_waiting);
 	assert(client-idle_flags != 0);
@@ -791,10 +785,9 @@ client_idle_notify(struct client *client)
 	client-idle_flags = 0;
 	client-idle_waiting = false;
 
-	for (i = 0; i  sizeof(idle_names) / sizeof(idle_names[0]); ++i) {
-		assert(idle_names[i] != NULL);
-
-		if (flags  (1  i))
+	idle_names = idle_get_names();
+	for (i = 0; idle_names[i]; ++i) {
+		if (flags  (1  i)  client-idle_subscriptions)
 			client_printf(client, changed: %s\n,
   idle_names[i]);
 	}
@@ -814,20 +807,22 @@ void client_manager_idle_add(unsigned flags)
 			continue;
 
 		client-idle_flags |= flags;
-		if (client-idle_waiting) {
+		if (client-idle_waiting
+		 (client-idle_flags  client-idle_subscriptions)) {
 			client_idle_notify(client);
 			client_write_output(client);
 		}
 	}
 }
 
-bool client_idle_wait(struct client *client)
+bool client_idle_wait(struct client *client, unsigned flags)
 {
 	assert(!client-idle_waiting);
 
 	client-idle_waiting = true;
+	client-idle_subscriptions = flags;
 
-	if (client-idle_flags != 0) {
+	if (client-idle_flags  client-idle_subscriptions) {
 		client_idle_notify(client);
 		return true;
 	} else
diff --git a/src/client.h b/src/client.h
index e6661e2..9c70318 100644
--- a/src/client.h
+++ b/src/client.h
@@ -78,6 +78,6 @@ void client_manager_idle_add(unsigned flags);
  * sent immediately and true is returned.  If no, it puts the
  * client into waiting mode and returns false.
  */
-bool client_idle_wait(struct client *client);
+bool client_idle_wait(struct client *client, unsigned flags);
 
 #endif
diff --git a/src/command.c b/src/command.c
index dc71f1d..6a9489d 100644
--- a/src/command.c
+++ b/src/command.c
@@ -39,6 +39,7 @@
 #include tag_print.h
 #include path.h
 #include os_compat.h
+#include idle.h
 
 #define COMMAND_STATUS_VOLUME   volume
 #define COMMAND_STATUS_STATEstate
@@ -1253,8 +1254,28 @@ static enum command_return
 handle_idle(struct client *client,
 	mpd_unused int argc, mpd_unused char *argv[])
 {
+unsigned flags = 0, j;
+int i;
+const char *const* idle_names;
+
+idle_names = idle_get_names();
+for (i = 1; i  argc; ++i) {
+if (!argv[i])
+continue;
+
+for (j = 0; idle_names[j]; ++j) {
+if (!strcasecmp(argv[i], idle_names[j])) {
+flags |= (1  j);
+}
+}
+}
+
+/* No argument means that the client wants to receive everything */
+if (flags == 0)
+flags = ~0;
+
 	/* enable idle mode on this client */
-	client_idle_wait(client);
+	client_idle_wait(client, flags);
 
 	/* return value 

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

2008-11-16 Thread Marc Pavot
Hi,

This new patch replaces the previous one. It adds the possibility to send
the new value in a notification.

For example, if the volume changes to 85,  MPD sends 'changed: mixer 85'.

Marc

2008/11/16 Marc Pavot [EMAIL PROTECTED]

 Hi,

 I propose you a patch that improves different aspects of idle command:
 - It adds a new 'elapsed' event to notify clients when the elapsed time has
 changed (in absolute value in second)
 - It adds the possibility to choose which notification you want to receive.
 The idle command can now take no argument (same behavior as before) or
 several arguments.
 For example if a client uses command 'idle mixer elapsed', it will only
 receive notifications when the volume changed or when the elapsed time
 changed.
 - And last, with this patch MPD doesn't leave idle mode anymore when a
 notification has been done. It means that idle mode will continue until
 'noidle' command is sent. I think this will easy client implementation of
 idle command and reduce a lot the amount of useless traffic. Please tell me
 if you see a major drawback with this behavior.

 Marc

diff --git a/src/client.c b/src/client.c
index ee98464..34610eb 100644
--- a/src/client.c
+++ b/src/client.c
@@ -91,6 +91,9 @@ struct client {
 	/** idle flags pending on this client, to be sent as soon as
 	the client enters idle */
 	unsigned idle_flags;
+
+	/** idle flags that the client wants to receive */
+	unsigned idle_subscriptions;
 };
 
 static LIST_HEAD(clients);
@@ -766,16 +769,6 @@ mpd_fprintf void client_printf(struct client *client, const char *fmt, ...)
 	va_end(args);
 }
 
-static const char *const idle_names[] = {
-	database,
-	stored_playlist,
-	playlist,
-	player,
-	mixer,
-	output,
-	options,
-};
-
 /**
  * Send idle response to this client.
  */
@@ -783,20 +776,26 @@ static void
 client_idle_notify(struct client *client)
 {
 	unsigned flags, i;
+const char *const* idle_names;
+char ** idle_values;
 
 	assert(client-idle_waiting);
 	assert(client-idle_flags != 0);
 
 	flags = client-idle_flags;
 	client-idle_flags = 0;
-	client-idle_waiting = false;
-
-	for (i = 0; i  sizeof(idle_names) / sizeof(idle_names[0]); ++i) {
-		assert(idle_names[i] != NULL);
 
-		if (flags  (1  i))
-			client_printf(client, changed: %s\n,
-  idle_names[i]);
+idle_names = idle_get_names();
+idle_values = idle_get_values();
+	for (i = 0; idle_names[i]; ++i) {
+		if (flags  (1  i)  client-idle_subscriptions) {
+if (idle_values[i])
+			client_printf(client, changed: %s %s\n,
+  idle_names[i], idle_values[i]);
+else
+			client_printf(client, changed: %s\n,
+  idle_names[i]);
+}
 	}
 
 	client_puts(client, OK\n);
@@ -821,11 +820,13 @@ void client_manager_idle_add(unsigned flags)
 	}
 }
 
-bool client_idle_wait(struct client *client)
+bool client_idle_wait(struct client *client,
+  unsigned flags)
 {
 	assert(!client-idle_waiting);
 
 	client-idle_waiting = true;
+	client-idle_subscriptions = flags;
 
 	if (client-idle_flags != 0) {
 		client_idle_notify(client);
diff --git a/src/client.h b/src/client.h
index e6661e2..9c70318 100644
--- a/src/client.h
+++ b/src/client.h
@@ -78,6 +78,6 @@ void client_manager_idle_add(unsigned flags);
  * sent immediately and true is returned.  If no, it puts the
  * client into waiting mode and returns false.
  */
-bool client_idle_wait(struct client *client);
+bool client_idle_wait(struct client *client, unsigned flags);
 
 #endif
diff --git a/src/command.c b/src/command.c
index dc71f1d..7a7cdfb 100644
--- a/src/command.c
+++ b/src/command.c
@@ -39,6 +39,7 @@
 #include tag_print.h
 #include path.h
 #include os_compat.h
+#include idle.h
 
 #define COMMAND_STATUS_VOLUME   volume
 #define COMMAND_STATUS_STATEstate
@@ -1253,8 +1254,31 @@ static enum command_return
 handle_idle(struct client *client,
 	mpd_unused int argc, mpd_unused char *argv[])
 {
+unsigned flags = 0, j;
+int i;
+const char *const* idle_names;
+
+idle_names = idle_get_names();
+for (i = 1; i  argc; ++i) {
+if (!argv[i])
+continue;
+
+for (j = 0; idle_names[j]; ++j) {
+if (!strcasecmp(argv[i], idle_names[j])) {
+flags |= (1  j);
+}
+}
+}
+
+/* No argument means that the client wants to receive everything */
+if (flags == 0) {
+for (j = 0; idle_names[j]; ++j) {
+flags |= (1  j);
+}
+}
+
 	/* enable idle mode on this client */
-	client_idle_wait(client);
+	client_idle_wait(client, flags);
 
 	/* return value is 1 so the caller won't print OK */
 	return 1;
@@ -1280,7 +1304,7 @@ static const struct command commands[] = {
 	{ disableoutput, PERMISSION_ADMIN, 1, 1

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

2008-11-15 Thread Marc Pavot
Hi,

I propose you a patch that improves different aspects of idle command:
- It adds a new 'elapsed' event to notify clients when the elapsed time has
changed (in absolute value in second)
- It adds the possibility to choose which notification you want to receive.
The idle command can now take no argument (same behavior as before) or
several arguments.
For example if a client uses command 'idle mixer elapsed', it will only
receive notifications when the volume changed or when the elapsed time
changed.
- And last, with this patch MPD doesn't leave idle mode anymore when a
notification has been done. It means that idle mode will continue until
'noidle' command is sent. I think this will easy client implementation of
idle command and reduce a lot the amount of useless traffic. Please tell me
if you see a major drawback with this behavior.

Marc
diff --git a/src/client.c b/src/client.c
index ee98464..224dfff 100644
--- a/src/client.c
+++ b/src/client.c
@@ -91,6 +91,9 @@ struct client {
 	/** idle flags pending on this client, to be sent as soon as
 	the client enters idle */
 	unsigned idle_flags;
+
+	/** idle flags that the client wants to receive */
+	unsigned idle_subscriptions;
 };
 
 static LIST_HEAD(clients);
@@ -766,16 +769,6 @@ mpd_fprintf void client_printf(struct client *client, const char *fmt, ...)
 	va_end(args);
 }
 
-static const char *const idle_names[] = {
-	database,
-	stored_playlist,
-	playlist,
-	player,
-	mixer,
-	output,
-	options,
-};
-
 /**
  * Send idle response to this client.
  */
@@ -783,23 +776,21 @@ static void
 client_idle_notify(struct client *client)
 {
 	unsigned flags, i;
+const char *const* idle_names;
 
 	assert(client-idle_waiting);
 	assert(client-idle_flags != 0);
 
 	flags = client-idle_flags;
 	client-idle_flags = 0;
-	client-idle_waiting = false;
-
-	for (i = 0; i  sizeof(idle_names) / sizeof(idle_names[0]); ++i) {
-		assert(idle_names[i] != NULL);
 
-		if (flags  (1  i))
+idle_names = idle_get_names();
+	for (i = 0; idle_names[i]; ++i) {
+		if (flags  (1  i)  client-idle_subscriptions)
 			client_printf(client, changed: %s\n,
   idle_names[i]);
 	}
 
-	client_puts(client, OK\n);
 	client-lastTime = time(NULL);
 }
 
@@ -821,11 +812,13 @@ void client_manager_idle_add(unsigned flags)
 	}
 }
 
-bool client_idle_wait(struct client *client)
+bool client_idle_wait(struct client *client,
+  unsigned flags)
 {
 	assert(!client-idle_waiting);
 
 	client-idle_waiting = true;
+	client-idle_subscriptions = flags;
 
 	if (client-idle_flags != 0) {
 		client_idle_notify(client);
diff --git a/src/client.h b/src/client.h
index e6661e2..9c70318 100644
--- a/src/client.h
+++ b/src/client.h
@@ -78,6 +78,6 @@ void client_manager_idle_add(unsigned flags);
  * sent immediately and true is returned.  If no, it puts the
  * client into waiting mode and returns false.
  */
-bool client_idle_wait(struct client *client);
+bool client_idle_wait(struct client *client, unsigned flags);
 
 #endif
diff --git a/src/command.c b/src/command.c
index dc71f1d..7a7cdfb 100644
--- a/src/command.c
+++ b/src/command.c
@@ -39,6 +39,7 @@
 #include tag_print.h
 #include path.h
 #include os_compat.h
+#include idle.h
 
 #define COMMAND_STATUS_VOLUME   volume
 #define COMMAND_STATUS_STATEstate
@@ -1253,8 +1254,31 @@ static enum command_return
 handle_idle(struct client *client,
 	mpd_unused int argc, mpd_unused char *argv[])
 {
+unsigned flags = 0, j;
+int i;
+const char *const* idle_names;
+
+idle_names = idle_get_names();
+for (i = 1; i  argc; ++i) {
+if (!argv[i])
+continue;
+
+for (j = 0; idle_names[j]; ++j) {
+if (!strcasecmp(argv[i], idle_names[j])) {
+flags |= (1  j);
+}
+}
+}
+
+/* No argument means that the client wants to receive everything */
+if (flags == 0) {
+for (j = 0; idle_names[j]; ++j) {
+flags |= (1  j);
+}
+}
+
 	/* enable idle mode on this client */
-	client_idle_wait(client);
+	client_idle_wait(client, flags);
 
 	/* return value is 1 so the caller won't print OK */
 	return 1;
@@ -1280,7 +1304,7 @@ static const struct command commands[] = {
 	{ disableoutput, PERMISSION_ADMIN, 1, 1, handle_disableoutput },
 	{ enableoutput, PERMISSION_ADMIN, 1, 1, handle_enableoutput },
 	{ find, PERMISSION_READ, 2, -1, handle_find },
-	{ idle, PERMISSION_READ, 0, 0, handle_idle },
+	{ idle, PERMISSION_READ, 0, -1, handle_idle },
 	{ kill, PERMISSION_ADMIN, -1, -1, handle_kill },
 	{ list, PERMISSION_READ, 1, -1, handle_list },
 	{ listall, PERMISSION_READ, 0, 1, handle_listall },
diff --git a/src/idle.c b/src/idle.c
index c779d0a..477a676 100644
--- a/src/idle.c
+++ b/src/idle.c
@@ -30,6 +30,24 @@
 static unsigned idle_flags;
 static pthread_mutex_t 

Re: [Musicpd-dev-team] idle command

2008-11-14 Thread Marc Pavot
The two sockets solution is easy to implement and interesting but as Max
sayed it soncumes precious ressources.
We may have another solution (used for example by XMMS2):
- Each query has an identifier
- Each reply has the identifier corresponding to the query
- Each subscription to an event notification also has an identifier
- Each notification has the identifier corresponding to the subscription

This means some important changes in MPD protocol but it has several
advantages:
- It uses only one socket
- It is easy to implement on client side (you just have to keep a list of
identifier to understand what you receive)
- It enables you to implement synchronous and asynchronous calls to MPD on
client side which is not an easy thing with current protocol.
- It will be easy to implement a publish-subscribe solution for event
notifications

Marc

2008/11/14 Max Kellermann [EMAIL PROTECTED]

 On 2008/11/14 11:15, Roeland Douma [EMAIL PROTECTED] wrote:
  Other than that I think an important event is missing. The event that
 notifies
  the user of the place the song is. Since If I start a client I want to
 know
  that. This can be very small messages. But they can be very use full.

 You mean which song is currently being played?  That's the event
 player.  Documentation incomplete again.

  This however would be better done with publish subscribe. Since some
 clients
  might or might not be interested. With the current implementation publish
  subscribe should just be which events you would like to receive and which
 not.
  Which is ore or less the general concept of publish subscribe of course.
 
  I have an example for you. Lets say I have a mobile MPD client on my
 phone. I
  want to display the current song, the next song. And some controls. Then
 I a
  not interested in any other events.

 See my previous response to Marc in this thread:

 On 2008/11/14 09:01, Max Kellermann [EMAIL PROTECTED] wrote:
  On 2008/11/13 21:45, Marc Pavot [EMAIL PROTECTED] wrote:
   - you cannot subscribe to receive only some of the notifications
 
  Sounds like a reasonable feature request.  What about idle mixer
  options to only receive mixer and options events?  Other ideas?

 Max

 -
 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

-
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


Re: [Musicpd-dev-team] idle command

2008-11-13 Thread Marc Pavot
Hi



 Why not? The client can let the connection block until something
 happens, or it can abort idle as soon as he wishes to use the
 connection for something else.  That is simple, but powerful.

 As already proposed by someone else, a publish-subscribe protocol would be
much more appropriate because with the 'idle' approach:
- you have to send 'noidle' command each time you want to send another
command
- you have to send 'idle' again after this command
- you have to send 'idle' again each time a notification has been done
- you cannot subscribe to receive only some of the notifications



 I could really need a helping hand on libmpdclient.  Are you familiar
 with asynchronous I/O?

 I am not an expert of asynchronous I/O but it may be time to become one
:-).

Marc
-
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