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.
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 {
- /** 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. */
#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 {
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)
.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(¤t_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;
}
/**
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)
{
{
osl_close_table(audio_file_table, OSL_MARK_CLEAN);
audio_file_table = NULL;
+ free(current_status_items);
+ current_status_items = NULL;
}
/**
"%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,
(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);
);
}
+/**
+ * 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)
{
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;
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++;
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;