AudioscrobblerEntry *
rb_audioscrobbler_entry_create (RhythmDBEntry *rb_entry)
{
	AudioscrobblerEntry *as_entry = g_new0 (AudioscrobblerEntry, 1);

	as_entry->title = rhythmdb_entry_dup_string (rb_entry, RHYTHMDB_PROP_TITLE);
	as_entry->track = rhythmdb_entry_get_ulong (rb_entry, RHYTHMDB_PROP_TRACK_NUMBER);
	as_entry->artist = rhythmdb_entry_dup_string (rb_entry, RHYTHMDB_PROP_ARTIST);
	as_entry->album = rhythmdb_entry_dup_string (rb_entry, RHYTHMDB_PROP_ALBUM);
	if (strcmp (as_entry->album, _("Unknown")) == 0) {
		g_free (as_entry->album);
		as_entry->album = g_strdup ("");
	}

	as_entry->length = rhythmdb_entry_get_ulong (rb_entry, RHYTHMDB_PROP_DURATION);
	as_entry->mbid = rhythmdb_entry_dup_string (rb_entry, RHYTHMDB_PROP_MUSICBRAINZ_TRACKID);
	if (strcmp (as_entry->mbid, _("Unknown")) == 0) {
		g_free (as_entry->mbid);
		as_entry->mbid = g_strdup ("");
	}

	/*
	 * TODO: identify the source type.  we just use 'P' for everything for now.
	 * should use 'R' for iradio, 'P' for everything else except last.fm.
	 * for last.fm, we need to extract the recommendation key from the db entry's
	 * extra data (see RBLastfmTrackEntryData in rb-lastfm-source.c) and include
	 * that in the source info here.
	 */
	as_entry->source = g_strdup ("P");

	return as_entry;
}
static LIBMTP_track_t *
transfer_track (RBMtpSource *source,
		LIBMTP_mtpdevice_t *device,
		RhythmDBEntry *entry,
		const char *filename,
		guint64 filesize,
		const char *mimetype)
{
	LIBMTP_track_t *trackmeta = LIBMTP_new_track_t ();
	GDate d;
	int ret;

	trackmeta->title = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_TITLE);
	trackmeta->album = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_ALBUM);
	trackmeta->artist = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_ARTIST);
	trackmeta->genre = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_GENRE);
	trackmeta->filename = g_path_get_basename (filename);

	if (rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DATE) > 0) { /* Entries without a date returns 0, g_date_set_julian don't accept that */
		g_date_set_julian (&d, rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DATE));
		trackmeta->date	= gdate_to_char (&d);
	}
	trackmeta->tracknumber = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TRACK_NUMBER);
	trackmeta->duration = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DURATION) * 1000;
	trackmeta->rating = rhythmdb_entry_get_double (entry, RHYTHMDB_PROP_RATING) * 20;
	trackmeta->usecount = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_PLAY_COUNT);
	trackmeta->filesize = filesize;
	if (mimetype == NULL) {
		mimetype = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MIMETYPE);
	}
	trackmeta->filetype = mimetype_to_filetype (source, mimetype);
	rb_debug ("using libmtp filetype %d (%s) for source media type %s",
		  trackmeta->filetype,
		  LIBMTP_Get_Filetype_Description (trackmeta->filetype),
		  mimetype);

#ifdef HAVE_LIBMTP_030
	ret = LIBMTP_Send_Track_From_File (device, filename, trackmeta, NULL, NULL);
#else
	ret = LIBMTP_Send_Track_From_File (device, filename, trackmeta, NULL, NULL, 0);
#endif
	rb_debug ("LIBMTP_Send_Track_From_File (%s) returned %d", filename, ret);
	if (ret != 0) {
		report_libmtp_errors (device, TRUE);
		LIBMTP_destroy_track_t (trackmeta);
		return NULL;
	}

	if (strcmp (trackmeta->album, _("Unknown")) != 0) {
		add_track_to_album (source, trackmeta->album, trackmeta);
	}

	return trackmeta;
}
示例#3
0
static void
podcast_post_date_cell_data_func (GtkTreeViewColumn *column,
				  GtkCellRenderer *renderer,
				  GtkTreeModel *tree_model,
				  GtkTreeIter *iter,
				  gpointer data)
{
	RhythmDBEntry *entry;
	gulong value;
	char *str;

	gtk_tree_model_get (tree_model, iter, 0, &entry, -1);

	value = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_POST_TIME);
        if (value == 0) {
		str = g_strdup (_("Unknown"));
	} else {
		str = rb_utf_friendly_time (value);
	}

	g_object_set (G_OBJECT (renderer), "text", str, NULL);
	g_free (str);

	rhythmdb_entry_unref (entry);
}
static gboolean
check_entry_grace_period (RhythmDB *db, RhythmDBEntry *entry)
{
	GTimeVal time;
	gulong last_seen;
	gulong grace_period;
	GError *error;

	error = NULL;
	grace_period = g_settings_get_int (db->priv->settings, "grace-period");
	if (error != NULL) {
		g_error_free (error);
		return FALSE;
	}

	/* This is a bit silly, but I prefer to make sure we won't
	 * overflow in the following calculations
	 */
	if ((grace_period <= 0) || (grace_period > 20000)) {
		return FALSE;
	}

	/* Convert from days to seconds */
	grace_period = grace_period * 60 * 60 * 24;
	g_get_current_time (&time);
	last_seen = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_LAST_SEEN);

	return (last_seen + grace_period < time.tv_sec);
}
static double
rb_random_by_age_and_rating_get_entry_weight (RBRandomPlayOrder *rorder, RhythmDB *db, RhythmDBEntry *entry)
{
	time_t now;
	gulong last_play;
	gulong seconds_since_last_play = 0;
	gdouble rating;
	RhythmDBEntry *playing_entry;

	/* This finds the log of the number of seconds since the last play.
	 * It handles never played automatically, since now-0 is a valid
	 * argument to log(). */
	time (&now);

	playing_entry = rb_play_order_get_playing_entry (RB_PLAY_ORDER (rorder));
	if (playing_entry != entry) {
		last_play = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_LAST_PLAYED);
		seconds_since_last_play = now - last_play;
	}
	if (playing_entry != NULL)
		rhythmdb_entry_unref (playing_entry);

	/* The lowest weight should be 0. */
	if (seconds_since_last_play < 1)
		seconds_since_last_play = 1;

	rating = rhythmdb_entry_get_double (entry, RHYTHMDB_PROP_RATING);

	/* treat unrated as 2.5 for the purposes of probabilities */
	if (rating < 0.01)
		rating = 2.5;

	return log (seconds_since_last_play) * (rating + 1.0);
}
示例#6
0
/**
 * rb_source_update_play_statistics:
 * @source: a #RBSource
 * @db: the #RhythmDB instance
 * @entry: the #RhythmDBEntry to update
 *
 * Updates play count and play time statistics for a database entry.
 * Sources containing entries that do not normally reach EOS should
 * call this for an entry when it is no longer being played.
 */
void
rb_source_update_play_statistics (RBSource *source,
				  RhythmDB *db,
				  RhythmDBEntry *entry)
{
	time_t now;
	gulong current_count;
	GValue value = { 0, };

	g_value_init (&value, G_TYPE_ULONG);

	current_count = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_PLAY_COUNT);

	g_value_set_ulong (&value, current_count + 1);

	/* Increment current play count */
	rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_PLAY_COUNT, &value);
	g_value_unset (&value);

	/* Reset the last played time */
	time (&now);

	g_value_init (&value, G_TYPE_ULONG);
	g_value_set_ulong (&value, now);
	rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_LAST_PLAYED, &value);
	g_value_unset (&value);

	rhythmdb_commit (db);
}
示例#7
0
static gint
podcast_post_date_sort_func (RhythmDBEntry *a,
			     RhythmDBEntry *b,
			     RhythmDBQueryModel *model)
{
	gulong a_val, b_val;
	gint ret;

	a_val = rhythmdb_entry_get_ulong (a, RHYTHMDB_PROP_POST_TIME);
	b_val = rhythmdb_entry_get_ulong (b, RHYTHMDB_PROP_POST_TIME);

	if (a_val != b_val)
		ret = (a_val > b_val) ? 1 : -1;
	else
		ret = rhythmdb_query_model_title_sort_func (a, b, model);

        return ret;
}
示例#8
0
/**
 * rb_transfer_target_check_duplicate:
 * @target: an #RBTransferTarget
 * @entry: a #RhythmDBEntry to check
 *
 * This checks for an existing entry in the target that matches
 * the title, album, artist, and track number of the entry being
 * considered.  This can be used to implement @should_transfer.
 *
 * Return value: %TRUE if the entry already exists on the target.
 */
gboolean
rb_transfer_target_check_duplicate (RBTransferTarget *target, RhythmDBEntry *entry)
{
	RhythmDBEntryType *entry_type;
	RhythmDB *db;
	RBShell *shell;
	const char *title;
	const char *album;
	const char *artist;
	gulong track_number;
	GtkTreeModel *query_model;
	GtkTreeIter iter;
	gboolean is_dup;

	g_object_get (target, "shell", &shell, "entry-type", &entry_type, NULL);
	g_object_get (shell, "db", &db, NULL);
	g_object_unref (shell);

	query_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	title = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE);
	album = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM);
	artist = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST);
	track_number = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TRACK_NUMBER);
	rhythmdb_do_full_query (db, RHYTHMDB_QUERY_RESULTS (query_model),
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_TYPE, entry_type,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_ARTIST, artist,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_ALBUM, album,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_TITLE, title,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_TRACK_NUMBER, track_number,
				RHYTHMDB_QUERY_END);

	is_dup = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (query_model), &iter);
	g_object_unref (entry_type);
	g_object_unref (query_model);
	g_object_unref (db);
	if (is_dup) {
		rb_debug ("not transferring %lu - %s - %s - %s as already present",
			  track_number, title, album, artist);
	}
	return is_dup;
}
static gboolean
burn_source_iter_func (GtkTreeModel *model,
                       GtkTreeIter  *iter,
                       char        **uri,
                       char        **artist,
                       char        **title,
                       gulong       *duration)
{
    RhythmDBEntry *entry;

    gtk_tree_model_get (model, iter, 0, &entry, -1);

    *uri = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_LOCATION);
    *title = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_TITLE);
    *artist = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_ARTIST);
    *duration = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DURATION);

    return TRUE;
}
示例#10
0
static char *
impl_build_dest_uri (RBRemovableMediaSource *source,
		     RhythmDBEntry *entry,
		     const char *mimetype,
		     const char *extension)
{
	gulong id;
	char *uri;
	LIBMTP_filetype_t filetype;

	if (mimetype == NULL) {
		mimetype = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MIMETYPE);
	}
	filetype = mimetype_to_filetype (RB_MTP_SOURCE (source), mimetype);
	rb_debug ("using libmtp filetype %d (%s) for source media type %s",
		  filetype,
		  LIBMTP_Get_Filetype_Description (filetype),
		  mimetype);

	/* the prepare-sink callback needs the entry ID to set up the
	 * upload data, and we want to use the supplied extension for
	 * the filename on the device.
	 *
	 * this is pretty ugly - it'd be much nicer to have a source-defined
	 * structure that got passed around (or was accessible from) the various
	 * hooks and methods called during the track transfer process.  probably
	 * something to address in my horribly stalled track transfer rewrite..
	 *
	 * the structure would either be created when queuing the track for transfer,
	 * or here; passed to any prepare-source or prepare-sink callbacks for the
	 * encoder; and then passed to whatever gets called when the transfer is complete.
	 */
	id = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_ENTRY_ID);
	if (extension == NULL) {
		extension = "";
	}
	uri = g_strdup_printf ("xrbmtp://%lu/%s/%d", id, extension, filetype);
	return uri;
}
static void
info_available_cb (RBPlayer *backend,
		   const char *uri,
		   RBMetaDataField field,
		   GValue *value,
		   RBIRadioSource *source)
{
	RhythmDBEntry *entry;
        RhythmDBPropType entry_field = 0;
        gboolean set_field = FALSE;
	char *str = NULL;

	/* sanity check */
	if (!rb_player_opened (backend)) {
		rb_debug ("Got info_available but not playing");
		return;
	}

	GDK_THREADS_ENTER ();

	entry = rb_shell_player_get_playing_entry (source->priv->player);
	if (check_entry_type (source, entry) == FALSE)
		goto out_unlock;

	/* validate the value */
	switch (field) {
	case RB_METADATA_FIELD_TITLE:
	case RB_METADATA_FIELD_ARTIST:
	case RB_METADATA_FIELD_GENRE:
	case RB_METADATA_FIELD_COMMENT:
		str = g_value_dup_string (value);
		if (!g_utf8_validate (str, -1, NULL)) {
			g_warning ("Invalid UTF-8 from internet radio: %s", str);
			g_free (str);
			goto out_unlock;
		}
		break;
	default:
		break;
	}


	switch (field) {
		/* streaming song information */
	case RB_METADATA_FIELD_TITLE:
	{
		rb_streaming_source_set_streaming_title (RB_STREAMING_SOURCE (source), str);
		break;
	}
	case RB_METADATA_FIELD_ARTIST:
	{
		rb_streaming_source_set_streaming_artist (RB_STREAMING_SOURCE (source), str);
		break;
	}

		/* station information */
	case RB_METADATA_FIELD_GENRE:
	{
		const char *existing;

		/* check if the db entry already has a genre; if so, don't change it */
		existing = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_GENRE);
		if ((existing == NULL) ||
		    (strcmp (existing, "") == 0) ||
		    (strcmp (existing, _("Unknown")) == 0)) {
			entry_field = RHYTHMDB_PROP_GENRE;
			rb_debug ("setting genre of iradio station to %s", str);
			set_field = TRUE;
		} else {
			rb_debug ("iradio station already has genre: %s; ignoring %s", existing, str);
		}
		break;
	}
	case RB_METADATA_FIELD_COMMENT:
	{
		const char *existing;
		const char *location;

		/* check if the db entry already has a title; if so, don't change it.
		 * consider title==URI to be the same as no title, since that's what
		 * happens for stations imported by DnD or commandline args.
		 * if the station title really is the same as the URI, then surely
		 * the station title in the stream metadata will say that too..
		 */
		existing = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE);
		location = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
		if ((existing == NULL) ||
		    (strcmp (existing, "") == 0) ||
		    (strcmp (existing, location) == 0)) {
			entry_field = RHYTHMDB_PROP_TITLE;
			rb_debug ("setting title of iradio station to %s", str);
			set_field = TRUE;
		} else {
			rb_debug ("iradio station already has title: %s; ignoring %s", existing, str);
		}
		break;
	}
	case RB_METADATA_FIELD_BITRATE:
		if (!rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_BITRATE)) {
			gulong bitrate;

			/* GStreamer sends us bitrate in bps, but we need it in kbps*/
			bitrate = g_value_get_ulong (value);
			g_value_set_ulong (value, bitrate/1000);

			rb_debug ("setting bitrate of iradio station to %lu",
				  g_value_get_ulong (value));
			entry_field = RHYTHMDB_PROP_BITRATE;
			set_field = TRUE;
		}
		break;
	default:
		break;
	}

	if (set_field && entry_field != 0) {
		rhythmdb_entry_set (source->priv->db, entry, entry_field, value);
		rhythmdb_commit (source->priv->db);
	}

	g_free (str);
 out_unlock:
	GDK_THREADS_LEAVE ();
}
示例#12
0
RBDAAPRecord *
rb_daap_record_new (RhythmDBEntry *entry)
{
	RBDAAPRecord *record = NULL;
	record = RB_DAAP_RECORD (g_object_new (RB_TYPE_DAAP_RECORD, NULL));

	/* When browsing, entry will be NULL because we will pull
	 * the metadata from the DAAP query. When sharing, entry will
	 * point to an existing entry from the Rhythmbox DB.
	 */
	if (entry) {
		gchar *ext;

		record->priv->filesize = rhythmdb_entry_get_uint64
						(entry, RHYTHMDB_PROP_FILE_SIZE);

		record->priv->location = rhythmdb_entry_dup_string
						(entry, RHYTHMDB_PROP_LOCATION);

		record->priv->title    = rhythmdb_entry_dup_string
						(entry, RHYTHMDB_PROP_TITLE);

		record->priv->artist   = rhythmdb_entry_dup_string
						(entry, RHYTHMDB_PROP_ARTIST);

		record->priv->album    = rhythmdb_entry_dup_string
						(entry, RHYTHMDB_PROP_ALBUM);

		/* Since we don't support album id's on Rhythmbox, "emulate" it */
		record->priv->albumid  = (gintptr) rhythmdb_entry_get_refstring
						(entry, RHYTHMDB_PROP_ALBUM);

		record->priv->genre    = rhythmdb_entry_dup_string
						(entry, RHYTHMDB_PROP_GENRE);

		/* FIXME: Support transcoding: */
		/* FIXME: we should use RHYTHMDB_PROP_MIMETYPE instead */
		ext = strrchr (record->priv->location, '.');
		if (ext == NULL) {
			ext = "mp3";
		} else {
			ext++;
		}
		record->priv->mediakind = DMAP_MEDIA_KIND_MUSIC;
		record->priv->real_format = g_strdup (ext);
		record->priv->format = g_strdup (record->priv->real_format);

		/* Only support songs */
		record->priv->mediakind = 1;

		record->priv->track    = rhythmdb_entry_get_ulong
						(entry, RHYTHMDB_PROP_TRACK_NUMBER);

		record->priv->duration = rhythmdb_entry_get_ulong
						(entry, RHYTHMDB_PROP_DURATION);

		record->priv->rating   = (gint) rhythmdb_entry_get_double
						(entry, RHYTHMDB_PROP_RATING);

		record->priv->year     = rhythmdb_entry_get_ulong
						(entry, RHYTHMDB_PROP_YEAR);

		record->priv->firstseen = rhythmdb_entry_get_ulong
						(entry, RHYTHMDB_PROP_FIRST_SEEN);

		record->priv->mtime     = rhythmdb_entry_get_ulong
						(entry, RHYTHMDB_PROP_MTIME);

		record->priv->disc      = rhythmdb_entry_get_ulong
						(entry, RHYTHMDB_PROP_DISC_NUMBER);

		record->priv->bitrate   = rhythmdb_entry_get_ulong
						(entry, RHYTHMDB_PROP_BITRATE);
	}

	return record;
}
示例#13
0
static void
prepare_encoder_sink_cb (RBEncoderFactory *factory,
			 const char *stream_uri,
			 GObject *sink,
			 RBMtpSource *source)
{
	RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source);
	RhythmDBEntry *entry;
	RhythmDB *db;
	LIBMTP_track_t *track;
	char **bits;
	char *extension;
	LIBMTP_filetype_t filetype;
	gulong track_id;
	GDate d;
	char **folder_path;

	/* make sure this stream is for a file on our device */
	if (g_str_has_prefix (stream_uri, "xrbmtp://") == FALSE)
		return;

	/* extract the entry ID, extension, and MTP filetype from the URI */
	bits = g_strsplit (stream_uri + strlen ("xrbmtp://"), "/", 3);
	track_id = strtoul (bits[0], NULL, 0);
	extension = g_strdup (bits[1]);
	filetype = strtoul (bits[2], NULL, 0);
	g_strfreev (bits);

	db = get_db_for_source (source);
	entry = rhythmdb_entry_lookup_by_id (db, track_id);
	g_object_unref (db);
	if (entry == NULL) {
		g_free (extension);
		return;
	}

	track = LIBMTP_new_track_t ();
	track->title = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_TITLE);
	track->album = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_ALBUM);
	track->artist = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_ARTIST);
	track->genre = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_GENRE);

	/* build up device filename */
	track->filename = g_strdup_printf ("%s - %s.%s",
					   rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST),
					   rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE),
					   extension);
	g_free (extension);

	/* construct folder path: artist/album */
	folder_path = g_new0 (char *, 3);
	folder_path[0] = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_ALBUM_ARTIST);
	if (folder_path[0] == NULL || folder_path[0][0] == '\0') {
		g_free (folder_path[0]);
		folder_path[0] = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_ARTIST);
	}
	folder_path[1] = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_ALBUM);

	/* ensure the filename is safe for FAT filesystems and doesn't contain slashes */
	sanitize_for_mtp (track->filename);
	sanitize_for_mtp (folder_path[0]);
	sanitize_for_mtp (folder_path[1]);

	if (rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DATE) > 0) {
		g_date_set_julian (&d, rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DATE));
		track->date = gdate_to_char (&d);
	}
	track->tracknumber = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TRACK_NUMBER);
	track->duration = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DURATION) * 1000;
	track->rating = rhythmdb_entry_get_double (entry, RHYTHMDB_PROP_RATING) * 20;
	track->usecount = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_PLAY_COUNT);

	track->filetype = filetype;

	g_object_set (sink,
		      "device-thread", priv->device_thread,
		      "folder-path", folder_path,
		      "mtp-track", track,
		      NULL);
	rhythmdb_entry_unref (entry);
	g_strfreev (folder_path);

	g_hash_table_insert (priv->track_transfer_map, g_strdup (stream_uri), track);
}
示例#14
0
static gboolean
start_next (RBTrackTransferBatch *batch)
{
	char *media_type = NULL;
	char *extension = NULL;

	if (batch->priv->cancelled == TRUE) {
		return FALSE;
	}

	if (batch->priv->entries == NULL) {
		/* guess we must be done.. */
		g_signal_emit (batch, signals[COMPLETE], 0);
		return FALSE;
	}

	batch->priv->current_fraction = 0.0;
	batch->priv->current_encoder = rb_encoder_new ();
	g_signal_connect_object (batch->priv->current_encoder, "progress",
				 G_CALLBACK (encoder_progress_cb),
				 batch, 0);
	g_signal_connect_object (batch->priv->current_encoder, "overwrite",
				 G_CALLBACK (encoder_overwrite_cb),
				 batch, 0);
	g_signal_connect_object (batch->priv->current_encoder, "completed",
				 G_CALLBACK (encoder_completed_cb),
				 batch, 0);

	rb_debug ("%d entries remain in the batch", g_list_length (batch->priv->entries));

	while ((batch->priv->entries != NULL) && (batch->priv->cancelled == FALSE)) {
		RhythmDBEntry *entry;
		guint64 filesize;
		gulong duration;
		double fraction;
		GList *n;

		n = batch->priv->entries;
		batch->priv->entries = g_list_remove_link (batch->priv->entries, n);
		entry = (RhythmDBEntry *)n->data;
		g_list_free_1 (n);

		rb_debug ("attempting to transfer %s", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));

		/* calculate the fraction of the transfer that this entry represents */
		filesize = rhythmdb_entry_get_uint64 (entry, RHYTHMDB_PROP_FILE_SIZE);
		duration = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DURATION);
		if (batch->priv->total_duration > 0) {
			g_assert (duration > 0);	/* otherwise total_duration would be 0 */
			fraction = ((double)duration) / (double) batch->priv->total_duration;
		} else if (batch->priv->total_size > 0) {
			g_assert (filesize > 0);	/* otherwise total_size would be 0 */
			fraction = ((double)filesize) / (double) batch->priv->total_size;
		} else {
			int count = g_list_length (batch->priv->entries) +
				    g_list_length (batch->priv->done_entries) + 1;
			fraction = 1.0 / ((double)count);
		}

		g_free (media_type);
		g_free (extension);
		media_type = NULL;
		extension = NULL;
		if (rb_encoder_get_media_type (batch->priv->current_encoder,
					       entry,
					       batch->priv->media_types,
					       &media_type,
					       &extension) == FALSE) {
			rb_debug ("skipping entry %s, can't find a destination format",
				  rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));
			rhythmdb_entry_unref (entry);
			batch->priv->total_fraction += fraction;
			continue;
		}

		g_free (batch->priv->current_dest_uri);
		batch->priv->current_dest_uri = NULL;
		g_signal_emit (batch, signals[GET_DEST_URI], 0,
			       entry,
			       media_type,
			       extension,
			       &batch->priv->current_dest_uri);
		if (batch->priv->current_dest_uri == NULL) {
			rb_debug ("unable to build destination URI for %s, skipping",
				  rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));
			rhythmdb_entry_unref (entry);
			batch->priv->total_fraction += fraction;
			continue;
		}

		batch->priv->current = entry;
		batch->priv->current_entry_fraction = fraction;
		break;
	}

	if (batch->priv->current == NULL) {
		g_object_unref (batch->priv->current_encoder);
		batch->priv->current_encoder = NULL;
	} else {
		g_signal_emit (batch, signals[TRACK_STARTED], 0,
			       batch->priv->current,
			       batch->priv->current_dest_uri);

		rb_encoder_encode (batch->priv->current_encoder,
				   batch->priv->current,
				   batch->priv->current_dest_uri,
				   media_type);
	}
	g_free (media_type);
	g_free (extension);

	return TRUE;
}
示例#15
0
static char *
impl_build_dest_uri (RBTransferTarget *target,
		     RhythmDBEntry *entry,
		     const char *media_type,
		     const char *extension)
{
	RBAndroidSourcePrivate *priv = GET_PRIVATE (target);
	const char *in_artist;
	char *artist, *album, *title;
	gulong track_number, disc_number;
	char *number;
	char *file = NULL;
	char *storage_uri;
	char *uri;
	char *ext;
	GFile *storage = NULL;

	if (extension != NULL) {
		ext = g_strconcat (".", extension, NULL);
	} else {
		ext = g_strdup ("");
	}

	in_artist = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM_ARTIST);
	if (in_artist[0] == '\0') {
		in_artist = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST);
	}
	artist = sanitize_path (in_artist);
	album = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM));
	title = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE));

	/* we really do need to fix this so untagged entries actually have NULL rather than
	 * a translated string.
	 */
	if (strcmp (artist, _("Unknown")) == 0 && strcmp (album, _("Unknown")) == 0 &&
	    g_str_has_suffix (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION), title)) {
		/* file isn't tagged, so just use the filename as-is, replacing the extension */
		char *p;

		p = g_utf8_strrchr (title, -1, '.');
		if (p != NULL) {
			*p = '\0';
		}
		file = g_strdup_printf ("%s%s", title, ext);
	}

	if (file == NULL) {
		track_number = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TRACK_NUMBER);
		disc_number = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DISC_NUMBER);
		if (disc_number > 0)
			number = g_strdup_printf ("%.02u.%.02u", (guint)disc_number, (guint)track_number);
		else
			number = g_strdup_printf ("%.02u", (guint)track_number);

		/* artist/album/number - title */
		file = g_strdup_printf (G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S "%s%%20-%%20%s%s",
					artist, album, number, title, ext);
		g_free (number);
	}

	g_free (artist);
	g_free (album);
	g_free (title);
	g_free (ext);

	/* pick storage container to use somehow
	for (l = priv->storage; l != NULL; l = l->next) {
	}
	*/
	if (priv->storage)
		storage = priv->storage->data;

	if (storage == NULL) {
		rb_debug ("couldn't find a container to store anything in");
		g_free (file);
		return NULL;
	}

	storage_uri = g_file_get_uri (storage);
	uri = g_strconcat (storage_uri, file, NULL);
	g_free (file);
	g_free (storage_uri);

	return uri;
}
static gboolean
start_next (RBTrackTransferBatch *batch)
{
	GstEncodingProfile *profile = NULL;

	if (batch->priv->cancelled == TRUE) {
		return FALSE;
	}

	if (batch->priv->entries == NULL) {
		/* guess we must be done.. */
		g_signal_emit (batch, signals[COMPLETE], 0);
		g_object_notify (G_OBJECT (batch), "task-outcome");
		return FALSE;
	}

	batch->priv->current_fraction = 0.0;

	rb_debug ("%d entries remain in the batch", g_list_length (batch->priv->entries));

	while ((batch->priv->entries != NULL) && (batch->priv->cancelled == FALSE)) {
		RhythmDBEntry *entry;
		guint64 filesize;
		gulong duration;
		double fraction;
		GList *n;
		char *media_type;
		char *extension;

		n = batch->priv->entries;
		batch->priv->entries = g_list_remove_link (batch->priv->entries, n);
		entry = (RhythmDBEntry *)n->data;
		g_list_free_1 (n);

		rb_debug ("attempting to transfer %s", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));

		/* calculate the fraction of the transfer that this entry represents */
		filesize = rhythmdb_entry_get_uint64 (entry, RHYTHMDB_PROP_FILE_SIZE);
		duration = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DURATION);
		if (batch->priv->total_duration > 0) {
			g_assert (duration > 0);	/* otherwise total_duration would be 0 */
			fraction = ((double)duration) / (double) batch->priv->total_duration;
		} else if (batch->priv->total_size > 0) {
			g_assert (filesize > 0);	/* otherwise total_size would be 0 */
			fraction = ((double)filesize) / (double) batch->priv->total_size;
		} else {
			int count = g_list_length (batch->priv->entries) +
				    g_list_length (batch->priv->done_entries) + 1;
			fraction = 1.0 / ((double)count);
		}

		profile = NULL;
		if (select_profile_for_entry (batch, entry, &profile, FALSE) == FALSE) {
			rb_debug ("skipping entry %s, can't find an encoding profile",
				  rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));
			rhythmdb_entry_unref (entry);
			batch->priv->total_fraction += fraction;
			continue;
		}

		if (profile != NULL) {
			media_type = rb_gst_encoding_profile_get_media_type (profile);
			extension = g_strdup (rb_gst_media_type_to_extension (media_type));

			rb_gst_encoding_profile_set_preset (profile, NULL);
			if (batch->priv->settings != NULL) {
				GVariant *preset_settings;
				char *active_preset;

				preset_settings = g_settings_get_value (batch->priv->settings,
									"media-type-presets");
				active_preset = NULL;
				g_variant_lookup (preset_settings, media_type, "s", &active_preset);

				rb_debug ("setting preset %s for media type %s",
					  active_preset, media_type);
				rb_gst_encoding_profile_set_preset (profile, active_preset);

				g_free (active_preset);
			}
		} else {
			media_type = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_MEDIA_TYPE);
			extension = g_strdup (rb_gst_media_type_to_extension (media_type));
			if (extension == NULL) {
				extension = get_extension_from_location (entry);
			}
		}

		g_free (batch->priv->current_dest_uri);
		batch->priv->current_dest_uri = NULL;
		g_signal_emit (batch, signals[GET_DEST_URI], 0,
			       entry,
			       media_type,
			       extension,
			       &batch->priv->current_dest_uri);
		g_free (media_type);
		g_free (extension);

		if (batch->priv->current_dest_uri == NULL) {
			rb_debug ("unable to build destination URI for %s, skipping",
				  rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));
			rhythmdb_entry_unref (entry);
			batch->priv->total_fraction += fraction;
			continue;
		}

		batch->priv->current = entry;
		batch->priv->current_entry_fraction = fraction;
		batch->priv->current_profile = profile;
		break;
	}

	if (batch->priv->current != NULL) {
		g_signal_emit (batch, signals[TRACK_STARTED], 0,
			       batch->priv->current,
			       batch->priv->current_dest_uri);
		start_encoding (batch, FALSE);
		g_object_notify (G_OBJECT (batch), "task-detail");
	}

	return TRUE;
}
/**
 * _rb_track_transfer_batch_start:
 * @batch: a #RBTrackTransferBatch
 * @queue: the #RBTrackTransferQueue
 *
 * Starts the batch transfer.  Only to be called by the #RBTrackTransferQueue.
 */
void
_rb_track_transfer_batch_start (RBTrackTransferBatch *batch, GObject *queue)
{
	gboolean total_duration_valid;
	gboolean total_size_valid;
	gboolean origin_valid;
	guint64 filesize;
	gulong duration;
	RBSource *origin = NULL;
	RBShell *shell;
	GList *l;

	g_object_get (queue, "shell", &shell, NULL);

	/* calculate total duration and file size and figure out the
	 * origin source if we weren't given one to start with.
	 */
	total_duration_valid = TRUE;
	total_size_valid = TRUE;
	origin_valid = TRUE;
	for (l = batch->priv->entries; l != NULL; l = l->next) {
		RhythmDBEntry *entry = (RhythmDBEntry *)l->data;

		filesize = rhythmdb_entry_get_uint64 (entry, RHYTHMDB_PROP_FILE_SIZE);
		if (total_size_valid && filesize > 0) {
			batch->priv->total_size += filesize;
		} else {
			total_size_valid = FALSE;
			batch->priv->total_size = 0;
		}

		duration = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DURATION);
		if (total_duration_valid && duration > 0) {
			batch->priv->total_duration += duration;
		} else {
			total_duration_valid = FALSE;
			batch->priv->total_duration = 0;
		}

		if (batch->priv->source == NULL) {
			RhythmDBEntryType *entry_type;
			RBSource *entry_origin;

			entry_type = rhythmdb_entry_get_entry_type (entry);
			entry_origin = rb_shell_get_source_by_entry_type (shell, entry_type);
			if (origin == NULL && origin_valid  == TRUE) {
				origin = entry_origin;
			} else if (origin != entry_origin) {
				origin = NULL;
				origin_valid = FALSE;
			}
		}
	}

	g_object_unref (shell);

	if (origin != NULL) {
		batch->priv->source = origin;
	}

	batch->priv->queue = RB_TRACK_TRANSFER_QUEUE (queue);
	batch->priv->cancelled = FALSE;
	batch->priv->total_fraction = 0.0;

	g_signal_emit (batch, signals[STARTED], 0);
	g_object_notify (G_OBJECT (batch), "task-progress");
	g_object_notify (G_OBJECT (batch), "task-detail");

	start_next (batch);
}
static char *
impl_build_dest_uri (RBRemovableMediaSource *source,
		     RhythmDBEntry *entry,
		     const char *mimetype,
		     const char *extension)
{
	RBGenericPlayerSourcePrivate *priv = GENERIC_PLAYER_SOURCE_GET_PRIVATE (source);
	char *artist, *album, *title;
	gulong track_number, disc_number;
	const char *folders;
	char **audio_folders;
	char *mount_path;
	char *number;
	char *file = NULL;
	char *path;
	char *ext;

	rb_debug ("building dest uri for entry at %s", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));

	if (extension != NULL) {
		ext = g_strconcat (".", extension, NULL);
	} else {
		ext = g_strdup ("");
	}

	artist = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST));
	album = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM));
	title = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE));

	/* we really do need to fix this so untagged entries actually have NULL rather than
	 * a translated string.
	 */
	if (strcmp (artist, _("Unknown")) == 0 && strcmp (album, _("Unknown")) == 0 &&
	    g_str_has_suffix (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION), title)) {
		/* file isn't tagged, so just use the filename as-is, replacing the extension */
		char *p;

		p = g_utf8_strrchr (title, -1, '.');
		if (p != NULL) {
			*p = '\0';
		}
		file = g_strdup_printf ("%s%s", title, ext);
	}

	if (file == NULL) {
		int folder_depth;

		track_number = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TRACK_NUMBER);
		disc_number = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DISC_NUMBER);
		if (disc_number > 0)
			number = g_strdup_printf ("%.02u.%.02u", (guint)disc_number, (guint)track_number);
		else
			number = g_strdup_printf ("%.02u", (guint)track_number);

		g_object_get (priv->device_info, "folder-depth", &folder_depth, NULL);
		switch (folder_depth) {
		case 0:
			/* artist - album - number - title */
			file = g_strdup_printf ("%s - %s - %s - %s%s",
						artist, album, number, title, ext);
			break;

		case 1:
			/* artist - album/number - title */
			file = g_strdup_printf ("%s - %s" G_DIR_SEPARATOR_S "%s - %s%s",
						artist, album, number, title, ext);
			break;

		default: /* use this for players that don't care */
		case 2:
			/* artist/album/number - title */
			file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S "%s - %s%s",
						artist, album, number, title, ext);
			break;
		}
		g_free (number);
	}

	g_free (artist);
	g_free (album);
	g_free (title);
	g_free (ext);

	if (file == NULL)
		return NULL;

	g_object_get (priv->device_info, "audio-folders", &audio_folders, NULL);
	if (audio_folders != NULL && g_strv_length (audio_folders) > 0) {
		folders = g_strdup (audio_folders[0]);
	} else {
		folders = "";
	}
	g_strfreev (audio_folders);

	mount_path = rb_generic_player_source_get_mount_path (RB_GENERIC_PLAYER_SOURCE (source));
	path = g_build_filename (mount_path, folders, file, NULL);
	g_free (file);
	g_free (mount_path);

	/* TODO: check for duplicates, or just overwrite by default? */
	rb_debug ("dest file is %s", path);
	return path;
}