예제 #1
0
/* Fix me:  This considers empty fields as duplicates. */
void playlist_remove_duplicates_by_scheme (int playlist, int scheme)
{
    int entries = playlist_entry_count (playlist);
    int count;

    if (entries < 1)
        return;

    playlist_select_all (playlist, FALSE);

    if (filename_comparisons[scheme] != NULL)
    {
        int (* compare) (const char * a, const char * b) =
         filename_comparisons[scheme];

        playlist_sort_by_filename (playlist, compare);
        char * last = playlist_entry_get_filename (playlist, 0);

        for (count = 1; count < entries; count ++)
        {
            char * current = playlist_entry_get_filename (playlist, count);

            if (compare (last, current) == 0)
                playlist_entry_set_selected (playlist, count, TRUE);

            str_unref (last);
            last = current;
        }

        str_unref (last);
    }
    else if (tuple_comparisons[scheme] != NULL)
    {
        int (* compare) (const Tuple * a, const Tuple * b) =
         tuple_comparisons[scheme];

        playlist_sort_by_tuple (playlist, compare);
        Tuple * last = playlist_entry_get_tuple (playlist, 0, FALSE);

        for (count = 1; count < entries; count ++)
        {
            Tuple * current = playlist_entry_get_tuple (playlist, count, FALSE);

            if (last != NULL && current != NULL && compare (last, current) == 0)
                playlist_entry_set_selected (playlist, count, TRUE);

            if (last)
                tuple_unref (last);
            last = current;
        }

        if (last)
            tuple_unref (last);
    }

    playlist_delete_selected (playlist);
}
예제 #2
0
파일: infowin.c 프로젝트: suaff/audacious
void audgui_infowin_show (int playlist, int entry)
{
    char * filename = aud_playlist_entry_get_filename (playlist, entry);
    g_return_if_fail (filename != NULL);

    PluginHandle * decoder = aud_playlist_entry_get_decoder (playlist, entry,
     FALSE);
    if (decoder == NULL)
        goto FREE;

    if (aud_custom_infowin (filename, decoder))
        goto FREE;

    Tuple * tuple = aud_playlist_entry_get_tuple (playlist, entry, FALSE);

    if (tuple == NULL)
    {
        char * message = g_strdup_printf (_("No info available for %s.\n"),
         filename);
        aud_interface_show_error (message);
        g_free (message);
        goto FREE;
    }

    infowin_show (playlist, entry, filename, tuple, decoder,
     aud_file_can_write_tuple (filename, decoder));
    tuple_unref (tuple);

FREE:
    str_unref (filename);
}
예제 #3
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);

}
예제 #4
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);
}
예제 #5
0
파일: scanner.c 프로젝트: Geotto/audacious
static void scan_request_free (ScanRequest * request)
{
    if (request->tuple)
        tuple_unref (request->tuple);

    str_unref (request->filename);
    g_free (request->image_data);
    str_unref (request->image_file);
    g_slice_free (ScanRequest, request);
}
예제 #6
0
bool_t playlist_save (int list, const char * filename)
{
    AUDDBG ("Saving playlist %s.\n", filename);

    PluginHandle * plugin = get_plugin (filename, TRUE);
    if (! plugin)
        return FALSE;

    PlaylistPlugin * pp = plugin_get_header (plugin);
    g_return_val_if_fail (pp && PLUGIN_HAS_FUNC (pp, load), FALSE);

    bool_t fast = get_bool (NULL, "metadata_on_play");

    VFSFile * file = vfs_fopen (filename, "w");
    if (! file)
        return FALSE;

    char * title = playlist_get_title (list);

    int entries = playlist_entry_count (list);
    Index * filenames = index_new ();
    index_allocate (filenames, entries);
    Index * tuples = index_new ();
    index_allocate (tuples, entries);

    for (int i = 0; i < entries; i ++)
    {
        index_append (filenames, playlist_entry_get_filename (list, i));
        index_append (tuples, playlist_entry_get_tuple (list, i, fast));
    }

    bool_t success = pp->save (filename, file, title, filenames, tuples);

    vfs_fclose (file);
    str_unref (title);

    for (int i = 0; i < entries; i ++)
    {
        str_unref (index_get (filenames, i));
        Tuple * tuple = index_get (tuples, i);
        if (tuple)
            tuple_unref (tuple);
    }

    index_free (filenames);
    index_free (tuples);

    return success;
}
예제 #7
0
static void file_close(void)
{
    plugin->close();
    convert_free();

    if (output_file != NULL)
        vfs_fclose(output_file);
    output_file = NULL;

    if (tuple)
    {
        tuple_unref (tuple);
        tuple = NULL;
    }
}
예제 #8
0
static void mlp_hook_playback_end(gpointer mlp_hook_data, gpointer user_data)
{
	sc_idle(m_scrobbler);

	if (track_timeout)
	{
		g_source_remove(track_timeout);
		track_timeout = 0;
	}

	if (submit_tuple != NULL)
	{
		tuple_unref (submit_tuple);
		submit_tuple = NULL;
	}
}
예제 #9
0
파일: playback.c 프로젝트: i-tek/audacious
static void * playback_thread (void * unused)
{
    PluginHandle * p = playback_entry_get_decoder ();
    current_decoder = p ? plugin_get_header (p) : NULL;

    if (! current_decoder)
    {
        char * error = g_strdup_printf (_("No decoder found for %s."),
         current_filename);
        interface_show_error (error);
        g_free (error);
        playback_error = TRUE;
        goto DONE;
    }

    current_data = NULL;
    current_bitrate = 0;
    current_samplerate = 0;
    current_channels = 0;

    Tuple * tuple = playback_entry_get_tuple ();
    read_gain_from_tuple (tuple);
    if (tuple)
        tuple_unref (tuple);

    bool_t seekable = (playback_entry_get_length () > 0);

    VFSFile * file = vfs_fopen (current_filename, "r");

    time_offset = seekable ? playback_entry_get_start_time () : 0;
    playback_error = ! current_decoder->play (& playback_api, current_filename,
     file, seekable ? time_offset + initial_seek : 0,
     seekable ? playback_entry_get_end_time () : -1, paused);

    output_close_audio ();

    if (file)
        vfs_fclose (file);

DONE:
    if (! ready_flag)
        set_pb_ready (& playback_api);

    end_source = g_timeout_add (0, end_cb, NULL);
    return NULL;
}
예제 #10
0
static void cleanup_current_track(void) {

    timestamp = 0;
    play_started_at = 0;
    pause_started_at = 0;
    time_until_scrobble = 0;
    if (queue_function_ID != 0) {
        gboolean success = g_source_remove(queue_function_ID);
        queue_function_ID = 0;
        if (!success) {
            AUDDBG("BUG: No success on g_source_remove!\n");
        }
    }
    if (playing_track != NULL) {
        tuple_unref(playing_track);
        playing_track = NULL;
    }
}
예제 #11
0
void playlist_select_by_patterns (int playlist, const Tuple * patterns)
{
    const int fields[] = {FIELD_TITLE, FIELD_ALBUM, FIELD_ARTIST,
     FIELD_FILE_NAME};

    int entries = playlist_entry_count (playlist);
    int field, entry;

    playlist_select_all (playlist, TRUE);

    for (field = 0; field < G_N_ELEMENTS (fields); field ++)
    {
        char * pattern = tuple_get_str (patterns, fields[field], NULL);
        regex_t regex;

        if (! pattern || ! pattern[0] || regcomp (& regex, pattern, REG_ICASE))
        {
            str_unref (pattern);
            continue;
        }

        for (entry = 0; entry < entries; entry ++)
        {
            if (! playlist_entry_get_selected (playlist, entry))
                continue;

            Tuple * tuple = playlist_entry_get_tuple (playlist, entry, FALSE);
            char * string = tuple ? tuple_get_str (tuple, fields[field], NULL) : NULL;

            if (! string || regexec (& regex, string, 0, NULL, 0))
                playlist_entry_set_selected (playlist, entry, FALSE);

            str_unref (string);
            if (tuple)
                tuple_unref (tuple);
        }

        regfree (& regex);
        str_unref (pattern);
    }
}
예제 #12
0
GList *
get_upload_list(void)
{
    GList *up_list=NULL;
    gint current_play = aud_playlist_get_active();
    gint i = (aud_playlist_entry_count(current_play) - 1);

    for (; i >= 0; i--)
    {
        if (aud_playlist_entry_get_selected(current_play, i))
        {
            Tuple * tuple = aud_playlist_entry_get_tuple (current_play, i, FALSE);
            aud_playlist_entry_set_selected(current_play, i, FALSE);
            up_list = g_list_prepend (up_list, (void *) tuple);

            if (tuple)
                tuple_unref (tuple);
        }
    }

    return g_list_reverse(up_list);
}
예제 #13
0
파일: infowin.c 프로젝트: suaff/audacious
static void infowin_update_tuple (void * unused)
{
    Tuple * tuple = tuple_new_from_filename (current_file);

    set_field_str_from_entry (tuple, FIELD_TITLE, entry_title);
    set_field_str_from_entry (tuple, FIELD_ARTIST, entry_artist);
    set_field_str_from_entry (tuple, FIELD_ALBUM, entry_album);
    set_field_str_from_entry (tuple, FIELD_COMMENT, entry_comment);
    set_field_str_from_entry (tuple, FIELD_GENRE, gtk_bin_get_child ((GtkBin *)
     entry_genre));
    set_field_int_from_entry (tuple, FIELD_YEAR, entry_year);
    set_field_int_from_entry (tuple, FIELD_TRACK_NUMBER, entry_track);

    if (aud_file_write_tuple (current_file, current_decoder, tuple))
    {
        ministatus_display_message (_("Metadata updated successfully"));
        something_changed = FALSE;
        gtk_widget_set_sensitive (btn_apply, FALSE);
    }
    else
        ministatus_display_message (_("Metadata updating failed"));

    tuple_unref (tuple);
}
예제 #14
0
static void xspf_add_file (xmlNode * track, const gchar * filename, const gchar
 * base, Index * filenames, Index * tuples)
{
    xmlNode *nptr;
    gchar *location = NULL;
    Tuple * tuple = NULL;

    for (nptr = track->children; nptr != NULL; nptr = nptr->next) {
        if (nptr->type == XML_ELEMENT_NODE) {
            if (!xmlStrcmp(nptr->name, (xmlChar *)"location")) {
                /* Location is a special case */
                gchar *str = (gchar *)xmlNodeGetContent(nptr);

                if (strstr (str, "://") != NULL)
                    location = str_get (str);
                else if (str[0] == '/' && base != NULL)
                {
                    const gchar * colon = strstr (base, "://");

                    if (colon != NULL)
                        location = str_printf ("%.*s%s", (gint) (colon + 3 -
                         base), base, str);
                }
                else if (base != NULL)
                {
                    const gchar * slash = strrchr (base, '/');

                    if (slash != NULL)
                        location = str_printf ("%.*s%s", (gint) (slash + 1 -
                         base), base, str);
                }

                xmlFree(str);
            } else {
                /* Rest of the nodes are handled here */
                gint i;
                gboolean isMeta;
                xmlChar *findName;

                if (!xmlStrcmp(nptr->name, (xmlChar *)"meta")) {
                    isMeta = TRUE;
                    findName = xmlGetProp(nptr, (xmlChar *)"rel");
                } else {
                    isMeta = FALSE;
                    findName = xmlStrdup(nptr->name);
                }

                for (i = 0; i < xspf_nentries; i++)
                if ((xspf_entries[i].isMeta == isMeta) &&
                    !xmlStrcmp(findName, (xmlChar *)xspf_entries[i].xspfName)) {
                    xmlChar *str = xmlNodeGetContent(nptr);
                    switch (xspf_entries[i].type) {
                        case TUPLE_STRING:
                            if (! tuple)
                                tuple = tuple_new ();
                            tuple_set_str(tuple, xspf_entries[i].tupleField, NULL, (gchar *)str);
                            break;

                        case TUPLE_INT:
                            if (! tuple)
                                tuple = tuple_new ();
                            tuple_set_int(tuple, xspf_entries[i].tupleField, NULL, atol((char *)str));
                            break;

                        default:
                            break;
                    }
                    xmlFree(str);
                    break;
                }

                xmlFree(findName);
            }
        }
    }

    if (location != NULL)
    {
        if (tuple)
            tuple_set_filename (tuple, location);

        index_append(filenames, location);
        index_append(tuples, tuple);
    }
    else if (tuple)
        tuple_unref (tuple);
}
예제 #15
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;
}
예제 #16
0
static void get_value (void * user, gint row, gint column, GValue * value)
{
    PlaylistWidgetData * data = user;
    g_return_if_fail (column >= 0 && column < pw_num_cols);
    g_return_if_fail (row >= 0 && row < aud_playlist_entry_count (data->list));

    column = pw_cols[column];

    gchar * title = NULL, * artist = NULL, * album = NULL;
    Tuple * tuple = NULL;

    if (column == PW_COL_TITLE || column == PW_COL_ARTIST || column ==
     PW_COL_ALBUM)
        aud_playlist_entry_describe (data->list, row, & title, & artist,
         & album, TRUE);
    else if (column == PW_COL_YEAR || column == PW_COL_TRACK || column ==
     PW_COL_GENRE || column == PW_COL_FILENAME || column == PW_COL_PATH ||
     column == PW_COL_BITRATE)
        tuple = aud_playlist_entry_get_tuple (data->list, row, TRUE);

    switch (column)
    {
    case PW_COL_NUMBER:
        g_value_set_int (value, 1 + row);
        break;
    case PW_COL_TITLE:
        g_value_set_string (value, title);
        break;
    case PW_COL_ARTIST:
        g_value_set_string (value, artist);
        break;
    case PW_COL_YEAR:
        set_int_from_tuple (value, tuple, FIELD_YEAR);
        break;
    case PW_COL_ALBUM:
        g_value_set_string (value, album);
        break;
    case PW_COL_TRACK:
        set_int_from_tuple (value, tuple, FIELD_TRACK_NUMBER);
        break;
    case PW_COL_GENRE:
        set_string_from_tuple (value, tuple, FIELD_GENRE);
        break;
    case PW_COL_QUEUED:
        set_queued (value, data->list, row);
        break;
    case PW_COL_LENGTH:
        set_length (value, data->list, row);
        break;
    case PW_COL_FILENAME:
        set_string_from_tuple (value, tuple, FIELD_FILE_NAME);
        break;
    case PW_COL_PATH:
        set_string_from_tuple (value, tuple, FIELD_FILE_PATH);
        break;
    case PW_COL_CUSTOM:;
        gchar * custom = aud_playlist_entry_get_title (data->list, row, TRUE);
        g_value_set_string (value, custom);
        str_unref (custom);
        break;
    case PW_COL_BITRATE:
        set_int_from_tuple (value, tuple, FIELD_BITRATE);
        break;
    }

    str_unref (title);
    str_unref (artist);
    str_unref (album);
    if (tuple)
        tuple_unref (tuple);
}
예제 #17
0
/* do_command(): do @cmd after replacing the format codes
   @cmd: command to run */
static void do_command (char * cmd)
{
    int playlist = aud_playlist_get_playing ();
    int pos = aud_playlist_get_position (playlist);

    char *shstring = NULL, *temp, numbuf[32];
    gboolean playing;
    Formatter *formatter;

    if (cmd && strlen(cmd) > 0)
    {
        formatter = formatter_new();

        char * ctitle = aud_playlist_entry_get_title (playlist, pos, FALSE);
        if (ctitle)
        {
            temp = escape_shell_chars (ctitle);
            formatter_associate(formatter, 's', temp);
            formatter_associate(formatter, 'n', temp);
            g_free(temp);
            str_unref (ctitle);
        }
        else
        {
            formatter_associate(formatter, 's', "");
            formatter_associate(formatter, 'n', "");
        }

        char * filename = aud_playlist_entry_get_filename (playlist, pos);
        if (filename)
        {
            temp = escape_shell_chars (filename);
            formatter_associate(formatter, 'f', temp);
            g_free(temp);
            str_unref (filename);
        }
        else
            formatter_associate(formatter, 'f', "");

        g_snprintf(numbuf, sizeof(numbuf), "%02d", pos + 1);
        formatter_associate(formatter, 't', numbuf);

        int length = aud_playlist_entry_get_length (playlist, pos, FALSE);
        if (length > 0)
        {
            g_snprintf(numbuf, sizeof(numbuf), "%d", length);
            formatter_associate(formatter, 'l', numbuf);
        }
        else
            formatter_associate(formatter, 'l', "0");

        playing = aud_drct_get_playing();
        g_snprintf(numbuf, sizeof(numbuf), "%d", playing);
        formatter_associate(formatter, 'p', numbuf);

        if (playing)
        {
            int brate, srate, chans;
            aud_drct_get_info (& brate, & srate, & chans);
            snprintf (numbuf, sizeof numbuf, "%d", brate);
            formatter_associate (formatter, 'r', numbuf);
            snprintf (numbuf, sizeof numbuf, "%d", srate);
            formatter_associate (formatter, 'F', numbuf);
            snprintf (numbuf, sizeof numbuf, "%d", chans);
            formatter_associate (formatter, 'c', numbuf);
        }

        Tuple * tuple = aud_playlist_entry_get_tuple
            (aud_playlist_get_active (), pos, 0);

        char * artist = tuple ? tuple_get_str (tuple, FIELD_ARTIST, NULL) : NULL;
        if (artist)
        {
            formatter_associate(formatter, 'a', artist);
            str_unref(artist);
        }
        else
            formatter_associate(formatter, 'a', "");

        char * album = tuple ? tuple_get_str (tuple, FIELD_ALBUM, NULL) : NULL;
        if (album)
        {
            formatter_associate(formatter, 'b', album);
            str_unref(album);
        }
        else
            formatter_associate(formatter, 'b', "");

        char * title = tuple ? tuple_get_str (tuple, FIELD_TITLE, NULL) : NULL;
        if (title)
        {
            formatter_associate(formatter, 'T', title);
            str_unref(title);
        }
        else
            formatter_associate(formatter, 'T', "");

        if (tuple)
            tuple_unref (tuple);

        shstring = formatter_format(formatter, cmd);
        formatter_destroy(formatter);

        if (shstring)
        {
            execute_command(shstring);
            /* FIXME: This can possibly be freed too early */
            g_free(shstring);
        }
    }
}
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.

  }
}
예제 #19
0
static void
test_iterator_restore_after_insertion()
{
	header();

	plan(1);

	/* Create key_def */
	uint32_t fields[] = { 0 };
	uint32_t types[] = { FIELD_TYPE_UNSIGNED };
	struct key_def *key_def = box_key_def_new(fields, types, 1);
	assert(key_def != NULL);

	/* Create format */
	struct tuple_format *format = vy_stmt_format_new(&stmt_env, &key_def, 1,
							 NULL, 0, 0, NULL);
	assert(format != NULL);
	tuple_format_ref(format);

	/* Create lsregion */
	struct lsregion lsregion;
	struct slab_cache *slab_cache = cord_slab_cache();
	lsregion_create(&lsregion, slab_cache->arena);

	struct vy_entry select_key = vy_entry_key_new(stmt_env.key_format,
						      key_def, NULL, 0);

	struct mempool history_node_pool;
	mempool_create(&history_node_pool, cord_slab_cache(),
		       sizeof(struct vy_history_node));

	uint64_t restore_on_value = 20;
	uint64_t restore_on_value_reverse = 60;
	char data[16];
	char *end = data;
	end = mp_encode_array(end, 1);
	end = mp_encode_uint(end, restore_on_value);
	struct vy_entry restore_on_key;
	restore_on_key.stmt = vy_stmt_new_replace(format, data, end);
	restore_on_key.hint = vy_stmt_hint(restore_on_key.stmt, key_def);
	vy_stmt_set_lsn(restore_on_key.stmt, 100);
	end = data;
	end = mp_encode_array(end, 1);
	end = mp_encode_uint(end, restore_on_value_reverse);
	struct vy_entry restore_on_key_reverse;
	restore_on_key_reverse.stmt = vy_stmt_new_replace(format, data, end);
	restore_on_key_reverse.hint = vy_stmt_hint(restore_on_key_reverse.stmt,
						   key_def);
	vy_stmt_set_lsn(restore_on_key_reverse.stmt, 100);

	bool wrong_output = false;
	int i_fail = 0;

	for (uint64_t i = 0; i < ((1000ULL * 3) << 2); i++) {
		uint64_t v = i;
		bool direct = !(v & 1);
		v >>= 1;
		bool has40_50 = v & 1;
		v >>= 1;
		bool has40_150 = v & 1;
		v >>= 1;
		const size_t possible_count = 9;
		uint64_t middle_value = possible_count / 2 * 10; /* 40 */
		bool hasX_100[possible_count]; /* X = 0,10,20,30,40,50,60,70,80 */
		bool addX_100[possible_count]; /* X = 0,10,20,30,40,50,60,70,80 */
		bool add_smth = false;
		for (size_t j = 0; j < possible_count; j++) {
			uint64_t trinity = v % 3;
			v /= 3;
			hasX_100[j] = trinity == 1;
			addX_100[j] = trinity == 2;
			add_smth = add_smth || addX_100[j];
		}
		if (!add_smth)
			continue;
		uint64_t expected_count = 0;
		uint64_t expected_values[possible_count];
		int64_t expected_lsns[possible_count];
		if (direct) {
			for (size_t j = 0; j < possible_count; j++) {
				if (hasX_100[j]) {
					expected_values[expected_count] = j * 10;
					expected_lsns[expected_count] = 100;
					expected_count++;
				} else if (j == possible_count / 2 && has40_50) {
					expected_values[expected_count] = middle_value;
					expected_lsns[expected_count] = 50;
					expected_count++;
				}
			}
		} else {
			for (size_t k = possible_count; k > 0; k--) {
				size_t j = k - 1;
				if (hasX_100[j]) {
					expected_values[expected_count] = j * 10;
					expected_lsns[expected_count] = 100;
					expected_count++;
				} else if (j == possible_count / 2 && has40_50) {
					expected_values[expected_count] = middle_value;
					expected_lsns[expected_count] = 50;
					expected_count++;
				}
			}
		}

		/* Create mem */
		struct vy_mem *mem = create_test_mem(key_def);
		if (has40_50) {
			const struct vy_stmt_template temp =
				STMT_TEMPLATE(50, REPLACE, 40);
			vy_mem_insert_template(mem, &temp);
		}
		if (has40_150) {
			const struct vy_stmt_template temp =
				STMT_TEMPLATE(150, REPLACE, 40);
			vy_mem_insert_template(mem, &temp);
		}
		for (size_t j = 0; j < possible_count; j++) {
			if (hasX_100[j]) {
				const struct vy_stmt_template temp =
					STMT_TEMPLATE(100, REPLACE, j * 10);
				vy_mem_insert_template(mem, &temp);
			}
		}

		struct vy_mem_iterator itr;
		struct vy_mem_iterator_stat stats = {0, {0, 0}};
		struct vy_read_view rv;
		rv.vlsn = 100;
		const struct vy_read_view *prv = &rv;
		vy_mem_iterator_open(&itr, &stats, mem,
				     direct ? ITER_GE : ITER_LE, select_key,
				     &prv);
		struct vy_entry e;
		struct vy_history history;
		vy_history_create(&history, &history_node_pool);
		int rc = vy_mem_iterator_next(&itr, &history);
		e = vy_history_last_stmt(&history);
		assert(rc == 0);
		size_t j = 0;
		while (e.stmt != NULL) {
			if (j >= expected_count) {
				wrong_output = true;
				break;
			}
			uint32_t val = 42;
			tuple_field_u32(e.stmt, 0, &val);
			if (val != expected_values[j] ||
			    vy_stmt_lsn(e.stmt) != expected_lsns[j]) {
				wrong_output = true;
				break;
			}
			j++;
			if (direct && val >= middle_value)
				break;
			else if(!direct && val <= middle_value)
				break;
			int rc = vy_mem_iterator_next(&itr, &history);
			e = vy_history_last_stmt(&history);
			assert(rc == 0);
		}
		if (e.stmt == NULL && j != expected_count)
			wrong_output = true;
		if (wrong_output) {
			i_fail = i;
			break;
		}


		for (size_t j = 0; j < possible_count; j++) {
			if (addX_100[j]) {
				const struct vy_stmt_template temp =
					STMT_TEMPLATE(100, REPLACE, j * 10);
				vy_mem_insert_template(mem, &temp);
			}
		}

		expected_count = 0;
		if (direct) {
			for (size_t j = 0; j < possible_count; j++) {
				if (j * 10 <= restore_on_value)
					continue;
				if (hasX_100[j] || addX_100[j]) {
					expected_values[expected_count] = j * 10;
					expected_lsns[expected_count] = 100;
					expected_count++;
				} else if (j == possible_count / 2 && has40_50) {
					expected_values[expected_count] = middle_value;
					expected_lsns[expected_count] = 50;
					expected_count++;
				}
			}
		} else {
			for (size_t k = possible_count; k > 0; k--) {
				size_t j = k - 1;
				if (j * 10 >= restore_on_value_reverse)
					continue;
				if (hasX_100[j] || addX_100[j]) {
					expected_values[expected_count] = j * 10;
					expected_lsns[expected_count] = 100;
					expected_count++;
				} else if (j == possible_count / 2 && has40_50) {
					expected_values[expected_count] = middle_value;
					expected_lsns[expected_count] = 50;
					expected_count++;
				}
			}
		}

		if (direct)
			rc = vy_mem_iterator_restore(&itr, restore_on_key, &history);
		else
			rc = vy_mem_iterator_restore(&itr, restore_on_key_reverse, &history);
		e = vy_history_last_stmt(&history);

		j = 0;
		while (e.stmt != NULL) {
			if (j >= expected_count) {
				wrong_output = true;
				break;
			}
			uint32_t val = 42;
			tuple_field_u32(e.stmt, 0, &val);
			if (val != expected_values[j] ||
			    vy_stmt_lsn(e.stmt) != expected_lsns[j]) {
				wrong_output = true;
				break;
			}
			j++;
			int rc = vy_mem_iterator_next(&itr, &history);
			e = vy_history_last_stmt(&history);
			assert(rc == 0);
		}
		if (j != expected_count)
			wrong_output = true;
		if (wrong_output) {
			i_fail = i;
			break;
		}

		vy_history_cleanup(&history);
		vy_mem_delete(mem);
		lsregion_gc(&lsregion, 2);
	}

	ok(!wrong_output, "check wrong_output %d", i_fail);

	/* Clean up */
	mempool_destroy(&history_node_pool);

	tuple_unref(select_key.stmt);
	tuple_unref(restore_on_key.stmt);
	tuple_unref(restore_on_key_reverse.stmt);

	tuple_format_unref(format);
	lsregion_destroy(&lsregion);
	key_def_delete(key_def);

	fiber_gc();

	check_plan();

	footer();
}