#include "portable_io.h"
static struct osl_table *audio_file_table;
-static char *current_status_items;
+static char *status_items;
+static char *parser_friendly_status_items;
/** The different sorting methods of the ls command. */
enum ls_sorting_method {
/** -lm */
LS_MODE_MBOX,
/** -lc */
- LS_MODE_CHUNKS
+ LS_MODE_CHUNKS,
+ /** -lp */
+ LS_MODE_PARSER,
};
/** The flags accepted by the ls command. */
afhi->header_offset = read_u32(buf + HEADER_OFFSET_OFFSET);
afhi->chunk_tv.tv_sec = read_u32(buf + CHUNK_TV_TV_SEC_OFFSET);
afhi->chunk_tv.tv_usec = read_u32(buf + CHUNK_TV_TV_USEC_OFFSET);
- afhi->techinfo = buf + AFHI_INFO_STRING_OFFSET;
+ afhi->techinfo = (char *)buf + AFHI_INFO_STRING_OFFSET;
afhi->tags.artist = afhi->techinfo + strlen(afhi->techinfo) + 1;
afhi->tags.title = afhi->tags.artist + strlen(afhi->tags.artist) + 1;
afhi->tags.year = afhi->tags.title + strlen(afhi->tags.title) + 1;
}
}
-static char *make_attribute_lines(const char *att_bitmap, struct afs_info *afsi)
+
+static int write_attribute_items(struct para_buffer *b,
+ const char *att_bitmap, struct afs_info *afsi)
{
- char *att_text, *att_lines;
+ char *att_text;
+ int ret;
- get_attribute_text(&afsi->attributes, " ", &att_text);
- if (!att_text)
- return para_strdup(att_bitmap);
- att_lines = make_message("%s: %s\n%s: %s",
- status_item_list[SI_ATTRIBUTES_BITMAP], att_bitmap,
- status_item_list[SI_ATTRIBUTES_TXT], att_text);
+ ret = WRITE_STATUS_ITEM(b, SI_ATTRIBUTES_BITMAP, "%s\n", att_bitmap);
+ if (ret < 0)
+ return ret;
+ ret = get_attribute_text(&afsi->attributes, " ", &att_text);
+ if (ret < 0)
+ return ret;
+ ret = WRITE_STATUS_ITEM(b, SI_ATTRIBUTES_TXT, "%s\n", att_text);
free(att_text);
- return att_lines;
+ return ret;
}
-static char *make_lyrics_lines(struct afs_info *afsi)
+static int write_lyrics_items(struct para_buffer *b, struct afs_info *afsi)
{
char *lyrics_name;
+ int ret;
+ ret = WRITE_STATUS_ITEM(b, SI_LYRICS_ID, "%u\n", afsi->lyrics_id);
+ if (ret < 0)
+ return ret;
lyr_get_name_by_id(afsi->lyrics_id, &lyrics_name);
- return make_message("%s: %u\n%s: %s\n",
- status_item_list[SI_LYRICS_ID], afsi->lyrics_id,
- status_item_list[SI_LYRICS_NAME], lyrics_name?
- lyrics_name : "(none)");
+ return WRITE_STATUS_ITEM(b, SI_LYRICS_NAME, "%s\n", lyrics_name?
+ lyrics_name : "(none)");
}
-static char *make_image_lines(struct afs_info *afsi)
+static int write_image_items(struct para_buffer *b, struct afs_info *afsi)
{
char *image_name;
+ int ret;
+
+ ret = WRITE_STATUS_ITEM(b, SI_IMAGE_ID, "%u\n", afsi->image_id);
+ if (ret < 0)
+ return ret;
img_get_name_by_id(afsi->image_id, &image_name);
- return make_message("%s: %u\n%s: %s\n",
- status_item_list[SI_IMAGE_ID], afsi->image_id,
- status_item_list[SI_IMAGE_NAME], image_name?
- image_name : "(none)");
+ return WRITE_STATUS_ITEM(b, SI_IMAGE_NAME, "%s\n", image_name?
+ image_name : "(none)");
}
-static char *make_filename_lines(const char *path, unsigned flags)
+static int write_filename_items(struct para_buffer *b, const char *path,
+ unsigned flags)
{
- char *dirname, *ret;
- const char *basename;
+ char *val;
+ int ret;
if (!(flags & LS_FLAG_FULL_PATH))
- return make_message("%s: %s\n",
- status_item_list[SI_BASENAME], path);
- basename = para_basename(path),
- dirname = para_dirname(path);
- ret = make_message("%s: %s\n%s: %s\n%s: %s\n",
- status_item_list[SI_PATH], path,
- status_item_list[SI_DIRECTORY], dirname? dirname : "?",
- status_item_list[SI_BASENAME], basename? basename : "?");
- free(dirname);
+ return WRITE_STATUS_ITEM(b, SI_BASENAME, "%s\n", path);
+ ret = WRITE_STATUS_ITEM(b, SI_PATH, "%s\n", path);
+ if (ret < 0)
+ return ret;
+ val = para_basename(path);
+ ret = WRITE_STATUS_ITEM(b, SI_BASENAME, "%s\n", val? val : "");
+ if (ret < 0)
+ return ret;
+ val = para_dirname(path);
+ ret = WRITE_STATUS_ITEM(b, SI_DIRECTORY, "%s\n", val? val : "");
+ free(val);
return ret;
}
return ret;
}
+static int write_score(struct para_buffer *b, struct ls_data *d,
+ struct ls_options *opts)
+{
+ if (!(opts->flags & LS_FLAG_ADMISSIBLE_ONLY)) /* no score*/
+ return 0;
+ return WRITE_STATUS_ITEM(b, SI_SCORE, "%li\n", d->score);
+}
+
static int print_list_item(struct ls_data *d, struct ls_options *opts,
struct para_buffer *b, time_t current_time)
{
char att_buf[65];
char last_played_time[30];
char duration_buf[30]; /* nobody has an audio file long enough to overflow this */
- char score_buf[30] = "";
struct afs_info *afsi = &d->afsi;
struct afh_info *afhi = &d->afhi;
- struct ls_widths *w = &opts->widths;
- int have_score = opts->flags & LS_FLAG_ADMISSIBLE_ONLY;
char asc_hash[2 * HASH_SIZE + 1];
- char *att_lines, *lyrics_lines, *image_lines, *filename_lines;
if (opts->mode == LS_MODE_SHORT) {
ret = para_printf(b, "%s\n", d->path);
if (ret < 0)
goto out;
get_duration_buf(afhi->seconds_total, duration_buf, opts);
- if (have_score) {
- if (opts->mode == LS_MODE_LONG)
- sprintf(score_buf, "%*li ", w->score_width, d->score);
- else
- sprintf(score_buf, "%li ", d->score);
- }
-
if (opts->mode == LS_MODE_LONG) {
+ struct ls_widths *w = &opts->widths;
+ if (opts->flags & LS_FLAG_ADMISSIBLE_ONLY) {
+ ret = para_printf(b, "%*li ",
+ opts->widths.score_width, d->score);
+ if (ret < 0)
+ goto out;
+ }
ret = para_printf(b,
- "%s" /* score */
"%s " /* attributes */
"%*u " /* amp */
"%*d " /* image_id */
"%*d " /* num_played */
"%s " /* last_played */
"%s\n", /* path */
- score_buf,
att_buf,
w->amp_width, afsi->amp,
w->image_id_width, afsi->image_id,
);
goto out;
}
- hash_to_asc(d->hash, asc_hash);
- att_lines = make_attribute_lines(att_buf, afsi);
- lyrics_lines = make_lyrics_lines(afsi);
- image_lines = make_image_lines(afsi);
- filename_lines = make_filename_lines(d->path, opts->flags);
if (opts->mode == LS_MODE_MBOX) {
const char *bn = para_basename(d->path);
ret = para_printf(b,
if (ret < 0)
goto out;
}
- ret = para_printf(b,
- "%s" /* filename stuff */
- "%s%s%s%s" /* score */
- "%s\n" /* attributes */
- "%s: %s\n" /* hash */
- "%s" /* image id, image name */
- "%s" /* lyrics */
- "%s: %dkbit/s\n" /* bitrate */
- "%s: %s\n" /* format */
- "%s: %dHz\n" /* frequency */
- "%s: %d\n" /* channels */
- "%s: %s\n" /* duration */
- "%s: %lu\n" /* seconds total */
- "%s: %s\n" /* last played time */
- "%s: %d\n" /* num_played */
- "%s: %u\n" /* amplification */
- "%s: %lu\n" /* chunk time */
- "%s: %lu\n" /* num chunks */
- "%s: %s\n" /* techinfo */
- "%s: %s\n" /* artist */
- "%s: %s\n" /* title */
- "%s: %s\n" /* year */
- "%s: %s\n" /* album */
- "%s: %s\n", /* comment */
- filename_lines,
- have_score? status_item_list[SI_SCORE] : "",
- have_score? ": " : "",
- score_buf,
- have_score? "\n" : "",
- att_lines,
- status_item_list[SI_HASH], asc_hash,
- image_lines,
- lyrics_lines,
- status_item_list[SI_BITRATE], afhi->bitrate,
- status_item_list[SI_FORMAT], audio_format_name(afsi->audio_format_id),
- status_item_list[SI_FREQUENCY], afhi->frequency,
- status_item_list[SI_CHANNELS], afhi->channels,
- status_item_list[SI_DURATION], duration_buf,
- status_item_list[SI_SECONDS_TOTAL], afhi->seconds_total,
- status_item_list[SI_LAST_PLAYED], last_played_time,
- status_item_list[SI_NUM_PLAYED], afsi->num_played,
- status_item_list[SI_AMPLIFICATION], afsi->amp,
- status_item_list[SI_CHUNK_TIME], tv2ms(&afhi->chunk_tv),
- status_item_list[SI_NUM_CHUNKS], afhi->chunks_total,
- status_item_list[SI_TECHINFO], afhi->techinfo,
- status_item_list[SI_ARTIST], afhi->tags.artist,
- status_item_list[SI_TITLE], afhi->tags.title,
- status_item_list[SI_YEAR], afhi->tags.year,
- status_item_list[SI_ALBUM], afhi->tags.album,
- status_item_list[SI_COMMENT], afhi->tags.comment
- );
+ ret = write_filename_items(b, d->path, opts->flags);
+ if (ret < 0)
+ goto out;
+ ret = write_score(b, d, opts);
+ if (ret < 0)
+ goto out;
+ ret = write_attribute_items(b, att_buf, afsi);
+ if (ret < 0)
+ goto out;
+ ret = write_image_items(b, afsi);
+ if (ret < 0)
+ goto out;
+ ret = write_lyrics_items(b, afsi);
+ if (ret < 0)
+ goto out;
+ hash_to_asc(d->hash, asc_hash);
+ ret = WRITE_STATUS_ITEM(b, SI_HASH, "%s\n", asc_hash);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_BITRATE, "%dkbit/s\n", afhi->bitrate);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_FORMAT, "%s\n",
+ audio_format_name(afsi->audio_format_id));
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_FREQUENCY, "%dHz\n", afhi->frequency);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_CHANNELS, "%d\n", afhi->channels);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_DURATION, "%s\n", duration_buf);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_SECONDS_TOTAL, "%lu\n",
+ afhi->seconds_total);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_LAST_PLAYED, "%s\n", last_played_time);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_NUM_PLAYED, "%d\n", afsi->num_played);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_AMPLIFICATION, "%u\n", afsi->amp);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_CHUNK_TIME, "%lu\n",
+ tv2ms(&afhi->chunk_tv));
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_NUM_CHUNKS, "%lu\n",
+ afhi->chunks_total);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_TECHINFO, "%s\n", afhi->techinfo);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_ARTIST, "%s\n", afhi->tags.artist);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_TITLE, "%s\n", afhi->tags.title);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_YEAR, "%s\n", afhi->tags.year);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_ALBUM, "%s\n", afhi->tags.album);
+ if (ret < 0)
+ goto out;
+ ret = WRITE_STATUS_ITEM(b, SI_COMMENT, "%s\n", afhi->tags.comment);
if (ret < 0)
goto out;
if (opts->mode == LS_MODE_MBOX) {
osl_close_disk_object(&lyrics_def);
}
}
- free(att_lines);
- free(lyrics_lines);
- free(image_lines);
- free(filename_lines);
out:
return ret;
}
ret = print_list_item(&d, &opts, &pb, current_time);
if (ret < 0)
return ret;
- free(current_status_items);
- current_status_items = pb.buf;
+ free(status_items);
+ status_items = pb.buf;
+ memset(&pb, 0, sizeof(pb));
+ pb.max_size = SHMMAX - 1;
+ pb.flags = PBF_SIZE_PREFIX;
+ ret = print_list_item(&d, &opts, &pb, current_time);
+ if (ret < 0) {
+ free(status_items);
+ status_items = NULL;
+ return ret;
+ }
+ free(parser_friendly_status_items);
+ parser_friendly_status_items = pb.buf;
return 1;
}
struct ls_options *opts = query->data;
char *p, *pattern_start = (char *)query->data + sizeof(*opts);
struct para_buffer b = {.max_size = SHMMAX,
+ .flags = (opts->mode == LS_MODE_PARSER)? PBF_SIZE_PREFIX : 0,
.max_size_handler = pass_buffer_as_shm, .private_data = &fd};
int i = 0, ret;
time_t current_time;
-
if (opts->num_patterns) {
opts->patterns = para_malloc(opts->num_patterns * sizeof(char *));
for (i = 0, p = pattern_start; i < opts->num_patterns; i++) {
case 'c':
mode = LS_MODE_CHUNKS;
continue;
+ case 'p':
+ mode = LS_MODE_PARSER;
+ continue;
default:
return -E_AFT_SYNTAX;
}
}
break;
}
- if (i + 1 >= argc) /* need at least souce file and pattern */
+ if (i + 1 >= argc) /* need at least source file and pattern */
return -E_AFT_SYNTAX;
if (!(flags & ~CPSI_FLAG_VERBOSE)) /* no copy flags given */
flags = ~(unsigned)CPSI_FLAG_VERBOSE | flags;
return ret;
}
-void afs_stat_callback(int fd, __a_unused const struct osl_object *query)
+void afs_stat_callback(int fd, const struct osl_object *query)
{
- if (current_status_items)
- pass_buffer_as_shm(current_status_items,
- strlen(current_status_items), &fd);
+ int *parser_friendly = query->data;
+ char *buf = *parser_friendly?
+ parser_friendly_status_items : status_items;
+
+ if (!buf)
+ return;
+ pass_buffer_as_shm(buf, strlen(buf), &fd);
}
-int send_afs_status(int fd)
+int send_afs_status(int fd, int parser_friendly)
{
- return send_callback_request(afs_stat_callback, NULL, send_result, &fd);
+ struct osl_object query = {.data = &parser_friendly,
+ .size = sizeof(parser_friendly)};
+
+ return send_callback_request(afs_stat_callback, &query, send_result, &fd);
}
/* TODO: optionally fix problems by removing offending rows */
{
osl_close_table(audio_file_table, OSL_MARK_CLEAN);
audio_file_table = NULL;
- free(current_status_items);
- current_status_items = NULL;
+ free(status_items);
+ status_items = NULL;
+ free(parser_friendly_status_items);
+ parser_friendly_status_items = NULL;
}
/**