コード例 #1
0
int MTPDevice::dirRemove(const std::string &path)
{
    const std::string tmp_basename(smtpfs_basename(path));
    const std::string tmp_dirname(smtpfs_dirname(path));
    const TypeDir *dir_parent = dirFetchContent(tmp_dirname);
    const TypeDir *dir_to_remove = dir_parent ? dir_parent->dir(tmp_basename) : nullptr;
    if (!dir_parent || !dir_to_remove || dir_parent->id() == 0) {
        logerr("No such directory '", path, "' to remove.\n");
        return -ENOENT;
    }
    if (!dir_to_remove->isEmpty())
        return -ENOTEMPTY;
    criticalEnter();
    int rval = LIBMTP_Delete_Object(m_device, dir_to_remove->id());
    criticalLeave();
    if (rval != 0){
        logerr("Could not remove the directory '", path, "'.\n");
        LIBMTP_Dump_Errorstack(m_device);
        LIBMTP_Clear_Errorstack(m_device);
        return -EINVAL;
    }
    const_cast<TypeDir*>(dir_parent)->removeDir(*dir_to_remove);
    logmsg("Folder '", path, "' removed.\n");
    return 0;
}
コード例 #2
0
static void prune_empty_folders(LIBMTP_mtpdevice_t *device, LIBMTP_file_t *files, LIBMTP_folder_t *folderlist, int do_delete)
{
    if(folderlist==NULL)
        return;

    if(folderlist->child == NULL) {

        int found = 0;
        LIBMTP_file_t *file;
        file = files;
        while (file != NULL) {
            if(file->parent_id == folderlist->folder_id) {
                found = 1;
                break;
            }
            file = file->next;
        }

        if(found == 0) {
            printf("empty folder %u (%s)\n",folderlist->folder_id,folderlist->name);
            if(do_delete) {
                if (LIBMTP_Delete_Object(device,folderlist->folder_id) != 0) {
                    printf("Couldn't delete folder %u\n",folderlist->folder_id);
                    LIBMTP_Dump_Errorstack(device);
                    LIBMTP_Clear_Errorstack(device);
                }
            }
        }
    }

    prune_empty_folders(device,files,folderlist->child,do_delete);
    prune_empty_folders(device,files,folderlist->sibling,do_delete);
}
コード例 #3
0
ファイル: playlist-spl.c プロジェクト: Abocer/android-4.2_r1
/**
 * Update a playlist on the device. If only the playlist's name is being
 * changed the pl->playlist_id will likely remain the same. An updated track
 * list will result in the old playlist being replaced (ie: new playlist_id).
 * NOTE: Other playlist metadata aside from playlist name and tracks are
 * ignored.
 *
 * @param device mtp device pointer
 * @param new the LIBMTP_playlist_t to convert (pl->playlist_id will be updated
 *           with the newly created object's id)
 * @return 0 on success, any other value means failure.
 */
int update_spl_playlist(LIBMTP_mtpdevice_t *device,
			  LIBMTP_playlist_t * const newlist)
{
  IF_DEBUG() printf("pl->name='%s'\n",newlist->name);

  // read in the playlist of interest
  LIBMTP_playlist_t * old = LIBMTP_Get_Playlist(device, newlist->playlist_id);
  
  // check to see if we found it
  if (!old)
    return -1;

  // check if the playlists match
  int delta = 0;
  int i;
  if(old->no_tracks != newlist->no_tracks)
    delta++;
  for(i=0;i<newlist->no_tracks && delta==0;i++) {
    if(old->tracks[i] != newlist->tracks[i])
      delta++;
  }

  // if not, kill the playlist and replace it
  if(delta) {
    IF_DEBUG() printf("new tracks detected:\n");
    IF_DEBUG() printf("delete old playlist and build a new one\n");
    IF_DEBUG() printf(" NOTE: new playlist_id will result!\n");
    if(LIBMTP_Delete_Object(device, old->playlist_id) != 0)
      return -1;

    IF_DEBUG() {
      if(strcmp(old->name,newlist->name) == 0)
        printf("name unchanged\n");
      else
        printf("name is changing too -> %s\n",newlist->name);
    }

    return LIBMTP_Create_New_Playlist(device, newlist);
  }


  // update the name only
  if(strcmp(old->name,newlist->name) != 0) {
    IF_DEBUG() printf("ONLY name is changing -> %s\n",newlist->name);
    IF_DEBUG() printf("playlist_id will remain unchanged\n");
    char* s = malloc(sizeof(char)*(strlen(newlist->name)+5));
    strcpy(s, newlist->name);
    strcat(s,".spl"); // FIXME check for success
    int ret = LIBMTP_Set_Playlist_Name(device, newlist, s);
    free(s);
    return ret;
  }

  IF_DEBUG() printf("no change\n");
  return 0; // nothing to be done, success
}
コード例 #4
0
static void
impl_delete (RBSource *source)
{
	RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source);
	GList *sel;
	GList *tem;
	RBEntryView *tracks;
	RhythmDB *db;
	int ret;

	db = get_db_for_source (RB_MTP_SOURCE (source));

	tracks = rb_source_get_entry_view (source);
	sel = rb_entry_view_get_selected_entries (tracks);
	for (tem = sel; tem != NULL; tem = tem->next) {
		LIBMTP_track_t *track;
		RhythmDBEntry *entry;
		const char *uri;
		const char *album_name;

		entry = (RhythmDBEntry *)tem->data;
		uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
		track = g_hash_table_lookup (priv->entry_map, entry);
		if (track == NULL) {
			rb_debug ("Couldn't find track on mtp-device! (%s)", uri);
			continue;
		}

		ret = LIBMTP_Delete_Object (priv->device, track->item_id);
		if (ret != 0) {
			rb_debug ("Delete track %d failed", track->item_id);
			report_libmtp_errors (priv->device, TRUE);
			continue;
		}

		album_name = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM);
		if (strcmp (album_name, _("Unknown")) != 0) {
			remove_track_from_album (RB_MTP_SOURCE (source), album_name, track);
		}

		g_hash_table_remove (priv->entry_map, entry);
		rhythmdb_entry_delete (db, entry);
	}
	rhythmdb_commit (db);

	g_list_free (sel);
	g_list_free (tem);
}
コード例 #5
0
int MTPDevice::filePush(const std::string &src, const std::string &dst)
{
    const std::string dst_basename(smtpfs_basename(dst));
    const std::string dst_dirname(smtpfs_dirname(dst));
    const TypeDir *dir_parent = dirFetchContent(dst_dirname);
    const TypeFile *file_to_remove = dir_parent ? dir_parent->file(dst_basename) : nullptr;
    if (dir_parent && file_to_remove) {
        criticalEnter();
        int rval = LIBMTP_Delete_Object(m_device, file_to_remove->id());
        criticalLeave();
        if (rval != 0) {
            logerr("Can not upload '", src, "' to '", dst, "'.\n");
            return -EINVAL;
        }
    }

    struct stat file_stat;
    stat(src.c_str(), &file_stat);
    TypeFile file_to_upload(0, dir_parent->id(), dir_parent->storageid(),
        dst_basename, static_cast<uint64_t>(file_stat.st_size), 0);
    LIBMTP_file_t *f = file_to_upload.toLIBMTPFile();
    if (file_stat.st_size)
        logmsg("Started uploading '", dst, "'.\n");
    criticalEnter();
    int rval = LIBMTP_Send_File_From_File(m_device, src.c_str(), f, nullptr, nullptr);
    criticalLeave();
    if (rval != 0) {
        logerr("Could not upload file '", src, "'.\n");
        LIBMTP_Dump_Errorstack(m_device);
        LIBMTP_Clear_Errorstack(m_device);
        rval = -EINVAL;
    } else {
        file_to_upload.setId(f->item_id);
        file_to_upload.setParent(f->parent_id);
        file_to_upload.setStorage(f->storage_id);
        file_to_upload.setName(std::string(f->filename));
        file_to_upload.setModificationDate(file_stat.st_mtime);
        if (file_to_remove)
            const_cast<TypeDir*>(dir_parent)->replaceFile(*file_to_remove, file_to_upload);
        else
            const_cast<TypeDir*>(dir_parent)->addFile(file_to_upload);
    }
    free(static_cast<void*>(f->filename));
    free(static_cast<void*>(f));
    logmsg("File '", dst, (file_stat.st_size ? " uploaded" : " created"), ".\n");
    return rval;
}
コード例 #6
0
ファイル: mtpdevice.cpp プロジェクト: Gu1/Clementine
bool MtpDevice::DeleteFromStorage(const DeleteJob& job) {
    // Extract the ID from the song's URL
    QString filename = job.metadata_.url().path();
    filename.remove('/');

    bool ok = false;
    uint32_t id = filename.toUInt(&ok);
    if (!ok) return false;

    // Remove the file
    int ret = LIBMTP_Delete_Object(connection_->device(), id);
    if (ret != 0) return false;

    // Remove it from our library model
    songs_to_remove_ << job.metadata_;

    return true;
}
コード例 #7
0
ファイル: libmtp.c プロジェクト: AEliu/calibre
// Device.delete_object {{{
static PyObject *
Device_delete_object(Device *self, PyObject *args) {
    PyObject *errs;
    unsigned long id;
    int res;

    ENSURE_DEV(NULL); ENSURE_STORAGE(NULL);

    if (!PyArg_ParseTuple(args, "k", &id)) return NULL;
    errs = PyList_New(0);
    if (errs == NULL) { PyErr_NoMemory(); return NULL; }

    Py_BEGIN_ALLOW_THREADS;
    res = LIBMTP_Delete_Object(self->device, (uint32_t)id);
    Py_END_ALLOW_THREADS;
    if (res != 0) dump_errorstack(self->device, errs);

    return Py_BuildValue("ON", (res == 0) ? Py_True : Py_False, errs);
} // }}}
コード例 #8
0
int MTPDevice::fileRemove(const std::string &path)
{
    const std::string tmp_basename(smtpfs_basename(path));
    const std::string tmp_dirname(smtpfs_dirname(path));
    const TypeDir *dir_parent = dirFetchContent(tmp_dirname);
    const TypeFile *file_to_remove = dir_parent ? dir_parent->file(tmp_basename) : nullptr;
    if (!dir_parent || !file_to_remove) {
        logerr("No such file '", path, "' to remove.\n");
        return -ENOENT;
    }
    criticalEnter();
    int rval = LIBMTP_Delete_Object(m_device, file_to_remove->id());
    criticalLeave();
    if (rval != 0) {
        logerr("Could not remove the directory '", path, "'.\n");
        return -EINVAL;
    }
    const_cast<TypeDir*>(dir_parent)->removeFile(*file_to_remove);
    logmsg("File '", path, "' removed.\n");
    return 0;
}
コード例 #9
0
static void
remove_track_from_album (RBMtpSource *source, const char *album_name, LIBMTP_track_t *track)
{
	RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source);
	LIBMTP_album_t *album;
	int i;

	album = g_hash_table_lookup (priv->album_map, album_name);
	if (album == NULL) {
		rb_debug ("Couldn't find an album for %s", album_name);
		return;
	}

	for (i = 0; i < album->no_tracks; i++) {
		if (album->tracks[i] == track->item_id) {
			break;
		}
	}

	if (i == album->no_tracks) {
		rb_debug ("Couldn't find track %d in album %d", track->item_id, album->album_id);
		return;
	}

	memmove (album->tracks + i, album->tracks + i + 1, album->no_tracks - (i+1));
	album->no_tracks--;

	if (album->no_tracks == 0) {
		rb_debug ("deleting empty album %d", album->album_id);
		if (LIBMTP_Delete_Object (priv->device, album->album_id) != 0) {
			report_libmtp_errors (priv->device, FALSE);
		}
		g_hash_table_remove (priv->album_map, album_name);
	} else {
		rb_debug ("updating album %d: %d tracks remaining", album->album_id, album->no_tracks);
		if (LIBMTP_Update_Album (priv->device, album) != 0) {
			report_libmtp_errors (priv->device, FALSE);
		}
	}
}
コード例 #10
0
static void
remove_track_from_album (RBMtpThread *thread, RBMtpThreadTask *task)
{
	LIBMTP_album_t *album;
	int i;

	album = g_hash_table_lookup (thread->albums, task->album);
	if (album == NULL) {
		rb_debug ("Couldn't find an album for %s", task->album);
		return;
	}

	for (i = 0; i < album->no_tracks; i++) {
		if (album->tracks[i] == task->track_id) {
			break;
		}
	}

	if (i == album->no_tracks) {
		rb_debug ("Couldn't find track %d in album %d", task->track_id, album->album_id);
		return;
	}

	memmove (album->tracks + i, album->tracks + i + 1, album->no_tracks - (i+1));
	album->no_tracks--;

	if (album->no_tracks == 0) {
		rb_debug ("deleting empty album %d", album->album_id);
		if (LIBMTP_Delete_Object (thread->device, album->album_id) != 0) {
			rb_mtp_thread_report_errors (thread, FALSE);
		}
		g_hash_table_remove (thread->albums, task->album);
	} else {
		rb_debug ("updating album %d: %d tracks remaining", album->album_id, album->no_tracks);
		if (LIBMTP_Update_Album (thread->device, album) != 0) {
			rb_mtp_thread_report_errors (thread, FALSE);
		}
	}
}
コード例 #11
0
ファイル: rb-mtp-source.c プロジェクト: dignan/control
static void
delete_done_cb (LIBMTP_mtpdevice_t *device, TracksDeletedCallbackData *data)
{
	LIBMTP_folder_t *folders;
	LIBMTP_file_t *files;

	data->actually_free = FALSE;
	update_free_space_cb (device, RB_MTP_SOURCE (data->source));

	/* if any of the folders we just deleted from are now empty, delete them */
	folders = LIBMTP_Get_Folder_List (device);
	files = LIBMTP_Get_Filelisting_With_Callback (device, NULL, NULL);
	if (folders != NULL) {
		GHashTableIter iter;
		gpointer key;
		g_hash_table_iter_init (&iter, data->check_folders);
		while (g_hash_table_iter_next (&iter, &key, NULL)) {
			LIBMTP_folder_t *f;
			LIBMTP_folder_t *c;
			LIBMTP_file_t *file;
			uint32_t folder_id = GPOINTER_TO_UINT(key);

			while (folder_id != device->default_music_folder && folder_id != 0) {

				f = LIBMTP_Find_Folder (folders, folder_id);
				if (f == NULL) {
					rb_debug ("unable to find folder %u", folder_id);
					break;
				}

				/* don't delete folders with children that we didn't just delete */
				for (c = f->child; c != NULL; c = c->sibling) {
					if (g_hash_table_lookup (data->check_folders,
								 GUINT_TO_POINTER (c->folder_id)) == NULL) {
						break;
					}
				}
				if (c != NULL) {
					rb_debug ("folder %s has children", f->name);
					break;
				}

				/* don't delete folders that contain files */
				for (file = files; file != NULL; file = file->next) {
					if (file->parent_id == folder_id) {
						break;
					}
				}

				if (file != NULL) {
					rb_debug ("folder %s contains at least one file: %s", f->name, file->filename);
					break;
				}

				/* ok, the folder is empty */
				rb_debug ("deleting empty folder %s", f->name);
				LIBMTP_Delete_Object (device, f->folder_id);

				/* if the folder we just deleted has siblings, the parent
				 * can't be empty.
				 */
				if (f->sibling != NULL) {
					rb_debug ("folder %s has siblings, can't delete parent", f->name);
					break;
				}
				folder_id = f->parent_id;
			}
		}

		LIBMTP_destroy_folder_t (folders);
	} else {
		rb_debug ("unable to get device folder list");
	}

	/* clean up the file list */
	while (files != NULL) {
		LIBMTP_file_t *n;

		n = files->next;
		LIBMTP_destroy_file_t (files);
		files = n;
	}

	g_idle_add ((GSourceFunc) delete_done_idle_cb, data);
}
コード例 #12
0
static gboolean 
run_task (RBMtpThread *thread, RBMtpThreadTask *task)
{
	char *name = task_name (task);
	rb_debug ("running task: %s", name);
	g_free (name);

	switch (task->task) {
	case OPEN_DEVICE:
		open_device (thread, task);
		break;

	case CLOSE_DEVICE:
		return TRUE;

	case SET_DEVICE_NAME:
		if (LIBMTP_Set_Friendlyname (thread->device, task->name)) {
			rb_mtp_thread_report_errors (thread, TRUE);
		}
		break;

	case THREAD_CALLBACK:
		{
			RBMtpThreadCallback cb = (RBMtpThreadCallback)task->callback;
			cb (thread->device, task->user_data);
		}
		break;

	case ADD_TO_ALBUM:
		add_track_to_album_and_update (thread, task);
		break;

	case REMOVE_FROM_ALBUM:
		remove_track_from_album (thread, task);
		break;

	case SET_ALBUM_IMAGE:
		set_album_image (thread, task);
		break;

	case GET_TRACK_LIST:
		get_track_list (thread, task);
		break;

	case DELETE_TRACK:
		if (LIBMTP_Delete_Object (thread->device, task->track_id)) {
			rb_mtp_thread_report_errors (thread, TRUE);
		}
		break;

	case UPLOAD_TRACK:
		upload_track (thread, task);
		break;

	case DOWNLOAD_TRACK:
		download_track (thread, task);
		break;

	default:
		g_assert_not_reached ();
	}

	return FALSE;
}
コード例 #13
0
static void
get_track_list (RBMtpThread *thread, RBMtpThreadTask *task)
{
	RBMtpTrackListCallback cb = task->callback;
	gboolean device_forgets_albums = TRUE;
	GHashTable *update_albums = NULL;
	LIBMTP_track_t *tracks = NULL;
	LIBMTP_album_t *albums;
	LIBMTP_album_t *album;

	/* get all the albums */
	albums = LIBMTP_Get_Album_List (thread->device);
	rb_mtp_thread_report_errors (thread, FALSE);
	if (albums != NULL) {
		LIBMTP_album_t *album;

		for (album = albums; album != NULL; album = album->next) {
			if (album->name == NULL)
				continue;

			rb_debug ("album: %s, %d tracks", album->name, album->no_tracks);
			g_hash_table_insert (thread->albums, album->name, album);
			if (album->no_tracks != 0) {
				device_forgets_albums = FALSE;
			}
		}

		if (device_forgets_albums) {
			rb_debug ("stupid mtp device detected.  will rebuild all albums.");
		}
	} else {
		rb_debug ("No albums");
		device_forgets_albums = FALSE;
	}

	tracks = LIBMTP_Get_Tracklisting_With_Callback (thread->device, NULL, NULL);
	rb_mtp_thread_report_errors (thread, FALSE);
	if (tracks == NULL) {
		rb_debug ("no tracks on the device");
	} else if (device_forgets_albums) {
		LIBMTP_track_t *track;
	       
		rb_debug ("rebuilding albums");
		update_albums = g_hash_table_new (g_direct_hash, g_direct_equal);
		for (track = tracks; track != NULL; track = track->next) {
			if (track->album != NULL) {
				gboolean new_album = FALSE;
				album = add_track_to_album (thread, track->album, track->item_id, track->storage_id, &new_album);
				g_hash_table_insert (update_albums, album, GINT_TO_POINTER (new_album));
			}
		}
		rb_debug ("finished rebuilding albums");
	}

	cb (tracks, task->user_data);
	/* the callback owns the tracklist */

	if (device_forgets_albums) {
		GHashTableIter iter;
		gpointer album_ptr;
		gpointer new_album_ptr;

		rb_debug ("writing rebuilt albums back to the device");
		g_hash_table_iter_init (&iter, update_albums);
		while (g_hash_table_iter_next (&iter, &album_ptr, &new_album_ptr)) {
			album = album_ptr;
			rb_debug ("writing album \"%s\"", album->name);
			write_album_to_device (thread, album, GPOINTER_TO_INT (new_album_ptr));
		}
		g_hash_table_destroy (update_albums);

		rb_debug ("removing remaining empty albums");
		g_hash_table_iter_init (&iter, thread->albums);
		while (g_hash_table_iter_next (&iter, NULL, &album_ptr)) {
			int ret;

			album = album_ptr;
			if (album->no_tracks == 0) {
				rb_debug ("pruning empty album \"%s\"", album->name); 
				ret = LIBMTP_Delete_Object (thread->device, album->album_id);
				if (ret != 0) {
					rb_mtp_thread_report_errors (thread, FALSE);
				}
				g_hash_table_iter_remove (&iter);
			}
		}

		rb_debug ("finished updating albums on the device");
	}
}
コード例 #14
0
static gboolean
load_mtp_db_idle_cb (RBMtpSource* source)
{
	RhythmDB *db = NULL;
	RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source);
	LIBMTP_track_t *tracks = NULL;
	LIBMTP_album_t *albums;
	gboolean device_forgets_albums = TRUE;

	db = get_db_for_source (source);

	g_assert (db != NULL);

	albums = LIBMTP_Get_Album_List (priv->device);
	report_libmtp_errors (priv->device, FALSE);
	if (albums != NULL) {
		LIBMTP_album_t *album;

		for (album = albums; album != NULL; album = album->next) {
			rb_debug ("album: %s, %d tracks", album->name, album->no_tracks);
			g_hash_table_insert (priv->album_map, album->name, album);
			if (album->no_tracks != 0) {
				device_forgets_albums = FALSE;
			}
		}

		if (device_forgets_albums) {
			rb_debug ("stupid mtp device detected.  will rebuild all albums.");
		}
	} else {
		rb_debug ("No albums");
		device_forgets_albums = FALSE;
	}

#ifdef HAVE_LIBMTP_030
	tracks = LIBMTP_Get_Tracklisting_With_Callback (priv->device, NULL, NULL);
#else
	tracks = LIBMTP_Get_Tracklisting (priv->device);
#endif
	report_libmtp_errors (priv->device, FALSE);
	if (tracks != NULL) {
		LIBMTP_track_t *track;
		for (track = tracks; track != NULL; track = track->next) {
			add_mtp_track_to_db (source, db, track);

			if (device_forgets_albums && track->album != NULL) {
				add_track_to_album (source, track->album, track);
			}
		}
	} else {
		rb_debug ("No tracks");
	}

	/* for stupid devices, remove any albums left with no tracks */
	if (device_forgets_albums) {
		GHashTableIter iter;
		gpointer value;
		LIBMTP_album_t *album;

		g_hash_table_iter_init (&iter, priv->album_map);
		while (g_hash_table_iter_next (&iter, NULL, &value)) {
			int ret;

			album = value;
			if (album->no_tracks == 0) {
				rb_debug ("pruning empty album \"%s\"", album->name); 
				ret = LIBMTP_Delete_Object (priv->device, album->album_id);
				if (ret != 0) {
					report_libmtp_errors (priv->device, FALSE);
				}
				g_hash_table_iter_remove (&iter);
			}
		}
	}


	g_object_unref (G_OBJECT (db));
	return FALSE;
}