/** * Insert an entry at a given position in the playlist without * validating it. * * @internal */ void xmms_playlist_insert_entry (xmms_playlist_t *playlist, const gchar *plname, guint32 pos, xmms_medialib_entry_t file, xmms_error_t *err) { xmms_medialib_session_t *session; xmmsv_t *dict; gint currpos; gint len; xmmsv_coll_t *plcoll; gboolean valid; g_mutex_lock (playlist->mutex); do { session = xmms_medialib_session_begin_ro (playlist->medialib); valid = xmms_medialib_check_id (session, file); } while (!xmms_medialib_session_commit (session)); if (!valid) { g_mutex_unlock (playlist->mutex); xmms_error_set (err, XMMS_ERROR_NOENT, "That is not a valid medialib id!"); return; } plcoll = xmms_playlist_get_coll (playlist, plname, err); if (plcoll == NULL) { /* FIXME: happens ? */ g_mutex_unlock (playlist->mutex); return; } len = xmms_playlist_coll_get_size (plcoll); if (pos > len) { xmms_error_set (err, XMMS_ERROR_GENERIC, "Could not insert entry outside of playlist!"); g_mutex_unlock (playlist->mutex); return; } xmmsv_coll_idlist_insert (plcoll, pos, file); /** propagate the MID ! */ dict = xmms_playlist_changed_msg_new (playlist, XMMS_PLAYLIST_CHANGED_INSERT, file, plname); xmmsv_dict_set_int (dict, "position", pos); xmms_playlist_changed_msg_send (playlist, dict); /** update position once client is familiar with the new item. */ currpos = xmms_playlist_coll_get_currpos (plcoll); if (pos <= currpos) { currpos++; xmms_collection_set_int_attr (plcoll, "position", currpos); XMMS_PLAYLIST_CURRPOS_MSG (currpos, plname); } g_mutex_unlock (playlist->mutex); }
static xmmsv_t * medialib_query (xmmsv_coll_t *coll, xmmsv_t *spec, xmms_error_t *err) { xmms_medialib_session_t *session; xmmsv_t *ret; session = xmms_medialib_session_begin (medialib); ret = xmms_medialib_query (session, coll, spec, err); xmms_medialib_session_commit (session); return ret; }
gint32 xmms_medialib_client_get_id (xmms_medialib_t *medialib, const gchar *url, xmms_error_t *error) { xmms_medialib_session_t *session; gint32 ret; do { session = xmms_medialib_session_begin_ro (medialib); ret = xmms_medialib_get_id (session, url, error); } while (!xmms_medialib_session_commit (session)); return ret; }
static void xmms_medialib_client_add_entry (xmms_medialib_t *medialib, const gchar *url, xmms_error_t *error) { xmms_medialib_session_t *session; g_return_if_fail (medialib); g_return_if_fail (url); do { session = xmms_medialib_session_begin (medialib); xmms_medialib_entry_new_encoded (session, url, error); } while (!xmms_medialib_session_commit (session)); }
/** * Insert an entry into the playlist at given position. * Creates a #xmms_medialib_entry for you and insert it * in the list. * * @param playlist the playlist to add it URL to. * @param pos the position where the entry is inserted. * @param url the URL to add. * @param err an #xmms_error_t that should be defined upon error. * @return TRUE on success and FALSE otherwise. * */ static void xmms_playlist_client_insert_url (xmms_playlist_t *playlist, const gchar *plname, gint32 pos, const gchar *url, xmms_error_t *err) { xmms_medialib_session_t *session; xmms_medialib_entry_t entry = 0; do { session = xmms_medialib_session_begin (playlist->medialib); entry = xmms_medialib_entry_new_encoded (session, url, err); } while (!xmms_medialib_session_commit (session)); if (entry) xmms_playlist_insert_entry (playlist, plname, pos, entry, err); }
static void xmms_medialib_client_remove_entry (xmms_medialib_t *medialib, xmms_medialib_entry_t entry, xmms_error_t *error) { xmms_medialib_session_t *session; do { session = xmms_medialib_session_begin (medialib); if (xmms_medialib_check_id (session, entry)) { xmms_medialib_entry_remove (session, entry); } else { xmms_error_set (error, XMMS_ERROR_NOENT, "No such entry"); } } while (!xmms_medialib_session_commit (session)); }
xmms_xform_t * xmms_xform_chain_setup (xmms_medialib_t *medialib, xmms_medialib_entry_t entry, GList *goal_formats, gboolean rehash) { xmms_medialib_session_t *session; xmms_xform_t *ret = NULL; do { session = xmms_medialib_session_begin (medialib); if (ret != NULL) xmms_object_unref (ret); ret = xmms_xform_chain_setup_session (medialib, session, entry, goal_formats, rehash); } while (!xmms_medialib_session_commit (session)); return ret; }
static void xmms_xform_metadata_update (xmms_xform_t *xform) { xmms_medialib_session_t *session; metadata_festate_t info; g_return_if_fail (xform->medialib); do { session = xmms_medialib_session_begin (xform->medialib); info.entry = xform->entry; info.session = session; xmms_xform_metadata_collect_one (xform, &info); } while (!xmms_medialib_session_commit (session)); }
/** * Convenient function for adding a URL to the playlist, * Creates a #xmms_medialib_entry_t for you and adds it * to the list. * * @param playlist the playlist to add it URL to. * @param plname the name of the playlist to modify. * @param nurl the URL to add * @param err an #xmms_error_t that should be defined upon error. * @return TRUE on success and FALSE otherwise. */ void xmms_playlist_client_add_url (xmms_playlist_t *playlist, const gchar *plname, const gchar *nurl, xmms_error_t *err) { xmms_medialib_session_t *session; xmms_medialib_entry_t entry = 0; do { session = xmms_medialib_session_begin (playlist->medialib); entry = xmms_medialib_entry_new_encoded (session, nurl, err); } while (!xmms_medialib_session_commit (session)); if (entry) { xmms_playlist_add_entry (playlist, plname, entry, err); } }
/** * Recursively scan a directory for media files. * * @return a reverse sorted list of encoded urls */ static gboolean process_dir (xmms_medialib_t *medialib, xmmsv_t *entries, const gchar *directory, xmms_error_t *error) { xmmsv_list_iter_t *it; xmmsv_t *list, *val; list = xmms_xform_browse (directory, error); if (!list) { return FALSE; } xmmsv_get_list_iter (list, &it); while (xmmsv_list_iter_entry (it, &val)) { const gchar *str; gint isdir; xmmsv_dict_entry_get_string (val, "path", &str); xmmsv_dict_entry_get_int (val, "isdir", &isdir); if (isdir == 1) { process_dir (medialib, entries, str, error); } else { xmms_medialib_session_t *session; xmms_medialib_entry_t entry; do { session = xmms_medialib_session_begin (medialib); entry = xmms_medialib_entry_new_encoded (session, str, error); } while (!xmms_medialib_session_commit (session)); if (entry) { xmmsv_coll_idlist_append (entries, entry); } } xmmsv_list_iter_remove (it); } xmmsv_unref (list); return TRUE; }
static void xmms_medialib_client_remove_property (xmms_medialib_t *medialib, xmms_medialib_entry_t entry, const gchar *source, const gchar *key, xmms_error_t *error) { xmms_medialib_session_t *session; do { session = xmms_medialib_session_begin (medialib); if (g_ascii_strcasecmp (source, "server") == 0) { xmms_error_set (error, XMMS_ERROR_GENERIC, "Can't remove properties set by the server!"); } else if (xmms_medialib_check_id (session, entry)) { xmms_medialib_property_remove (session, entry, source, key, error); } else { xmms_error_set (error, XMMS_ERROR_NOENT, "No such entry"); } } while (!xmms_medialib_session_commit (session)); }
static xmmsv_t * xmms_medialib_client_get_info (xmms_medialib_t *medialib, xmms_medialib_entry_t entry, xmms_error_t *err) { xmms_medialib_session_t *session; xmmsv_t *ret = NULL; do { session = xmms_medialib_session_begin_ro (medialib); if (xmms_medialib_check_id (session, entry)) { ret = xmms_medialib_entry_to_tree (session, entry); } else { xmms_error_set (err, XMMS_ERROR_NOENT, "No such entry"); } } while (!xmms_medialib_session_commit (session)); return ret; }
/** * Performance test predicate */ static gboolean run_performance_test (xmms_medialib_t *medialib, const gchar *name, xmmsv_t *content, xmmsv_t *coll, xmmsv_t *specification, xmmsv_t *expected, gint format, const gchar *datasetname) { xmms_medialib_session_t *session; xmms_error_t err; GTimeVal t0, t1; guint64 duration; xmmsv_t *ret; session = xmms_medialib_session_begin (medialib); g_get_current_time (&t0); ret = xmms_medialib_query (session, coll, specification, &err); g_get_current_time (&t1); xmms_medialib_session_commit (session); duration = (guint64)((t1.tv_sec - t0.tv_sec) * G_USEC_PER_SEC) + (t1.tv_usec - t0.tv_usec); if (format == FORMAT_PRETTY) g_print ("* Test %s\n", name); if (xmms_error_iserror (&err)) { if (format == FORMAT_CSV) { g_print ("\"%s\",\"%s\",0,0\n", datasetname, name); } else { g_print (" - Query failed: %s\n", xmms_error_message_get (&err)); } } else { if (format == FORMAT_CSV) { g_print ("\"%s\",\"%s\",1,%" G_GUINT64_FORMAT "\n", datasetname, name, duration); } else { g_print (" - Time elapsed: %.3fms\n", duration / 1000.0); } } xmmsv_unref (ret); return TRUE; }
static void xmms_medialib_client_rehash (xmms_medialib_t *medialib, xmms_medialib_entry_t entry, xmms_error_t *error) { xmms_medialib_session_t *session; do { session = xmms_medialib_session_begin (medialib); if (xmms_medialib_check_id (session, entry)) { xmms_medialib_entry_status_set (session, entry, XMMS_MEDIALIB_ENTRY_STATUS_REHASH); } else if (entry == 0) { s4_sourcepref_t *sourcepref; s4_resultset_t *set; s4_val_t *status; gint i; sourcepref = xmms_medialib_session_get_source_preferences (session); status = s4_val_new_int (XMMS_MEDIALIB_ENTRY_STATUS_OK); set = xmms_medialib_filter (session, XMMS_MEDIALIB_ENTRY_PROPERTY_STATUS, status, 0, sourcepref, "song_id", S4_FETCH_PARENT); s4_val_free (status); s4_sourcepref_unref (sourcepref); for (i = 0; i < s4_resultset_get_rowcount (set); i++) { const s4_result_t *res; res = s4_resultset_get_result (set, i, 0); for (; res != NULL; res = s4_result_next (res)) { xmms_medialib_entry_t item; s4_val_get_int (s4_result_get_val (res), &item); xmms_medialib_entry_status_set (session, item, XMMS_MEDIALIB_ENTRY_STATUS_REHASH); } } s4_resultset_free (set); } else { xmms_error_set (error, XMMS_ERROR_NOENT, "No such entry"); } } while (!xmms_medialib_session_commit (session)); }
static void xmms_medialib_client_set_property_int (xmms_medialib_t *medialib, xmms_medialib_entry_t entry, const gchar *source, const gchar *key, gint32 value, xmms_error_t *error) { xmms_medialib_session_t *session; do { session = xmms_medialib_session_begin (medialib); if (g_ascii_strcasecmp (source, "server") == 0) { xmms_error_set (error, XMMS_ERROR_GENERIC, "Can't write to source server!"); } else if (xmms_medialib_check_id (session, entry)) { xmms_medialib_entry_property_set_int_source (session, entry, key, value, source); } else { xmms_error_set (error, XMMS_ERROR_NOENT, "No such entry"); } } while (!xmms_medialib_session_commit (session)); }
xmms_medialib_entry_t xmms_mock_entry (xmms_medialib_t *medialib, gint tracknr, const gchar *artist, const gchar *album, const gchar *title) { xmms_medialib_session_t *session; xmms_medialib_entry_t entry; xmms_error_t err; gchar *path; xmms_error_reset (&err); path = g_strconcat (artist, album, title, NULL); session = xmms_medialib_session_begin (medialib); entry = xmms_medialib_entry_new (session, path, &err); xmms_medialib_entry_property_set_int (session, entry, XMMS_MEDIALIB_ENTRY_PROPERTY_TRACKNR, tracknr); xmms_medialib_entry_property_set_str (session, entry, XMMS_MEDIALIB_ENTRY_PROPERTY_ARTIST, artist); xmms_medialib_entry_property_set_str (session, entry, XMMS_MEDIALIB_ENTRY_PROPERTY_ALBUM, album); xmms_medialib_entry_property_set_str (session, entry, XMMS_MEDIALIB_ENTRY_PROPERTY_TITLE, title); xmms_medialib_entry_property_set_int (session, entry, XMMS_MEDIALIB_ENTRY_PROPERTY_STATUS, XMMS_MEDIALIB_ENTRY_STATUS_OK); xmms_medialib_session_commit (session); g_free (path); return entry; }
/** * Changes the URL of an entry in the medialib. * * @param medialib Medialib pointer * @param entry entry to modify * @param url URL to change to * @param error In case of error this will be filled. */ static void xmms_medialib_client_move_entry (xmms_medialib_t *medialib, xmms_medialib_entry_t entry, const gchar *url, xmms_error_t *error) { xmms_medialib_session_t *session; gchar *encoded; encoded = xmms_medialib_url_encode (url); do { session = xmms_medialib_session_begin (medialib); if (xmms_medialib_check_id (session, entry)) { xmms_medialib_entry_property_set_str_source (session, entry, XMMS_MEDIALIB_ENTRY_PROPERTY_URL, encoded, "server"); } else { xmms_error_set (error, XMMS_ERROR_NOENT, "No such entry"); } } while (!xmms_medialib_session_commit (session)); g_free (encoded); }
/** * Unit test predicate */ static void run_unit_test (xmms_medialib_t *mlib, const gchar *name, xmmsv_t *content, xmmsv_coll_t *coll, xmmsv_t *specification, xmmsv_t *expected, gint format, const gchar *datasetname) { gboolean matches, ordered = FALSE; xmmsv_t *ret, *value; xmms_error_t err; xmms_medialib_t *medialib; xmms_medialib_session_t *session; g_debug ("Running test: %s", name); xmms_ipc_init (); xmms_config_init ("memory://"); xmms_config_property_register ("medialib.path", "memory://", NULL, NULL); medialib = xmms_medialib_init (); populate_medialib (medialib, content); session = xmms_medialib_session_begin (medialib); ret = xmms_medialib_query (session, coll, specification, &err); xmms_medialib_session_commit (session); xmmsv_dict_get (expected, "result", &value); xmmsv_dict_entry_get_int (expected, "ordered", &ordered); if (ordered) { matches = xmmsv_compare (ret, value); } else { matches = xmmsv_compare_unordered (ret, value); } if (matches) { if (format == FORMAT_CSV) { g_print ("\"%s\", 1\n", name); } else { g_print ("............................................................ Success!"); g_print ("\r%s \n", name); } } else { if (format == FORMAT_CSV) { g_print ("\"%s\", 0\n", name); } else { g_print ("............................................................ Failure!"); g_print ("\r%s \n", name); } g_printerr ("The result: "); xmmsv_dump (ret); g_printerr ("Does not equal: "); xmmsv_dump (value); } xmmsv_unref (ret); xmms_object_unref (medialib); xmms_config_shutdown (); xmms_ipc_shutdown (); }
/** * TODO: Should check for '/' in the key, and set source if found. */ static void populate_medialib (xmms_medialib_t *medialib, xmmsv_t *content) { xmms_medialib_session_t *session; xmms_medialib_entry_t entry = 0; xmmsv_list_iter_t *lit; session = xmms_medialib_session_begin (medialib); xmmsv_get_list_iter (content, &lit); while (xmmsv_list_iter_valid (lit)) { xmmsv_dict_iter_t *dit; xmms_error_t err; xmmsv_t *dict; xmms_error_reset (&err); xmmsv_list_iter_entry (lit, &dict); if (xmmsv_dict_has_key (dict, "url")) { const gchar *url; xmmsv_dict_entry_get_string (dict, "url", &url); entry = xmms_medialib_entry_new (session, url, &err); } else { gchar *url; url = g_strdup_printf ("file://%d.mp3", entry + 1); entry = xmms_medialib_entry_new (session, url, &err); g_free (url); } xmmsv_get_dict_iter (dict, &dit); while (xmmsv_dict_iter_valid (dit)) { const gchar *key, *source; gchar **parts; xmmsv_t *container; xmmsv_dict_iter_pair (dit, &key, &container); parts = g_strsplit (key, "/", 2); key = (parts[1] != NULL) ? parts[1] : key; source = (parts[1] != NULL) ? parts[0] : NULL; if (xmmsv_is_type (container, XMMSV_TYPE_STRING)) { const gchar *value; xmmsv_get_string (container, &value); if (source != NULL) { xmms_medialib_entry_property_set_str_source (session, entry, key, value, source); } else { xmms_medialib_entry_property_set_str (session, entry, key, value); } } else { gint32 value; xmmsv_get_int (container, &value); if (source != NULL) { xmms_medialib_entry_property_set_int_source (session, entry, key, value, source); } else { xmms_medialib_entry_property_set_int (session, entry, key, value); } } g_strfreev (parts); xmmsv_dict_iter_next (dit); } xmmsv_list_iter_next (lit); } xmms_medialib_session_commit (session); }
static void * xmms_output_filler (void *arg) { xmms_output_t *output = (xmms_output_t *)arg; xmms_xform_t *chain = NULL; gboolean last_was_kill = FALSE; char buf[4096]; xmms_error_t err; gint ret; xmms_error_reset (&err); g_mutex_lock (&output->filler_mutex); while (output->filler_state != FILLER_QUIT) { if (output->filler_state == FILLER_STOP) { if (chain) { xmms_object_unref (chain); chain = NULL; } xmms_ringbuf_set_eos (output->filler_buffer, TRUE); g_cond_wait (&output->filler_state_cond, &output->filler_mutex); last_was_kill = FALSE; continue; } if (output->filler_state == FILLER_KILL) { if (chain) { xmms_object_unref (chain); chain = NULL; output->filler_state = FILLER_RUN; last_was_kill = TRUE; } else { output->filler_state = FILLER_STOP; } continue; } if (output->filler_state == FILLER_SEEK) { if (!chain) { XMMS_DBG ("Seek without chain, ignoring.."); output->filler_state = FILLER_STOP; continue; } ret = xmms_xform_this_seek (chain, output->filler_seek, XMMS_XFORM_SEEK_SET, &err); if (ret == -1) { XMMS_DBG ("Seeking failed: %s", xmms_error_message_get (&err)); } else { XMMS_DBG ("Seek ok! %d", ret); output->filler_skip = output->filler_seek - ret; if (output->filler_skip < 0) { XMMS_DBG ("Seeked %d samples too far! Updating position...", -output->filler_skip); output->filler_skip = 0; output->filler_seek = ret; } xmms_ringbuf_clear (output->filler_buffer); xmms_ringbuf_hotspot_set (output->filler_buffer, seek_done, NULL, output); } output->filler_state = FILLER_RUN; } if (!chain) { xmms_medialib_entry_t entry; xmms_output_song_changed_arg_t *hsarg; g_mutex_unlock (&output->filler_mutex); entry = xmms_playlist_current_entry (output->playlist); if (!entry) { XMMS_DBG ("No entry from playlist!"); output->filler_state = FILLER_STOP; g_mutex_lock (&output->filler_mutex); continue; } chain = xmms_xform_chain_setup (output->medialib, entry, output->format_list, FALSE); if (!chain) { xmms_medialib_session_t *session; do { session = xmms_medialib_session_begin (output->medialib); if (xmms_medialib_entry_property_get_int (session, entry, XMMS_MEDIALIB_ENTRY_PROPERTY_STATUS) == XMMS_MEDIALIB_ENTRY_STATUS_NEW) { xmms_medialib_entry_remove (session, entry); } else { xmms_medialib_entry_status_set (session, entry, XMMS_MEDIALIB_ENTRY_STATUS_NOT_AVAILABLE); } } while (!xmms_medialib_session_commit (session)); if (!xmms_playlist_advance (output->playlist)) { XMMS_DBG ("End of playlist"); output->filler_state = FILLER_STOP; } g_mutex_lock (&output->filler_mutex); continue; } hsarg = g_new0 (xmms_output_song_changed_arg_t, 1); hsarg->output = output; hsarg->chain = chain; hsarg->flush = last_was_kill; xmms_object_ref (chain); last_was_kill = FALSE; g_mutex_lock (&output->filler_mutex); xmms_ringbuf_hotspot_set (output->filler_buffer, song_changed, song_changed_arg_free, hsarg); } xmms_ringbuf_wait_free (output->filler_buffer, sizeof (buf), &output->filler_mutex); if (output->filler_state != FILLER_RUN) { XMMS_DBG ("State changed while waiting..."); continue; } g_mutex_unlock (&output->filler_mutex); ret = xmms_xform_this_read (chain, buf, sizeof (buf), &err); g_mutex_lock (&output->filler_mutex); if (ret > 0) { gint skip = MIN (ret, output->toskip); output->toskip -= skip; if (ret > skip) { xmms_ringbuf_write_wait (output->filler_buffer, buf + skip, ret - skip, &output->filler_mutex); } } else { if (ret == -1) { /* print error */ xmms_error_reset (&err); } xmms_object_unref (chain); chain = NULL; if (!xmms_playlist_advance (output->playlist)) { XMMS_DBG ("End of playlist"); output->filler_state = FILLER_STOP; } } } if (chain) xmms_object_unref (chain); g_mutex_unlock (&output->filler_mutex); return NULL; }