Obtain afs status items directly from afs.
authorAndre Noll <maan@systemlinux.org>
Mon, 29 Jun 2009 17:34:24 +0000 (19:34 +0200)
committerAndre Noll <maan@systemlinux.org>
Mon, 29 Jun 2009 17:34:24 +0000 (19:34 +0200)
This patch changes the way how the afs status items are passed from afs to the stat
command handler. Previously, afs passed the status item string to the server process
whenever a new audio file was loaded. The server process stored the string in the mmd
shared memory area from which it was available to the client process that executed the
stat command.

This approach has the disadvantage that  the size of the string must be restricted to a
fixed number of bytes,  VERBOSE_LS_OUTPUT_SIZE, determined at compile time and
independent of the audio file.  As version 2 id3 tags and vorbis comments do not impose
an upper bound on the size of the tags a rather ugly patch was merged recently to the master
branch which truncated the size of the tags if it exceeded VERBOSE_LS_OUTPUT_SIZE.

This patch gets rid of this restriction by not storing the info string in the mmd structure. Instead,
the stat command requests the information directly from the afs process via the callback
mechanism which is also used by other afs commands.

afs.h
aft.c
command.c
vss.c

diff --git a/afs.h b/afs.h
index a58518b..269927f 100644 (file)
--- a/afs.h
+++ b/afs.h
@@ -117,15 +117,10 @@ struct ls_data {
        HASH_TYPE *hash;
 };
 
        HASH_TYPE *hash;
 };
 
-void make_empty_status_items(char *buf);
-
-/** At most that many bytes will be passed from afs to para_server. */
-#define VERBOSE_LS_OUTPUT_SIZE 4096
+int send_afs_status(int fd);
 
 /** Data about the current audio file, passed from afs to server. */
 struct audio_file_data {
 
 /** Data about the current audio file, passed from afs to server. */
 struct audio_file_data {
-       /** Same info as ls -lv -p current audio_file. */
-       char verbose_ls_output[VERBOSE_LS_OUTPUT_SIZE];
        /** The open file descriptor to the current audio file. */
        int fd;
        /** Vss needs this for streaming. */
        /** The open file descriptor to the current audio file. */
        int fd;
        /** Vss needs this for streaming. */
diff --git a/aft.c b/aft.c
index 23b36a8..7027e7f 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -24,6 +24,7 @@
 #include "portable_io.h"
 
 static struct osl_table *audio_file_table;
 #include "portable_io.h"
 
 static struct osl_table *audio_file_table;
+static char *current_status_items;
 
 /** The different sorting methods of the ls command. */
 enum ls_sorting_method {
 
 /** The different sorting methods of the ls command. */
 enum ls_sorting_method {
@@ -962,72 +963,6 @@ out:
        return ret;
 }
 
        return ret;
 }
 
-/**
- * Write a list of audio-file related status items with empty values.
- *
- * \param buf Result pointer.
- *
- * This is used by vss when currently no audio file is open.
- */
-void make_empty_status_items(char *buf)
-{
-       sprintf(buf,
-               "%s: \n" /* path */
-               "%s: \n" /* dirname */
-               "%s: \n" /* basename */
-               "%s: \n" /* score */
-               "%s: \n" /* attributes bitmap */
-               "%s: \n" /* attributes txt */
-               "%s: \n" /* hash */
-               "%s: \n" /* image id */
-               "%s: \n" /* image name */
-               "%s: \n" /* lyrics id */
-               "%s: \n" /* lyrics name */
-               "%s: \n" /* bitrate */
-               "%s: \n" /* format */
-               "%s: \n" /* frequency */
-               "%s: \n" /* channels */
-               "%s: \n" /* duration */
-               "%s: \n" /* seconds total */
-               "%s: \n" /* num played */
-               "%s: \n" /* last played */
-               "%s: \n" /* techinfo */
-               "%s: \n" /* artist */
-               "%s: \n" /* title */
-               "%s: \n" /* year */
-               "%s: \n" /* album */
-               "%s: \n" /* comment */
-               "%s: \n" /* amplification */
-               ,
-               status_item_list[SI_PATH],
-               status_item_list[SI_DIRECTORY],
-               status_item_list[SI_BASENAME],
-               status_item_list[SI_SCORE],
-               status_item_list[SI_ATTRIBUTES_BITMAP],
-               status_item_list[SI_ATTRIBUTES_TXT],
-               status_item_list[SI_HASH],
-               status_item_list[SI_IMAGE_ID],
-               status_item_list[SI_IMAGE_NAME],
-               status_item_list[SI_LYRICS_ID],
-               status_item_list[SI_LYRICS_NAME],
-               status_item_list[SI_BITRATE],
-               status_item_list[SI_FORMAT],
-               status_item_list[SI_FREQUENCY],
-               status_item_list[SI_CHANNELS],
-               status_item_list[SI_DURATION],
-               status_item_list[SI_SECONDS_TOTAL],
-               status_item_list[SI_NUM_PLAYED],
-               status_item_list[SI_LAST_PLAYED],
-               status_item_list[SI_TECHINFO],
-               status_item_list[SI_ARTIST],
-               status_item_list[SI_TITLE],
-               status_item_list[SI_YEAR],
-               status_item_list[SI_ALBUM],
-               status_item_list[SI_COMMENT],
-               status_item_list[SI_AMPLIFICATION]
-       );
-}
-
 static int make_status_items(struct audio_file_data *afd,
                struct afs_info *afsi, char *path, long score,
                HASH_TYPE *hash)
 static int make_status_items(struct audio_file_data *afd,
                struct afs_info *afsi, char *path, long score,
                HASH_TYPE *hash)
@@ -1043,19 +978,17 @@ static int make_status_items(struct audio_file_data *afd,
                .flags = LS_FLAG_FULL_PATH | LS_FLAG_ADMISSIBLE_ONLY,
                .mode = LS_MODE_VERBOSE,
        };
                .flags = LS_FLAG_FULL_PATH | LS_FLAG_ADMISSIBLE_ONLY,
                .mode = LS_MODE_VERBOSE,
        };
-       struct para_buffer pb = {.max_size = VERBOSE_LS_OUTPUT_SIZE - 1};
+       struct para_buffer pb = {.max_size = SHMMAX - 1};
        time_t current_time;
        int ret;
 
        time(&current_time);
        ret = print_list_item(&d, &opts, &pb, current_time);
        if (ret < 0)
        time_t current_time;
        int ret;
 
        time(&current_time);
        ret = print_list_item(&d, &opts, &pb, current_time);
        if (ret < 0)
-               goto out;
-       strncpy(afd->verbose_ls_output, pb.buf, VERBOSE_LS_OUTPUT_SIZE);
-       afd->verbose_ls_output[VERBOSE_LS_OUTPUT_SIZE - 1] = '\0';
-out:
-       free(pb.buf);
-       return ret;
+               return ret;
+       free(current_status_items);
+       current_status_items = pb.buf;
+       return 1;
 }
 
 /**
 }
 
 /**
@@ -2444,6 +2377,18 @@ int com_cpsi(int fd, int argc,  char * const * const argv)
        return ret;
 }
 
        return ret;
 }
 
+void afs_stat_callback(int fd, __a_unused const struct osl_object *query)
+{
+       if (current_status_items)
+               pass_buffer_as_shm(current_status_items,
+                       strlen(current_status_items), &fd);
+}
+
+int send_afs_status(int fd)
+{
+       return send_callback_request(afs_stat_callback, NULL, send_result, &fd);
+}
+
 /* TODO: optionally fix problems by removing offending rows */
 static int check_audio_file(struct osl_row *row, void *data)
 {
 /* TODO: optionally fix problems by removing offending rows */
 static int check_audio_file(struct osl_row *row, void *data)
 {
@@ -2522,6 +2467,8 @@ static void aft_close(void)
 {
        osl_close_table(audio_file_table, OSL_MARK_CLEAN);
        audio_file_table = NULL;
 {
        osl_close_table(audio_file_table, OSL_MARK_CLEAN);
        audio_file_table = NULL;
+       free(current_status_items);
+       current_status_items = NULL;
 }
 
 /**
 }
 
 /**
index 603715b..e6a16e5 100644 (file)
--- a/command.c
+++ b/command.c
@@ -128,8 +128,7 @@ static char *get_status(struct misc_meta_data *nmmd)
                "%s: %li\n" /* offset */
                "%s: %s\n" /* afs mode */
                "%s: %lu.%lu\n" /* stream start */
                "%s: %li\n" /* offset */
                "%s: %s\n" /* afs mode */
                "%s: %lu.%lu\n" /* stream start */
-               "%s: %lu.%lu\n" /* current server time */
-               "%s", /* afs status info */
+               "%s: %lu.%lu\n", /* current server time */
                status_item_list[SI_FILE_SIZE], nmmd->size / 1024,
                status_item_list[SI_MTIME], mtime,
                status_item_list[SI_STATUS], status,
                status_item_list[SI_FILE_SIZE], nmmd->size / 1024,
                status_item_list[SI_MTIME], mtime,
                status_item_list[SI_STATUS], status,
@@ -143,10 +142,7 @@ static char *get_status(struct misc_meta_data *nmmd)
                        (long unsigned)nmmd->stream_start.tv_usec,
                status_item_list[SI_CURRENT_TIME],
                        (long unsigned)current_time.tv_sec,
                        (long unsigned)nmmd->stream_start.tv_usec,
                status_item_list[SI_CURRENT_TIME],
                        (long unsigned)current_time.tv_sec,
-                       (long unsigned)current_time.tv_usec,
-
-               nmmd->afd.verbose_ls_output
-
+                       (long unsigned)current_time.tv_usec
        );
        free(flags);
        free(status);
        );
        free(flags);
        free(status);
@@ -305,6 +301,70 @@ int com_version(int fd, int argc, __a_unused char * const * argv)
        );
 }
 
        );
 }
 
+/**
+ * Write a list of audio-file related status items with empty values.
+ *
+ * This is used by vss when currently no audio file is open.
+ */
+static char *empty_status_items(void)
+{
+       return make_message(
+               "%s: \n" /* path */
+               "%s: \n" /* dirname */
+               "%s: \n" /* basename */
+               "%s: \n" /* score */
+               "%s: \n" /* attributes bitmap */
+               "%s: \n" /* attributes txt */
+               "%s: \n" /* hash */
+               "%s: \n" /* image id */
+               "%s: \n" /* image name */
+               "%s: \n" /* lyrics id */
+               "%s: \n" /* lyrics name */
+               "%s: \n" /* bitrate */
+               "%s: \n" /* format */
+               "%s: \n" /* frequency */
+               "%s: \n" /* channels */
+               "%s: \n" /* duration */
+               "%s: \n" /* seconds total */
+               "%s: \n" /* num played */
+               "%s: \n" /* last played */
+               "%s: \n" /* techinfo */
+               "%s: \n" /* artist */
+               "%s: \n" /* title */
+               "%s: \n" /* year */
+               "%s: \n" /* album */
+               "%s: \n" /* comment */
+               "%s: \n" /* amplification */
+               ,
+               status_item_list[SI_PATH],
+               status_item_list[SI_DIRECTORY],
+               status_item_list[SI_BASENAME],
+               status_item_list[SI_SCORE],
+               status_item_list[SI_ATTRIBUTES_BITMAP],
+               status_item_list[SI_ATTRIBUTES_TXT],
+               status_item_list[SI_HASH],
+               status_item_list[SI_IMAGE_ID],
+               status_item_list[SI_IMAGE_NAME],
+               status_item_list[SI_LYRICS_ID],
+               status_item_list[SI_LYRICS_NAME],
+               status_item_list[SI_BITRATE],
+               status_item_list[SI_FORMAT],
+               status_item_list[SI_FREQUENCY],
+               status_item_list[SI_CHANNELS],
+               status_item_list[SI_DURATION],
+               status_item_list[SI_SECONDS_TOTAL],
+               status_item_list[SI_NUM_PLAYED],
+               status_item_list[SI_LAST_PLAYED],
+               status_item_list[SI_TECHINFO],
+               status_item_list[SI_ARTIST],
+               status_item_list[SI_TITLE],
+               status_item_list[SI_YEAR],
+               status_item_list[SI_ALBUM],
+               status_item_list[SI_COMMENT],
+               status_item_list[SI_AMPLIFICATION]
+       );
+}
+
 /* stat */
 int com_stat(int fd, int argc, char * const * argv)
 {
 /* stat */
 int com_stat(int fd, int argc, char * const * argv)
 {
@@ -326,6 +386,15 @@ int com_stat(int fd, int argc, char * const * argv)
                free(s);
                if (ret < 0)
                        goto out;
                free(s);
                if (ret < 0)
                        goto out;
+               if (nmmd->vss_status_flags & VSS_NEXT) {
+                       static char *esi;
+                       if (!esi)
+                               esi = empty_status_items();
+                       ret = send_buffer(fd, esi);
+                       if (ret < 0)
+                               goto out;
+               } else
+                       send_afs_status(fd);
                ret = 1;
                if (num > 0 && !--num)
                        goto out;
                ret = 1;
                if (num > 0 && !--num)
                        goto out;
diff --git a/vss.c b/vss.c
index 458394b..57e531e 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -629,7 +629,6 @@ static void vss_eof(struct vss_task *vsst)
        mmd->afd.afhi.chunk_tv.tv_usec = 0;
        free(mmd->afd.afhi.chunk_table);
        mmd->afd.afhi.chunk_table = NULL;
        mmd->afd.afhi.chunk_tv.tv_usec = 0;
        free(mmd->afd.afhi.chunk_table);
        mmd->afd.afhi.chunk_table = NULL;
-       make_empty_status_items(mmd->afd.verbose_ls_output);
        mmd->mtime = 0;
        mmd->size = 0;
        mmd->events++;
        mmd->mtime = 0;
        mmd->size = 0;
        mmd->events++;
@@ -952,7 +951,6 @@ void init_vss_task(int afs_socket)
        free(hn);
        free(home);
        mmd->sender_cmd_data.cmd_num = -1;
        free(hn);
        free(home);
        mmd->sender_cmd_data.cmd_num = -1;
-       make_empty_status_items(mmd->afd.verbose_ls_output);
        if (conf.autoplay_given) {
                struct timeval tmp;
                mmd->vss_status_flags |= VSS_PLAYING;
        if (conf.autoplay_given) {
                struct timeval tmp;
                mmd->vss_status_flags |= VSS_PLAYING;