Beispiel #1
0
static gboolean queue_track_to_scrobble (gpointer data) {
    AUDDBG("The playing track is going to be ENQUEUED!\n.");
    gchar *tab_remover;

    char *queuepath = g_strconcat(aud_get_path(AUD_PATH_USER_DIR),"/scrobbler.log", NULL);

    char *artist = tuple_get_str(playing_track, FIELD_ARTIST);
    char *title  = tuple_get_str(playing_track, FIELD_TITLE);
    char *album  = tuple_get_str(playing_track, FIELD_ALBUM);

    tab_remover = remove_tabs(artist);
    str_unref(artist);
    artist = tab_remover;

    tab_remover = remove_tabs(title);
    str_unref(title);
    title = tab_remover;

    tab_remover = remove_tabs(album);
    str_unref(album);
    album = tab_remover;
    tab_remover = NULL;

    int number = tuple_get_int(playing_track, FIELD_TRACK_NUMBER);
    int length = tuple_get_int(playing_track, FIELD_LENGTH) / 1000;

    //artist, title and timestamp are required for a successful scrobble
    if (  artist != NULL && strlen(artist) > 0
        && title != NULL && strlen(title)  > 0) {

        pthread_mutex_lock(&log_access_mutex);
        FILE *f = fopen(queuepath, "a");

        if (f == NULL) {
            perror("fopen");
        } else {
            //This isn't exactly the scrobbler.log format because the header
            //is missing, but we're sticking to it anyway...
            //See http://www.audioscrobbler.net/wiki/Portable_Player_Logging
            if (fprintf(f, "%s\t%s\t%s\t%i\t%i\t%s\t%"G_GINT64_FORMAT"\n",
                        artist, (album == NULL ? "" : album), title, number, length, "L", timestamp
                       ) < 0) {
                perror("fprintf");
            } else {
                pthread_mutex_lock(&communication_mutex);
                pthread_cond_signal(&communication_signal);
                pthread_mutex_unlock(&communication_mutex);
            }
            fclose(f);
        }
        pthread_mutex_unlock(&log_access_mutex);
    }
    g_free(queuepath);
    g_free(artist);
    g_free(title);
    g_free(album);

    cleanup_current_track();
    return FALSE;
}
Beispiel #2
0
static void decode_rva (Tuple * tuple, const guchar * data, gint size)
{
    const gchar * domain;
    gint channel, adjustment, adjustment_unit, peak, peak_unit;

    if (memchr (data, 0, size) == NULL)
        return;

    domain = (const gchar *) data;

    TAGDBG ("RVA domain: %s\n", domain);

    size -= strlen (domain) + 1;
    data += strlen (domain) + 1;

    while (size > 0)
    {
        if (! decode_rva_block (& data, & size, & channel, & adjustment,
         & adjustment_unit, & peak, & peak_unit))
            break;

        if (channel != 1) /* specific channel? */
            continue;

        if (tuple_get_value_type (tuple, FIELD_GAIN_GAIN_UNIT, NULL) ==
         TUPLE_INT)
            adjustment = adjustment * (gint64) tuple_get_int (tuple,
             FIELD_GAIN_GAIN_UNIT, NULL) / adjustment_unit;
        else
            tuple_associate_int (tuple, FIELD_GAIN_GAIN_UNIT, NULL,
             adjustment_unit);

        if (peak_unit)
        {
            if (tuple_get_value_type (tuple, FIELD_GAIN_PEAK_UNIT, NULL) ==
             TUPLE_INT)
                peak = peak * (gint64) tuple_get_int (tuple,
                 FIELD_GAIN_PEAK_UNIT, NULL) / peak_unit;
            else
                tuple_associate_int (tuple, FIELD_GAIN_PEAK_UNIT, NULL,
                 peak_unit);
        }

        if (! strcasecmp (domain, "album"))
        {
            tuple_associate_int (tuple, FIELD_GAIN_ALBUM_GAIN, NULL, adjustment);

            if (peak_unit)
                tuple_associate_int (tuple, FIELD_GAIN_ALBUM_PEAK, NULL, peak);
        }
        else if (! strcasecmp (domain, "track"))
        {
            tuple_associate_int (tuple, FIELD_GAIN_TRACK_GAIN, NULL, adjustment);

            if (peak_unit)
                tuple_associate_int (tuple, FIELD_GAIN_TRACK_PEAK, NULL, peak);
        }
    }
}
Beispiel #3
0
static int tuple_compare_int (const Tuple * a, const Tuple * b, int field)
{
    if (tuple_get_value_type (a, field, NULL) != TUPLE_INT)
        return (tuple_get_value_type (b, field, NULL) != TUPLE_INT) ? 0 : -1;
    if (tuple_get_value_type (b, field, NULL) != TUPLE_INT)
        return 1;

    int int_a = tuple_get_int (a, field, NULL);
    int int_b = tuple_get_int (b, field, NULL);

    return (int_a < int_b) ? -1 : (int_a > int_b);
}
Beispiel #4
0
Tuple * xs_probe_for_tuple(const char *filename, VFSFile *fd)
{
    Tuple *tuple;
    xs_tuneinfo_t *info;
    int tune = -1;

    pthread_mutex_lock(&xs_status_mutex);
    if (!xs_sidplayfp_probe(fd)) {
        pthread_mutex_unlock(&xs_status_mutex);
        return NULL;
    }
    pthread_mutex_unlock(&xs_status_mutex);

    /* Get information from URL */
    tuple = tuple_new_from_filename (filename);
    tune = tuple_get_int (tuple, FIELD_SUBSONG_NUM);

    /* Get tune information from emulation engine */
    pthread_mutex_lock(&xs_status_mutex);
    info = xs_sidplayfp_getinfo (filename);
    pthread_mutex_unlock(&xs_status_mutex);

    if (info == NULL)
        return tuple;

    xs_get_song_tuple_info(tuple, info, tune);

    if (xs_cfg.subAutoEnable && info->nsubTunes > 1 && ! tune)
        xs_fill_subtunes(tuple, info);

    xs_tuneinfo_free(info);

    return tuple;
}
Beispiel #5
0
static void mlp_hook_playback_begin(gpointer hook_data, gpointer user_data)
{
	gint playlist = mlp_playlist_get_playing();
	gint pos = mlp_playlist_get_position(playlist);

	if (mlp_playlist_entry_get_length (playlist, pos, FALSE) < 30)
	{
		AUDDBG(" *** not submitting due to entry->length < 30");
		return;
	}

	gchar * filename = mlp_playlist_entry_get_filename (playlist, pos);
	if (ishttp (filename))
	{
		AUDDBG(" *** not submitting due to HTTP source");
		str_unref (filename);
		return;
	}
	str_unref (filename);

	sc_idle(m_scrobbler);

	if (submit_tuple)
		tuple_unref (submit_tuple);
	submit_tuple = mlp_playlist_entry_get_tuple (playlist, pos, FALSE);
	if (! submit_tuple)
		return;

	sc_addentry(m_scrobbler, submit_tuple, tuple_get_int(submit_tuple, FIELD_LENGTH, NULL) / 1000);

	if (!track_timeout)
		track_timeout = g_timeout_add_seconds(1, sc_timeout, NULL);
}
Beispiel #6
0
static void insert_vorbis_comment (FLAC__StreamMetadata * meta,
 const char * name, const Tuple * tuple, int field)
{
    TupleValueType type = tuple_field_get_type (field);
    if (tuple_get_value_type (tuple, field, NULL) != type)
        return;

    char * temp;

    switch (type)
    {
    case TUPLE_INT:;
        int ival = tuple_get_int (tuple, field, NULL);
        temp = g_strdup_printf ("%s=%d", name, ival);
        break;
    case TUPLE_STRING:;
        char * sval = tuple_get_str (tuple, field, NULL);
        temp = g_strdup_printf ("%s=%s", name, sval);
        str_unref (sval);
    default:
        return;
    }

    FLAC__StreamMetadata_VorbisComment_Entry comment;
    comment.length = strlen (temp);
    comment.entry = (unsigned char *) temp;

    FLAC__metadata_object_vorbiscomment_insert_comment (meta,
     meta->data.vorbis_comment.num_comments, comment, TRUE);

    g_free (temp);
}
/* builtin-keyword: ${(empty)?}. returns TRUE if <arg> is empty. */
static gboolean
tuple_formatter_expression_empty(Tuple *tuple, const gchar *expression)
{
    gboolean ret = TRUE;
    const gchar *iter;
    TupleValueType type = tuple_get_value_type(tuple, -1, expression);

    if (type == TUPLE_UNKNOWN)
        return TRUE;

    if (type == TUPLE_INT)
        return (tuple_get_int(tuple, -1, expression) == 0);

    iter = tuple_get_string(tuple, -1, expression);
    if (!iter)
        return TRUE;

    while (ret && *iter != '\0')
    {
        if (*iter == ' ')
            iter++;
        else
            ret = FALSE;
    }

    return ret;
}
Beispiel #8
0
static void ready (void *hook_data, void *user_data) {
    cleanup_current_track();

    Tuple *current_track = aud_playlist_entry_get_tuple(aud_playlist_get_playing(), aud_playlist_get_position(aud_playlist_get_playing()), FALSE);

    int duration_seconds = tuple_get_int(current_track, FIELD_LENGTH) / 1000;
    if (duration_seconds <= 30) {
        tuple_unref(current_track);
        return;
    }

    pthread_mutex_lock(&communication_mutex);
    now_playing_track = tuple_ref(current_track);
    now_playing_requested = TRUE;
    pthread_cond_signal(&communication_signal);
    pthread_mutex_unlock(&communication_mutex);

    time_until_scrobble = (((gint64)duration_seconds)*G_USEC_PER_SEC) / 2;
    if (time_until_scrobble > 4*60*G_USEC_PER_SEC) {
        time_until_scrobble = 4*60*G_USEC_PER_SEC;
    }
    timestamp = g_get_real_time() / G_USEC_PER_SEC;
    play_started_at = g_get_monotonic_time();
    playing_track = current_track;

    queue_function_ID = g_timeout_add_seconds(time_until_scrobble / G_USEC_PER_SEC, (GSourceFunc) queue_track_to_scrobble, NULL);

}
Beispiel #9
0
static bool_t audpl_save (const char * path, VFSFile * file,
 const char * title, Index * filenames, Index * tuples)
{
    if (! write_key (file, "title", title))
        return FALSE;

    int count = index_count (filenames);

    for (int i = 0; i < count; i ++)
    {
        if (! write_key (file, "uri", index_get (filenames, i)))
            return FALSE;

        const Tuple * tuple = tuples ? index_get (tuples, i) : NULL;

        if (tuple)
        {
            int keys = 0;

            for (int f = 0; f < TUPLE_FIELDS; f ++)
            {
                if (f == FIELD_FILE_PATH || f == FIELD_FILE_NAME || f == FIELD_FILE_EXT)
                    continue;

                TupleValueType type = tuple_get_value_type (tuple, f, NULL);

                if (type == TUPLE_STRING)
                {
                    char * str = tuple_get_str (tuple, f, NULL);

                    if (! write_key (file, tuple_field_get_name (f), str))
                    {
                        str_unref (str);
                        return FALSE;
                    }

                    str_unref (str);
                    keys ++;
                }
                else if (type == TUPLE_INT)
                {
                    char buf[32];
                    snprintf (buf, sizeof buf, "%d", tuple_get_int (tuple, f, NULL));

                    if (! write_key (file, tuple_field_get_name (f), buf))
                        return FALSE;

                    keys ++;
                }
            }

            /* distinguish between an empty tuple and no tuple at all */
            if (! keys && ! write_key (file, "empty", "1"))
                return FALSE;
        }
    }

    return TRUE;
}
static void set_int_from_tuple (GValue * value, const Tuple * tuple, gint field)
{
    gint i = tuple ? tuple_get_int (tuple, field, NULL) : 0;
    if (i > 0)
        g_value_take_string (value, g_strdup_printf ("%d", i));
    else
        g_value_set_string (value, "");
}
static void insert_int_tuple_field_to_dictionary (const Tuple * tuple, int
 fieldn, GHashTable * dict, const char * key)
{
    int val = tuple_get_int (tuple, fieldn);

    if (val > 0)
        g_hash_table_insert (dict, str_get (key), int_to_str (val));
    else
        g_hash_table_remove (dict, key);
}
Beispiel #12
0
LIBMTP_track_t *track_metadata(Tuple *from_tuple)
{
    LIBMTP_track_t *tr;
    gchar *filename, *uri_path;
    VFSFile *f;
    uint64_t filesize;
    struct stat sb;

    uri_path = strdup_tuple_filename (from_tuple);
    gchar *tmp = g_strescape(uri_path,NULL);
    filename=g_filename_from_uri(tmp,NULL,NULL);
    g_free(tmp);
    /* dealing the stream upload (invalidating)*/
    if(filename)
    {
        f = vfs_fopen(uri_path,"r");
        g_free(uri_path);
        if(vfs_is_streaming(f))
        {
            vfs_fclose(f);
            g_free(filename);
            return NULL;
        }
    }
    else
    {
        g_print("Warning! the filename is NULL, exiting");
        return NULL;

    }

    if ( stat(filename, &sb) == -1 )
    {
#if DEBUG
        g_print("ERROR! encountered while stat()'ing \"%s\"\n",filename);
#endif
        g_free(filename);
        return NULL;
    }
    filesize = (uint64_t) sb.st_size;

    /* track metadata*/
    tr = LIBMTP_new_track_t();
    tr->title = strdup_tuple_field (from_tuple, FIELD_TITLE);
    tr->artist = strdup_tuple_field (from_tuple, FIELD_ARTIST);
    tr->album = strdup_tuple_field (from_tuple, FIELD_ALBUM);
    tr->filesize = filesize;
    tr->filename = strdup_tuple_field (from_tuple, FIELD_FILE_NAME);
    tr->duration = (uint32_t)tuple_get_int(from_tuple, FIELD_LENGTH, NULL);
    tr->filetype = find_filetype (filename);
    tr->genre = strdup_tuple_field (from_tuple, FIELD_GENRE);
    tr->date = strdup_tuple_field (from_tuple, FIELD_YEAR);
    g_free(filename);
    return tr;
}
Beispiel #13
0
/* clears gain info if tuple == NULL */
static void read_gain_from_tuple (const Tuple * tuple)
{
    memset (& gain_from_playlist, 0, sizeof gain_from_playlist);

    if (tuple == NULL)
        return;

    int album_gain = tuple_get_int (tuple, FIELD_GAIN_ALBUM_GAIN, NULL);
    int album_peak = tuple_get_int (tuple, FIELD_GAIN_ALBUM_PEAK, NULL);
    int track_gain = tuple_get_int (tuple, FIELD_GAIN_TRACK_GAIN, NULL);
    int track_peak = tuple_get_int (tuple, FIELD_GAIN_TRACK_PEAK, NULL);
    int gain_unit = tuple_get_int (tuple, FIELD_GAIN_GAIN_UNIT, NULL);
    int peak_unit = tuple_get_int (tuple, FIELD_GAIN_PEAK_UNIT, NULL);

    if (gain_unit)
    {
        gain_from_playlist.album_gain = album_gain / (float) gain_unit;
        gain_from_playlist.track_gain = track_gain / (float) gain_unit;
    }

    if (peak_unit)
    {
        gain_from_playlist.album_peak = album_peak / (float) peak_unit;
        gain_from_playlist.track_peak = track_peak / (float) peak_unit;
    }
}
Beispiel #14
0
static void set_gain_info(Tuple *tuple, int field, int unit_field, const char *text)
{
    int value, unit;

    parse_gain_text(text, &value, &unit);

    if (tuple_get_value_type(tuple, unit_field, NULL) == TUPLE_INT)
        value = value * (int64_t) tuple_get_int(tuple, unit_field, NULL) / unit;
    else
        tuple_set_int(tuple, unit_field, NULL, unit);

    tuple_set_int(tuple, field, NULL, value);
}
Beispiel #15
0
static void add_frameFromTupleInt (const Tuple * tuple, int field, int
 id3_field, GHashTable * dict)
{
    if (tuple_get_value_type (tuple, field) != TUPLE_INT)
    {
        remove_frame (id3_field, dict);
        return;
    }

    char scratch[16];
    str_itoa (tuple_get_int (tuple, field), scratch, sizeof scratch);
    add_text_frame (id3_field, scratch, dict);
}
Beispiel #16
0
static void add_frameFromTupleInt (const Tuple * tuple, gint field, gint
 id3_field, mowgli_dictionary_t * dict)
{
    if (tuple_get_value_type (tuple, field, NULL) != TUPLE_INT)
    {
        remove_frame (id3_field, dict);
        return;
    }

    gchar scratch[16];
    snprintf (scratch, sizeof scratch, "%d", tuple_get_int (tuple, field, NULL));
    add_text_frame (id3_field, scratch, dict);
}
Beispiel #17
0
static void infowin_show (gint list, gint entry, const gchar * filename,
 const Tuple * tuple, PluginHandle * decoder, gboolean updating_enabled)
{
    gchar * tmp;

    if (infowin == NULL)
        create_infowin ();
    else
        clear_infowin ();

    current_file = g_strdup (filename);
    current_decoder = decoder;
    can_write = updating_enabled;

    set_entry_str_from_field (entry_title, tuple, FIELD_TITLE, updating_enabled);
    set_entry_str_from_field (entry_artist, tuple, FIELD_ARTIST,
     updating_enabled);
    set_entry_str_from_field (entry_album, tuple, FIELD_ALBUM, updating_enabled);
    set_entry_str_from_field (entry_comment, tuple, FIELD_COMMENT,
     updating_enabled);
    set_entry_str_from_field (gtk_bin_get_child ((GtkBin *) entry_genre), tuple,
     FIELD_GENRE, updating_enabled);

    tmp = uri_to_display (filename);
    gtk_label_set_text ((GtkLabel *) location_text, tmp);
    g_free (tmp);

    set_entry_int_from_field (entry_year, tuple, FIELD_YEAR, updating_enabled);
    set_entry_int_from_field (entry_track, tuple, FIELD_TRACK_NUMBER,
     updating_enabled);

    infowin_label_set_text (label_format_name, tuple_get_string (tuple,
     FIELD_CODEC, NULL));
    infowin_label_set_text (label_quality, tuple_get_string (tuple,
     FIELD_QUALITY, NULL));

    if (tuple_get_value_type (tuple, FIELD_BITRATE, NULL) == TUPLE_INT)
    {
        tmp = g_strdup_printf (_("%d kb/s"), tuple_get_int (tuple,
         FIELD_BITRATE, NULL));
        infowin_label_set_text (label_bitrate, tmp);
        g_free (tmp);
    }
    else
        infowin_label_set_text (label_bitrate, NULL);

    infowin_entry_set_image (image_artwork, list, entry);

    gtk_window_present ((GtkWindow *) infowin);
}
Beispiel #18
0
static void set_entry_int_from_field (GtkWidget * widget, const Tuple * tuple,
 int fieldn, bool_t editable)
{
    char scratch[32];

    if (tuple_get_value_type (tuple, fieldn, NULL) == TUPLE_INT)
        snprintf (scratch, sizeof scratch, "%d", tuple_get_int (tuple, fieldn,
         NULL));
    else
        scratch[0] = 0;

    gtk_entry_set_text ((GtkEntry *) widget, scratch);
    gtk_editable_set_editable ((GtkEditable *) widget, editable);
}
Beispiel #19
0
static void insert_int_tuple_to_vc (FLAC__StreamMetadata * vc_block,
 const Tuple * tuple, int tuple_name, char * field_name)
{
    FLAC__StreamMetadata_VorbisComment_Entry entry;
    int val = tuple_get_int(tuple, tuple_name, NULL);

    if (val <= 0)
        return;

    SPRINTF (str, "%s=%d", field_name, val);
    entry.entry = (FLAC__byte *) str;
    entry.length = strlen(str);
    FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,
        vc_block->data.vorbis_comment.num_comments, entry, true);
}
/* processes an expression and optional argument pair. */
gchar *
tuple_formatter_process_expr(Tuple *tuple, const gchar *expression,
    const gchar *argument)
{
    TupleFormatterExpression *expr = NULL;
    GList *iter;

    g_return_val_if_fail(tuple != NULL, NULL);
    g_return_val_if_fail(expression != NULL, NULL);

    for (iter = tuple_formatter_expr_list; iter != NULL; iter = iter->next)
    {
        TupleFormatterExpression *tmp = (TupleFormatterExpression *) iter->data;

        if (g_str_has_prefix(expression, tmp->name) == TRUE)
        {
            expr = tmp;
            expression += strlen(tmp->name);
        }
    }

    /* ${artist} */
    if (expr == NULL && argument == NULL)
    {
        TupleValueType type = tuple_get_value_type(tuple, -1, expression);

        switch(type)
        {
        case TUPLE_STRING:
             return g_strdup(tuple_get_string(tuple, -1, expression));
             break;
        case TUPLE_INT:
             return g_strdup_printf("%d", tuple_get_int(tuple, -1, expression));
             break;
        case TUPLE_UNKNOWN:
        default:
             return NULL;
        }
    }
    else if (expr != NULL)
    {
        if (expr->func(tuple, expression) == TRUE && argument != NULL)
            return tuple_formatter_process_construct(tuple, argument);
    }

    return NULL;
}
Beispiel #21
0
static GValue *tuple_value_to_gvalue(const Tuple * tuple, const gchar * key)
{
    GValue *val;
    TupleValueType type = tuple_get_value_type((Tuple *) tuple, -1, key);

    if (type == TUPLE_STRING)
    {
        val = g_new0(GValue, 1);
        g_value_init(val, G_TYPE_STRING);
        g_value_take_string(val, g_strdup(tuple_get_string((Tuple *) tuple, -1, key)));
        return val;
    }
    else if (type == TUPLE_INT)
    {
        val = g_new0(GValue, 1);
        g_value_init(val, G_TYPE_INT);
        g_value_set_int(val, tuple_get_int((Tuple *) tuple, -1, key));
        return val;
    }
    return NULL;
}
Beispiel #22
0
static char * strdup_tuple_field (const Tuple * tuple, int field)
{
    char * sval, * dup;
    int ival;

    switch (tuple_get_value_type (tuple, field, NULL))
    {
    case TUPLE_INT:
        ival = tuple_get_int (tuple, field, NULL);
        dup = g_strdup_printf ("%d", ival);
        break;
    case TUPLE_STRING:
        sval = tuple_get_str (tuple, field, NULL);
        dup = g_strdup (sval);
        str_unref (sval);
        break;
    default:
        dup = NULL;
        break;
    }

    return dup;
}
Beispiel #23
0
Tuple * xs_probe_for_tuple(const gchar *filename, xs_file_t *fd)
{
    Tuple *tuple;
    xs_tuneinfo_t *info;
    gint tune = -1;

    if (xs_status.sidPlayer == NULL || filename == NULL)
        return NULL;

    XS_MUTEX_LOCK(xs_status);
    if (!xs_status.sidPlayer->plrProbe(fd)) {
        XS_MUTEX_UNLOCK(xs_status);
        return NULL;
    }
    XS_MUTEX_UNLOCK(xs_status);

    /* Get information from URL */
    tuple = tuple_new_from_filename (filename);
    tune = tuple_get_int (tuple, FIELD_SUBSONG_NUM, NULL);

    /* Get tune information from emulation engine */
    XS_MUTEX_LOCK(xs_status);
    info = xs_status.sidPlayer->plrGetSIDInfo (filename);
    XS_MUTEX_UNLOCK(xs_status);

    if (info == NULL)
        return tuple;

    xs_get_song_tuple_info(tuple, info, tune);

    if (xs_cfg.subAutoEnable && info->nsubTunes > 1 && ! tune)
        xs_fill_subtunes(tuple, info);

    xs_tuneinfo_free(info);

    return tuple;
}
Beispiel #24
0
static gint vorbis_open(void)
{
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_init(NULL);

    vorbis_info_init(&vi);
    vorbis_comment_init(&vc);

    if (tuple)
    {
        gchar tmpstr[32];
        gint scrint;

        add_string_from_tuple (& vc, "title", tuple, FIELD_TITLE);
        add_string_from_tuple (& vc, "artist", tuple, FIELD_ARTIST);
        add_string_from_tuple (& vc, "album", tuple, FIELD_ALBUM);
        add_string_from_tuple (& vc, "genre", tuple, FIELD_GENRE);
        add_string_from_tuple (& vc, "date", tuple, FIELD_DATE);
        add_string_from_tuple (& vc, "comment", tuple, FIELD_COMMENT);

        if ((scrint = tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL)))
        {
            g_snprintf(tmpstr, sizeof(tmpstr), "%d", scrint);
            vorbis_comment_add_tag(&vc, "tracknumber", tmpstr);
        }

        if ((scrint = tuple_get_int(tuple, FIELD_YEAR, NULL)))
        {
            g_snprintf(tmpstr, sizeof(tmpstr), "%d", scrint);
            vorbis_comment_add_tag(&vc, "year", tmpstr);
        }
    }

    if (vorbis_encode_init_vbr (& vi, input.channels, input.frequency,
     v_base_quality))
    {
        vorbis_info_clear(&vi);
        return 0;
    }

    vorbis_analysis_init(&vd, &vi);
    vorbis_block_init(&vd, &vb);

    srand(time(NULL));
    ogg_stream_init(&os, rand());

    vorbis_analysis_headerout(&vd, &vc, &header, &header_comm, &header_code);

    ogg_stream_packetin(&os, &header);
    ogg_stream_packetin(&os, &header_comm);
    ogg_stream_packetin(&os, &header_code);

    while (ogg_stream_flush (& os, & og))
    {
        write_output(og.header, og.header_len);
        write_output(og.body, og.body_len);
    }

    return 1;
}
Beispiel #25
0
Tuple *flac_probe_for_tuple(const char *filename, VFSFile *fd)
{
    AUDDBG("Probe for tuple.\n");

    Tuple *tuple = NULL;
    FLAC__Metadata_Iterator *iter;
    FLAC__Metadata_Chain *chain;
    FLAC__StreamMetadata *metadata = NULL;
    FLAC__Metadata_ChainStatus status;
    FLAC__StreamMetadata_VorbisComment_Entry *entry;
    char *key;
    char *value;

    tuple = tuple_new_from_filename(filename);

    tuple_set_str(tuple, FIELD_CODEC, NULL, "Free Lossless Audio Codec (FLAC)");
    tuple_set_str(tuple, FIELD_QUALITY, NULL, _("lossless"));

    chain = FLAC__metadata_chain_new();

    if (!FLAC__metadata_chain_read_with_callbacks(chain, fd, io_callbacks))
        goto ERR;

    iter = FLAC__metadata_iterator_new();

    FLAC__metadata_iterator_init(iter, chain);

    do
    {
        switch (FLAC__metadata_iterator_get_block_type(iter))
        {
            case FLAC__METADATA_TYPE_VORBIS_COMMENT:

                if (FLAC__metadata_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_VORBIS_COMMENT)
                {
                    metadata = FLAC__metadata_iterator_get_block(iter);

                    AUDDBG("Vorbis comment contains %d fields\n", metadata->data.vorbis_comment.num_comments);
                    AUDDBG("Vendor string: %s\n", metadata->data.vorbis_comment.vendor_string.entry);

                    entry = metadata->data.vorbis_comment.comments;

                    for (int i = 0; i < metadata->data.vorbis_comment.num_comments; i++, entry++)
                    {
                        if (FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(*entry, &key, &value) == false)
                            AUDDBG("Could not parse comment\n");
                        else
                        {
                            parse_comment(tuple, key, value);
                            free(key);
                            free(value);
                        }
                    }
                }
                break;

            case FLAC__METADATA_TYPE_STREAMINFO:
                metadata = FLAC__metadata_iterator_get_block(iter);

                /* Calculate the stream length (milliseconds) */
                if (metadata->data.stream_info.sample_rate == 0)
                {
                    FLACNG_ERROR("Invalid sample rate for stream!\n");
                    tuple_set_int(tuple, FIELD_LENGTH, NULL, -1);
                }
                else
                {
                    tuple_set_int(tuple, FIELD_LENGTH, NULL,
                        (metadata->data.stream_info.total_samples / metadata->data.stream_info.sample_rate) * 1000);
                    AUDDBG("Stream length: %d seconds\n", tuple_get_int(tuple, FIELD_LENGTH, NULL));
                }

                int64_t size = vfs_fsize(fd);

                if (size == -1 || metadata->data.stream_info.total_samples == 0)
                    tuple_set_int(tuple, FIELD_BITRATE, NULL, 0);
                else
                {
                    int bitrate = 8 * size *
                        (int64_t) metadata->data.stream_info.sample_rate / metadata->data.stream_info.total_samples;

                    tuple_set_int(tuple, FIELD_BITRATE, NULL, (bitrate + 500) / 1000);
                }
                break;

            default:
                ;
        }
    } while (FLAC__metadata_iterator_next(iter));

    FLAC__metadata_iterator_delete(iter);
    FLAC__metadata_chain_delete(chain);

    return tuple;

ERR:
    status = FLAC__metadata_chain_status(chain);
    FLAC__metadata_chain_delete(chain);

    FLACNG_ERROR("An error occured: %s\n", FLAC__Metadata_ChainStatusString[status]);
    return tuple;
}
Beispiel #26
0
static gboolean xspf_playlist_save (const gchar * filename, VFSFile * file,
 const gchar * title, Index * filenames, Index * tuples)
{
    gint entries = index_count (filenames);
    xmlDocPtr doc;
    xmlNodePtr rootnode, tracklist;
    gint count;

    doc = xmlNewDoc((xmlChar *)"1.0");
    doc->charset = XML_CHAR_ENCODING_UTF8;
    doc->encoding = xmlStrdup((xmlChar *)"UTF-8");

    rootnode = xmlNewNode(NULL, (xmlChar *)XSPF_ROOT_NODE_NAME);
    xmlSetProp(rootnode, (xmlChar *)"version", (xmlChar *)"1");
    xmlSetProp(rootnode, (xmlChar *)"xmlns", (xmlChar *)XSPF_XMLNS);

    /* common */
    xmlDocSetRootElement(doc, rootnode);

    if (title)
        xspf_add_node (rootnode, TUPLE_STRING, FALSE, "title", title, 0);

    tracklist = xmlNewNode(NULL, (xmlChar *)"trackList");
    xmlAddChild(rootnode, tracklist);

    for (count = 0; count < entries; count ++)
    {
        const gchar * filename = index_get (filenames, count);
        const Tuple * tuple = index_get (tuples, count);
        xmlNodePtr track, location;
        gchar *scratch = NULL;
        gint scratchi = 0;

        track = xmlNewNode(NULL, (xmlChar *)"track");
        location = xmlNewNode(NULL, (xmlChar *)"location");

        xmlAddChild(location, xmlNewText((xmlChar *)filename));
        xmlAddChild(track, location);
        xmlAddChild(tracklist, track);

        if (tuple != NULL)
        {
            gint i;
            for (i = 0; i < xspf_nentries; i++) {
                const xspf_entry_t *xs = &xspf_entries[i];
                gboolean isOK = (tuple_get_value_type (tuple, xs->tupleField,
                 NULL) == xs->type);

                switch (xs->type) {
                    case TUPLE_STRING:
                        scratch = tuple_get_str (tuple, xs->tupleField, NULL);
                        if (! scratch)
                            isOK = FALSE;
                        str_unref(scratch);
                        break;
                    case TUPLE_INT:
                        scratchi = tuple_get_int (tuple, xs->tupleField, NULL);
                        break;
                    default:
                        break;
                }

                if (isOK)
                    xspf_add_node(track, xs->type, xs->isMeta, xs->xspfName, scratch, scratchi);
            }
        }
    }

    xmlSaveCtxt * save = xmlSaveToIO (write_cb, close_cb, file, NULL,
     XML_SAVE_FORMAT);
    if (! save)
        goto ERR;

    if (xmlSaveDoc (save, doc) < 0 || xmlSaveClose (save) < 0)
        goto ERR;

    xmlFreeDoc(doc);
    return TRUE;

ERR:
    xmlFreeDoc (doc);
    return FALSE;
}
static gint file_open(gint fmt, gint rate, gint nch)
{
    gchar *filename = NULL, *temp = NULL;
    gchar * directory;
    gint pos;
    gint rv;
    gint playlist;

    input.format = fmt;
    input.frequency = rate;
    input.channels = nch;

    playlist = aud_playlist_get_playing ();
    if (playlist < 0)
        return 0;

    pos = aud_playlist_get_position(playlist);
    tuple = aud_playlist_entry_get_tuple (playlist, pos, FALSE);
    if (tuple == NULL)
        return 0;

    if (filenamefromtags)
    {
        gchar * utf8 = aud_playlist_entry_get_title (playlist, pos, FALSE);
        string_replace_char (utf8, '/', ' ');

        gchar buf[3 * strlen (utf8) + 1];
        str_encode_percent (utf8, -1, buf);
        str_unref (utf8);

        filename = g_strdup (buf);
    }
    else
    {
        temp = aud_playlist_entry_get_filename (playlist, pos);
        gchar * original = strrchr (temp, '/');
        g_return_val_if_fail (original != NULL, 0);
        filename = g_strdup (original + 1);
        str_unref (temp);

        if (!use_suffix)
            if ((temp = strrchr(filename, '.')) != NULL)
                *temp = '\0';
    }

    if (prependnumber)
    {
        gint number = tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL);
        if (!tuple || !number)
            number = pos + 1;

        temp = g_strdup_printf ("%d%%20%s", number, filename);
        g_free(filename);
        filename = temp;
    }

    if (save_original)
    {
        temp = aud_playlist_entry_get_filename (playlist, pos);
        directory = g_strdup (temp);
        str_unref (temp);
        temp = strrchr (directory, '/');
        g_return_val_if_fail (temp != NULL, 0);
        temp[1] = 0;
    }
    else
    {
        g_return_val_if_fail (file_path[0], 0);
        if (file_path[strlen (file_path) - 1] == '/')
            directory = g_strdup (file_path);
        else
            directory = g_strdup_printf ("%s/", file_path);
    }

    temp = g_strdup_printf ("%s%s.%s", directory, filename, fileext_str[fileext]);
    g_free (directory);
    g_free (filename);
    filename = temp;

    output_file = safe_create (filename);
    g_free (filename);

    if (output_file == NULL)
        return 0;

    convert_init (fmt, plugin->format_required (fmt), nch);

    rv = (plugin->open)();

    samples_written = 0;

    return rv;
}
Beispiel #28
0
static bool_t playlist_load_cue (const char * cue_filename, VFSFile * file,
 char * * title, Index * filenames, Index * tuples)
{
    void * buffer = NULL;
    vfs_file_read_all (file, & buffer, NULL);
    if (! buffer)
        return FALSE;

    * title = NULL;

    Cd * cd = cue_parse_string (buffer);
    g_free (buffer);
    if (cd == NULL)
        return FALSE;

    int tracks = cd_get_ntrack (cd);
    if (tracks == 0)
        return FALSE;

    Track * current = cd_get_track (cd, 1);
    if (current == NULL)
        return FALSE;

    char * track_filename = track_get_filename (current);
    if (track_filename == NULL)
        return FALSE;

    char * filename = uri_construct (track_filename, cue_filename);

    Tuple * base_tuple = NULL;
    bool_t base_tuple_scanned = FALSE;

    for (int track = 1; track <= tracks; track ++)
    {
        if (current == NULL || filename == NULL)
            return FALSE;

        if (base_tuple == NULL && ! base_tuple_scanned)
        {
            base_tuple_scanned = TRUE;
            PluginHandle * decoder = aud_file_find_decoder (filename, FALSE);
            if (decoder != NULL)
                base_tuple = aud_file_read_tuple (filename, decoder);
        }

        Track * next = (track + 1 <= tracks) ? cd_get_track (cd, track + 1) : NULL;
        char * next_filename = (next != NULL) ? uri_construct
         (track_get_filename (next), cue_filename) : NULL;
        bool_t last_track = (next_filename == NULL || strcmp (next_filename, filename));

        Tuple * tuple = (base_tuple != NULL) ? tuple_copy (base_tuple) :
         tuple_new_from_filename (filename);
        tuple_set_int (tuple, FIELD_TRACK_NUMBER, track);

        int begin = (int64_t) track_get_start (current) * 1000 / 75;
        tuple_set_int (tuple, FIELD_SEGMENT_START, begin);

        if (last_track)
        {
            if (base_tuple != NULL && tuple_get_value_type (base_tuple,
             FIELD_LENGTH) == TUPLE_INT)
                tuple_set_int (tuple, FIELD_LENGTH, tuple_get_int
                 (base_tuple, FIELD_LENGTH) - begin);
        }
        else
        {
            int length = (int64_t) track_get_length (current) * 1000 / 75;
            tuple_set_int (tuple, FIELD_LENGTH, length);
            tuple_set_int (tuple, FIELD_SEGMENT_END, begin + length);
        }

        for (int i = 0; i < ARRAY_LEN (pti_map); i ++)
            tuple_attach_cdtext (tuple, current, pti_map[i].tuple_type, pti_map[i].pti);

        index_insert (filenames, -1, str_get (filename));
        index_insert (tuples, -1, tuple);

        current = next;
        str_unref (filename);
        filename = next_filename;

        if (last_track && base_tuple != NULL)
        {
            tuple_unref (base_tuple);
            base_tuple = NULL;
            base_tuple_scanned = FALSE;
        }
    }

    return TRUE;
}
/* builtin-keyword: ${==arg1,arg2}, returns TRUE if <arg1> and <arg2> match.
   <arg1> and <arg2> can also be raw text, which should be enclosed in "double quotes". */
static gboolean
tuple_formatter_expression_match(Tuple *tuple, const gchar *expression)
{
    gchar **args = g_strsplit(expression, ",", 2);
    gchar *arg1 = NULL, *arg2 = NULL;
    gint ret;

    if (args[0][0] == '\"') /* check if arg1 is "raw text" */
    {
        if ( strlen(args[0]) > 1 )
        {
            args[0][strlen(args[0]) - 1] = '\0';
            arg1 = g_strdup(&(args[0][1]));
            args[0][strlen(args[0]) - 1] = '\"';
        }
        else /* bad formatted arg */
            return FALSE;
    }
    else if (tuple_get_value_type(tuple, -1, args[0]) == TUPLE_UNKNOWN)
    {
        g_strfreev(args);
        return FALSE;
    }

    if (args[1][0] == '\"') /* check if arg2 is "raw text" */
    {
        if ( strlen(args[1]) > 1 )
        {
            args[1][strlen(args[1]) - 1] = '\0';
            arg2 = g_strdup(&(args[1][1]));
            args[1][strlen(args[1]) - 1] = '\"';
        }
        else /* bad formatted arg */
            return FALSE;
    }
    else if (tuple_get_value_type(tuple, -1, args[1]) == TUPLE_UNKNOWN)
    {
        g_strfreev(args);
        return FALSE;
    }

    if (!arg1) /* if arg1 is not "raw text", get the tuple value */
    {
        if (tuple_get_value_type(tuple, -1, args[0]) == TUPLE_STRING)
            arg1 = g_strdup(tuple_get_string(tuple, -1, args[0]));
        else
            arg1 = g_strdup_printf("%d", tuple_get_int(tuple, -1, args[0]));
    }

    if (!arg2) /* if arg2 is not "raw text", get the tuple value */
    {
        if (tuple_get_value_type(tuple, -1, args[1]) == TUPLE_STRING)
            arg2 = g_strdup(tuple_get_string(tuple, -1, args[1]));
        else
            arg2 = g_strdup_printf("%d", tuple_get_int(tuple, -1, args[1]));
    }

    ret = g_ascii_strcasecmp(arg1, arg2);
    g_free(arg1);
    g_free(arg2);
    g_strfreev(args);

    return ret ? FALSE : TRUE;
}
static void send_now_playing() {

  gchar *error_code = NULL;
  gchar *error_detail = NULL;
  /*
   * now_playing_track can be set to something else while we this method is
   * running. Creating a local variable avoids to get data for different tracks,
   * while now_playing_track was updated concurrently.
   */
  Tuple *curr_track = now_playing_track;

  gchar *tab_remover;

  gchar *artist = tuple_get_str(curr_track, FIELD_ARTIST, NULL);
  gchar *album = tuple_get_str(curr_track, FIELD_ALBUM, NULL);
  gchar *title = tuple_get_str(curr_track, FIELD_TITLE, NULL);

  tab_remover = remove_tabs(artist);
  str_unref(artist);
  artist = tab_remover;

  tab_remover = remove_tabs(album);
  str_unref(album);
  album = tab_remover;

  tab_remover = remove_tabs(title);
  str_unref(title);
  title = tab_remover;

  tab_remover = NULL;

  gchar *number = g_strdup_printf("%i", tuple_get_int(curr_track, FIELD_TRACK_NUMBER, NULL));
  gchar *length = g_strdup_printf("%i", tuple_get_int(curr_track, FIELD_LENGTH, NULL) / 1000);
  tuple_unref(curr_track);


  if (artist != NULL && strlen(artist) > 0 &&
       title != NULL && strlen(title)  > 0) {

    gchar *playingmsg = create_message_to_lastfm("track.updateNowPlaying",
                                            7,
                                           "artist", artist,
                                           "album", (album == NULL ? "" : album),
                                           "track", title,
                                           "trackNumber", number,
                                           "duration", length,
                                           "api_key", SCROBBLER_API_KEY,
                                           "sk", session_key);
    g_free(artist);
    g_free(album);
    g_free(title);
    g_free(number);
    g_free(length);

    bool_t success = send_message_to_lastfm(playingmsg);
    g_free(playingmsg);
    if (success == FALSE) {
      AUDDBG("Network problems. Could not send \"now playing\" to last.fm\n");
      scrobbling_enabled = FALSE;
      return;
    }

    if (read_scrobble_result(&error_code, &error_detail) == TRUE) {
      //see scrobble_cached_queue()
      AUDDBG("NOW PLAYING OK.\n");
    } else {
      AUDDBG("NOW PLAYING NOT OK. Error code: %s. Error detail: %s.\n", error_code, error_detail);
      //From the API: Now Playing requests that fail should not be retried.

      if (g_strcmp0(error_code, "9") == 0) {
        //Bad Session. Reauth.
        //We don't really care about any other errors.
        scrobbling_enabled = FALSE;
        g_free(session_key);
        session_key = NULL;
        aud_set_string("scrobbler", "session_key", "");
      }

    }
    g_free(error_code);
    g_free(error_detail);
    //We don't care if the now playing was not accepted, no need to read the result from the server.

  }
}