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_STATE            "state"
@@ -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..7a7b665 100644
--- a/src/idle.c
+++ b/src/idle.c
@@ -23,6 +23,8 @@
 
 #include "idle.h"
 #include "main_notify.h"
+#include "utils.h"
+#include "glib.h"
 
 #include <assert.h>
 #include <pthread.h>
@@ -30,13 +32,67 @@
 static unsigned idle_flags;
 static pthread_mutex_t idle_mutex = PTHREAD_MUTEX_INITIALIZER;
 
+static const char *const idle_names[] = {
+	"database",
+	"stored_playlist",
+	"playlist",
+	"player",
+	"mixer",
+	"output",
+	"options",
+	"elapsed",
+        NULL
+};
+
+static char * idle_values[] = {
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+        NULL
+};
+
+const char*const*
+idle_get_names(void)
+{
+        return idle_names;
+}
+
+char**
+idle_get_values(void)
+{
+        return idle_values;
+}
+
 void
 idle_add(unsigned flags)
 {
+        idle_add_value(flags, NULL);
+}
+
+void
+idle_add_value(unsigned flags,
+               const char *value)
+{
+	unsigned i;
 	assert(flags != 0);
 
 	pthread_mutex_lock(&idle_mutex);
 	idle_flags |= flags;
+	for (i = 0; idle_names[i]; ++i) {
+		if (flags & (1 << i)) {
+			g_free (idle_values[i]);
+                        if (value)
+        			idle_values[i] = xstrdup(value);
+                        else
+                                idle_values[i] = NULL;
+                }
+	}
+
 	pthread_mutex_unlock(&idle_mutex);
 
 	wakeup_main_task();
diff --git a/src/idle.h b/src/idle.h
index 69756b1..206dc2b 100644
--- a/src/idle.h
+++ b/src/idle.h
@@ -46,9 +46,24 @@ enum {
 
 	/** options have changed: crossfade, random, repeat, ... */
 	IDLE_OPTIONS = 0x40,
+
+	/** elapsed time has changed */
+	IDLE_ELAPSED = 0x80,
 };
 
 /**
+ * Get idle names
+ */
+const char*const*
+idle_get_names(void);
+
+/**
+ * Get idle values
+ */
+char**
+idle_get_values(void);
+
+/**
  * Adds idle flag (with bitwise "or") and queues notifications to all
  * clients.
  */
@@ -56,6 +71,13 @@ void
 idle_add(unsigned flags);
 
 /**
+ * Adds idle flag and queues notifications to all
+ * clients. This will notify the new value.
+ */
+void
+idle_add_value(unsigned flag, const char *value);
+
+/**
  * Atomically reads and resets the global idle flags value.
  */
 unsigned
diff --git a/src/player_control.c b/src/player_control.c
index 1d5c76a..00b7bea 100644
--- a/src/player_control.c
+++ b/src/player_control.c
@@ -25,6 +25,7 @@
 #include "pcm_utils.h"
 #include "os_compat.h"
 #include "main_notify.h"
+#include <glib.h>
 
 struct player_control pc;
 
@@ -116,6 +117,22 @@ int getPlayerElapsedTime(void)
 	return (int)(pc.elapsed_time + 0.5);
 }
 
+void setPlayerElapsedTime(float elapsedTime)
+{
+        int before, after;
+        char *val;
+
+        before = getPlayerElapsedTime();
+	pc.elapsed_time = elapsedTime;
+        after = getPlayerElapsedTime();
+
+        if (before != after) {
+                val = g_strdup_printf ("%d", after);
+                idle_add_value(IDLE_ELAPSED, val);
+                g_free (val);
+        }
+}
+
 unsigned long getPlayerBitRate(void)
 {
 	return pc.bit_rate;
diff --git a/src/player_control.h b/src/player_control.h
index 2ae1fb6..68507b0 100644
--- a/src/player_control.h
+++ b/src/player_control.h
@@ -102,6 +102,8 @@ int getPlayerTotalTime(void);
 
 int getPlayerElapsedTime(void);
 
+void setPlayerElapsedTime(float elapsedTime);
+
 unsigned long getPlayerBitRate(void);
 
 enum player_state getPlayerState(void);
diff --git a/src/player_thread.c b/src/player_thread.c
index ac060dd..43fb55e 100644
--- a/src/player_thread.c
+++ b/src/player_thread.c
@@ -134,7 +134,7 @@ static bool player_seek_decoder(struct player *player)
 
 	ret = dc_seek(&pc.notify, where);
 	if (ret)
-		pc.elapsed_time = where;
+                setPlayerElapsedTime(where);
 
 	player_command_finished();
 
@@ -221,7 +221,7 @@ static int
 play_chunk(struct song *song, struct music_chunk *chunk,
 	   const struct audio_format *format, double sizeToTime)
 {
-	pc.elapsed_time = chunk->times;
+        setPlayerElapsedTime(chunk->times);
 	pc.bit_rate = chunk->bit_rate;
 
 	if (chunk->tag != NULL) {
@@ -284,7 +284,8 @@ static void do_play(void)
 		return;
 	}
 
-	pc.elapsed_time = 0;
+        setPlayerElapsedTime(0);
+
 	pc.state = PLAYER_STATE_PLAY;
 	player_command_finished();
 
diff --git a/src/volume.c b/src/volume.c
index 9fd33f0..cbb060f 100644
--- a/src/volume.c
+++ b/src/volume.c
@@ -496,22 +496,29 @@ static int changeSoftwareVolume(int change, int rel)
 
 int changeVolumeLevel(int change, int rel)
 {
-	idle_add(IDLE_MIXER);
+        char *val;
+        int ret;
 
 	switch (volume_mixerType) {
 #ifdef HAVE_ALSA
 	case VOLUME_MIXER_TYPE_ALSA:
-		return changeAlsaVolumeLevel(change, rel);
+		ret = changeAlsaVolumeLevel(change, rel);
 #endif
 #ifdef HAVE_OSS
 	case VOLUME_MIXER_TYPE_OSS:
-		return changeOssVolumeLevel(change, rel);
+		ret = changeOssVolumeLevel(change, rel);
 #endif
 	case VOLUME_MIXER_TYPE_SOFTWARE:
-		return changeSoftwareVolume(change, rel);
+		ret = changeSoftwareVolume(change, rel);
 	default:
-		return 0;
+		ret = 0;
 	}
+        
+        val = g_strdup_printf ("%d", getVolumeLevel());
+	idle_add_value(IDLE_MIXER, val);
+        g_free (val);
+
+        return ret;
 }
 
 void read_sw_volume_state(FILE *fp)
-------------------------------------------------------------------------
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=100&url=/
_______________________________________________
Musicpd-dev-team mailing list
Musicpd-dev-team@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/musicpd-dev-team

Reply via email to