summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--configure.ac2
-rw-r--r--doc/examples.h1
-rw-r--r--examples/.cvsignore1
-rw-r--r--examples/Makefile.am5
-rw-r--r--examples/delfile.c2
-rw-r--r--examples/files.c2
-rw-r--r--examples/getplaylist.c2
-rw-r--r--examples/playlists.c47
-rw-r--r--src/Makefile.am6
-rw-r--r--src/libmtp.c582
-rw-r--r--src/libmtp.h.in97
-rw-r--r--src/unicode.c10
-rw-r--r--src/unicode.h4
14 files changed, 549 insertions, 222 deletions
diff --git a/ChangeLog b/ChangeLog
index d756385..1ef0e99 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2006-06-07 Linus Walleij <triad@df.lth.se>
+
+ * src/libmtp.h.in: new playlist API and refactorings.
+ * src/libmtp.c: ditto, and refactorings.
+ * src/unicode.h: const correctness.
+ * src/unicode.c: ditto.
+ * examples/playlists.c: new example program.
+ * configure.ac: bump to 0.0.9
+ * src/Makefile.am: bump library interface.
+
2006-06-05 Linus Walleij <triad@df.lth.se>
* examples/sendtr.c: fixed annoying bug that made this
diff --git a/configure.ac b/configure.ac
index a5a5f5c..adc4e1c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.52)
-AC_INIT([libmtp], [0.0.8], [libmtp-users@lists.sourceforge.net])
+AC_INIT([libmtp], [0.0.9], [libmtp-users@lists.sourceforge.net])
AM_INIT_AUTOMAKE([foreign])
AC_CONFIG_SRCDIR([src/libmtp.c])
AC_CONFIG_HEADER([config.h])
diff --git a/doc/examples.h b/doc/examples.h
index 9ea3dc1..3e88ca4 100644
--- a/doc/examples.h
+++ b/doc/examples.h
@@ -12,5 +12,6 @@
/** \example sendtr.c */
/** \example tracks.c */
/** \example trexist.c */
+/** \example playlists.c */
/** \example getplaylist.c */
/** \example refactortest.c */
diff --git a/examples/.cvsignore b/examples/.cvsignore
index c1614ac..d5b6afb 100644
--- a/examples/.cvsignore
+++ b/examples/.cvsignore
@@ -15,3 +15,4 @@ tracks
trexist
getplaylist
refactortest
+playlists
diff --git a/examples/Makefile.am b/examples/Makefile.am
index b1f62bb..f993726 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -1,4 +1,6 @@
-bin_PROGRAMS=detect tracks files getfile sendtr delfile hotplug folders newfolder trexist sendfile getplaylist refactortest
+bin_PROGRAMS=detect tracks files getfile sendtr delfile hotplug \
+ folders newfolder trexist sendfile playlists getplaylist \
+ refactortest
detect_SOURCES=detect.c common.h
tracks_SOURCES=tracks.c common.h
@@ -11,6 +13,7 @@ hotplug_SOURCES=hotplug.c common.h
folders_SOURCES=folders.c common.h
newfolder_SOURCES=newfolder.c common.h
trexist_SOURCES=trexist.c common.h
+playlists_SOURCES=playlists.c common.h
getplaylist_SOURCES=getplaylist.c common.h
refactortest_SOURCES=refactortest.c common.h
diff --git a/examples/delfile.c b/examples/delfile.c
index a6a9dc9..44ed9ac 100644
--- a/examples/delfile.c
+++ b/examples/delfile.c
@@ -37,7 +37,7 @@ int main (int argc, char **argv)
return 0;
}
- ret = LIBMTP_Delete_File(device, id);
+ ret = LIBMTP_Delete_Object(device, id);
if ( ret != 0 ) {
printf("Failed to delete file.\n");
diff --git a/examples/files.c b/examples/files.c
index c4ead19..759d4f4 100644
--- a/examples/files.c
+++ b/examples/files.c
@@ -5,7 +5,7 @@ static void dump_fileinfo(LIBMTP_file_t *file)
printf("File ID: %d\n", file->item_id);
if (file->filename != NULL)
printf(" Filename: %s\n", file->filename);
- printf(" File size %llu bytes\n", file->filesize);
+ printf(" File size %llu (0x%08X) bytes\n", file->filesize, file->filesize);
printf(" Parent ID: %d\n", file->parent_id);
printf(" Filetype: %s\n", LIBMTP_Get_Filetype_Description(file->filetype));
}
diff --git a/examples/getplaylist.c b/examples/getplaylist.c
index a1e59b0..14b3edb 100644
--- a/examples/getplaylist.c
+++ b/examples/getplaylist.c
@@ -7,7 +7,7 @@ uint32_t LIBMTP_Get_Playlist(LIBMTP_mtpdevice_t *device, uint32_t playlist_id)
uint32_t i;
ret = LIBMTP_Get_Object_References (device, playlist_id, &items, &len);
- if (ret != 0x2001) {
+ if (ret != 0) {
printf("LIBMTP_Get_Playlist: Could not get object references\n");
return -1;
}
diff --git a/examples/playlists.c b/examples/playlists.c
new file mode 100644
index 0000000..28c4130
--- /dev/null
+++ b/examples/playlists.c
@@ -0,0 +1,47 @@
+#include "common.h"
+
+static void dump_plinfo(LIBMTP_playlist_t *pl)
+{
+ uint32_t i;
+
+ printf("Playlist ID: %d\n", pl->playlist_id);
+ if (pl->name != NULL)
+ printf(" Name: %s\n", pl->name);
+ printf(" Tracks: ");
+ for (i = 0; i < pl->no_tracks; i++) {
+ printf("%d, ", pl->tracks[i]);
+ }
+ printf("\n");
+}
+
+int main (int argc, char **argv)
+{
+ LIBMTP_mtpdevice_t *device;
+ LIBMTP_playlist_t *playlists;
+
+ LIBMTP_Init();
+ device = LIBMTP_Get_First_Device();
+ if (device == NULL) {
+ printf("No devices.\n");
+ exit (0);
+ }
+
+ // Get playlist listing.
+ playlists = LIBMTP_Get_Playlist_List(device);
+ if (playlists == NULL) {
+ printf("No playlists.\n");
+ } else {
+ LIBMTP_playlist_t *pl, *tmp;
+ pl = playlists;
+ while (pl != NULL) {
+ dump_plinfo(pl);
+ tmp = pl;
+ pl = pl->next;
+ LIBMTP_destroy_playlist_t(tmp);
+ }
+ }
+
+ LIBMTP_Release_Device(device);
+ printf("OK.\n");
+ exit (0);
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index 1d43188..dfdfb88 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,9 +29,9 @@ EXTRA_DIST=libmtp.h.in libmtp.sym ptp-pack.c
# increment AGE, Otherwise AGE is reset to 0. If CURRENT has changed,
# REVISION is set to 0, otherwise REVISION is incremented.
# ---------------------------------------------------------------------------
-CURRENT=1
-REVISION=0
-AGE=0
+CURRENT=2
+REVISION=1
+AGE=1
SOVERSION=$(CURRENT):$(REVISION):$(AGE)
libmtp_la_LDFLAGS=@LDFLAGS@ -version-info $(SOVERSION)
diff --git a/src/libmtp.c b/src/libmtp.c
index 6e2a288..e184fd7 100644
--- a/src/libmtp.c
+++ b/src/libmtp.c
@@ -27,9 +27,7 @@
* otherwise the libmtp.h device has to be dependent on ptp.h
* to be installed too, and we don't want that.
*/
-
typedef struct filemap_t LIBMTP_filemap_t;
-
struct filemap_t {
char *description; /**< Text description for the file type */
LIBMTP_filetype_t id; /**< LIBMTP internal type for the file type */
@@ -40,22 +38,16 @@ struct filemap_t {
LIBMTP_filemap_t *next;
};
-// Map this libptp2 single-threaded callback to the LIBMTP callback type
-// extern Progress_Callback* globalCallback;
-// static Progress_Callback single_threaded_callback_helper;
-
-static void *single_threaded_callback_data;
-static LIBMTP_progressfunc_t *single_threaded_callback;
-
// Global variables
+// This holds the global filetype mapping table
static LIBMTP_filemap_t *filemap = NULL;
// Forward declarations of local functions
+static void flush_handles(LIBMTP_mtpdevice_t *device);
static int send_file_object(LIBMTP_mtpdevice_t *device,
int const fd, uint64_t size,
LIBMTP_progressfunc_t const * const callback,
void const * const data);
-static int delete_item(LIBMTP_mtpdevice_t *device, uint32_t item_id);
static uint16_t map_libmtp_type_to_ptp_type(LIBMTP_filetype_t intype);
static LIBMTP_filetype_t map_ptp_type_to_libmtp_type(uint16_t intype);
@@ -90,8 +82,9 @@ static LIBMTP_filemap_t *new_filemap_entry()
* @param datafunc Pointer to function to fill data structure
* @return 0 for success any other value means error.
*/
-
-int LIBMTP_Register_Filetype(char *description, LIBMTP_filetype_t id, uint16_t ptp_id, void *constructor, void *destructor, void *datafunc)
+int LIBMTP_Register_Filetype(char const * const description, LIBMTP_filetype_t const id,
+ uint16_t const ptp_id, void const * const constructor,
+ void const * const destructor, void const * const datafunc)
{
LIBMTP_filemap_t *new = NULL, *current;
@@ -112,11 +105,13 @@ int LIBMTP_Register_Filetype(char *description, LIBMTP_filetype_t id, uint16_t p
}
new->id = id;
- if(description != NULL) new->description = (char *)strdup(description);
+ if(description != NULL) {
+ new->description = strdup(description);
+ }
new->ptp_id = ptp_id;
- new->constructor = constructor;
- new->destructor = destructor;
- new->datafunc = datafunc;
+ new->constructor = (void*) constructor;
+ new->destructor = (void*) destructor;
+ new->datafunc = (void*) datafunc;
// Add the entry to the list
if(filemap == NULL) {
@@ -128,15 +123,17 @@ int LIBMTP_Register_Filetype(char *description, LIBMTP_filetype_t id, uint16_t p
}
// Update the existing entry
} else {
- free(current->description);
+ if (current->description != NULL) {
+ free(current->description);
+ }
current->description = NULL;
if(description != NULL) {
- current->description = (char *)strdup(description);
+ current->description = strdup(description);
}
current->ptp_id = ptp_id;
- current->constructor = constructor;
- current->destructor = destructor;
- current->datafunc = datafunc;
+ current->constructor = (void*) constructor;
+ current->destructor = (void*) destructor;
+ current->datafunc = (void*) datafunc;
}
return 0;
@@ -149,12 +146,12 @@ int LIBMTP_Register_Filetype(char *description, LIBMTP_filetype_t id, uint16_t p
* @param description Text description of filetype
* @return 0 on success, any other value means error.
*/
-int LIBMTP_Set_Filetype_Description(LIBMTP_filetype_t id, char *description)
+int LIBMTP_Set_Filetype_Description(LIBMTP_filetype_t const id, char const * const description)
{
LIBMTP_filemap_t *current;
if (filemap == NULL) {
- return 1;
+ return -1;
}
// Go through the filemap until an entry is found
@@ -168,7 +165,7 @@ int LIBMTP_Set_Filetype_Description(LIBMTP_filetype_t id, char *description)
}
if(current == NULL) {
- return 1;
+ return -1;
}
if (current->description != NULL) {
@@ -176,7 +173,7 @@ int LIBMTP_Set_Filetype_Description(LIBMTP_filetype_t id, char *description)
current->description = NULL;
}
if(description != NULL) {
- current->description = (char *) strdup(description);
+ current->description = strdup(description);
}
return 0;
}
@@ -188,12 +185,12 @@ int LIBMTP_Set_Filetype_Description(LIBMTP_filetype_t id, char *description)
* @param constructor Pointer to a constructor function
* @return 0 on success, any other value means failure
*/
-int LIBMTP_Set_Constructor(LIBMTP_filetype_t id, void *constructor)
+int LIBMTP_Set_Constructor(LIBMTP_filetype_t const id, void const * const constructor)
{
LIBMTP_filemap_t *current;
if (filemap == NULL) {
- return 1;
+ return -1;
}
// Go through the filemap until an entry is found
@@ -207,10 +204,10 @@ int LIBMTP_Set_Constructor(LIBMTP_filetype_t id, void *constructor)
}
if (current == NULL) {
- return 1;
+ return -1;
}
- current->constructor = constructor;
+ current->constructor = (void*) constructor;
return 0;
}
@@ -221,12 +218,12 @@ int LIBMTP_Set_Constructor(LIBMTP_filetype_t id, void *constructor)
* @param destructor Pointer to a destructor function
* @return 0 on success, any other value means failure
*/
-int LIBMTP_Set_Destructor(LIBMTP_filetype_t id, void *destructor)
+int LIBMTP_Set_Destructor(LIBMTP_filetype_t const id, void const * const destructor)
{
LIBMTP_filemap_t *current;
if (filemap == NULL) {
- return 1;
+ return -1;
}
// Go through the filemap until an entry is found
@@ -240,10 +237,10 @@ int LIBMTP_Set_Destructor(LIBMTP_filetype_t id, void *destructor)
}
if(current == NULL) {
- return 1;
+ return -1;
}
- current->destructor = destructor;
+ current->destructor = (void *) destructor;
return 0;
}
@@ -254,12 +251,12 @@ int LIBMTP_Set_Destructor(LIBMTP_filetype_t id, void *destructor)
* @param datafunc Pointer to a data function
* @return 0 on success, any other value means failure
*/
-int LIBMTP_Set_Datafunc(LIBMTP_filetype_t id, void *datafunc)
+int LIBMTP_Set_Datafunc(LIBMTP_filetype_t const id, void const * const datafunc)
{
LIBMTP_filemap_t *current;
if (filemap == NULL) {
- return 1;
+ return -1;
}
// Go through the filemap until an entry is found
@@ -273,10 +270,10 @@ int LIBMTP_Set_Datafunc(LIBMTP_filetype_t id, void *datafunc)
}
if(current == NULL) {
- return 1;
+ return -1;
}
- current->datafunc = datafunc;
+ current->datafunc = (void *) datafunc;
return 0;
}
@@ -336,7 +333,8 @@ static uint16_t map_libmtp_type_to_ptp_type(LIBMTP_filetype_t intype)
/**
- * Returns the libmtp internal filetype that maps to a certain MTP file type.
+ * Returns the PTP internal filetype that maps to a certain libmtp
+ * interface file type.
* @param intype the MTP library interface type
* @return the PTP (libgphoto2) interface type
*/
@@ -364,9 +362,9 @@ static LIBMTP_filetype_t map_ptp_type_to_libmtp_type(uint16_t intype)
static void *get_datafunc(uint16_t intype)
{
LIBMTP_filemap_t *current;
-
+
current = filemap;
-
+
while (current != NULL) {
if(current->ptp_id == intype) {
return current->datafunc;
@@ -385,9 +383,9 @@ static void *get_datafunc(uint16_t intype)
static void *get_constructor(uint16_t intype)
{
LIBMTP_filemap_t *current;
-
+
current = filemap;
-
+
while (current != NULL) {
if(current->ptp_id == intype) {
return current->constructor;
@@ -405,7 +403,7 @@ static void *get_constructor(uint16_t intype)
static void *get_destructor(uint16_t intype)
{
LIBMTP_filemap_t *current;
-
+
current = filemap;
while (current != NULL) {
@@ -429,7 +427,7 @@ char const * LIBMTP_Get_Filetype_Description(LIBMTP_filetype_t intype)
LIBMTP_filemap_t *current;
current = filemap;
-
+
while (current != NULL) {
if(current->id == intype) {
return current->description;
@@ -441,22 +439,6 @@ char const * LIBMTP_Get_Filetype_Description(LIBMTP_filetype_t intype)
}
/**
- * This is a ugly workaround due to limitations in callback set by
- * libptp2...
- */
-static int single_threaded_callback_helper(uint32_t sent, uint32_t total) {
- if (single_threaded_callback != NULL) {
- /*
- * If the callback return anything else than 0, we should interrupt the processing,
- * but currently libptp2 does not offer anything meaningful here so we have to ignore
- * the return value.
- */
- (void) single_threaded_callback(sent, total, single_threaded_callback_data);
- }
- return 0;
-}
-
-/**
* Initialize the library. You are only supposed to call this
* one, before using the library for the first time in a program.
* Never re-initialize libmtp!
@@ -477,23 +459,23 @@ void LIBMTP_Init(void)
* @param object_id Object reference
* @param attribute_id PTP attribute ID
* @param getUtf8 retrieve the string as UTF8. Specify 1 for UTF8.
- * @return valid string or NULL on failure.
+ * @return valid string or NULL on failure. The returned string
+ * must bee <code>free()</code>:ed by the caller after
+ * use.
*/
-char *LIBMTP_Get_String_From_Object(LIBMTP_mtpdevice_t *device, uint32_t object_id,
- uint32_t attribute_id, char getUtf8)
+char *LIBMTP_Get_String_From_Object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
+ uint32_t const attribute_id, uint8_t const getUtf8)
{
PTPPropertyValue propval;
char *retstring = NULL;
PTPParams *params = (PTPParams *) device->params;
- int ret;
+ uint16_t ret;
- if ( device == NULL ) {
+ if ( device == NULL || object_id == 0) {
return NULL;
}
- ret = ptp_mtp_getobjectpropvalue(params, object_id,
- attribute_id,
- &propval,
+ ret = ptp_mtp_getobjectpropvalue(params, object_id, attribute_id, &propval,
( getUtf8 == 1 ? PTP_DTC_UNISTR : PTP_DTC_STR ));
if (ret == PTP_RC_OK) {
if (getUtf8 == 1) {
@@ -508,7 +490,7 @@ char *LIBMTP_Get_String_From_Object(LIBMTP_mtpdevice_t *device, uint32_t object_
}
}
}
-
+
return retstring;
}
@@ -521,14 +503,14 @@ char *LIBMTP_Get_String_From_Object(LIBMTP_mtpdevice_t *device, uint32_t object_
* @param value_default Default value to return on failure
* @return the value
*/
-uint32_t LIBMTP_Get_U32_From_Object(LIBMTP_mtpdevice_t *device,uint32_t object_id,
- uint32_t attribute_id, uint32_t value_default)
+uint32_t LIBMTP_Get_U32_From_Object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
+ uint32_t const attribute_id, uint32_t const value_default)
{
PTPPropertyValue propval;
uint32_t retval = value_default;
PTPParams *params = (PTPParams *) device->params;
- int ret;
-
+ uint16_t ret;
+
if ( device == NULL ) {
return value_default;
}
@@ -553,13 +535,13 @@ uint32_t LIBMTP_Get_U32_From_Object(LIBMTP_mtpdevice_t *device,uint32_t object_i
* @param value_default Default value to return on failure
* @return a value
*/
-uint16_t LIBMTP_Get_U16_From_Object(LIBMTP_mtpdevice_t *device, uint32_t object_id,
- uint32_t attribute_id, uint16_t value_default)
+uint16_t LIBMTP_Get_U16_From_Object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
+ uint32_t const attribute_id, uint16_t const value_default)
{
PTPPropertyValue propval;
uint16_t retval = value_default;
PTPParams *params = (PTPParams *) device->params;
- int ret;
+ uint16_t ret;
if ( device == NULL ) {
return value_default;
@@ -586,29 +568,30 @@ uint16_t LIBMTP_Get_U16_From_Object(LIBMTP_mtpdevice_t *device, uint32_t object_
* @param setUtf8 Specify string as UTF8. Set to 1 if UTF8.
* @return 0 on success, any other value means failure
*/
-int LIBMTP_Set_Object_String(LIBMTP_mtpdevice_t *device, uint32_t object_id, uint32_t attribute_id,
- char *string, int setUtf8)
+int LIBMTP_Set_Object_String(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
+ uint32_t const attribute_id, char const * const string,
+ uint8_t const setUtf8)
{
PTPPropertyValue propval;
PTPParams *params = (PTPParams *) device->params;
- int ret;
+ uint16_t ret;
if (device == NULL || string == NULL) {
- return 1;
+ return -1;
}
if (setUtf8 == 1) {
- propval.unistr = utf8_to_ucs2((const unsigned char *) string);
+ propval.unistr = utf8_to_ucs2((unsigned char const * const) string);
ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_UNISTR);
free(propval.unistr);
} else {
- propval.str = string;
+ propval.str = (char *) string;
ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_STR);
}
if (ret != PTP_RC_OK) {
- return 1;
+ return -1;
}
-
+
return 0;
}
@@ -621,21 +604,21 @@ int LIBMTP_Set_Object_String(LIBMTP_mtpdevice_t *device, uint32_t object_id, uin
* @param value 32-bit unsigned integer to set
* @return 0 on success, any other value means failure
*/
-int LIBMTP_Set_Object_U32(LIBMTP_mtpdevice_t *device,uint32_t object_id,
- uint32_t attribute_id, uint32_t value)
+int LIBMTP_Set_Object_U32(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
+ uint32_t const attribute_id, uint32_t const value)
{
PTPPropertyValue propval;
PTPParams *params = (PTPParams *) device->params;
- int ret;
+ uint16_t ret;
if (device == NULL) {
- return 1;
+ return -1;
}
propval.u32 = value;
ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_UINT32);
if (ret != PTP_RC_OK) {
- return 1;
+ return -1;
}
return 0;
@@ -650,12 +633,12 @@ int LIBMTP_Set_Object_U32(LIBMTP_mtpdevice_t *device,uint32_t object_id,
* @param value 16-bit unsigned integer to set
* @return 0 on success, any other value means failure
*/
-int LIBMTP_Set_Object_U16(LIBMTP_mtpdevice_t *device,uint32_t object_id,
- uint32_t attribute_id, uint16_t value)
+int LIBMTP_Set_Object_U16(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
+ uint32_t const attribute_id, uint16_t const value)
{
PTPPropertyValue propval;
PTPParams *params = (PTPParams *) device->params;
- int ret;
+ uint16_t ret;
if (device == NULL) {
return 1;
@@ -679,11 +662,11 @@ int LIBMTP_Set_Object_U16(LIBMTP_mtpdevice_t *device,uint32_t object_id,
* @param len length of array
* @return 0 on success, any other value means failure
*/
-int LIBMTP_Get_Object_References(LIBMTP_mtpdevice_t *device, uint32_t object_id,
+int LIBMTP_Get_Object_References(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
uint32_t **items, uint32_t *len)
{
PTPParams *params = (PTPParams *) device->params;
- uint32_t ret;
+ uint16_t ret;
// A device must be attached
if (device == NULL ) {
@@ -711,17 +694,17 @@ int LIBMTP_Get_Object_References(LIBMTP_mtpdevice_t *device, uint32_t object_id,
* @param len length of array
* @return 0 on success, any other value means failure
*/
-int LIBMTP_Set_Object_References(LIBMTP_mtpdevice_t *device, uint32_t object_id,
- uint32_t *items, uint32_t len)
+int LIBMTP_Set_Object_References(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
+ uint32_t const * const items, uint32_t const len)
{
PTPParams *params = (PTPParams *) device->params;
- uint32_t ret;
+ uint16_t ret;
if (device == NULL || items == NULL) {
return 1;
}
- ret = ptp_mtp_setobjectreferences (params, object_id, items, len);
+ ret = ptp_mtp_setobjectreferences (params, object_id, (uint32_t *) items, len);
if (ret != PTP_RC_OK) {
ptp_perror(params, ret);
printf("LIBMTP_Set_Object_References: Could not set object references\n");
@@ -757,7 +740,8 @@ int LIBMTP_Get_Supported_Devices_List(LIBMTP_device_entry_t ** const devices, in
}
/**
- * Get the first connected MTP device.
+ * Get the first connected MTP device. There is currently no API for
+ * retrieveing multiple devices.
* @return a device pointer.
*/
LIBMTP_mtpdevice_t *LIBMTP_Get_First_Device(void)
@@ -852,11 +836,41 @@ void LIBMTP_Release_Device(LIBMTP_mtpdevice_t *device)
// ptp_free_deviceinfo(&params->deviceinfo);
if (params->handles.Handler != NULL) {
free(params->handles.Handler);
+ params->handles.Handler = NULL;
}
free(device);
}
/**
+ * This function refresh the internal handle list whenever
+ * the items stored inside the device is altered. On operations
+ * that do not add or remove objects, this is typically not
+ * called.
+ * @param device a pointer to the MTP device to flush handles for.
+ */
+static void flush_handles(LIBMTP_mtpdevice_t *device)
+{
+ PTPParams *params = (PTPParams *) device->params;
+ uint16_t ret;
+
+ if (params->handles.Handler != NULL) {
+ free(params->handles.Handler);
+ }
+
+ // Get all the handles if we haven't already done that
+ ret = ptp_getobjecthandles(params,
+ PTP_GOH_ALL_STORAGE,
+ PTP_GOH_ALL_FORMATS,
+ PTP_GOH_ALL_ASSOCS,
+ &params->handles);
+ if (ret != PTP_RC_OK) {
+ printf("flush_handles(): LIBMTP panic: Could not get object handles...\n");
+ }
+
+ return;
+}
+
+/**
* This function dumps out a large chunk of textual information
* provided from the PTP protocol and additionally some extra
* MTP-specific information where applicable.
@@ -1168,17 +1182,10 @@ LIBMTP_file_t *LIBMTP_Get_Filelisting(LIBMTP_mtpdevice_t *device)
LIBMTP_file_t *retfiles = NULL;
LIBMTP_file_t *curfile = NULL;
PTPParams *params = (PTPParams *) device->params;
-
+
+ // Get all the handles if we haven't already done that
if (params->handles.Handler == NULL) {
- // Get all the handles if we haven't already done that
- if (ptp_getobjecthandles(params,
- PTP_GOH_ALL_STORAGE,
- PTP_GOH_ALL_FORMATS,
- PTP_GOH_ALL_ASSOCS,
- &params->handles) != PTP_RC_OK) {
- printf("LIBMTP panic: Could not get object handles...\n");
- return NULL;
- }
+ flush_handles(device);
}
for (i = 0; i < params->handles.n; i++) {
@@ -1327,17 +1334,10 @@ LIBMTP_track_t *LIBMTP_Get_Tracklisting(LIBMTP_mtpdevice_t *device)
LIBMTP_track_t *retracks = NULL;
LIBMTP_track_t *curtrack = NULL;
PTPParams *params = (PTPParams *) device->params;
-
+
+ // Get all the handles if we haven't already done that
if (params->handles.Handler == NULL) {
- // Get all the handles if we haven't already done that
- if (ptp_getobjecthandles(params,
- PTP_GOH_ALL_STORAGE,
- PTP_GOH_ALL_FORMATS,
- PTP_GOH_ALL_ASSOCS,
- &params->handles) != PTP_RC_OK) {
- printf("LIBMTP panic: Could not get object handles...\n");
- return NULL;
- }
+ flush_handles(device);
}
for (i = 0; i < params->handles.n; i++) {
@@ -1468,16 +1468,11 @@ int LIBMTP_Get_File_To_File_Descriptor(LIBMTP_mtpdevice_t *device,
void const * const data)
{
PTPObjectInfo oi;
- void *image = NULL;
- int ret;
+ unsigned char *image = NULL;
+ uint16_t ret;
PTPParams *params = (PTPParams *) device->params;
ssize_t written;
- single_threaded_callback_data = (void *) data;
- single_threaded_callback = callback;
- // Disabled since the new ptp.c from libgphoto2 doesn't seem to have this anymore.
- // globalCallback = single_threaded_callback_helper;
-
if (ptp_getobjectinfo(params, id, &oi) != PTP_RC_OK) {
printf("LIBMTP_Get_File_To_File_Descriptor(): Could not get object info\n");
return -1;
@@ -1489,7 +1484,7 @@ int LIBMTP_Get_File_To_File_Descriptor(LIBMTP_mtpdevice_t *device,
// Copy object to memory
// We could use ptp_getpartialobject to make for progress bars etc.
- ret = ptp_getobject(params, id, (unsigned char **) &image);
+ ret = ptp_getobject(params, id, &image);
if (ret != PTP_RC_OK) {
printf("LIBMTP_Get_File_To_File_Descriptor(): Could not get file from device (%d)\n", ret);
@@ -1571,6 +1566,7 @@ int LIBMTP_Get_Track_To_File_Descriptor(LIBMTP_mtpdevice_t *device,
* @return 0 if the transfer was successful, any other value means
* failure.
* @see LIBMTP_Send_Track_From_File_Descriptor()
+ * @see LIBMTP_Delete_Object()
*/
int LIBMTP_Send_Track_From_File(LIBMTP_mtpdevice_t *device,
char const * const path, LIBMTP_track_t * const metadata,
@@ -1626,7 +1622,7 @@ int send_file_object(LIBMTP_mtpdevice_t *device,
void const * const data)
{
void *image = NULL;
- int ret;
+ uint16_t ret;
PTPParams *params = (PTPParams *) device->params;
ssize_t readb;
@@ -1791,6 +1787,7 @@ int send_file_object(LIBMTP_mtpdevice_t *device,
* @return 0 if the transfer was successful, any other value means
* failure.
* @see LIBMTP_Send_Track_From_File()
+ * @see LIBMTP_Delete_Object()
*/
int LIBMTP_Send_Track_From_File_Descriptor(LIBMTP_mtpdevice_t *device,
int const fd, LIBMTP_track_t * const metadata,
@@ -1830,7 +1827,7 @@ int LIBMTP_Send_Track_From_File_Descriptor(LIBMTP_mtpdevice_t *device,
subcall_ret = send_file_object(device, fd, metadata->filesize, callback, data);
if (subcall_ret != 0) {
printf("LIBMTP_Send_Track_From_File_Descriptor: error sending track object\n");
- (void) delete_item(device, metadata->item_id);
+ (void) LIBMTP_Delete_Object(device, metadata->item_id);
return -1;
}
@@ -1838,9 +1835,12 @@ int LIBMTP_Send_Track_From_File_Descriptor(LIBMTP_mtpdevice_t *device,
subcall_ret = LIBMTP_Update_Track_Metadata(device, metadata);
if (subcall_ret != 0) {
printf("LIBMTP_Send_Track_From_File_Descriptor: error setting metadata for new track\n");
- (void) delete_item(device, metadata->item_id);
+ (void) LIBMTP_Delete_Object(device, metadata->item_id);
return -1;
}
+
+ // Added object so flush handles
+ flush_handles(device);
return 0;
}
@@ -1864,6 +1864,7 @@ int LIBMTP_Send_Track_From_File_Descriptor(LIBMTP_mtpdevice_t *device,
* @return 0 if the transfer was successful, any other value means
* failure.
* @see LIBMTP_Send_File_From_File_Descriptor()
+ * @see LIBMTP_Delete_Object()
*/
int LIBMTP_Send_File_From_File(LIBMTP_mtpdevice_t *device,
char const * const path, LIBMTP_file_t * const filedata,
@@ -1916,6 +1917,7 @@ int LIBMTP_Send_File_From_File(LIBMTP_mtpdevice_t *device,
* @return 0 if the transfer was successful, any other value means
* failure.
* @see LIBMTP_Send_File_From_File()
+ * @see LIBMTP_Delete_Object()
*/
int LIBMTP_Send_File_From_File_Descriptor(LIBMTP_mtpdevice_t *device,
int const fd, LIBMTP_file_t * const filedata,
@@ -1945,10 +1947,12 @@ int LIBMTP_Send_File_From_File_Descriptor(LIBMTP_mtpdevice_t *device,
subcall_ret = send_file_object(device, fd, filedata->filesize, callback, data);
if (subcall_ret != 0) {
printf("LIBMTP_Send_File_From_File_Descriptor: error sending track object\n");
- (void) delete_item(device, filedata->item_id);
+ (void) LIBMTP_Delete_Object(device, filedata->item_id);
return -1;
}
-
+
+ // Added object so flush handles.
+ flush_handles(device);
return 0;
}
@@ -2031,40 +2035,31 @@ int LIBMTP_Update_Track_Metadata(LIBMTP_mtpdevice_t *device,
}
/**
- * Internal function called to delete tracks and files alike.
- * @param device a pointer to the device to delete the item from.
+ * This function deletes a single file, track, playlist or
+ * any other object off the MTP device,
+ * identified by an object ID.
+ * @param device a pointer to the device to delete the file or track from.
* @param item_id the item to delete.
* @return 0 on success, any other value means failure.
*/
-static int delete_item(LIBMTP_mtpdevice_t *device,
- uint32_t item_id)
+int LIBMTP_Delete_Object(LIBMTP_mtpdevice_t *device,
+ uint32_t object_id)
{
- int ret;
+ uint16_t ret;
PTPParams *params = (PTPParams *) device->params;
- ret = ptp_deleteobject(params, item_id, 0);
+ ret = ptp_deleteobject(params, object_id, 0);
if (ret != PTP_RC_OK) {
ptp_perror(params, ret);
- printf("delete_item(): could not delete track object\n");
+ printf("LIBMTP_Delete_Object(): could not delete object\n");
return -1;
}
+ // Removed object so flush handles.
+ flush_handles(device);
return 0;
}
/**
- * This function deletes a single file or track off the MTP device,
- * identified by an object ID.
- * @param device a pointer to the device to delete the file or track from.
- * @param item_id the item to delete.
- * @return 0 on success, any other value means failure.
- */
-int LIBMTP_Delete_File(LIBMTP_mtpdevice_t *device,
- uint32_t item_id)
-{
- return delete_item(device, item_id);
-}
-
-/**
* Helper function. This indicates if a track exists on the device
* @param device a pointer to the device to get the track from.
* @param id the track ID of the track to retrieve.
@@ -2077,7 +2072,7 @@ int LIBMTP_Track_Exists(LIBMTP_mtpdevice_t *device,
PTPParams *params = (PTPParams *) device->params;
if (ptp_getobjectinfo(params, id, &oi) == PTP_RC_OK) {
- return 1;
+ return -1;
}
return 0;
}
@@ -2220,18 +2215,10 @@ LIBMTP_folder_t *LIBMTP_Get_Folder_List(LIBMTP_mtpdevice_t *device)
uint32_t i = 0;
LIBMTP_folder_t *retfolders = NULL;
PTPParams *params = (PTPParams *) device->params;
- uint32_t ret = 0;
-
+
+ // Get all the handles if we haven't already done that
if (params->handles.Handler == NULL) {
- // Get all the handles if we haven't already done that
- if ((ret=ptp_getobjecthandles(params,
- PTP_GOH_ALL_STORAGE,
- PTP_GOH_ALL_FORMATS,
- PTP_GOH_ALL_ASSOCS,
- &params->handles)) != PTP_RC_OK) {
- printf("LIBMTP_Get_Folder_List: Could not get object handles...(0x%08X)\n", ret);
- return NULL;
- }
+ flush_handles(device);
}
for (i = 0; i < params->handles.n; i++) {
@@ -2298,7 +2285,7 @@ uint32_t LIBMTP_Create_Folder(LIBMTP_mtpdevice_t *device, char *name, uint32_t p
uint32_t parenthandle = 0;
uint32_t store = 0;
PTPObjectInfo new_folder;
- uint32_t ret;
+ uint16_t ret;
uint32_t new_id = 0;
memset(&new_folder, 0, sizeof(new_folder));
@@ -2315,6 +2302,8 @@ uint32_t LIBMTP_Create_Folder(LIBMTP_mtpdevice_t *device, char *name, uint32_t p
printf("LIBMTP_Create_Folder: Could not send object info\n");
return 0;
}
+ // Created new object so flush handles
+ flush_handles(device);
return new_id;
}
@@ -2370,20 +2359,12 @@ LIBMTP_object_t *LIBMTP_Make_List(LIBMTP_mtpdevice_t *device, uint32_t *filter,
uint32_t i = 0;
LIBMTP_object_t *objectlist = NULL;
PTPParams *params = (PTPParams *) device->params;
- uint32_t ret = 0;
uint32_t max_exclusions = 0;
uint32_t max_filter = 0;
-
+
+ // Get all the handles if we haven't already done that
if (params->handles.Handler == NULL) {
- // Get all the handles if we haven't already done that
- if ((ret=ptp_getobjecthandles(params,
- PTP_GOH_ALL_STORAGE,
- PTP_GOH_ALL_FORMATS,
- PTP_GOH_ALL_ASSOCS,
- &params->handles)) != PTP_RC_OK) {
- printf("LIBMTP_Make_List: Could not get object handles...(0x%08X)\n", ret);
- return NULL;
- }
+ flush_handles(device);
}
if(filter != NULL) max_filter = filter_len;
@@ -2493,3 +2474,252 @@ void LIBMTP_Dump_List(LIBMTP_object_t *list)
LIBMTP_Dump_List(list->child);
LIBMTP_Dump_List(list->sibling);
}
+
+/**
+ * This creates a new playlist metadata structure and allocates memory
+ * for it. Notice that if you add strings to this structure they
+ * will be freed by the corresponding <code>LIBMTP_destroy_playlist_t</code>
+ * operation later, so be careful of using strdup() when assigning
+ * strings, e.g.:
+ *
+ * <pre>
+ * LIBMTP_playlist_t *pl = LIBMTP_new_playlist_t();
+ * pl->name = strdup(str);
+ * ....
+ * LIBMTP_destroy_playlist_t(pl);
+ * </pre>
+ *
+ * @return a pointer to the newly allocated metadata structure.
+ * @see LIBMTP_destroy_playlist_t()
+ */
+LIBMTP_playlist_t *LIBMTP_new_playlist_t(void)
+{
+ LIBMTP_playlist_t *new = (LIBMTP_playlist_t *) malloc(sizeof(LIBMTP_playlist_t));
+ if (new == NULL) {
+ return NULL;
+ }
+ new->playlist_id = 0;
+ new->name = NULL;
+ new->tracks = NULL;
+ new->no_tracks = 0;
+ new->next = NULL;
+ return new;
+}
+
+/**
+ * This destroys a playlist metadata structure and deallocates the memory
+ * used by it, including any strings. Never use a track metadata
+ * structure again after calling this function on it.
+ * @param playlist the playlist metadata to destroy.
+ * @see LIBMTP_new_playlist_t()
+ */
+void LIBMTP_destroy_playlist_t(LIBMTP_playlist_t *playlist)
+{
+ if (playlist == NULL) {
+ return;
+ }
+ if (playlist->name != NULL)
+ free(playlist->name);
+ if (playlist->tracks != NULL)
+ free(playlist->tracks);
+ free(playlist);
+ return;
+}
+
+/**
+ * This function returns a list of the playlists available on the
+ * device. Typical usage:
+ *
+ * <pre>
+ * </pre>
+ *
+ * @param device a pointer to the device to get the playlist listing from.
+ * @return a playlist list on success, else NULL. If there are no playlists
+ * on the device, NULL will be returned as well.
+ */
+LIBMTP_playlist_t *LIBMTP_Get_Playlist_List(LIBMTP_mtpdevice_t *device)
+{
+ PTPParams *params = (PTPParams *) device->params;
+ LIBMTP_playlist_t *retlists = NULL;
+ LIBMTP_playlist_t *curlist = NULL;
+ uint32_t i;
+
+ // Get all the handles if we haven't already done that
+ if (params->handles.Handler == NULL) {
+ flush_handles(device);
+ }
+
+ for (i = 0; i < params->handles.n; i++) {
+ LIBMTP_playlist_t *pl;
+ PTPObjectInfo oi;
+ uint16_t ret;
+
+ ret = ptp_getobjectinfo(params, params->handles.Handler[i], &oi);
+ if ( ret == PTP_RC_OK) {
+
+ // Ignore stuff that isn't playlists
+ if ( oi.ObjectFormat != PTP_OFC_MTP_AbstractAudioVideoPlaylist ) {
+ continue;
+ }
+
+ // Allocate a new playlist type
+ pl = LIBMTP_new_playlist_t();
+
+ // Ignoring the io.Filename field.
+ pl->name = LIBMTP_Get_String_From_Object(device, params->handles.Handler[i], PTP_OPC_Name, 1);
+
+ // This is some sort of unique playlist ID so we can keep track of it
+ pl->playlist_id = params->handles.Handler[i];
+
+ // Then get the track listing for this playlist
+ ret = ptp_mtp_getobjectreferences(params, pl->playlist_id, &pl->tracks, &pl->no_tracks);
+ if (ret != PTP_RC_OK) {
+ printf("LIBMTP_Get_Playlist: Could not get object references\n");
+ pl->tracks = NULL;
+ pl->no_tracks = 0;
+ }
+
+ // Add playlist to a list that will be returned afterwards.
+ if (retlists == NULL) {
+ retlists = pl;
+ curlist = pl;
+ } else {
+ curlist->next = pl;
+ curlist = pl;
+ }
+
+ // Call callback here if we decide to add that possibility...
+
+ } else {
+ printf("LIBMTP panic: Found a bad handle, trying to ignore it.\n");
+ }
+ }
+ return retlists;
+}
+
+/**
+ * This routine creates a new playlist based on the metadata
+ * supplied. If the <code>tracks</code> field of the metadata
+ * contains a track listing, these tracks will be added to the
+ * playlist.
+ * @param device a pointer to the device to create the new playlist on.
+ * @param metadata the metadata for the new playlist. If the function
+ * exits with success, the <code>playlist_id</code> field of this
+ * struct will contain the new playlist ID of the playlist.
+ * @param parenthandle the parent (e.g. folder) to store this playlist
+ * in. Pass in 0 to put the playlist in the root directory.
+ * @return 0 on success, any other value means failure.
+ * @see LIBMTP_Update_Playlist()
+ * @see LIBMTP_Delete_Object()
+ */
+int LIBMTP_Create_New_Playlist(LIBMTP_mtpdevice_t *device,
+ LIBMTP_playlist_t * const metadata,
+ uint32_t const parenthandle)
+{
+ uint16_t ret;
+ uint32_t store = 0;
+ PTPObjectInfo new_pl;
+ PTPParams *params = (PTPParams *) device->params;
+ uint32_t localph = parenthandle;
+ char fname[256];
+
+ // .zpl is the "abstract audio/video playlist "file" suffix
+ new_pl.Filename = NULL;
+ if (strlen(metadata->name) > 4) {
+ char *suff = &metadata->name[strlen(metadata->name)-4];
+ if (!strcmp(suff, ".zpl")) {
+ // Home free.
+ new_pl.Filename = metadata->name;
+ }
+ }
+ // If it didn't end with ".zpl" then add that here.
+ if (new_pl.Filename == NULL) {
+ strncpy(fname, metadata->name, sizeof(fname)-5);
+ strcat(fname, ".zpl");
+ fname[sizeof(fname)-1] = '\0';
+ new_pl.Filename = fname;
+ }
+
+ // Means size = -1, probably N/A
+ new_pl.ObjectCompressedSize = 0xFFFFFFFFU;
+ new_pl.ObjectFormat = PTP_OFC_MTP_AbstractAudioVideoPlaylist;
+
+ // Create the object
+ ret = ptp_sendobjectinfo(params, &store, &localph, &metadata->playlist_id, &new_pl);
+ if (ret != PTP_RC_OK) {
+ ptp_perror(params, ret);
+ printf("LIBMTP_New_Playlist(): Could not send object info (the playlist itself)\n");
+ return -1;
+ }
+
+ /*
+ * TODO: determine if we really have to send this "blank" data or if we can
+ * just pass in an object of size -1 as info.
+ *
+ * unsigned char *data = "\0";
+ * ret = ptp_sendobject(&params, data, 1);
+ * if (ret != PTP_RC_OK) {
+ * ptp_perror(params, ret);
+ * printf("LIBMTP_New_Playlist(): Could not send object data (the tracks)\n");
+ * return -1;
+ * }
+ */
+
+ // Update title
+ ret = LIBMTP_Set_Object_String(device, metadata->playlist_id, PTP_OPC_Name, metadata->name, 1);
+ if (ret != PTP_RC_OK) {
+ printf("LIBMTP_New_Playlist(): could not set playlist name\n");
+ return -1;
+ }
+
+ if (metadata->no_tracks > 0) {
+ // Add tracks to the new playlist as object references.
+ ret = ptp_mtp_setobjectreferences (params, metadata->playlist_id, metadata->tracks, metadata->no_tracks);
+ if (ret != PTP_RC_OK) {
+ printf("LIBMTP_New_Playlist(): could not add tracks as object references\n");
+ return -1;
+ }
+ }
+
+ // Created new item, so flush handles
+ flush_handles(device);
+
+ return 0;
+}
+
+/**
+ * This routine updates a playlist based on the metadata
+ * supplied. If the <code>tracks</code> field of the metadata
+ * contains a track listing, these tracks will be added to the
+ * playlist in place of those already present, i.e. the
+ * previous track listing will be deleted.
+ * @param device a pointer to the device to create the new playlist on.
+ * @param metadata the metadata for the playlist to be updated.
+ * notice that the field <code>playlist_id</code>
+ * must contain the apropriate playlist ID.
+ * @return 0 on success, any other value means failure.
+ * @see LIBMTP_Create_New_Playlist()
+ * @see LIBMTP_Delete_Object()
+ */
+int LIBMTP_Update_Playlist(LIBMTP_mtpdevice_t *device,
+ LIBMTP_playlist_t * const metadata)
+{
+ uint16_t ret;
+
+ // Update title
+ ret = LIBMTP_Set_Object_String(device, metadata->playlist_id, PTP_OPC_Name, metadata->name, 1);
+ if (ret != PTP_RC_OK) {
+ printf("LIBMTP_Update_Playlist(): could not set playlist name\n");
+ return -1;
+ }
+
+ if (metadata->no_tracks > 0) {
+ // Add tracks to the new playlist as object references.
+ ret = ptp_mtp_setobjectreferences (params, metadata->playlist_id, metadata->tracks, metadata->no_tracks);
+ if (ret != PTP_RC_OK) {
+ printf("LIBMTP_Update_Playlist(): could not add tracks as object references\n");
+ return -1;
+ }
+ }
+ return 0;
+}
diff --git a/src/libmtp.h.in b/src/libmtp.h.in
index 7dde458..72fefa5 100644
--- a/src/libmtp.h.in
+++ b/src/libmtp.h.in
@@ -39,7 +39,7 @@ typedef unsigned __int64 uint64_t;
#endif
/**
- * @defgroup types libnjb global type definitions
+ * @defgroup types libmtp global type definitions
* @{
* The filetypes defined here are the external types used
* by the libmtp library interface. The types used internally
@@ -79,9 +79,28 @@ typedef struct LIBMTP_device_entry_struct LIBMTP_device_entry_t; /**< @see LIBMT
typedef struct LIBMTP_mtpdevice_struct LIBMTP_mtpdevice_t; /**< @see LIBMTP_mtpdevice_struct */
typedef struct LIBMTP_file_struct LIBMTP_file_t; /**< @see LIBMTP_file_struct */
typedef struct LIBMTP_track_struct LIBMTP_track_t; /**< @see LIBMTP_track_struct */
+typedef struct LIBMTP_playlist_struct LIBMTP_playlist_t; /**< @see LIBMTP_playlist_struct */
typedef struct LIBMTP_folder_struct LIBMTP_folder_t; /**< @see LIBMTP_folder_t */
typedef struct LIBMTP_object_struct LIBMTP_object_t; /**< @see LIBMTP_object_t */
-/** @} */
+
+/**
+ * The callback type definition. Notice that a progress percentage ratio
+ * is easy to calculate by dividing <code>sent</code> by
+ * <code>total</code>.
+ * @param sent the number of bytes sent so far
+ * @param total the total number of bytes to send
+ * @param data a user-defined dereferencable pointer
+ * @return if anything else than 0 is returned, the current transfer will be
+ * interrupted / cancelled.
+ */
+typedef int LIBMTP_progressfunc_t (uint64_t const sent, uint64_t const total,
+ void const * const data);
+
+/**
+ * @}
+ * @defgroup structar libmtp data structures
+ * @{
+ */
/**
* A data structure to hold MTP device entries
@@ -145,6 +164,17 @@ struct LIBMTP_track_struct {
};
/**
+ * MTP Playlist structure
+ */
+struct LIBMTP_playlist_struct {
+ uint32_t playlist_id; /**< Unique playlist ID */
+ char *name; /**< Name of playlist */
+ uint32_t *tracks; /**< The tracks in this playlist */
+ uint32_t no_tracks; /**< The number of tracks in this playlist */
+ LIBMTP_playlist_t *next; /**< Next playlist or NULL if last playlist */
+};
+
+/**
* MTP Folder structure
*/
struct LIBMTP_folder_struct {
@@ -169,24 +199,13 @@ struct LIBMTP_object_struct {
LIBMTP_object_t *child;
};
+/** @} */
+
/* Make functions available for C++ */
#ifdef __cplusplus
extern "C" {
#endif
-/**
- * The callback type definition. Notice that a progress percentage ratio
- * is easy to calculate by dividing <code>sent</code> by
- * <code>total</code>.
- * @param sent the number of bytes sent so far
- * @param total the total number of bytes to send
- * @param data a user-defined dereferencable pointer
- * @return if anything else than 0 is returned, the current transfer will be
- * interrupted / cancelled.
- */
-typedef int LIBMTP_progressfunc_t (uint64_t const sent, uint64_t const total,
- void const * const data);
-
/**
* @defgroup internals The libmtp internals API.
* @{
@@ -222,7 +241,6 @@ LIBMTP_file_t *LIBMTP_new_file_t(void);
void LIBMTP_destroy_file_t(LIBMTP_file_t*);
char const * LIBMTP_Get_Filetype_Description(LIBMTP_filetype_t);
LIBMTP_file_t *LIBMTP_Get_Filelisting(LIBMTP_mtpdevice_t *device);
-int LIBMTP_Delete_File(LIBMTP_mtpdevice_t *, uint32_t);
int LIBMTP_Get_File_To_File(LIBMTP_mtpdevice_t*, uint32_t, char const * const,
LIBMTP_progressfunc_t const * const, void const * const);
int LIBMTP_Get_File_To_File_Descriptor(LIBMTP_mtpdevice_t*, uint32_t const, int const,
@@ -267,27 +285,42 @@ LIBMTP_folder_t *LIBMTP_new_folder_t(void);
void LIBMTP_destroy_folder_t(LIBMTP_folder_t*);
LIBMTP_folder_t *LIBMTP_Get_Folder_List(LIBMTP_mtpdevice_t*);
LIBMTP_folder_t *LIBMTP_Find_Folder(LIBMTP_folder_t*, uint32_t const);
-uint32_t LIBMTP_Create_Folder(LIBMTP_mtpdevice_t*, char * , uint32_t);
+uint32_t LIBMTP_Create_Folder(LIBMTP_mtpdevice_t*, char *, uint32_t);
/** @} */
+
+/**
+ * @}
+ * @defgroup playlists The audio/video playlist management API.
+ * @{
+ */
+LIBMTP_playlist_t *LIBMTP_new_playlist_t(void);
+void LIBMTP_destroy_playlist_t(LIBMTP_playlist_t *);
+LIBMTP_playlist_t *LIBMTP_Get_Playlist_List(LIBMTP_mtpdevice_t *);
+int LIBMTP_Create_New_Playlist(LIBMTP_mtpdevice_t *, LIBMTP_playlist_t * const, uint32_t const);
+int LIBMTP_Update_Playlist(LIBMTP_mtpdevice_t *, LIBMTP_playlist_t const * const);
+
+
/**
* @}
* @defgroup objects The object management API.
* @{
*/
-char *LIBMTP_Get_String_From_Object(LIBMTP_mtpdevice_t *,uint32_t, uint32_t, char);
-uint32_t LIBMTP_Get_U32_From_Object(LIBMTP_mtpdevice_t *,uint32_t, uint32_t, uint32_t);
-uint16_t LIBMTP_Get_U16_From_Object(LIBMTP_mtpdevice_t *,uint32_t, uint32_t, uint16_t);
-int LIBMTP_Set_Object_String(LIBMTP_mtpdevice_t *,uint32_t, uint32_t, char *, int);
-int LIBMTP_Set_Object_U32(LIBMTP_mtpdevice_t *,uint32_t, uint32_t, uint32_t);
-int LIBMTP_Set_Object_U16(LIBMTP_mtpdevice_t *,uint32_t, uint32_t, uint16_t);
-int LIBMTP_Get_Object_References(LIBMTP_mtpdevice_t *, uint32_t, uint32_t **, uint32_t *);
-int LIBMTP_Set_Object_References(LIBMTP_mtpdevice_t *, uint32_t, uint32_t *, uint32_t);
+char *LIBMTP_Get_String_From_Object(LIBMTP_mtpdevice_t *,const uint32_t, const uint32_t, uint8_t);
+uint32_t LIBMTP_Get_U32_From_Object(LIBMTP_mtpdevice_t *,const uint32_t, const uint32_t, const uint32_t);
+uint16_t LIBMTP_Get_U16_From_Object(LIBMTP_mtpdevice_t *,const uint32_t, const uint32_t, const uint16_t);
+int LIBMTP_Set_Object_String(LIBMTP_mtpdevice_t *,const uint32_t,const uint32_t,
+ char const * const, const uint8_t);
+int LIBMTP_Set_Object_U32(LIBMTP_mtpdevice_t *,const uint32_t, const uint32_t, const uint32_t);
+int LIBMTP_Set_Object_U16(LIBMTP_mtpdevice_t *,const uint32_t, const uint32_t, const uint16_t);
+int LIBMTP_Get_Object_References(LIBMTP_mtpdevice_t *, const uint32_t, uint32_t **, uint32_t *);
+int LIBMTP_Set_Object_References(LIBMTP_mtpdevice_t *, const uint32_t, uint32_t const * const, const uint32_t);
LIBMTP_object_t *LIBMTP_Make_List(LIBMTP_mtpdevice_t *, uint32_t *, uint32_t, uint32_t *, uint32_t);
-LIBMTP_object_t *LIBMTP_Find_Object(LIBMTP_object_t *, uint32_t);
+LIBMTP_object_t *LIBMTP_Find_Object(LIBMTP_object_t *, const uint32_t);
void LIBMTP_Dump_List(LIBMTP_object_t *);
LIBMTP_object_t *LIBMTP_new_object_t(void);
void LIBMTP_destroy_object_t(LIBMTP_object_t *, uint32_t);
+int LIBMTP_Delete_Object(LIBMTP_mtpdevice_t *, uint32_t);
/** @} */
/**
@@ -295,11 +328,13 @@ void LIBMTP_destroy_object_t(LIBMTP_object_t *, uint32_t);
* @defgroup File mapping The file mapping API
* @{
*/
-int LIBMTP_Register_Filetype(char *, LIBMTP_filetype_t, uint16_t, void *, void *, void *);
-int LIBMTP_Set_Description(LIBMTP_filetype_t, char *);
-int LIBMTP_Set_Constructor(LIBMTP_filetype_t, void *);
-int LIBMTP_Set_Destructor(LIBMTP_filetype_t, void *);
-int LIBMTP_Set_Datafunc(LIBMTP_filetype_t, void *);
+int LIBMTP_Register_Filetype(char const * const, LIBMTP_filetype_t const,
+ uint16_t const, void const * const,
+ void const * const, void const * const);
+int LIBMTP_Set_Filetype_Description(LIBMTP_filetype_t, char const * const);
+int LIBMTP_Set_Constructor(LIBMTP_filetype_t, void const * const);
+int LIBMTP_Set_Destructor(LIBMTP_filetype_t, void const * const);
+int LIBMTP_Set_Datafunc(LIBMTP_filetype_t, void const * const);
/** @} */
diff --git a/src/unicode.c b/src/unicode.c
index be07e21..7084f2b 100644
--- a/src/unicode.c
+++ b/src/unicode.c
@@ -28,7 +28,7 @@
* want to know the length in bytes, multiply this by two and
* add two (for zero terminator).
*/
-int ucs2_strlen(const uint16_t *unicstr)
+int ucs2_strlen(uint16_t const * const unicstr)
{
int length;
@@ -45,7 +45,7 @@ int ucs2_strlen(const uint16_t *unicstr)
* @return the number of bytes this string would occupy
* in UTF-8
*/
-static int ucs2utf8len(const uint16_t *unicstr){
+static int ucs2utf8len(uint16_t const * const unicstr){
int length=0;
int i;
uint8_t *locstr = (uint8_t *) unicstr;
@@ -67,7 +67,7 @@ static int ucs2utf8len(const uint16_t *unicstr){
* @param unicstr the UCS-2 string to copy
* @return a newly allocated copy of the string
*/
-static uint16_t *ucs2strdup(const uint16_t *unicstr) {
+static uint16_t *ucs2strdup(uint16_t const * const unicstr) {
int length = ucs2_strlen(unicstr);
uint8_t *data;
@@ -87,7 +87,7 @@ static uint16_t *ucs2strdup(const uint16_t *unicstr) {
* @param unicstr the UCS-2 unicode string to convert
* @return a UTF-8 string.
*/
-char *ucs2_to_utf8(const uint16_t *unicstr){
+char *ucs2_to_utf8(uint16_t const * const unicstr){
char *data = NULL;
int i = 0;
int l = 0;
@@ -126,7 +126,7 @@ char *ucs2_to_utf8(const uint16_t *unicstr){
* @param str the UTF-8 string to convert.
* @return a pointer to a newly allocated UCS-2 string.
*/
-uint16_t *utf8_to_ucs2(const unsigned char *str) {
+uint16_t *utf8_to_ucs2(unsigned char const * const str) {
uint16_t *retval;
int i;
unsigned char buffer[STRING_BUFFER_LENGTH*2];
diff --git a/src/unicode.h b/src/unicode.h
index 50b9c0b..1c07c48 100644
--- a/src/unicode.h
+++ b/src/unicode.h
@@ -1,8 +1,8 @@
#ifndef __MTP__UNICODE__H
#define __MTP__UNICODE__H
-int ucs2_strlen(const uint16_t*);
+int ucs2_strlen(uint16_t const * const);
char *ucs2_to_utf8(const uint16_t*);
-uint16_t *utf8_to_ucs2(const unsigned char *);
+uint16_t *utf8_to_ucs2(unsigned char const * const);
#endif /* __MTP__UNICODE__H */