NEWS
====
+
---------------------
current master branch
---------------------
+The highlight of this release is the version 2 mood parser. But there
+is a lot more than that, as summarized in the list below. And of
+course we have many small usability improvements and bug fixes not
+mentioned here.
+
+- A more intuitive syntax for moods ("version 2 moods"). The
+ traditional version 1 moods are still supported but are deprecated
+ now. Removal of the version 1 mood parser is scheduled for the next
+ major release.
+- Flex and bison are now required to build para_server.
- New sort order for the ls command: -s=h sorts the ls output by hash
value of the audio file.
- autogen.sh now runs the test suite after a successful build.
- The contents of overview.pdf have been integrated into the user
manual.
+- Fixed sized audio format headers for ogg/opus streams.
- The doxygen source browser has been disabled temporarily. The
API reference is still online, though.
- Overhaul of the source code documentation.
spx_afh_init, flac_afh_init, opus_afh_init;
/** The list of all status items */
-const char *status_item_list[] = {STATUS_ITEM_ARRAY};
+const char *status_item_list[] = {STATUS_ITEMS};
/**
* The list of supported audio formats.
"%s: %s\n" /* year */
"%s: %s\n" /* album */
"%s: %s\n", /* comment */
- status_item_list[SI_BITRATE], afhi->bitrate,
- status_item_list[SI_FORMAT], audio_format_name(audio_format_num),
- status_item_list[SI_FREQUENCY], afhi->frequency,
- status_item_list[SI_CHANNELS], afhi->channels,
- status_item_list[SI_SECONDS_TOTAL], afhi->seconds_total,
- status_item_list[SI_CHUNK_TIME], (long unsigned)afhi->chunk_tv.tv_sec,
+ status_item_list[SI_bitrate], afhi->bitrate,
+ status_item_list[SI_format], audio_format_name(audio_format_num),
+ status_item_list[SI_frequency], afhi->frequency,
+ status_item_list[SI_channels], afhi->channels,
+ status_item_list[SI_seconds_total], afhi->seconds_total,
+ status_item_list[SI_chunk_time], (long unsigned)afhi->chunk_tv.tv_sec,
(long unsigned)afhi->chunk_tv.tv_usec,
- status_item_list[SI_NUM_CHUNKS], afhi->chunks_total,
- status_item_list[SI_MAX_CHUNK_SIZE], afhi->max_chunk_size,
- status_item_list[SI_TECHINFO], afhi->techinfo? afhi->techinfo : "",
- status_item_list[SI_ARTIST], afhi->tags.artist? afhi->tags.artist : "",
- status_item_list[SI_TITLE], afhi->tags.title? afhi->tags.title : "",
- status_item_list[SI_YEAR], afhi->tags.year? afhi->tags.year : "",
- status_item_list[SI_ALBUM], afhi->tags.album? afhi->tags.album : "",
- status_item_list[SI_COMMENT], afhi->tags.comment? afhi->tags.comment : ""
+ status_item_list[SI_num_chunks], afhi->chunks_total,
+ status_item_list[SI_max_chunk_size], afhi->max_chunk_size,
+ status_item_list[SI_techinfo], afhi->techinfo? afhi->techinfo : "",
+ status_item_list[SI_artist], afhi->tags.artist? afhi->tags.artist : "",
+ status_item_list[SI_title], afhi->tags.title? afhi->tags.title : "",
+ status_item_list[SI_year], afhi->tags.year? afhi->tags.year : "",
+ status_item_list[SI_album], afhi->tags.album? afhi->tags.album : "",
+ status_item_list[SI_comment], afhi->tags.comment? afhi->tags.comment : ""
);
}
&pard->afh_context);
if (ret < 0)
goto out;
- PARA_INFO_LOG("adding %zu bytes\n", size);
+ PARA_DEBUG_LOG("adding %zu bytes\n", size);
btr_add_output_dont_free(start, size, btrn);
}
ret = -E_RECV_EOF;
char *att_text;
int ret;
- WRITE_STATUS_ITEM(b, SI_ATTRIBUTES_BITMAP, "%s\n", att_bitmap);
+ WRITE_STATUS_ITEM(b, SI_attributes_bitmap, "%s\n", att_bitmap);
ret = get_attribute_text(&afsi->attributes, " ", &att_text);
if (ret < 0)
return ret;
- WRITE_STATUS_ITEM(b, SI_ATTRIBUTES_TXT, "%s\n", att_text);
+ WRITE_STATUS_ITEM(b, SI_attributes_txt, "%s\n", att_text);
free(att_text);
return ret;
}
{
char *lyrics_name;
- WRITE_STATUS_ITEM(b, SI_LYRICS_ID, "%u\n", afsi->lyrics_id);
+ WRITE_STATUS_ITEM(b, SI_lyrics_id, "%u\n", afsi->lyrics_id);
lyr_get_name_by_id(afsi->lyrics_id, &lyrics_name);
- WRITE_STATUS_ITEM(b, SI_LYRICS_NAME, "%s\n", lyrics_name?
+ WRITE_STATUS_ITEM(b, SI_lyrics_name, "%s\n", lyrics_name?
lyrics_name : "(none)");
}
{
char *image_name;
- WRITE_STATUS_ITEM(b, SI_IMAGE_ID, "%u\n", afsi->image_id);
+ WRITE_STATUS_ITEM(b, SI_image_id, "%u\n", afsi->image_id);
img_get_name_by_id(afsi->image_id, &image_name);
- WRITE_STATUS_ITEM(b, SI_IMAGE_NAME, "%s\n", image_name?
+ WRITE_STATUS_ITEM(b, SI_image_name, "%s\n", image_name?
image_name : "(none)");
}
char *val;
if (basename) {
- WRITE_STATUS_ITEM(b, SI_BASENAME, "%s\n", path);
+ WRITE_STATUS_ITEM(b, SI_basename, "%s\n", path);
return;
}
- WRITE_STATUS_ITEM(b, SI_PATH, "%s\n", path);
+ WRITE_STATUS_ITEM(b, SI_path, "%s\n", path);
val = para_basename(path);
- WRITE_STATUS_ITEM(b, SI_BASENAME, "%s\n", val? val : "");
+ WRITE_STATUS_ITEM(b, SI_basename, "%s\n", val? val : "");
val = para_dirname(path);
- WRITE_STATUS_ITEM(b, SI_DIRECTORY, "%s\n", val? val : "");
+ WRITE_STATUS_ITEM(b, SI_directory, "%s\n", val? val : "");
free(val);
}
}
write_filename_items(b, d->path, lls_opt_given(r_b));
if (lls_opt_given(r_a))
- WRITE_STATUS_ITEM(b, SI_SCORE, "%li\n", d->score);
+ WRITE_STATUS_ITEM(b, SI_score, "%li\n", d->score);
ret = write_attribute_items(b, att_buf, afsi);
if (ret < 0)
goto out;
write_image_items(b, afsi);
write_lyrics_items(b, afsi);
hash_to_asc(d->hash, asc_hash);
- WRITE_STATUS_ITEM(b, SI_HASH, "%s\n", asc_hash);
- WRITE_STATUS_ITEM(b, SI_BITRATE, "%dkbit/s\n", afhi->bitrate);
- WRITE_STATUS_ITEM(b, SI_FORMAT, "%s\n",
+ WRITE_STATUS_ITEM(b, SI_hash, "%s\n", asc_hash);
+ WRITE_STATUS_ITEM(b, SI_bitrate, "%dkbit/s\n", afhi->bitrate);
+ WRITE_STATUS_ITEM(b, SI_format, "%s\n",
audio_format_name(afsi->audio_format_id));
- WRITE_STATUS_ITEM(b, SI_FREQUENCY, "%dHz\n", afhi->frequency);
- WRITE_STATUS_ITEM(b, SI_CHANNELS, "%d\n", afhi->channels);
- WRITE_STATUS_ITEM(b, SI_DURATION, "%s\n", duration_buf);
- WRITE_STATUS_ITEM(b, SI_SECONDS_TOTAL, "%" PRIu32 "\n",
+ WRITE_STATUS_ITEM(b, SI_frequency, "%dHz\n", afhi->frequency);
+ WRITE_STATUS_ITEM(b, SI_channels, "%d\n", afhi->channels);
+ WRITE_STATUS_ITEM(b, SI_duration, "%s\n", duration_buf);
+ WRITE_STATUS_ITEM(b, SI_seconds_total, "%" PRIu32 "\n",
afhi->seconds_total);
- WRITE_STATUS_ITEM(b, SI_LAST_PLAYED, "%s\n", last_played_time);
- WRITE_STATUS_ITEM(b, SI_NUM_PLAYED, "%u\n", afsi->num_played);
- WRITE_STATUS_ITEM(b, SI_AMPLIFICATION, "%u\n", afsi->amp);
- WRITE_STATUS_ITEM(b, SI_CHUNK_TIME, "%lu\n", tv2ms(&afhi->chunk_tv));
- WRITE_STATUS_ITEM(b, SI_NUM_CHUNKS, "%" PRIu32 "\n",
+ WRITE_STATUS_ITEM(b, SI_last_played, "%s\n", last_played_time);
+ WRITE_STATUS_ITEM(b, SI_num_played, "%u\n", afsi->num_played);
+ WRITE_STATUS_ITEM(b, SI_amplification, "%u\n", afsi->amp);
+ WRITE_STATUS_ITEM(b, SI_chunk_time, "%lu\n", tv2ms(&afhi->chunk_tv));
+ WRITE_STATUS_ITEM(b, SI_num_chunks, "%" PRIu32 "\n",
afhi->chunks_total);
- WRITE_STATUS_ITEM(b, SI_MAX_CHUNK_SIZE, "%" PRIu32 "\n",
+ WRITE_STATUS_ITEM(b, SI_max_chunk_size, "%" PRIu32 "\n",
afhi->max_chunk_size);
- WRITE_STATUS_ITEM(b, SI_TECHINFO, "%s\n", afhi->techinfo);
- WRITE_STATUS_ITEM(b, SI_ARTIST, "%s\n", afhi->tags.artist);
- WRITE_STATUS_ITEM(b, SI_TITLE, "%s\n", afhi->tags.title);
- WRITE_STATUS_ITEM(b, SI_YEAR, "%s\n", afhi->tags.year);
- WRITE_STATUS_ITEM(b, SI_ALBUM, "%s\n", afhi->tags.album);
- WRITE_STATUS_ITEM(b, SI_COMMENT, "%s\n", afhi->tags.comment);
+ WRITE_STATUS_ITEM(b, SI_techinfo, "%s\n", afhi->techinfo);
+ WRITE_STATUS_ITEM(b, SI_artist, "%s\n", afhi->tags.artist);
+ WRITE_STATUS_ITEM(b, SI_title, "%s\n", afhi->tags.title);
+ WRITE_STATUS_ITEM(b, SI_year, "%s\n", afhi->tags.year);
+ WRITE_STATUS_ITEM(b, SI_album, "%s\n", afhi->tags.album);
+ WRITE_STATUS_ITEM(b, SI_comment, "%s\n", afhi->tags.comment);
if (opts->mode == LS_MODE_MBOX) {
struct osl_object lyrics_def;
lyr_get_def_by_id(afsi->lyrics_id, &lyrics_def);
ret = strftime(mtime_str, 29, "%b %d %Y", &mtime_tm);
assert(ret > 0); /* number of bytes placed in mtime_str */
out:
- WRITE_STATUS_ITEM(pb, SI_MTIME, "%s\n", mtime_str);
- WRITE_STATUS_ITEM(pb, SI_FILE_SIZE, "%ld\n", statbuf.st_size / 1024);
+ WRITE_STATUS_ITEM(pb, SI_mtime, "%s\n", mtime_str);
+ WRITE_STATUS_ITEM(pb, SI_file_size, "%ld\n", statbuf.st_size / 1024);
}
static int make_status_items(void)
fn->private_data = pad;
fn->min_iqs = 2;
- if (!given && stat_item_values[SI_AMPLIFICATION])
- sscanf(stat_item_values[SI_AMPLIFICATION], "%u", &pad->amp);
+ if (!given && stat_item_values[SI_amplification])
+ sscanf(stat_item_values[SI_amplification], "%u", &pad->amp);
else
pad->amp = amp_arg;
PARA_INFO_LOG("amplification: %u (scaling factor: %1.2f)\n",
static void stat_completer(struct i9e_completion_info *ci,
struct i9e_completion_result *cr)
{
- char *sia[] = {STATUS_ITEM_ARRAY NULL};
+ char *sia[] = {STATUS_ITEMS NULL};
char *opts[] = {LSG_AUDIOD_CMD_STAT_OPTS, NULL};
if (ci->word_num <= 2 && ci->word && ci->word[0] == '-')
EMBRACE(.name = name, .context = rn));
ret = r->open(rn);
if (ret < 0) {
+ PARA_ERROR_LOG("could not open %s receiver\n", name);
btr_remove_node(&rn->btrn);
free(rn);
return ret;
{
long unsigned sec, usec;
- if (stat_task->clock_diff_count && itemnum != SI_CURRENT_TIME)
+ if (stat_task->clock_diff_count && itemnum != SI_current_time)
return 1;
free(stat_item_values[itemnum]);
stat_item_values[itemnum] = para_strdup(buf);
stat_client_write_item(itemnum);
switch (itemnum) {
- case SI_STATUS_FLAGS:
+ case SI_status_flags:
stat_task->vss_status = 0;
if (strchr(buf, 'N'))
stat_task->vss_status |= VSS_STATUS_FLAG_NEXT;
if (strchr(buf, 'P'))
stat_task->vss_status |= VSS_STATUS_FLAG_PLAYING;
break;
- case SI_OFFSET:
+ case SI_offset:
stat_task->offset_seconds = atoi(buf);
break;
- case SI_SECONDS_TOTAL:
+ case SI_seconds_total:
stat_task->length_seconds = atoi(buf);
break;
- case SI_STREAM_START:
+ case SI_stream_start:
if (sscanf(buf, "%lu.%lu", &sec, &usec) == 2) {
stat_task->server_stream_start.tv_sec = sec;
stat_task->server_stream_start.tv_usec = usec;
}
break;
- case SI_CURRENT_TIME:
+ case SI_current_time:
if (sscanf(buf, "%lu.%lu", &sec, &usec) == 2) {
struct timeval tv = {sec, usec};
compute_time_diff(&tv);
}
break;
- case SI_FORMAT:
+ case SI_format:
stat_task->current_audio_format_num
= get_audio_format_num(buf);
}
client_open(argc, argv, &st->ct, NULL, NULL, st->btrn, s);
set_stat_task_restart_barrier(5);
}
- free(stat_item_values[SI_BASENAME]);
- stat_item_values[SI_BASENAME] = para_strdup(
+ free(stat_item_values[SI_basename]);
+ stat_item_values[SI_basename] = para_strdup(
"no connection to para_server");
- stat_client_write_item(SI_BASENAME);
+ stat_client_write_item(SI_basename);
st->last_status_read = *now;
out:
start_stop_decoders();
static int num_clients;
/** The list of all status items used by para_{server,audiod,gui}. */
-const char *status_item_list[] = {STATUS_ITEM_ARRAY};
+const char *status_item_list[] = {STATUS_ITEMS};
static void dump_stat_client_list(void)
{
{
char *old, *new;
- old = stat_item_values[SI_PLAY_TIME];
+ old = stat_item_values[SI_play_time];
new = get_time_string();
if (new) {
if (force || !old || strcmp(old, new)) {
free(old);
- stat_item_values[SI_PLAY_TIME] = new;
- stat_client_write_item(SI_PLAY_TIME);
+ stat_item_values[SI_play_time] = new;
+ stat_client_write_item(SI_play_time);
} else
free(new);
}
new = daemon_get_uptime_str(now);
- old = stat_item_values[SI_AUDIOD_UPTIME];
+ old = stat_item_values[SI_audiod_uptime];
if (force || !old || strcmp(old, new)) {
free(old);
- stat_item_values[SI_AUDIOD_UPTIME] = new;
- stat_client_write_item(SI_AUDIOD_UPTIME);
+ stat_item_values[SI_audiod_uptime] = new;
+ stat_client_write_item(SI_audiod_uptime);
} else
free(new);
- old = stat_item_values[SI_AUDIOD_STATUS];
+ old = stat_item_values[SI_audiod_status];
new = audiod_status_string();
if (force || !old || strcmp(old, new)) {
free(old);
- stat_item_values[SI_AUDIOD_STATUS] = new;
- stat_client_write_item(SI_AUDIOD_STATUS);
+ stat_item_values[SI_audiod_status] = new;
+ stat_client_write_item(SI_audiod_status);
} else
free(new);
- old = stat_item_values[SI_DECODER_FLAGS];
+ old = stat_item_values[SI_decoder_flags];
new = audiod_get_decoder_flags();
if (force || !old || strcmp(old, new)) {
free(old);
- stat_item_values[SI_DECODER_FLAGS] = new;
- stat_client_write_item(SI_DECODER_FLAGS);
+ stat_item_values[SI_decoder_flags] = new;
+ stat_client_write_item(SI_decoder_flags);
} else
free(new);
}
*/
static int uint32_compare(const struct osl_object *obj1, const struct osl_object *obj2)
{
- uint32_t d1 = read_u32((const char *)obj1->data);
- uint32_t d2 = read_u32((const char *)obj2->data);
+ uint32_t d1 = read_u32(obj1->data);
+ uint32_t d2 = read_u32(obj2->data);
if (d1 < d2)
return 1;
* clang is not smart enough to prove this and complains nevertheless.
* Casting the return value to void silences clang.
*/
- (void)WRITE_STATUS_ITEM(&b, SI_STATUS, "%s\n", status);
- (void)WRITE_STATUS_ITEM(&b, SI_STATUS_FLAGS, "%s\n", flags);
- (void)WRITE_STATUS_ITEM(&b, SI_OFFSET, "%li\n", offset);
- (void)WRITE_STATUS_ITEM(&b, SI_AFS_MODE, "%s\n", mmd->afs_mode_string);
- (void)WRITE_STATUS_ITEM(&b, SI_STREAM_START, "%lu.%lu\n",
+ (void)WRITE_STATUS_ITEM(&b, SI_status, "%s\n", status);
+ (void)WRITE_STATUS_ITEM(&b, SI_status_flags, "%s\n", flags);
+ (void)WRITE_STATUS_ITEM(&b, SI_offset, "%li\n", offset);
+ (void)WRITE_STATUS_ITEM(&b, SI_afs_mode, "%s\n", mmd->afs_mode_string);
+ (void)WRITE_STATUS_ITEM(&b, SI_stream_start, "%lu.%lu\n",
(long unsigned)nmmd->stream_start.tv_sec,
(long unsigned)nmmd->stream_start.tv_usec);
- (void)WRITE_STATUS_ITEM(&b, SI_CURRENT_TIME, "%lu.%lu\n",
+ (void)WRITE_STATUS_ITEM(&b, SI_current_time, "%lu.%lu\n",
(long unsigned)current_time.tv_sec,
(long unsigned)current_time.tv_usec);
free(flags);
/** These status items are cleared if no audio file is currently open. */
#define EMPTY_STATUS_ITEMS \
- ITEM(PATH) \
- ITEM(DIRECTORY) \
- ITEM(BASENAME) \
- ITEM(SCORE) \
- ITEM(ATTRIBUTES_BITMAP) \
- ITEM(ATTRIBUTES_TXT) \
- ITEM(HASH) \
- ITEM(IMAGE_ID) \
- ITEM(IMAGE_NAME) \
- ITEM(LYRICS_ID) \
- ITEM(LYRICS_NAME) \
- ITEM(BITRATE) \
- ITEM(FORMAT) \
- ITEM(FREQUENCY) \
- ITEM(CHANNELS) \
- ITEM(DURATION) \
- ITEM(SECONDS_TOTAL) \
- ITEM(NUM_PLAYED) \
- ITEM(LAST_PLAYED) \
- ITEM(TECHINFO) \
- ITEM(ARTIST) \
- ITEM(TITLE) \
- ITEM(YEAR) \
- ITEM(ALBUM) \
- ITEM(COMMENT) \
- ITEM(MTIME) \
- ITEM(FILE_SIZE) \
- ITEM(CHUNK_TIME) \
- ITEM(NUM_CHUNKS) \
- ITEM(AMPLIFICATION) \
+ ITEM(path) \
+ ITEM(directory) \
+ ITEM(basename) \
+ ITEM(score) \
+ ITEM(attributes_bitmap) \
+ ITEM(attributes_txt) \
+ ITEM(hash) \
+ ITEM(image_id) \
+ ITEM(image_name) \
+ ITEM(lyrics_id) \
+ ITEM(lyrics_name) \
+ ITEM(bitrate) \
+ ITEM(format) \
+ ITEM(frequency) \
+ ITEM(channels) \
+ ITEM(duration) \
+ ITEM(seconds_total) \
+ ITEM(num_played) \
+ ITEM(last_played) \
+ ITEM(techinfo) \
+ ITEM(artist) \
+ ITEM(title) \
+ ITEM(year) \
+ ITEM(album) \
+ ITEM(comment) \
+ ITEM(mtime) \
+ ITEM(file_size) \
+ ITEM(chunk_time) \
+ ITEM(num_chunks) \
+ ITEM(amplification) \
/*
* Create a set of audio-file related status items with empty values. These are
fi
audioc_objs="$audioc_errlist_objs"
AC_SUBST(audioc_objs, add_dot_o($audioc_objs))
-################################################################## status items
-
-status_items="basename status num_played mtime bitrate frequency file_size
-status_flags format score techinfo afs_mode
-attributes_txt decoder_flags audiod_status play_time attributes_bitmap
-offset seconds_total stream_start current_time audiod_uptime image_id
-lyrics_id duration directory lyrics_name image_name path hash channels
-last_played num_chunks chunk_time amplification artist title year album
-comment max_chunk_size"
-
-result=
-for i in $status_items; do
- result="$result SI_$(echo $i | tr 'a-z' 'A-Z'), "
-done
-AC_DEFINE_UNQUOTED(STATUS_ITEM_ENUM, [$result],
- [enum of all status items])
-
-result=
-for i in $status_items; do
- result="$result \"$i\", "
-done
-AC_DEFINE_UNQUOTED(STATUS_ITEM_ARRAY, [$result],
- [char * array of all status items])
AC_DEFINE_UNQUOTED(AUDIO_FORMAT_HANDLERS, "$audio_format_handlers",
[formats supported by para_server and para_afh])
-
AC_SUBST(executables)
AC_OUTPUT
#include "fd.h"
#include "crypt_backend.h"
#include "base64.h"
+#include "portable_io.h"
struct asymmetric_key {
RSA *rsa;
return -E_BIGNUM;
if (p + 4 > end)
return -E_BIGNUM;
- bnsize = read_ssh_u32(p);
+ bnsize = read_u32_be(p);
PARA_DEBUG_LOG("bnsize: %u\n", bnsize);
p += 4;
if (p + bnsize < p)
#define AES_CRT128_BLOCK_SIZE 16
size_t is_ssh_rsa_key(char *data, size_t size);
-uint32_t read_ssh_u32(const void *vp);
int check_ssh_key_header(const unsigned char *blob, int blen);
int check_private_key_file(const char *file);
#include "string.h"
#include "crypt.h"
#include "crypt_backend.h"
+#include "portable_io.h"
/** If the key begins with this text, we treat it as an ssh key. */
#define KEY_TYPE_TXT "ssh-rsa"
return cp - data;
}
-/**
- * Read a 4-byte number from a buffer in big-endian format.
- *
- * \param vp The buffer.
- *
- * The byte-order of the buffer is expected to be big-endian, unlike read_u32()
- * of portable_io.h which expects little endian.
- *
- * \return The 32 bit number given by \a vp.
- */
-uint32_t read_ssh_u32(const void *vp)
-{
- const unsigned char *p = (const unsigned char *)vp;
- uint32_t v;
-
- v = (uint32_t)p[0] << 24;
- v |= (uint32_t)p[1] << 16;
- v |= (uint32_t)p[2] << 8;
- v |= (uint32_t)p[3];
-
- return v;
-}
-
/**
* Sanity checks for the header of an ssh key.
*
if (p + 4 > end)
return -E_SSH_KEY_HEADER;
- rlen = read_ssh_u32(p);
+ rlen = read_u32_be(p);
p += 4;
if (p + rlen < p)
return -E_SSH_KEY_HEADER;
return ret;
}
-/**
- * A wrapper for fchdir().
- *
- * \param fd An open file descriptor.
- *
- * \return Standard.
- */
-static int para_fchdir(int fd)
-{
- if (fchdir(fd) < 0)
- return -ERRNO_TO_PARA_ERROR(errno);
- return 1;
-}
-
/**
* A wrapper for mkdir(2).
*
{
DIR *dir;
struct dirent *entry;
- int cwd_fd, ret2, ret = para_opendir(dirname, &dir, &cwd_fd);
+ int cwd_fd, ret = para_opendir(dirname, &dir, &cwd_fd);
if (ret < 0)
return ret == -ERRNO_TO_PARA_ERROR(EACCES)? 1 : ret;
ret = 1;
out:
closedir(dir);
- ret2 = para_fchdir(cwd_fd);
- if (ret2 < 0 && ret >= 0)
- ret = ret2;
+ if (fchdir(cwd_fd) < 0 && ret >= 0)
+ ret = -ERRNO_TO_PARA_ERROR(errno);
close(cwd_fd);
return ret;
}
#define OPT_UINT32_VAL(_name) (lls_uint32_val(0, OPT_RESULT(_name)))
/** The list of all status items used by para_{server,audiod,gui}. */
-const char *status_item_list[] = {STATUS_ITEM_ARRAY};
+const char *status_item_list[] = {STATUS_ITEMS};
/**
* Dummy version which only contains NULL pointers.
#include "string.h"
/** Iterate over all filters. */
-#define FOR_EACH_FILTER(j) for (j = 1; lls_cmd(j, filter_cmd_suite); j++)
+#define FOR_EACH_FILTER(j) for (j = 1; FILTER_CMD(j); j++)
/**
* Obtain a reference to a filter structure.
if (buf && buf[0])
goto dup;
switch (item_num) {
- case SI_ARTIST:
+ case SI_artist:
*c = para_strdup("(artist tag not set)");
goto print;
- case SI_TITLE:
+ case SI_title:
*c = para_strdup("(title tag not set)");
goto print;
- case SI_YEAR:
+ case SI_year:
*c = para_strdup("????");
goto print;
- case SI_ALBUM:
+ case SI_album:
*c = para_strdup("(album tag not set)");
goto print;
- case SI_COMMENT:
+ case SI_comment:
*c = para_strdup("(comment tag not set)");
goto print;
}
close(st->fd);
st->fd = -1;
clear_all_items();
- free(stat_content[SI_BASENAME]);
- stat_content[SI_BASENAME] =
+ free(stat_content[SI_basename]);
+ stat_content[SI_basename] =
para_strdup("stat command terminated!?");
print_all_items();
return 0;
t->dflt.bg = COLOR_BLUE;
t->sep_char = '*';
- d[SI_BASENAME].prefix = "";
- d[SI_BASENAME].postfix = "";
- d[SI_BASENAME].color.fg = COLOR_WHITE;
- d[SI_BASENAME].color.bg = COLOR_BLUE;
- d[SI_BASENAME].align = CENTER;
- d[SI_BASENAME].x = 0;
- d[SI_BASENAME].y = 7;
- d[SI_BASENAME].len = 100;
-
- d[SI_STATUS].prefix = "para_server: ";
- d[SI_STATUS].postfix = "";
- d[SI_STATUS].color.fg = COLOR_WHITE;
- d[SI_STATUS].color.bg = COLOR_BLUE;
- d[SI_STATUS].align = CENTER;
- d[SI_STATUS].x = 0;
- d[SI_STATUS].y = 60;
- d[SI_STATUS].len = 50;
-
- d[SI_AUDIOD_STATUS].prefix = "para_audiod: ";
- d[SI_AUDIOD_STATUS].postfix = "";
- d[SI_AUDIOD_STATUS].color.fg = COLOR_WHITE;
- d[SI_AUDIOD_STATUS].color.bg = COLOR_BLUE;
- d[SI_AUDIOD_STATUS].align = CENTER;
- d[SI_AUDIOD_STATUS].x = 50;
- d[SI_AUDIOD_STATUS].y = 60;
- d[SI_AUDIOD_STATUS].len = 50;
+ d[SI_basename].prefix = "";
+ d[SI_basename].postfix = "";
+ d[SI_basename].color.fg = COLOR_WHITE;
+ d[SI_basename].color.bg = COLOR_BLUE;
+ d[SI_basename].align = CENTER;
+ d[SI_basename].x = 0;
+ d[SI_basename].y = 7;
+ d[SI_basename].len = 100;
+
+ d[SI_status].prefix = "para_server: ";
+ d[SI_status].postfix = "";
+ d[SI_status].color.fg = COLOR_WHITE;
+ d[SI_status].color.bg = COLOR_BLUE;
+ d[SI_status].align = CENTER;
+ d[SI_status].x = 0;
+ d[SI_status].y = 60;
+ d[SI_status].len = 50;
+
+ d[SI_audiod_status].prefix = "para_audiod: ";
+ d[SI_audiod_status].postfix = "";
+ d[SI_audiod_status].color.fg = COLOR_WHITE;
+ d[SI_audiod_status].color.bg = COLOR_BLUE;
+ d[SI_audiod_status].align = CENTER;
+ d[SI_audiod_status].x = 50;
+ d[SI_audiod_status].y = 60;
+ d[SI_audiod_status].len = 50;
}
t->dflt.fg = COLOR_MAGENTA;
- d[SI_PLAY_TIME].prefix = "";
- d[SI_PLAY_TIME].postfix = "";
- d[SI_PLAY_TIME].color.fg = COLOR_CYAN;
- d[SI_PLAY_TIME].color.bg = COLOR_BLACK;
- d[SI_PLAY_TIME].align = CENTER;
- d[SI_PLAY_TIME].x = 0;
- d[SI_PLAY_TIME].y = 7;
- d[SI_PLAY_TIME].len = 35;
-
- d[SI_BASENAME].prefix = "";
- d[SI_BASENAME].postfix = "";
- d[SI_BASENAME].color.fg = COLOR_CYAN;
- d[SI_BASENAME].color.bg = COLOR_BLACK;
- d[SI_BASENAME].align = LEFT;
- d[SI_BASENAME].x = 35;
- d[SI_BASENAME].y = 7;
- d[SI_BASENAME].len = 65;
-
- d[SI_STATUS].prefix = "";
- d[SI_STATUS].postfix = " ";
- d[SI_STATUS].color.fg = COLOR_RED;
- d[SI_STATUS].color.bg = COLOR_BLACK;
- d[SI_STATUS].align = RIGHT;
- d[SI_STATUS].x = 0;
- d[SI_STATUS].y = 17;
- d[SI_STATUS].len = 11;
-
- d[SI_STATUS_FLAGS].prefix = "(";
- d[SI_STATUS_FLAGS].postfix = ")";
- d[SI_STATUS_FLAGS].color.fg = COLOR_RED;
- d[SI_STATUS_FLAGS].color.bg = COLOR_BLACK;
- d[SI_STATUS_FLAGS].align = LEFT;
- d[SI_STATUS_FLAGS].x = 11;
- d[SI_STATUS_FLAGS].y = 17;
- d[SI_STATUS_FLAGS].len = 10;
-
- d[SI_IMAGE_ID].prefix = "img: ";
- d[SI_IMAGE_ID].postfix = "";
- d[SI_IMAGE_ID].color.fg = COLOR_RED;
- d[SI_IMAGE_ID].color.bg = COLOR_BLACK;
- d[SI_IMAGE_ID].align = CENTER;
- d[SI_IMAGE_ID].x = 21;
- d[SI_IMAGE_ID].y = 17;
- d[SI_IMAGE_ID].len = 10;
-
- d[SI_LYRICS_ID].prefix = "lyr: ";
- d[SI_LYRICS_ID].postfix = "";
- d[SI_LYRICS_ID].color.fg = COLOR_RED;
- d[SI_LYRICS_ID].color.bg = COLOR_BLACK;
- d[SI_LYRICS_ID].align = CENTER;
- d[SI_LYRICS_ID].x = 31;
- d[SI_LYRICS_ID].y = 17;
- d[SI_LYRICS_ID].len = 11;
-
- d[SI_FORMAT].prefix = "format: ";
- d[SI_FORMAT].postfix = "";
- d[SI_FORMAT].color.fg = COLOR_RED;
- d[SI_FORMAT].color.bg = COLOR_BLACK;
- d[SI_FORMAT].align = CENTER;
- d[SI_FORMAT].x = 42;
- d[SI_FORMAT].y = 17;
- d[SI_FORMAT].len = 18;
-
- d[SI_NUM_PLAYED].prefix = "#";
- d[SI_NUM_PLAYED].postfix = "";
- d[SI_NUM_PLAYED].color.fg = COLOR_RED;
- d[SI_NUM_PLAYED].color.bg = COLOR_BLACK;
- d[SI_NUM_PLAYED].align = LEFT;
- d[SI_NUM_PLAYED].x = 60;
- d[SI_NUM_PLAYED].y = 17;
- d[SI_NUM_PLAYED].len = 5;
-
- d[SI_BITRATE].prefix = "";
- d[SI_BITRATE].postfix = "";
- d[SI_BITRATE].color.fg = COLOR_RED;
- d[SI_BITRATE].color.bg = COLOR_BLACK;
- d[SI_BITRATE].align = CENTER;
- d[SI_BITRATE].x = 65;
- d[SI_BITRATE].y = 17;
- d[SI_BITRATE].len = 13;
-
- d[SI_FREQUENCY].prefix = "";
- d[SI_FREQUENCY].postfix = "";
- d[SI_FREQUENCY].color.fg = COLOR_RED;
- d[SI_FREQUENCY].color.bg = COLOR_BLACK;
- d[SI_FREQUENCY].align = CENTER;
- d[SI_FREQUENCY].x = 78;
- d[SI_FREQUENCY].y = 17;
- d[SI_FREQUENCY].len = 10;
-
- d[SI_SCORE].prefix = "sc: ";
- d[SI_SCORE].postfix = "";
- d[SI_SCORE].color.fg = COLOR_RED;
- d[SI_SCORE].color.bg = COLOR_BLACK;
- d[SI_SCORE].align = CENTER;
- d[SI_SCORE].x = 88;
- d[SI_SCORE].y = 17;
- d[SI_SCORE].len = 10;
-
- d[SI_AUDIOD_STATUS].prefix = "";
- d[SI_AUDIOD_STATUS].postfix = "";
- d[SI_AUDIOD_STATUS].color.fg = COLOR_MAGENTA;
- d[SI_AUDIOD_STATUS].color.bg = COLOR_BLACK;
- d[SI_AUDIOD_STATUS].align = CENTER;
- d[SI_AUDIOD_STATUS].x = 0;
- d[SI_AUDIOD_STATUS].y = 27;
- d[SI_AUDIOD_STATUS].len = 5;
-
- d[SI_DECODER_FLAGS].prefix = "[";
- d[SI_DECODER_FLAGS].postfix = "]";
- d[SI_DECODER_FLAGS].color.fg = COLOR_MAGENTA;
- d[SI_DECODER_FLAGS].color.bg = COLOR_BLACK;
- d[SI_DECODER_FLAGS].align = CENTER;
- d[SI_DECODER_FLAGS].x = 5;
- d[SI_DECODER_FLAGS].y = 27;
- d[SI_DECODER_FLAGS].len = 10;
-
- d[SI_MTIME].prefix = "mod: ";
- d[SI_MTIME].postfix = "";
- d[SI_MTIME].color.fg = COLOR_MAGENTA;
- d[SI_MTIME].color.bg = COLOR_BLACK;
- d[SI_MTIME].align = CENTER;
- d[SI_MTIME].x = 15;
- d[SI_MTIME].y = 27;
- d[SI_MTIME].len = 22;
-
- d[SI_FILE_SIZE].prefix = "";
- d[SI_FILE_SIZE].postfix = "kb";
- d[SI_FILE_SIZE].color.fg = COLOR_MAGENTA;
- d[SI_FILE_SIZE].color.bg = COLOR_BLACK;
- d[SI_FILE_SIZE].align = CENTER;
- d[SI_FILE_SIZE].x = 37;
- d[SI_FILE_SIZE].y = 27;
- d[SI_FILE_SIZE].len = 10;
-
- d[SI_CHANNELS].prefix = "";
- d[SI_CHANNELS].postfix = "ch";
- d[SI_CHANNELS].color.fg = COLOR_MAGENTA;
- d[SI_CHANNELS].color.bg = COLOR_BLACK;
- d[SI_CHANNELS].align = CENTER;
- d[SI_CHANNELS].x = 47;
- d[SI_CHANNELS].y = 27;
- d[SI_CHANNELS].len = 5;
-
- d[SI_LAST_PLAYED].prefix = "lp: ";
- d[SI_LAST_PLAYED].postfix = "";
- d[SI_LAST_PLAYED].color.fg = COLOR_MAGENTA;
- d[SI_LAST_PLAYED].color.bg = COLOR_BLACK;
- d[SI_LAST_PLAYED].align = CENTER;
- d[SI_LAST_PLAYED].x = 52;
- d[SI_LAST_PLAYED].y = 27;
- d[SI_LAST_PLAYED].len = 21;
-
- d[SI_NUM_CHUNKS].prefix = "";
- d[SI_NUM_CHUNKS].postfix = "x";
- d[SI_NUM_CHUNKS].color.fg = COLOR_MAGENTA;
- d[SI_NUM_CHUNKS].color.bg = COLOR_BLACK;
- d[SI_NUM_CHUNKS].align = RIGHT;
- d[SI_NUM_CHUNKS].x = 73;
- d[SI_NUM_CHUNKS].y = 27;
- d[SI_NUM_CHUNKS].len = 11;
-
- d[SI_CHUNK_TIME].prefix = "";
- d[SI_CHUNK_TIME].postfix = "ms";
- d[SI_CHUNK_TIME].color.fg = COLOR_MAGENTA;
- d[SI_CHUNK_TIME].color.bg = COLOR_BLACK;
- d[SI_CHUNK_TIME].align = LEFT;
- d[SI_CHUNK_TIME].x = 84;
- d[SI_CHUNK_TIME].y = 27;
- d[SI_CHUNK_TIME].len = 8;
-
- d[SI_AMPLIFICATION].prefix = "amp:";
- d[SI_AMPLIFICATION].postfix = "";
- d[SI_AMPLIFICATION].color.fg = COLOR_MAGENTA;
- d[SI_AMPLIFICATION].color.bg = COLOR_BLACK;
- d[SI_AMPLIFICATION].align = RIGHT;
- d[SI_AMPLIFICATION].x = 92;
- d[SI_AMPLIFICATION].y = 27;
- d[SI_AMPLIFICATION].len = 8;
-
- d[SI_TECHINFO].prefix = "";
- d[SI_TECHINFO].postfix = "";
- d[SI_TECHINFO].color.fg = COLOR_GREEN;
- d[SI_TECHINFO].color.bg = COLOR_BLACK;
- d[SI_TECHINFO].align = CENTER;
- d[SI_TECHINFO].x = 0;
- d[SI_TECHINFO].y = 43;
- d[SI_TECHINFO].len = 100;
-
- d[SI_TITLE].prefix = "";
- d[SI_TITLE].postfix = ",";
- d[SI_TITLE].color.fg = COLOR_GREEN;
- d[SI_TITLE].color.bg = COLOR_BLACK;
- d[SI_TITLE].align = RIGHT;
- d[SI_TITLE].x = 0;
- d[SI_TITLE].y = 53;
- d[SI_TITLE].len = 45;
-
- d[SI_ARTIST].prefix = " by ";
- d[SI_ARTIST].postfix = "";
- d[SI_ARTIST].color.fg = COLOR_GREEN;
- d[SI_ARTIST].color.bg = COLOR_BLACK;
- d[SI_ARTIST].align = LEFT;
- d[SI_ARTIST].x = 45;
- d[SI_ARTIST].y = 53;
- d[SI_ARTIST].len = 45;
-
- d[SI_YEAR].prefix = "(";
- d[SI_YEAR].postfix = ")";
- d[SI_YEAR].color.fg = COLOR_GREEN;
- d[SI_YEAR].color.bg = COLOR_BLACK;
- d[SI_YEAR].align = RIGHT;
- d[SI_YEAR].x = 90;
- d[SI_YEAR].y = 53;
- d[SI_YEAR].len = 10;
-
- d[SI_ALBUM].prefix = "A: ";
- d[SI_ALBUM].postfix = ",";
- d[SI_ALBUM].color.fg = COLOR_GREEN;
- d[SI_ALBUM].color.bg = COLOR_BLACK;
- d[SI_ALBUM].align = RIGHT;
- d[SI_ALBUM].x = 0;
- d[SI_ALBUM].y = 63;
- d[SI_ALBUM].len = 50;
-
- d[SI_COMMENT].prefix = " C: ";
- d[SI_COMMENT].postfix = "";
- d[SI_COMMENT].color.fg = COLOR_GREEN;
- d[SI_COMMENT].color.bg = COLOR_BLACK;
- d[SI_COMMENT].align = LEFT;
- d[SI_COMMENT].x = 50;
- d[SI_COMMENT].y = 63;
- d[SI_COMMENT].len = 50;
-
- d[SI_AFS_MODE].prefix = "";
- d[SI_AFS_MODE].postfix = "";
- d[SI_AFS_MODE].color.fg = COLOR_YELLOW;
- d[SI_AFS_MODE].color.bg = COLOR_BLACK;
- d[SI_AFS_MODE].align = CENTER;
- d[SI_AFS_MODE].x = 0;
- d[SI_AFS_MODE].y = 77;
- d[SI_AFS_MODE].len = 100;
-
- d[SI_ATTRIBUTES_TXT].prefix = "";
- d[SI_ATTRIBUTES_TXT].postfix = "";
- d[SI_ATTRIBUTES_TXT].color.fg = COLOR_YELLOW;
- d[SI_ATTRIBUTES_TXT].color.bg = COLOR_BLACK;
- d[SI_ATTRIBUTES_TXT].align = CENTER;
- d[SI_ATTRIBUTES_TXT].x = 0;
- d[SI_ATTRIBUTES_TXT].y = 87;
- d[SI_ATTRIBUTES_TXT].len = 100;
-
- d[SI_DIRECTORY].prefix = "dir: ";
- d[SI_DIRECTORY].postfix = "";
- d[SI_DIRECTORY].color.fg = COLOR_YELLOW;
- d[SI_DIRECTORY].color.bg = COLOR_BLACK;
- d[SI_DIRECTORY].align = CENTER;
- d[SI_DIRECTORY].x = 0;
- d[SI_DIRECTORY].y = 97;
- d[SI_DIRECTORY].len = 100;
+ d[SI_play_time].prefix = "";
+ d[SI_play_time].postfix = "";
+ d[SI_play_time].color.fg = COLOR_CYAN;
+ d[SI_play_time].color.bg = COLOR_BLACK;
+ d[SI_play_time].align = CENTER;
+ d[SI_play_time].x = 0;
+ d[SI_play_time].y = 7;
+ d[SI_play_time].len = 35;
+
+ d[SI_basename].prefix = "";
+ d[SI_basename].postfix = "";
+ d[SI_basename].color.fg = COLOR_CYAN;
+ d[SI_basename].color.bg = COLOR_BLACK;
+ d[SI_basename].align = LEFT;
+ d[SI_basename].x = 35;
+ d[SI_basename].y = 7;
+ d[SI_basename].len = 65;
+
+ d[SI_status].prefix = "";
+ d[SI_status].postfix = " ";
+ d[SI_status].color.fg = COLOR_RED;
+ d[SI_status].color.bg = COLOR_BLACK;
+ d[SI_status].align = RIGHT;
+ d[SI_status].x = 0;
+ d[SI_status].y = 17;
+ d[SI_status].len = 11;
+
+ d[SI_status_flags].prefix = "(";
+ d[SI_status_flags].postfix = ")";
+ d[SI_status_flags].color.fg = COLOR_RED;
+ d[SI_status_flags].color.bg = COLOR_BLACK;
+ d[SI_status_flags].align = LEFT;
+ d[SI_status_flags].x = 11;
+ d[SI_status_flags].y = 17;
+ d[SI_status_flags].len = 10;
+
+ d[SI_image_id].prefix = "img: ";
+ d[SI_image_id].postfix = "";
+ d[SI_image_id].color.fg = COLOR_RED;
+ d[SI_image_id].color.bg = COLOR_BLACK;
+ d[SI_image_id].align = CENTER;
+ d[SI_image_id].x = 21;
+ d[SI_image_id].y = 17;
+ d[SI_image_id].len = 10;
+
+ d[SI_lyrics_id].prefix = "lyr: ";
+ d[SI_lyrics_id].postfix = "";
+ d[SI_lyrics_id].color.fg = COLOR_RED;
+ d[SI_lyrics_id].color.bg = COLOR_BLACK;
+ d[SI_lyrics_id].align = CENTER;
+ d[SI_lyrics_id].x = 31;
+ d[SI_lyrics_id].y = 17;
+ d[SI_lyrics_id].len = 11;
+
+ d[SI_format].prefix = "format: ";
+ d[SI_format].postfix = "";
+ d[SI_format].color.fg = COLOR_RED;
+ d[SI_format].color.bg = COLOR_BLACK;
+ d[SI_format].align = CENTER;
+ d[SI_format].x = 42;
+ d[SI_format].y = 17;
+ d[SI_format].len = 18;
+
+ d[SI_num_played].prefix = "#";
+ d[SI_num_played].postfix = "";
+ d[SI_num_played].color.fg = COLOR_RED;
+ d[SI_num_played].color.bg = COLOR_BLACK;
+ d[SI_num_played].align = LEFT;
+ d[SI_num_played].x = 60;
+ d[SI_num_played].y = 17;
+ d[SI_num_played].len = 5;
+
+ d[SI_bitrate].prefix = "";
+ d[SI_bitrate].postfix = "";
+ d[SI_bitrate].color.fg = COLOR_RED;
+ d[SI_bitrate].color.bg = COLOR_BLACK;
+ d[SI_bitrate].align = CENTER;
+ d[SI_bitrate].x = 65;
+ d[SI_bitrate].y = 17;
+ d[SI_bitrate].len = 13;
+
+ d[SI_frequency].prefix = "";
+ d[SI_frequency].postfix = "";
+ d[SI_frequency].color.fg = COLOR_RED;
+ d[SI_frequency].color.bg = COLOR_BLACK;
+ d[SI_frequency].align = CENTER;
+ d[SI_frequency].x = 78;
+ d[SI_frequency].y = 17;
+ d[SI_frequency].len = 10;
+
+ d[SI_score].prefix = "sc: ";
+ d[SI_score].postfix = "";
+ d[SI_score].color.fg = COLOR_RED;
+ d[SI_score].color.bg = COLOR_BLACK;
+ d[SI_score].align = CENTER;
+ d[SI_score].x = 88;
+ d[SI_score].y = 17;
+ d[SI_score].len = 10;
+
+ d[SI_audiod_status].prefix = "";
+ d[SI_audiod_status].postfix = "";
+ d[SI_audiod_status].color.fg = COLOR_MAGENTA;
+ d[SI_audiod_status].color.bg = COLOR_BLACK;
+ d[SI_audiod_status].align = CENTER;
+ d[SI_audiod_status].x = 0;
+ d[SI_audiod_status].y = 27;
+ d[SI_audiod_status].len = 5;
+
+ d[SI_decoder_flags].prefix = "[";
+ d[SI_decoder_flags].postfix = "]";
+ d[SI_decoder_flags].color.fg = COLOR_MAGENTA;
+ d[SI_decoder_flags].color.bg = COLOR_BLACK;
+ d[SI_decoder_flags].align = CENTER;
+ d[SI_decoder_flags].x = 5;
+ d[SI_decoder_flags].y = 27;
+ d[SI_decoder_flags].len = 10;
+
+ d[SI_mtime].prefix = "mod: ";
+ d[SI_mtime].postfix = "";
+ d[SI_mtime].color.fg = COLOR_MAGENTA;
+ d[SI_mtime].color.bg = COLOR_BLACK;
+ d[SI_mtime].align = CENTER;
+ d[SI_mtime].x = 15;
+ d[SI_mtime].y = 27;
+ d[SI_mtime].len = 22;
+
+ d[SI_file_size].prefix = "";
+ d[SI_file_size].postfix = "kb";
+ d[SI_file_size].color.fg = COLOR_MAGENTA;
+ d[SI_file_size].color.bg = COLOR_BLACK;
+ d[SI_file_size].align = CENTER;
+ d[SI_file_size].x = 37;
+ d[SI_file_size].y = 27;
+ d[SI_file_size].len = 10;
+
+ d[SI_channels].prefix = "";
+ d[SI_channels].postfix = "ch";
+ d[SI_channels].color.fg = COLOR_MAGENTA;
+ d[SI_channels].color.bg = COLOR_BLACK;
+ d[SI_channels].align = CENTER;
+ d[SI_channels].x = 47;
+ d[SI_channels].y = 27;
+ d[SI_channels].len = 5;
+
+ d[SI_last_played].prefix = "lp: ";
+ d[SI_last_played].postfix = "";
+ d[SI_last_played].color.fg = COLOR_MAGENTA;
+ d[SI_last_played].color.bg = COLOR_BLACK;
+ d[SI_last_played].align = CENTER;
+ d[SI_last_played].x = 52;
+ d[SI_last_played].y = 27;
+ d[SI_last_played].len = 21;
+
+ d[SI_num_chunks].prefix = "";
+ d[SI_num_chunks].postfix = "x";
+ d[SI_num_chunks].color.fg = COLOR_MAGENTA;
+ d[SI_num_chunks].color.bg = COLOR_BLACK;
+ d[SI_num_chunks].align = RIGHT;
+ d[SI_num_chunks].x = 73;
+ d[SI_num_chunks].y = 27;
+ d[SI_num_chunks].len = 11;
+
+ d[SI_chunk_time].prefix = "";
+ d[SI_chunk_time].postfix = "ms";
+ d[SI_chunk_time].color.fg = COLOR_MAGENTA;
+ d[SI_chunk_time].color.bg = COLOR_BLACK;
+ d[SI_chunk_time].align = LEFT;
+ d[SI_chunk_time].x = 84;
+ d[SI_chunk_time].y = 27;
+ d[SI_chunk_time].len = 8;
+
+ d[SI_amplification].prefix = "amp:";
+ d[SI_amplification].postfix = "";
+ d[SI_amplification].color.fg = COLOR_MAGENTA;
+ d[SI_amplification].color.bg = COLOR_BLACK;
+ d[SI_amplification].align = RIGHT;
+ d[SI_amplification].x = 92;
+ d[SI_amplification].y = 27;
+ d[SI_amplification].len = 8;
+
+ d[SI_techinfo].prefix = "";
+ d[SI_techinfo].postfix = "";
+ d[SI_techinfo].color.fg = COLOR_GREEN;
+ d[SI_techinfo].color.bg = COLOR_BLACK;
+ d[SI_techinfo].align = CENTER;
+ d[SI_techinfo].x = 0;
+ d[SI_techinfo].y = 43;
+ d[SI_techinfo].len = 100;
+
+ d[SI_title].prefix = "";
+ d[SI_title].postfix = ",";
+ d[SI_title].color.fg = COLOR_GREEN;
+ d[SI_title].color.bg = COLOR_BLACK;
+ d[SI_title].align = RIGHT;
+ d[SI_title].x = 0;
+ d[SI_title].y = 53;
+ d[SI_title].len = 45;
+
+ d[SI_artist].prefix = " by ";
+ d[SI_artist].postfix = "";
+ d[SI_artist].color.fg = COLOR_GREEN;
+ d[SI_artist].color.bg = COLOR_BLACK;
+ d[SI_artist].align = LEFT;
+ d[SI_artist].x = 45;
+ d[SI_artist].y = 53;
+ d[SI_artist].len = 45;
+
+ d[SI_year].prefix = "(";
+ d[SI_year].postfix = ")";
+ d[SI_year].color.fg = COLOR_GREEN;
+ d[SI_year].color.bg = COLOR_BLACK;
+ d[SI_year].align = RIGHT;
+ d[SI_year].x = 90;
+ d[SI_year].y = 53;
+ d[SI_year].len = 10;
+
+ d[SI_album].prefix = "A: ";
+ d[SI_album].postfix = ",";
+ d[SI_album].color.fg = COLOR_GREEN;
+ d[SI_album].color.bg = COLOR_BLACK;
+ d[SI_album].align = RIGHT;
+ d[SI_album].x = 0;
+ d[SI_album].y = 63;
+ d[SI_album].len = 50;
+
+ d[SI_comment].prefix = " C: ";
+ d[SI_comment].postfix = "";
+ d[SI_comment].color.fg = COLOR_GREEN;
+ d[SI_comment].color.bg = COLOR_BLACK;
+ d[SI_comment].align = LEFT;
+ d[SI_comment].x = 50;
+ d[SI_comment].y = 63;
+ d[SI_comment].len = 50;
+
+ d[SI_afs_mode].prefix = "";
+ d[SI_afs_mode].postfix = "";
+ d[SI_afs_mode].color.fg = COLOR_YELLOW;
+ d[SI_afs_mode].color.bg = COLOR_BLACK;
+ d[SI_afs_mode].align = CENTER;
+ d[SI_afs_mode].x = 0;
+ d[SI_afs_mode].y = 77;
+ d[SI_afs_mode].len = 100;
+
+ d[SI_attributes_txt].prefix = "";
+ d[SI_attributes_txt].postfix = "";
+ d[SI_attributes_txt].color.fg = COLOR_YELLOW;
+ d[SI_attributes_txt].color.bg = COLOR_BLACK;
+ d[SI_attributes_txt].align = CENTER;
+ d[SI_attributes_txt].x = 0;
+ d[SI_attributes_txt].y = 87;
+ d[SI_attributes_txt].len = 100;
+
+ d[SI_directory].prefix = "dir: ";
+ d[SI_directory].postfix = "";
+ d[SI_directory].color.fg = COLOR_YELLOW;
+ d[SI_directory].color.bg = COLOR_BLACK;
+ d[SI_directory].align = CENTER;
+ d[SI_directory].x = 0;
+ d[SI_directory].y = 97;
+ d[SI_directory].len = 100;
}
struct theme_description {
*/
static struct mood *current_mood;
-/**
- * Rough approximation to sqrt.
+/*
+ * Find the position of the most-significant set bit.
*
- * \param x Integer of which to calculate the sqrt.
+ * Copied and slightly adapted from the linux source tree, version 4.9.39
+ * (2017-07).
+ */
+__a_const static uint32_t fls64(uint64_t v)
+{
+ int n = 63;
+ const uint64_t ones = ~(uint64_t)0U;
+
+ if ((v & (ones << 32)) == 0) {
+ n -= 32;
+ v <<= 32;
+ }
+ if ((v & (ones << (64 - 16))) == 0) {
+ n -= 16;
+ v <<= 16;
+ }
+ if ((v & (ones << (64 - 8))) == 0) {
+ n -= 8;
+ v <<= 8;
+ }
+ if ((v & (ones << (64 - 4))) == 0) {
+ n -= 4;
+ v <<= 4;
+ }
+ if ((v & (ones << (64 - 2))) == 0) {
+ n -= 2;
+ v <<= 2;
+ }
+ if ((v & (ones << (64 - 1))) == 0)
+ n -= 1;
+ return n;
+}
+
+/*
+ * Compute the integer square root floor(sqrt(x)).
*
- * \return An integer res with res * res <= x.
+ * Taken 2007 from the linux source tree.
*/
__a_const static uint64_t int_sqrt(uint64_t x)
{
- uint64_t op, res, one = 1;
- op = x;
- res = 0;
-
- one = one << 62;
- while (one > op)
- one >>= 2;
+ uint64_t op = x, res = 0, one = 1;
+ one = one << (fls64(x) & ~one);
while (one != 0) {
if (op >= res + one) {
op = op - (res + one);
- res = res + 2 * one;
+ res = res + 2 * one;
}
res /= 2;
one /= 4;
}
-// PARA_NOTICE_LOG("sqrt(%llu) = %llu\n", x, res);
return res;
}
{
int ret;
struct private_vorbis_data pvd;
- struct ogg_afh_callback_info vorbis_callback_info = {
+ struct oac_callback_info vorbis_callback_info = {
.packet_callback = vorbis_packet_callback,
.private_data = &pvd,
};
vorbis_info_init(&pvd.vi);
vorbis_comment_init(&pvd.vc);
- ret = ogg_get_file_info(map, numbytes, afhi, &vorbis_callback_info);
+ ret = oac_get_file_info(map, numbytes, afhi, &vorbis_callback_info);
vorbis_info_clear(&pvd.vi);
vorbis_comment_clear(&pvd.vc);
return ret;
}
-struct vorbis_get_header_data {
- ogg_stream_state os;
- char *buf;
- size_t len;
-};
-
-static void add_ogg_page(ogg_page *og, struct vorbis_get_header_data *vghd)
-{
- size_t old_len = vghd->len;
- size_t new_len = vghd->len + og->header_len + og->body_len;
- char *buf = para_realloc(vghd->buf, new_len), *p = buf + old_len;
-
- memcpy(p, og->header, og->header_len);
- memcpy(p + og->header_len, og->body, og->body_len);
- vghd->buf = buf;
- vghd->len = new_len;
- PARA_DEBUG_LOG("header/body/old/new: %li/%li/%zu/%zu\n",
- og->header_len, og->body_len, old_len, new_len);
-}
-
static int vorbis_get_header_callback(ogg_packet *packet, int packet_num,
int serial, __a_unused struct afh_info *afhi, void *private_data)
{
int ret;
- struct vorbis_get_header_data *vghd = private_data;
- ogg_page og;
+ struct oac_custom_header *h = private_data;
static unsigned char dummy_packet[] = {
0x03,
'v', 'o', 'r', 'b', 'i', 's',
};
PARA_DEBUG_LOG("processing ogg packet #%d\n", packet_num);
- if (packet_num > 2)
- return 0;
if (packet_num == 0) {
- ogg_stream_init(&vghd->os, serial);
- ret = ogg_stream_packetin(&vghd->os, packet);
+ oac_custom_header_init(serial, h);
+ ret = oac_custom_header_append(packet, h);
if (ret < 0)
- goto out;
- ret = -E_OGG_STREAM_FLUSH;
- if (ogg_stream_flush(&vghd->os, &og) == 0)
- goto out;
- add_ogg_page(&og, vghd);
+ return ret;
+ oac_custom_header_flush(h);
return 1;
}
if (packet_num == 1) {
PARA_INFO_LOG("replacing metadata packet\n");
replacement.packet = dummy_packet;
replacement.bytes = sizeof(dummy_packet);
- ret = ogg_stream_packetin(&vghd->os, &replacement);
- if (ret >= 0)
- return 1;
- ret = -E_OGG_PACKET_IN;
- goto out;
+ ret = oac_custom_header_append(&replacement, h);
+ return ret < 0? ret : 1;
}
- ret = -E_OGG_PACKET_IN;
- if (ogg_stream_packetin(&vghd->os, packet) < 0)
- goto out;
- while (ogg_stream_flush(&vghd->os, &og))
- add_ogg_page(&og, vghd);
- ret = 0;
-out:
- ogg_stream_clear(&vghd->os);
- return ret;
+ assert(packet_num == 2);
+ ret = oac_custom_header_append(packet, h);
+ if (ret < 0)
+ return ret;
+ oac_custom_header_flush(h);
+ return 0;
}
static void vorbis_get_header(void *map, size_t mapsize, char **buf,
size_t *len)
{
int ret;
- struct vorbis_get_header_data vghd = {.len = 0};
- struct ogg_afh_callback_info cb = {
+ struct oac_custom_header *h = oac_custom_header_new();
+ struct oac_callback_info cb = {
.packet_callback = vorbis_get_header_callback,
- .private_data = &vghd,
+ .private_data = h,
};
- ret = ogg_get_file_info(map, mapsize, NULL, &cb);
- if (ret < 0)
- goto fail;
- *buf = vghd.buf;
- *len = vghd.len;
- PARA_INFO_LOG("created %zu byte ogg vorbis header\n", *len);
- return;
-fail:
- PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+ ret = oac_get_file_info(map, mapsize, NULL, &cb);
+ *len = oac_custom_header_get(buf, h);
+ if (ret < 0) {
+ PARA_ERROR_LOG("could not create ogg/vorbis header: %s\n",
+ para_strerror(-ret));
+ free(*buf);
+ *buf = NULL;
+ *len = 0;
+ } else
+ PARA_INFO_LOG("created %zu byte ogg vorbis header\n", *len);
}
static int vorbis_make_meta_packet(struct taginfo *tags, ogg_packet *result)
ret = vorbis_make_meta_packet(tags, &packet);
if (ret < 0)
return ret;
- ret = ogg_rewrite_tags(map, mapsize, output_fd, (char *)packet.packet,
+ ret = oac_rewrite_tags(map, mapsize, output_fd, (char *)packet.packet,
packet.bytes);
free(packet.packet);
return ret;
/* Taken from decoder_example.c of libvorbis-1.2.3. */
static int process_packets_2_and_3(ogg_sync_state *oss,
ogg_stream_state *stream, struct afh_info *afhi,
- struct ogg_afh_callback_info *ci)
+ struct oac_callback_info *ci)
{
ogg_page page;
ogg_packet packet;
}
static int process_ogg_packets(ogg_sync_state *oss, struct afh_info *afhi,
- struct ogg_afh_callback_info *ci)
+ struct oac_callback_info *ci)
{
ogg_packet packet;
ogg_stream_state stream;
*
* \return Standard.
*/
-int ogg_get_file_info(char *map, size_t numbytes, struct afh_info *afhi,
- struct ogg_afh_callback_info *ci)
+int oac_get_file_info(char *map, size_t numbytes, struct afh_info *afhi,
+ struct oac_callback_info *ci)
{
ogg_sync_state oss;
ogg_page op;
*
* \return Standard.
*/
-int ogg_rewrite_tags(const char *map, size_t map_sz, int fd,
+int oac_rewrite_tags(const char *map, size_t map_sz, int fd,
char *meta_packet, size_t meta_sz)
{
ogg_sync_state oss_in, oss_out;
ogg_stream_clear(so);
return ret;
}
+
+/* Structure for providing custom headers for streaming. */
+struct oac_custom_header {
+ char *buf;
+ size_t len;
+ ogg_stream_state oss;
+};
+
+/**
+ * Allocate and return a custom header structure.
+ *
+ * For some audio codecs which employ the ogg container format, the server side
+ * wants to replace the meta tags at the beginning of the file because they are
+ * not needed for streaming and can be arbitrary large. The structure returned
+ * by this function is typically used as the ->private field of struct \ref
+ * oac_callback_info for \ref oac_get_file_info(). This allows the audio format
+ * handler to set up a custom header which is identical to the original header,
+ * but with the meta data part replaced by fixed length dummy contents.
+ *
+ * \return The returned memory must be initialized with the serial number of
+ * the ogg stream before ogg packets can be submitted to it. This is not done
+ * here because the header structure is allocated before \ref
+ * oac_get_file_info() is called, and the serial number is not known at this
+ * point.
+ *
+ * \sa \ref oac_custom_header_init().
+ */
+struct oac_custom_header *oac_custom_header_new(void)
+{
+ return para_calloc(sizeof(struct oac_custom_header));
+}
+
+/**
+ * Set the serial number of an allocated header structure.
+ *
+ * \param serial Passed to the callback function.
+ * \param h As returned from \ref oac_custom_header_new().
+ *
+ * This function must be called before any packets are submitted.
+ */
+void oac_custom_header_init(int serial, struct oac_custom_header *h)
+{
+ ogg_stream_init(&h->oss, serial);
+}
+
+/**
+ * Submit an ogg packet to a custom header structure.
+ *
+ * \param op The packet to append.
+ * \param h Must be initialized.
+ *
+ * The packet may be the one which was passed to the callback, or a completely
+ * different one, like a dummy metadata packet.
+ *
+ * \return Standard.
+ */
+int oac_custom_header_append(ogg_packet *op, struct oac_custom_header *h)
+{
+ return ogg_stream_packetin(&h->oss, op) < 0? -E_OGG_PACKET_IN : 1;
+}
+
+/**
+ * Force remaining packets into an ogg page.
+ *
+ * \param h Should contain submitted but not yet flushed packets.
+ *
+ * This is called after the first packet has been submitted with \ref
+ * oac_custom_header_append() to make sure the first ogg page contains only
+ * this packet. Also when header processing is complete, the callbacks call
+ * this to force the previously submitted packets into a page.
+ */
+void oac_custom_header_flush(struct oac_custom_header *h)
+{
+ ogg_page og;
+
+ while (ogg_stream_flush(&h->oss, &og)) {
+ size_t len = og.header_len + og.body_len;
+ h->buf = para_realloc(h->buf, h->len + len);
+ memcpy(h->buf + h->len, og.header, og.header_len);
+ memcpy(h->buf + h->len + og.header_len, og.body, og.body_len);
+ h->len += len;
+ }
+}
+
+/**
+ * Return the custom header buffer and deallocate resources.
+ *
+ * This is called after the ogg packets which comprise the header have been
+ * submitted and flushed.
+ *
+ * \param buf Result pointer.
+ * \param h Must not be used any more after the call.
+ *
+ * \return The size of the header. This is the sum of the sizes of all ogg
+ * pages that have been flushed out.
+ */
+size_t oac_custom_header_get(char **buf, struct oac_custom_header *h)
+{
+ size_t ret = h->len;
+
+ *buf = h->buf;
+ ogg_stream_clear(&h->oss);
+ free(h);
+ return ret;
+}
* handlers that use the ogg container format.
*/
+struct oac_custom_header *oac_custom_header_new(void);
+void oac_custom_header_init(int serial, struct oac_custom_header *h);
+int oac_custom_header_append(ogg_packet *op, struct oac_custom_header *h);
+void oac_custom_header_flush(struct oac_custom_header *h);
+size_t oac_custom_header_get(char **buf, struct oac_custom_header *h);
+
/**
* Callback structure provided by audio format handlers.
*
* function whose purpose is to extract the meta information about the audio
* file from the first few ogg packets of the bitstream.
*/
-struct ogg_afh_callback_info {
+struct oac_callback_info {
/**
* ogg_get_file_info() calls this function for the first three ogg
* packets, or until the callback returns a non-positive value. If it
void *private_data;
};
-int ogg_get_file_info(char *map, size_t numbytes, struct afh_info *afhi,
- struct ogg_afh_callback_info *ci);
-int ogg_rewrite_tags(const char *map, size_t mapsize, int fd,
+int oac_get_file_info(char *map, size_t numbytes, struct afh_info *afhi,
+ struct oac_callback_info *ci);
+int oac_rewrite_tags(const char *map, size_t mapsize, int fd,
char *meta_packet, size_t meta_sz);
return 1;
}
+/*
+ * Ogg/Opus has two mandatory header packets:
+ *
+ * 1. ID header (identifies the stream as Opus). Dedicated "BOS" ogg page.
+ * 2. Comment header (metadata). May span multiple pages.
+ *
+ * See doc/draft-ietf-codec-oggopus.xml in the opus source tree for details.
+ */
static int opus_packet_callback(ogg_packet *packet, int packet_num,
__a_unused int serial, struct afh_info *afhi,
void *private_data)
int ret, ms;
struct opus_header oh = {.version = 0};
- struct ogg_afh_callback_info opus_callback_info = {
+ struct oac_callback_info opus_callback_info = {
.packet_callback = opus_packet_callback,
.private_data = &oh,
};
- ret = ogg_get_file_info(map, numbytes, afhi, &opus_callback_info);
+ ret = oac_get_file_info(map, numbytes, afhi, &opus_callback_info);
if (ret < 0)
return ret;
ret = (afhi->chunk_table[afhi->chunks_total] - afhi->chunk_table[0]) * 8; /* bits */
int ret;
meta_sz = opus_make_meta_packet(tags, &meta_packet);
- ret = ogg_rewrite_tags(map, mapsize, output_fd, meta_packet, meta_sz);
+ ret = oac_rewrite_tags(map, mapsize, output_fd, meta_packet, meta_sz);
free(meta_packet);
return ret;
}
+/*
+ * See doc/draft-ietf-codec-oggopus.xml in the opus source tree for details
+ * about the format of the comment header.
+ */
+static int opus_get_header_callback(ogg_packet *packet, int packet_num,
+ int serial, __a_unused struct afh_info *afhi, void *private_data)
+{
+ struct oac_custom_header *h = private_data;
+ int ret;
+ static unsigned char dummy_tags[] = { /* a minimal comment header */
+ 'O', 'p', 'u', 's', 'T', 'a', 'g', 's',
+ 0x06, 0x00, 0x00, 0x00, /* vendor string length */
+ 'd', 'u', 'm', 'm', 'y', '\0', /* vendor string */
+ 0x00, 0x00, 0x00, 0x00, /* user comment list length */
+ };
+ ogg_packet replacement;
+
+ if (packet_num == 0) {
+ oac_custom_header_init(serial, h);
+ ret = oac_custom_header_append(packet, h);
+ if (ret < 0)
+ return ret;
+ oac_custom_header_flush(h);
+ return 1;
+ }
+ assert(packet_num == 1);
+ PARA_INFO_LOG("replacing metadata packet\n");
+ replacement = *packet;
+ replacement.packet = dummy_tags;
+ replacement.bytes = sizeof(dummy_tags);
+ ret = oac_custom_header_append(&replacement, h);
+ if (ret < 0)
+ return ret;
+ oac_custom_header_flush(h);
+ return 0;
+}
+
+static void opus_get_header(void *map, size_t mapsize, char **buf,
+ size_t *len)
+{
+ int ret;
+ struct oac_custom_header *h = oac_custom_header_new();
+ struct oac_callback_info cb = {
+ .packet_callback = opus_get_header_callback,
+ .private_data = h,
+ };
+
+ ret = oac_get_file_info(map, mapsize, NULL, &cb);
+ *len = oac_custom_header_get(buf, h);
+ if (ret < 0) {
+ PARA_ERROR_LOG("could not create custom header: %s\n",
+ para_strerror(-ret));
+ free(*buf);
+ *buf = NULL;
+ *len = 0;
+ } else
+ PARA_INFO_LOG("created %zu byte ogg/opus header\n", *len);
+}
+
/**
* The init function of the ogg/opus audio format handler.
*
void opus_afh_init(struct audio_format_handler *afh)
{
afh->get_file_info = opus_get_file_info,
+ afh->get_header = opus_get_header;
afh->suffixes = opus_suffixes;
afh->rewrite_tags = opus_rewrite_tags;
}
struct timeval *result);
struct timeval *clock_get_realtime(struct timeval *tv);
-/** The enum of all status items. */
-enum status_items {STATUS_ITEM_ENUM NUM_STAT_ITEMS};
-extern const char *status_item_list[];
-/** Loop over each status item. */
-#define FOR_EACH_STATUS_ITEM(i) for (i = 0; i < NUM_STAT_ITEMS; i++)
-int for_each_stat_item(char *item_buf, size_t num_bytes,
- int (*item_handler)(int, char *));
-
-
/**
* Return a random non-negative integer in an interval.
*
#define PARA_ERROR_LOG(f,...) para_log(LL_ERROR, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
#define PARA_CRIT_LOG(f,...) para_log(LL_CRIT, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
#define PARA_EMERG_LOG(f,...) para_log(LL_EMERG, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
+
+#define STATUS_ITEMS \
+ STATUS_ITEM(basename) \
+ STATUS_ITEM(status) \
+ STATUS_ITEM(num_played) \
+ STATUS_ITEM(mtime) \
+ STATUS_ITEM(bitrate) \
+ STATUS_ITEM(frequency) \
+ STATUS_ITEM(file_size) \
+ STATUS_ITEM(status_flags) \
+ STATUS_ITEM(format) \
+ STATUS_ITEM(score) \
+ STATUS_ITEM(techinfo) \
+ STATUS_ITEM(afs_mode) \
+ STATUS_ITEM(attributes_txt) \
+ STATUS_ITEM(decoder_flags) \
+ STATUS_ITEM(audiod_status) \
+ STATUS_ITEM(play_time) \
+ STATUS_ITEM(attributes_bitmap) \
+ STATUS_ITEM(offset) \
+ STATUS_ITEM(seconds_total) \
+ STATUS_ITEM(stream_start) \
+ STATUS_ITEM(current_time) \
+ STATUS_ITEM(audiod_uptime) \
+ STATUS_ITEM(image_id) \
+ STATUS_ITEM(lyrics_id) \
+ STATUS_ITEM(duration) \
+ STATUS_ITEM(directory) \
+ STATUS_ITEM(lyrics_name) \
+ STATUS_ITEM(image_name) \
+ STATUS_ITEM(path) \
+ STATUS_ITEM(hash) \
+ STATUS_ITEM(channels) \
+ STATUS_ITEM(last_played) \
+ STATUS_ITEM(num_chunks) \
+ STATUS_ITEM(chunk_time) \
+ STATUS_ITEM(amplification) \
+ STATUS_ITEM(artist) \
+ STATUS_ITEM(title) \
+ STATUS_ITEM(year) \
+ STATUS_ITEM(album) \
+ STATUS_ITEM(comment) \
+ STATUS_ITEM(max_chunk_size) \
+
+#define STATUS_ITEM(_name) SI_ ##_name,
+enum status_items {STATUS_ITEMS NUM_STAT_ITEMS};
+#undef STATUS_ITEM
+#define STATUS_ITEM(_name) #_name,
+
+extern const char *status_item_list[];
+/** Loop over each status item. */
+#define FOR_EACH_STATUS_ITEM(i) for (i = 0; i < NUM_STAT_ITEMS; i++)
+int for_each_stat_item(char *item_buf, size_t num_bytes,
+ int (*item_handler)(int, char *));
/** \file portable_io.h Inline functions for binary IO. */
-static inline uint64_t read_portable(unsigned bits, const char *buf)
+static inline uint64_t read_portable(unsigned bits, const void *buf)
{
uint64_t ret = 0;
int i, num_bytes = bits / 8;
+ const uint8_t *p = (typeof(p))buf;
for (i = 0; i < num_bytes; i++) {
- unsigned char c = buf[i];
+ unsigned char c = p[i];
ret += ((uint64_t)c << (8 * i));
}
return ret;
}
-static inline uint64_t read_portable_be(unsigned bits, const char *buf)
+static inline uint64_t read_portable_be(unsigned bits, const void *buf)
{
uint64_t ret = 0;
int i, num_bytes = bits / 8;
+ const uint8_t *p = (typeof(p))buf;
for (i = 0; i < num_bytes; i++) {
- unsigned char c = buf[i];
+ unsigned char c = p[i];
ret += ((uint64_t)c << (8 * (num_bytes - i - 1)));
}
return ret;
}
-static inline uint64_t read_u64(const char *buf)
+static inline uint64_t read_u64(const void *buf)
{
return read_portable(64, buf);
}
-static inline uint32_t read_u32(const char *buf)
+static inline uint32_t read_u32(const void *buf)
{
return read_portable(32, buf);
}
-static inline uint16_t read_u16(const char *buf)
+static inline uint16_t read_u16(const void *buf)
{
return read_portable(16, buf);
}
-static inline uint8_t read_u8(const char *buf)
+static inline uint8_t read_u8(const void *buf)
{
return read_portable(8, buf);
}
-static inline uint64_t read_u64_be(const char *buf)
+static inline uint64_t read_u64_be(const void *buf)
{
return read_portable_be(64, buf);
}
-static inline uint32_t read_u32_be(const char *buf)
+static inline uint32_t read_u32_be(const void *buf)
{
return read_portable_be(32, buf);
}
-static inline uint16_t read_u16_be(const char *buf)
+static inline uint16_t read_u16_be(const void *buf)
{
return read_portable_be(16, buf);
}
static inline void write_portable(unsigned bits, char *buf, uint64_t val)
{
int i, num_bytes = bits / 8;
+ uint8_t *p = (typeof(p))buf;
+
for (i = 0; i < num_bytes; i++) {
- buf[i] = val & 0xff;
+ p[i] = val & 0xff;
val = val >> 8;
}
}
static inline void write_portable_be(unsigned bits, char *buf, uint64_t val)
{
int i, num_bytes = bits / 8;
+ uint8_t *p = (typeof(p))buf;
+
for (i = 0; i < num_bytes; i++) {
- buf[num_bytes - i - 1] = val & 0xff;
+ p[num_bytes - i - 1] = val & 0xff;
val = val >> 8;
}
}
-static inline void write_u64(char *buf, uint64_t val)
+static inline void write_u64(void *buf, uint64_t val)
{
write_portable(64, buf, val);
}
-static inline void write_u32(char *buf, uint32_t val)
+static inline void write_u32(void *buf, uint32_t val)
{
write_portable(32, buf, (uint64_t) val);
}
-static inline void write_u16(char *buf, uint16_t val)
+static inline void write_u16(void *buf, uint16_t val)
{
write_portable(16, buf, (uint64_t) val);
}
-static inline void write_u8(char *buf, uint8_t val)
+static inline void write_u8(void *buf, uint8_t val)
{
write_portable(8, buf, (uint64_t) val);
}
-static inline void write_u64_be(char *buf, uint64_t val)
+static inline void write_u64_be(void *buf, uint64_t val)
{
write_portable_be(64, buf, val);
}
-static inline void write_u32_be(char *buf, uint32_t val)
+static inline void write_u32_be(void *buf, uint32_t val)
{
write_portable_be(32, buf, (uint64_t) val);
}
-static inline void write_u16_be(char *buf, uint16_t val)
+static inline void write_u16_be(void *buf, uint16_t val)
{
write_portable_be(16, buf, (uint64_t) val);
}
struct afh_info *afhi)
{
struct private_spx_data psd;
- struct ogg_afh_callback_info spx_callback_info = {
+ struct oac_callback_info spx_callback_info = {
.packet_callback = spx_packet_callback,
.private_data = &psd,
};
memset(&psd, 0, sizeof(psd));
- return ogg_get_file_info(map, numbytes, afhi, &spx_callback_info);
+ return oac_get_file_info(map, numbytes, afhi, &spx_callback_info);
}
static size_t spx_make_meta_packet(struct taginfo *tags, char **result)
int ret;
meta_sz = spx_make_meta_packet(tags, &meta_packet);
- ret = ogg_rewrite_tags(map, mapsize, output_fd, meta_packet, meta_sz);
+ ret = oac_rewrite_tags(map, mapsize, output_fd, meta_packet, meta_sz);
free(meta_packet);
return ret;
}
git clone git://git.tuebingen.mpg.de/osl
-- [openssl](http://www.openssl.org/) or
+- [openssl](https://www.openssl.org/) or
[libgcrypt](ftp://ftp.gnupg.org/gcrypt/libgcrypt/). At least one
of these two libraries is needed as the backend for cryptographic
routines on both the server and the client side. Both openssl and
not necessary on the server side, i.e., for sending MP3 files.
- [libid3tag](http://www.underbit.com/products/mad/). For version-2
-ID3 tag support, you willl need the libid3tag development package
+ID3 tag support, you will need the libid3tag development package
`libid3tag0-dev`. Without libid3tag, only version-1 tags are
recognized. The mp3 tagger also needs this library for modifying
(id3v1 and id3v2) tags.
-- [ogg vorbis](http://www.xiph.org/downloads/). For ogg vorbis streams
+- [ogg vorbis](https://www.xiph.org/downloads/). For ogg vorbis streams
you need libogg, libvorbis, libvorbisfile. The corresponding Debian
packages are called `libogg-dev` and `libvorbis-dev`.
libfaad package. Install the faad library from sources (available
through the above link) to get the mp4ff library and header files.
-- [speex](http://www.speex.org/). In order to stream or decode speex
+- [speex](https://www.speex.org/). In order to stream or decode speex
files, libspeex (`libspeex-dev`) is required.
-- [flac](http://flac.sourceforge.net/). To stream or decode files
+- [flac](https://xiph.org/flac/). To stream or decode files
encoded with the _Free Lossless Audio Codec_, libFLAC (`libFLAC-dev`)
must be installed.
- [alsa-lib](ftp://ftp.alsa-project.org/pub/lib/). On Linux, you will
need to have the ALSA development package `libasound2-dev` installed.
-- [libao](http://downloads.xiph.org/releases/ao/). Needed to build
+- [libao](https://ftp.osuosl.org/pub/xiph/releases/ao/). Needed to build
the ao writer (ESD, PulseAudio,...). Debian package: `libao-dev`.
- [curses](ftp://ftp.gnu.org/pub/gnu/ncurses). Needed for
- UDP. Recommended for multicast LAN streaming.
-See the Appendix on [network protocols](/#Network.protocols)
+See the Appendix on [network protocols](#Network.protocols)
for brief descriptions of the various protocols relevant for network
audio streaming with paraslash.
the configure file which is shipped in the tarballs but has to be
generated when compiling from git.
-- [discount](http://www.pell.portland.or.us/~orc/Code/discount). The
+- [discount](http://www.pell.portland.or.us/~orc/Code/discount/). The
HTML version of this manual and some of the paraslash web pages are
written in the Markdown markup language and are translated into html
with the converter of the *Discount* package.
The preferred coding style for paraslash coincides more or less
with the style of the Linux kernel. So rather than repeating what is
-written [there](http://www.kernel.org/doc/Documentation/process/coding-style.rst),
+written [there](https://www.kernel.org/doc/Documentation/process/coding-style.rst),
here are the most important points.
- Burn the GNU coding standards.
---------------------
- [paraslash](http://people.tuebingen.mpg.de/maan/paraslash/)
-- [xmms](http://xmms2.org/wiki/Main_Page)
+- [xmms](https://xmms2.org/wiki/Main_Page)
- [mpg123](http://www.mpg123.de/)
-- [gstreamer](http://gstreamer.freedesktop.org/)
+- [gstreamer](https://gstreamer.freedesktop.org/)
- [icecast](http://www.icecast.org/)
-- [Audio Compress](http://beesbuzz.biz/code/audiocompress.php)
+- [Audio Compress](https://beesbuzz.biz/code/audiocompress.php)
External documentation
----------------------
- [The mathematics of
-Raid6](http://kernel.org/pub/linux/kernel/people/hpa/raid6.pdf)
+Raid6](https://www.kernel.org/pub/linux/kernel/people/hpa/raid6.pdf)
by H. Peter Anvin
- [Effective Erasure Codes for reliable Computer Communication