13aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
23aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * \file libmtp.c
33aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
43aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Copyright (C) 2005-2009 Linus Walleij <triad@df.lth.se>
53aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Copyright (C) 2005-2008 Richard A. Low <richard@wentnet.com>
63aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Copyright (C) 2007 Ted Bullock <tbullock@canada.com>
73aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Copyright (C) 2007 Tero Saarni <tero.saarni@gmail.com>
83aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Copyright (C) 2008 Florent Mertens <flomertens@gmail.com>
93aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This library is free software; you can redistribute it and/or
113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * modify it under the terms of the GNU Lesser General Public
123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * License as published by the Free Software Foundation; either
133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * version 2 of the License, or (at your option) any later version.
143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This library is distributed in the hope that it will be useful,
163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * but WITHOUT ANY WARRANTY; without even the implied warranty of
173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Lesser General Public License for more details.
193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * You should have received a copy of the GNU Lesser General Public
213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * License along with this library; if not, write to the
223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Boston, MA 02111-1307, USA.
243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This file provides an interface "glue" to the underlying
263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * PTP implementation from libgphoto2. It uses some local
273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * code to convert from/to UTF-8 (stored in unicode.c/.h)
283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * and some small utility functions, mainly for debugging
293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * (stored in util.c/.h).
303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * The three PTP files (ptp.c, ptp.h and ptp-pack.c) are
323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * plain copied from the libhphoto2 codebase.
333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * The files libusb-glue.c/.h are just what they say: an
353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * interface to libusb for the actual, physical USB traffic.
363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include "config.h"
383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include "libmtp.h"
393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include "unicode.h"
403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include "ptp.h"
413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include "libusb-glue.h"
423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include "device-flags.h"
433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include "playlist-spl.h"
443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include <stdlib.h>
463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include <unistd.h>
473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include <string.h>
483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include <sys/types.h>
493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include <sys/stat.h>
503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include <fcntl.h>
513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include <time.h>
523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include <errno.h>
533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef _MSC_VER // For MSVC++
543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#define USE_WINDOWS_IO_H
553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include <io.h>
563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/* To enable PTP level debug prints (all ptp_debug(...)), switch on this */
593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev//#define ENABLE_PTP_DEBUG
603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/*
623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This is a mapping between libmtp internal MTP filetypes and
633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * the libgphoto2/PTP equivalent defines. We need this because
643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * otherwise the libmtp.h device has to be dependent on ptp.h
653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * to be installed too, and we don't want that.
663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev//typedef struct filemap_struct filemap_t;
683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevtypedef struct filemap_struct {
693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  char *description; /**< Text description for the file type */
703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_filetype_t id; /**< LIBMTP internal type for the file type */
713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ptp_id; /**< PTP ID for the filetype */
723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  struct filemap_struct *next;
733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev} filemap_t;
743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/*
763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This is a mapping between libmtp internal MTP properties and
773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * the libgphoto2/PTP equivalent defines. We need this because
783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * otherwise the libmtp.h device has to be dependent on ptp.h
793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * to be installed too, and we don't want that.
803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevtypedef struct propertymap_struct {
823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  char *description; /**< Text description for the property */
833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_property_t id; /**< LIBMTP internal type for the property */
843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ptp_id; /**< PTP ID for the property */
853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  struct propertymap_struct *next;
863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev} propertymap_t;
873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev// Global variables
893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev// This holds the global filetype mapping table
903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic filemap_t *filemap = NULL;
913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev// This holds the global property mapping table
923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic propertymap_t *propertymap = NULL;
933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int load_cache_on_demand = 0;
953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/*
963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Forward declarations of local (static) functions.
973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int register_filetype(char const * const description, LIBMTP_filetype_t const id,
993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			     uint16_t const ptp_id);
1003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void init_filemap();
1013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int register_property(char const * const description, LIBMTP_property_t const id,
1023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			     uint16_t const ptp_id);
1033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void init_propertymap();
1043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void add_error_to_errorstack(LIBMTP_mtpdevice_t *device,
1053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    LIBMTP_error_number_t errornumber,
1063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    char const * const error_text);
1073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void add_ptp_error_to_errorstack(LIBMTP_mtpdevice_t *device,
1083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					uint16_t ptp_error,
1093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					char const * const error_text);
1103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void flush_handles(LIBMTP_mtpdevice_t *device);
1113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void get_handles_recursively(LIBMTP_mtpdevice_t *device,
1123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    PTPParams *params,
1133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint32_t storageid,
1143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint32_t parent);
1153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void free_storage_list(LIBMTP_mtpdevice_t *device);
1163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int sort_storage_by(LIBMTP_mtpdevice_t *device, int const sortby);
1173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint32_t get_writeable_storageid(LIBMTP_mtpdevice_t *device, uint64_t fitsize);
1183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int get_storage_freespace(LIBMTP_mtpdevice_t *device,
1193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				 LIBMTP_devicestorage_t *storage,
1203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				 uint64_t *freespace);
1213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int check_if_file_fits(LIBMTP_mtpdevice_t *device,
1223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      LIBMTP_devicestorage_t *storage,
1233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      uint64_t const filesize);
1243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint16_t map_libmtp_type_to_ptp_type(LIBMTP_filetype_t intype);
1253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic LIBMTP_filetype_t map_ptp_type_to_libmtp_type(uint16_t intype);
1263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint16_t map_libmtp_property_to_ptp_property(LIBMTP_property_t inproperty);
1273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic LIBMTP_property_t map_ptp_property_to_libmtp_property(uint16_t intype);
1283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int get_device_unicode_property(LIBMTP_mtpdevice_t *device,
1293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				       char **unicstring, uint16_t property);
1303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint16_t adjust_u16(uint16_t val, PTPObjectPropDesc *opd);
1313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint32_t adjust_u32(uint32_t val, PTPObjectPropDesc *opd);
1323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic char *get_iso8601_stamp(void);
1333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic char *get_string_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint16_t const attribute_id);
1353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint64_t get_u64_from_object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
1363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                    uint16_t const attribute_id, uint64_t const value_default);
1373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint32_t get_u32_from_object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
1383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint16_t const attribute_id, uint32_t const value_default);
1393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint16_t get_u16_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint16_t const attribute_id, uint16_t const value_default);
1413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint8_t get_u8_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  uint16_t const attribute_id, uint8_t const value_default);
1433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int set_object_string(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			     uint16_t const attribute_id, char const * const string);
1453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int set_object_u32(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			  uint16_t const attribute_id, uint32_t const value);
1473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int set_object_u16(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			  uint16_t const attribute_id, uint16_t const value);
1493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int set_object_u8(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 uint16_t const attribute_id, uint8_t const value);
1513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void get_track_metadata(LIBMTP_mtpdevice_t *device, uint16_t objectformat,
1523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       LIBMTP_track_t *track);
1533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic LIBMTP_folder_t *get_subfolders_for_folder(LIBMTP_folder_t *list, uint32_t parent);
1543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int create_new_abstract_list(LIBMTP_mtpdevice_t *device,
1553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    char const * const name,
1563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    char const * const artist,
1573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    char const * const composer,
1583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    char const * const genre,
1593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint32_t const parenthandle,
1603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint32_t const storageid,
1613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint16_t const objectformat,
1623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    char const * const suffix,
1633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint32_t * const newid,
1643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint32_t const * const tracks,
1653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint32_t const no_tracks);
1663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int update_abstract_list(LIBMTP_mtpdevice_t *device,
1673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				char const * const name,
1683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				char const * const artist,
1693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				char const * const composer,
1703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				char const * const genre,
1713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				uint32_t const objecthandle,
1723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				uint16_t const objectformat,
1733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				uint32_t const * const tracks,
1743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				uint32_t const no_tracks);
1753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int send_file_object_info(LIBMTP_mtpdevice_t *device, LIBMTP_file_t *filedata);
1763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void add_object_to_cache(LIBMTP_mtpdevice_t *device, uint32_t object_id);
1773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void update_metadata_cache(LIBMTP_mtpdevice_t *device, uint32_t object_id);
1783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int set_object_filename(LIBMTP_mtpdevice_t *device,
1793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		uint32_t object_id,
1803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		uint16_t ptp_type,
1813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                const char **newname);
1823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
1843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * These are to wrap the get/put handlers to convert from the MTP types to PTP types
1853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * in a reliable way
1863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
1873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevtypedef struct _MTPDataHandler {
1883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	MTPDataGetFunc		getfunc;
1893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	MTPDataPutFunc		putfunc;
1903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	void			*priv;
1913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev} MTPDataHandler;
1923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint16_t get_func_wrapper(PTPParams* params, void* priv, unsigned long wantlen, unsigned char *data, unsigned long *gotlen);
1943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint16_t put_func_wrapper(PTPParams* params, void* priv, unsigned long sendlen, unsigned char *data, unsigned long *putlen);
1953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
1963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
1973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Checks if a filename ends with ".ogg". Used in various
1983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * situations when the device has no idea that it support
1993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * OGG but still does.
2003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
2013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param name string to be checked.
2023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if this does not end with ogg, any other
2033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *           value means it does.
2043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
2053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int has_ogg_extension(char *name) {
2063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  char *ptype;
2073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (name == NULL)
2093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 0;
2103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptype = strrchr(name,'.');
2113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ptype == NULL)
2123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 0;
2133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!strcasecmp (ptype, ".ogg"))
2143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 1;
2153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
2163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
2173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
2193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Checks if a filename ends with ".flac". Used in various
2203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * situations when the device has no idea that it support
2213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * FLAC but still does.
2223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
2233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param name string to be checked.
2243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if this does not end with flac, any other
2253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *           value means it does.
2263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
2273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int has_flac_extension(char *name) {
2283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  char *ptype;
2293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (name == NULL)
2313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 0;
2323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptype = strrchr(name,'.');
2333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ptype == NULL)
2343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 0;
2353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!strcasecmp (ptype, ".flac"))
2363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 1;
2373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
2383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
2393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
2433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Create a new file mapping entry
2443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a newly allocated filemapping entry.
2453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
2463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic filemap_t *new_filemap_entry()
2473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
2483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filemap_t *filemap;
2493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filemap = (filemap_t *)malloc(sizeof(filemap_t));
2513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if( filemap != NULL ) {
2533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    filemap->description = NULL;
2543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    filemap->id = LIBMTP_FILETYPE_UNKNOWN;
2553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    filemap->ptp_id = PTP_OFC_Undefined;
2563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    filemap->next = NULL;
2573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
2583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return filemap;
2603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
2613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
2633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Register an MTP or PTP filetype for data retrieval
2643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
2653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param description Text description of filetype
2663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param id libmtp internal filetype id
2673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param ptp_id PTP filetype id
2683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 for success any other value means error.
2693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev*/
2703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int register_filetype(char const * const description, LIBMTP_filetype_t const id,
2713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			     uint16_t const ptp_id)
2723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
2733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filemap_t *new = NULL, *current;
2743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Has this LIBMTP filetype been registered before ?
2763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current = filemap;
2773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  while (current != NULL) {
2783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(current->id == id) {
2793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
2803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
2813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    current = current->next;
2823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
2833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Create the entry
2853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(current == NULL) {
2863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new = new_filemap_entry();
2873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(new == NULL) {
2883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return 1;
2893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
2903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new->id = id;
2923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(description != NULL) {
2933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      new->description = strdup(description);
2943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
2953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new->ptp_id = ptp_id;
2963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
2973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Add the entry to the list
2983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(filemap == NULL) {
2993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      filemap = new;
3003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
3013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      current = filemap;
3023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      while (current->next != NULL ) current=current->next;
3033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      current->next = new;
3043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
3053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Update the existing entry
3063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
3073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (current->description != NULL) {
3083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      free(current->description);
3093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
3103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    current->description = NULL;
3113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(description != NULL) {
3123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      current->description = strdup(description);
3133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
3143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    current->ptp_id = ptp_id;
3153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
3163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
3183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
3193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void init_filemap()
3213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
3223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Folder", LIBMTP_FILETYPE_FOLDER, PTP_OFC_Association);
3233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("MediaCard", LIBMTP_FILETYPE_MEDIACARD, PTP_OFC_MTP_MediaCard);
3243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("RIFF WAVE file", LIBMTP_FILETYPE_WAV, PTP_OFC_WAV);
3253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("ISO MPEG-1 Audio Layer 3", LIBMTP_FILETYPE_MP3, PTP_OFC_MP3);
3263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("ISO MPEG-1 Audio Layer 2", LIBMTP_FILETYPE_MP2, PTP_OFC_MTP_MP2);
3273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Microsoft Windows Media Audio", LIBMTP_FILETYPE_WMA, PTP_OFC_MTP_WMA);
3283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Ogg container format", LIBMTP_FILETYPE_OGG, PTP_OFC_MTP_OGG);
3293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Free Lossless Audio Codec (FLAC)", LIBMTP_FILETYPE_FLAC, PTP_OFC_MTP_FLAC);
3303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Advanced Audio Coding (AAC)/MPEG-2 Part 7/MPEG-4 Part 3", LIBMTP_FILETYPE_AAC, PTP_OFC_MTP_AAC);
3313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("MPEG-4 Part 14 Container Format (Audio Emphasis)", LIBMTP_FILETYPE_M4A, PTP_OFC_MTP_M4A);
3323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("MPEG-4 Part 14 Container Format (Audio+Video Emphasis)", LIBMTP_FILETYPE_MP4, PTP_OFC_MTP_MP4);
3333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Audible.com Audio Codec", LIBMTP_FILETYPE_AUDIBLE, PTP_OFC_MTP_AudibleCodec);
3343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Undefined audio file", LIBMTP_FILETYPE_UNDEF_AUDIO, PTP_OFC_MTP_UndefinedAudio);
3353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Microsoft Windows Media Video", LIBMTP_FILETYPE_WMV, PTP_OFC_MTP_WMV);
3363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Audio Video Interleave", LIBMTP_FILETYPE_AVI, PTP_OFC_AVI);
3373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("MPEG video stream", LIBMTP_FILETYPE_MPEG, PTP_OFC_MPEG);
3383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Microsoft Advanced Systems Format", LIBMTP_FILETYPE_ASF, PTP_OFC_ASF);
3393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Apple Quicktime container format", LIBMTP_FILETYPE_QT, PTP_OFC_QT);
3403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Undefined video file", LIBMTP_FILETYPE_UNDEF_VIDEO, PTP_OFC_MTP_UndefinedVideo);
3413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("JPEG file", LIBMTP_FILETYPE_JPEG, PTP_OFC_EXIF_JPEG);
3423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("JP2 file", LIBMTP_FILETYPE_JP2, PTP_OFC_JP2);
3433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("JPX file", LIBMTP_FILETYPE_JPX, PTP_OFC_JPX);
3443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("JFIF file", LIBMTP_FILETYPE_JFIF, PTP_OFC_JFIF);
3453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("TIFF bitmap file", LIBMTP_FILETYPE_TIFF, PTP_OFC_TIFF);
3463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("BMP bitmap file", LIBMTP_FILETYPE_BMP, PTP_OFC_BMP);
3473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("GIF bitmap file", LIBMTP_FILETYPE_GIF, PTP_OFC_GIF);
3483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("PICT bitmap file", LIBMTP_FILETYPE_PICT, PTP_OFC_PICT);
3493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Portable Network Graphics", LIBMTP_FILETYPE_PNG, PTP_OFC_PNG);
3503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Microsoft Windows Image Format", LIBMTP_FILETYPE_WINDOWSIMAGEFORMAT, PTP_OFC_MTP_WindowsImageFormat);
3513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("VCalendar version 1", LIBMTP_FILETYPE_VCALENDAR1, PTP_OFC_MTP_vCalendar1);
3523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("VCalendar version 2", LIBMTP_FILETYPE_VCALENDAR2, PTP_OFC_MTP_vCalendar2);
3533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("VCard version 2", LIBMTP_FILETYPE_VCARD2, PTP_OFC_MTP_vCard2);
3543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("VCard version 3", LIBMTP_FILETYPE_VCARD3, PTP_OFC_MTP_vCard3);
3553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Undefined Windows executable file", LIBMTP_FILETYPE_WINEXEC, PTP_OFC_MTP_UndefinedWindowsExecutable);
3563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Text file", LIBMTP_FILETYPE_TEXT, PTP_OFC_Text);
3573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("HTML file", LIBMTP_FILETYPE_HTML, PTP_OFC_HTML);
3583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("XML file", LIBMTP_FILETYPE_XML, PTP_OFC_MTP_XMLDocument);
3593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("DOC file", LIBMTP_FILETYPE_DOC, PTP_OFC_MTP_MSWordDocument);
3603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("XLS file", LIBMTP_FILETYPE_XLS, PTP_OFC_MTP_MSExcelSpreadsheetXLS);
3613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("PPT file", LIBMTP_FILETYPE_PPT, PTP_OFC_MTP_MSPowerpointPresentationPPT);
3623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("MHT file", LIBMTP_FILETYPE_MHT, PTP_OFC_MTP_MHTCompiledHTMLDocument);
3633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Firmware file", LIBMTP_FILETYPE_FIRMWARE, PTP_OFC_MTP_Firmware);
3643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Abstract Album file", LIBMTP_FILETYPE_ALBUM, PTP_OFC_MTP_AbstractAudioAlbum);
3653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Abstract Playlist file", LIBMTP_FILETYPE_PLAYLIST, PTP_OFC_MTP_AbstractAudioVideoPlaylist);
3663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_filetype("Undefined filetype", LIBMTP_FILETYPE_UNKNOWN, PTP_OFC_Undefined);
3673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
3683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
3703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Returns the PTP filetype that maps to a certain libmtp internal file type.
3713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param intype the MTP library interface type
3723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return the PTP (libgphoto2) interface type
3733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
3743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint16_t map_libmtp_type_to_ptp_type(LIBMTP_filetype_t intype)
3753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
3763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filemap_t *current;
3773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current = filemap;
3793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  while (current != NULL) {
3813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(current->id == intype) {
3823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return current->ptp_id;
3833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
3843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    current = current->next;
3853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
3863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // printf("map_libmtp_type_to_ptp_type: unknown filetype.\n");
3873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return PTP_OFC_Undefined;
3883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
3893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
3913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
3923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Returns the MTP internal interface type that maps to a certain ptp
3933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * interface type.
3943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param intype the PTP (libgphoto2) interface type
3953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return the MTP library interface type
3963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
3973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic LIBMTP_filetype_t map_ptp_type_to_libmtp_type(uint16_t intype)
3983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
3993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filemap_t *current;
4003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current = filemap;
4023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  while (current != NULL) {
4043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(current->ptp_id == intype) {
4053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return current->id;
4063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
4073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    current = current->next;
4083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
4093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // printf("map_ptp_type_to_libmtp_type: unknown filetype.\n");
4103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return LIBMTP_FILETYPE_UNKNOWN;
4113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
4123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
4143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Create a new property mapping entry
4153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a newly allocated propertymapping entry.
4163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
4173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic propertymap_t *new_propertymap_entry()
4183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
4193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  propertymap_t *propertymap;
4203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  propertymap = (propertymap_t *)malloc(sizeof(propertymap_t));
4223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if( propertymap != NULL ) {
4243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    propertymap->description = NULL;
4253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    propertymap->id = LIBMTP_PROPERTY_UNKNOWN;
4263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    propertymap->ptp_id = 0;
4273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    propertymap->next = NULL;
4283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
4293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return propertymap;
4313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
4323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
4343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Register an MTP or PTP property for data retrieval
4353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
4363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param description Text description of property
4373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param id libmtp internal property id
4383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param ptp_id PTP property id
4393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 for success any other value means error.
4403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev*/
4413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int register_property(char const * const description, LIBMTP_property_t const id,
4423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			     uint16_t const ptp_id)
4433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
4443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  propertymap_t *new = NULL, *current;
4453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Has this LIBMTP propety been registered before ?
4473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current = propertymap;
4483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  while (current != NULL) {
4493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(current->id == id) {
4503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
4513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
4523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    current = current->next;
4533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
4543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Create the entry
4563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(current == NULL) {
4573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new = new_propertymap_entry();
4583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(new == NULL) {
4593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return 1;
4603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
4613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new->id = id;
4633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(description != NULL) {
4643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      new->description = strdup(description);
4653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
4663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new->ptp_id = ptp_id;
4673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Add the entry to the list
4693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(propertymap == NULL) {
4703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      propertymap = new;
4713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
4723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      current = propertymap;
4733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      while (current->next != NULL ) current=current->next;
4743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      current->next = new;
4753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
4763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Update the existing entry
4773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
4783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (current->description != NULL) {
4793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      free(current->description);
4803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
4813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    current->description = NULL;
4823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(description != NULL) {
4833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      current->description = strdup(description);
4843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
4853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    current->ptp_id = ptp_id;
4863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
4873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
4893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
4903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void init_propertymap()
4923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
4933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Storage ID", LIBMTP_PROPERTY_StorageID, PTP_OPC_StorageID);
4943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Object Format", LIBMTP_PROPERTY_ObjectFormat, PTP_OPC_ObjectFormat);
4953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Protection Status", LIBMTP_PROPERTY_ProtectionStatus, PTP_OPC_ProtectionStatus);
4963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Object Size", LIBMTP_PROPERTY_ObjectSize, PTP_OPC_ObjectSize);
4973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Association Type", LIBMTP_PROPERTY_AssociationType, PTP_OPC_AssociationType);
4983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Association Desc", LIBMTP_PROPERTY_AssociationDesc, PTP_OPC_AssociationDesc);
4993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Object File Name", LIBMTP_PROPERTY_ObjectFileName, PTP_OPC_ObjectFileName);
5003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Date Created", LIBMTP_PROPERTY_DateCreated, PTP_OPC_DateCreated);
5013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Date Modified", LIBMTP_PROPERTY_DateModified, PTP_OPC_DateModified);
5023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Keywords", LIBMTP_PROPERTY_Keywords, PTP_OPC_Keywords);
5033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Parent Object", LIBMTP_PROPERTY_ParentObject, PTP_OPC_ParentObject);
5043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Allowed Folder Contents", LIBMTP_PROPERTY_AllowedFolderContents, PTP_OPC_AllowedFolderContents);
5053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Hidden", LIBMTP_PROPERTY_Hidden, PTP_OPC_Hidden);
5063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("System Object", LIBMTP_PROPERTY_SystemObject, PTP_OPC_SystemObject);
5073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Persistant Unique Object Identifier", LIBMTP_PROPERTY_PersistantUniqueObjectIdentifier, PTP_OPC_PersistantUniqueObjectIdentifier);
5083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Sync ID", LIBMTP_PROPERTY_SyncID, PTP_OPC_SyncID);
5093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Property Bag", LIBMTP_PROPERTY_PropertyBag, PTP_OPC_PropertyBag);
5103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Name", LIBMTP_PROPERTY_Name, PTP_OPC_Name);
5113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Created By", LIBMTP_PROPERTY_CreatedBy, PTP_OPC_CreatedBy);
5123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Artist", LIBMTP_PROPERTY_Artist, PTP_OPC_Artist);
5133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Date Authored", LIBMTP_PROPERTY_DateAuthored, PTP_OPC_DateAuthored);
5143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Description", LIBMTP_PROPERTY_Description, PTP_OPC_Description);
5153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("URL Reference", LIBMTP_PROPERTY_URLReference, PTP_OPC_URLReference);
5163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Language Locale", LIBMTP_PROPERTY_LanguageLocale, PTP_OPC_LanguageLocale);
5173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Copyright Information", LIBMTP_PROPERTY_CopyrightInformation, PTP_OPC_CopyrightInformation);
5183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Source", LIBMTP_PROPERTY_Source, PTP_OPC_Source);
5193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Origin Location", LIBMTP_PROPERTY_OriginLocation, PTP_OPC_OriginLocation);
5203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Date Added", LIBMTP_PROPERTY_DateAdded, PTP_OPC_DateAdded);
5213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Non Consumable", LIBMTP_PROPERTY_NonConsumable, PTP_OPC_NonConsumable);
5223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Corrupt Or Unplayable", LIBMTP_PROPERTY_CorruptOrUnplayable, PTP_OPC_CorruptOrUnplayable);
5233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Producer Serial Number", LIBMTP_PROPERTY_ProducerSerialNumber, PTP_OPC_ProducerSerialNumber);
5243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Representative Sample Format", LIBMTP_PROPERTY_RepresentativeSampleFormat, PTP_OPC_RepresentativeSampleFormat);
5253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Representative Sample Sise", LIBMTP_PROPERTY_RepresentativeSampleSize, PTP_OPC_RepresentativeSampleSize);
5263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Representative Sample Height", LIBMTP_PROPERTY_RepresentativeSampleHeight, PTP_OPC_RepresentativeSampleHeight);
5273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Representative Sample Width", LIBMTP_PROPERTY_RepresentativeSampleWidth, PTP_OPC_RepresentativeSampleWidth);
5283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Representative Sample Duration", LIBMTP_PROPERTY_RepresentativeSampleDuration, PTP_OPC_RepresentativeSampleDuration);
5293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Representative Sample Data", LIBMTP_PROPERTY_RepresentativeSampleData, PTP_OPC_RepresentativeSampleData);
5303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Width", LIBMTP_PROPERTY_Width, PTP_OPC_Width);
5313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Height", LIBMTP_PROPERTY_Height, PTP_OPC_Height);
5323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Duration", LIBMTP_PROPERTY_Duration, PTP_OPC_Duration);
5333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Rating", LIBMTP_PROPERTY_Rating, PTP_OPC_Rating);
5343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Track", LIBMTP_PROPERTY_Track, PTP_OPC_Track);
5353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Genre", LIBMTP_PROPERTY_Genre, PTP_OPC_Genre);
5363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Credits", LIBMTP_PROPERTY_Credits, PTP_OPC_Credits);
5373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Lyrics", LIBMTP_PROPERTY_Lyrics, PTP_OPC_Lyrics);
5383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Subscription Content ID", LIBMTP_PROPERTY_SubscriptionContentID, PTP_OPC_SubscriptionContentID);
5393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Produced By", LIBMTP_PROPERTY_ProducedBy, PTP_OPC_ProducedBy);
5403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Use Count", LIBMTP_PROPERTY_UseCount, PTP_OPC_UseCount);
5413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Skip Count", LIBMTP_PROPERTY_SkipCount, PTP_OPC_SkipCount);
5423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Last Accessed", LIBMTP_PROPERTY_LastAccessed, PTP_OPC_LastAccessed);
5433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Parental Rating", LIBMTP_PROPERTY_ParentalRating, PTP_OPC_ParentalRating);
5443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Meta Genre", LIBMTP_PROPERTY_MetaGenre, PTP_OPC_MetaGenre);
5453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Composer", LIBMTP_PROPERTY_Composer, PTP_OPC_Composer);
5463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Effective Rating", LIBMTP_PROPERTY_EffectiveRating, PTP_OPC_EffectiveRating);
5473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Subtitle", LIBMTP_PROPERTY_Subtitle, PTP_OPC_Subtitle);
5483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Original Release Date", LIBMTP_PROPERTY_OriginalReleaseDate, PTP_OPC_OriginalReleaseDate);
5493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Album Name", LIBMTP_PROPERTY_AlbumName, PTP_OPC_AlbumName);
5503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Album Artist", LIBMTP_PROPERTY_AlbumArtist, PTP_OPC_AlbumArtist);
5513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Mood", LIBMTP_PROPERTY_Mood, PTP_OPC_Mood);
5523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("DRM Status", LIBMTP_PROPERTY_DRMStatus, PTP_OPC_DRMStatus);
5533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Sub Description", LIBMTP_PROPERTY_SubDescription, PTP_OPC_SubDescription);
5543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Is Cropped", LIBMTP_PROPERTY_IsCropped, PTP_OPC_IsCropped);
5553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Is Color Corrected", LIBMTP_PROPERTY_IsColorCorrected, PTP_OPC_IsColorCorrected);
5563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Image Bit Depth", LIBMTP_PROPERTY_ImageBitDepth, PTP_OPC_ImageBitDepth);
5573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("f Number", LIBMTP_PROPERTY_Fnumber, PTP_OPC_Fnumber);
5583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Exposure Time", LIBMTP_PROPERTY_ExposureTime, PTP_OPC_ExposureTime);
5593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Exposure Index", LIBMTP_PROPERTY_ExposureIndex, PTP_OPC_ExposureIndex);
5603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Display Name", LIBMTP_PROPERTY_DisplayName, PTP_OPC_DisplayName);
5613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Body Text", LIBMTP_PROPERTY_BodyText, PTP_OPC_BodyText);
5623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Subject", LIBMTP_PROPERTY_Subject, PTP_OPC_Subject);
5633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Priority", LIBMTP_PROPERTY_Priority, PTP_OPC_Priority);
5643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Given Name", LIBMTP_PROPERTY_GivenName, PTP_OPC_GivenName);
5653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Middle Names", LIBMTP_PROPERTY_MiddleNames, PTP_OPC_MiddleNames);
5663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Family Name", LIBMTP_PROPERTY_FamilyName, PTP_OPC_FamilyName);
5673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Prefix", LIBMTP_PROPERTY_Prefix, PTP_OPC_Prefix);
5683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Suffix", LIBMTP_PROPERTY_Suffix, PTP_OPC_Suffix);
5693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Phonetic Given Name", LIBMTP_PROPERTY_PhoneticGivenName, PTP_OPC_PhoneticGivenName);
5703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Phonetic Family Name", LIBMTP_PROPERTY_PhoneticFamilyName, PTP_OPC_PhoneticFamilyName);
5713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Email: Primary", LIBMTP_PROPERTY_EmailPrimary, PTP_OPC_EmailPrimary);
5723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Email: Personal 1", LIBMTP_PROPERTY_EmailPersonal1, PTP_OPC_EmailPersonal1);
5733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Email: Personal 2", LIBMTP_PROPERTY_EmailPersonal2, PTP_OPC_EmailPersonal2);
5743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Email: Business 1", LIBMTP_PROPERTY_EmailBusiness1, PTP_OPC_EmailBusiness1);
5753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Email: Business 2", LIBMTP_PROPERTY_EmailBusiness2, PTP_OPC_EmailBusiness2);
5763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Email: Others", LIBMTP_PROPERTY_EmailOthers, PTP_OPC_EmailOthers);
5773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Phone Number: Primary", LIBMTP_PROPERTY_PhoneNumberPrimary, PTP_OPC_PhoneNumberPrimary);
5783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Phone Number: Personal", LIBMTP_PROPERTY_PhoneNumberPersonal, PTP_OPC_PhoneNumberPersonal);
5793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Phone Number: Personal 2", LIBMTP_PROPERTY_PhoneNumberPersonal2, PTP_OPC_PhoneNumberPersonal2);
5803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Phone Number: Business", LIBMTP_PROPERTY_PhoneNumberBusiness, PTP_OPC_PhoneNumberBusiness);
5813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Phone Number: Business 2", LIBMTP_PROPERTY_PhoneNumberBusiness2, PTP_OPC_PhoneNumberBusiness2);
5823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Phone Number: Mobile", LIBMTP_PROPERTY_PhoneNumberMobile, PTP_OPC_PhoneNumberMobile);
5833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Phone Number: Mobile 2", LIBMTP_PROPERTY_PhoneNumberMobile2, PTP_OPC_PhoneNumberMobile2);
5843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Fax Number: Primary", LIBMTP_PROPERTY_FaxNumberPrimary, PTP_OPC_FaxNumberPrimary);
5853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Fax Number: Personal", LIBMTP_PROPERTY_FaxNumberPersonal, PTP_OPC_FaxNumberPersonal);
5863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Fax Number: Business", LIBMTP_PROPERTY_FaxNumberBusiness, PTP_OPC_FaxNumberBusiness);
5873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Pager Number", LIBMTP_PROPERTY_PagerNumber, PTP_OPC_PagerNumber);
5883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Phone Number: Others", LIBMTP_PROPERTY_PhoneNumberOthers, PTP_OPC_PhoneNumberOthers);
5893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Primary Web Address", LIBMTP_PROPERTY_PrimaryWebAddress, PTP_OPC_PrimaryWebAddress);
5903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Personal Web Address", LIBMTP_PROPERTY_PersonalWebAddress, PTP_OPC_PersonalWebAddress);
5913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Business Web Address", LIBMTP_PROPERTY_BusinessWebAddress, PTP_OPC_BusinessWebAddress);
5923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Instant Messenger Address 1", LIBMTP_PROPERTY_InstantMessengerAddress, PTP_OPC_InstantMessengerAddress);
5933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Instant Messenger Address 2", LIBMTP_PROPERTY_InstantMessengerAddress2, PTP_OPC_InstantMessengerAddress2);
5943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Instant Messenger Address 3", LIBMTP_PROPERTY_InstantMessengerAddress3, PTP_OPC_InstantMessengerAddress3);
5953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Personal: Full", LIBMTP_PROPERTY_PostalAddressPersonalFull, PTP_OPC_PostalAddressPersonalFull);
5963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Personal: Line 1", LIBMTP_PROPERTY_PostalAddressPersonalFullLine1, PTP_OPC_PostalAddressPersonalFullLine1);
5973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Personal: Line 2", LIBMTP_PROPERTY_PostalAddressPersonalFullLine2, PTP_OPC_PostalAddressPersonalFullLine2);
5983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Personal: City", LIBMTP_PROPERTY_PostalAddressPersonalFullCity, PTP_OPC_PostalAddressPersonalFullCity);
5993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Personal: Region", LIBMTP_PROPERTY_PostalAddressPersonalFullRegion, PTP_OPC_PostalAddressPersonalFullRegion);
6003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Personal: Postal Code", LIBMTP_PROPERTY_PostalAddressPersonalFullPostalCode, PTP_OPC_PostalAddressPersonalFullPostalCode);
6013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Personal: Country", LIBMTP_PROPERTY_PostalAddressPersonalFullCountry, PTP_OPC_PostalAddressPersonalFullCountry);
6023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Business: Full", LIBMTP_PROPERTY_PostalAddressBusinessFull, PTP_OPC_PostalAddressBusinessFull);
6033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Business: Line 1", LIBMTP_PROPERTY_PostalAddressBusinessLine1, PTP_OPC_PostalAddressBusinessLine1);
6043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Business: Line 2", LIBMTP_PROPERTY_PostalAddressBusinessLine2, PTP_OPC_PostalAddressBusinessLine2);
6053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Business: City", LIBMTP_PROPERTY_PostalAddressBusinessCity, PTP_OPC_PostalAddressBusinessCity);
6063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Business: Region", LIBMTP_PROPERTY_PostalAddressBusinessRegion, PTP_OPC_PostalAddressBusinessRegion);
6073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Business: Postal Code", LIBMTP_PROPERTY_PostalAddressBusinessPostalCode, PTP_OPC_PostalAddressBusinessPostalCode);
6083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Business: Country", LIBMTP_PROPERTY_PostalAddressBusinessCountry, PTP_OPC_PostalAddressBusinessCountry);
6093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Other: Full", LIBMTP_PROPERTY_PostalAddressOtherFull, PTP_OPC_PostalAddressOtherFull);
6103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Other: Line 1", LIBMTP_PROPERTY_PostalAddressOtherLine1, PTP_OPC_PostalAddressOtherLine1);
6113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Other: Line 2", LIBMTP_PROPERTY_PostalAddressOtherLine2, PTP_OPC_PostalAddressOtherLine2);
6123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Other: City", LIBMTP_PROPERTY_PostalAddressOtherCity, PTP_OPC_PostalAddressOtherCity);
6133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Other: Region", LIBMTP_PROPERTY_PostalAddressOtherRegion, PTP_OPC_PostalAddressOtherRegion);
6143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Other: Postal Code", LIBMTP_PROPERTY_PostalAddressOtherPostalCode, PTP_OPC_PostalAddressOtherPostalCode);
6153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Postal Address: Other: Counrtry", LIBMTP_PROPERTY_PostalAddressOtherCountry, PTP_OPC_PostalAddressOtherCountry);
6163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Organization Name", LIBMTP_PROPERTY_OrganizationName, PTP_OPC_OrganizationName);
6173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Phonetic Organization Name", LIBMTP_PROPERTY_PhoneticOrganizationName, PTP_OPC_PhoneticOrganizationName);
6183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Role", LIBMTP_PROPERTY_Role, PTP_OPC_Role);
6193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Birthdate", LIBMTP_PROPERTY_Birthdate, PTP_OPC_Birthdate);
6203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Message To", LIBMTP_PROPERTY_MessageTo, PTP_OPC_MessageTo);
6213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Message CC", LIBMTP_PROPERTY_MessageCC, PTP_OPC_MessageCC);
6223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Message BCC", LIBMTP_PROPERTY_MessageBCC, PTP_OPC_MessageBCC);
6233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Message Read", LIBMTP_PROPERTY_MessageRead, PTP_OPC_MessageRead);
6243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Message Received Time", LIBMTP_PROPERTY_MessageReceivedTime, PTP_OPC_MessageReceivedTime);
6253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Message Sender", LIBMTP_PROPERTY_MessageSender, PTP_OPC_MessageSender);
6263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Activity Begin Time", LIBMTP_PROPERTY_ActivityBeginTime, PTP_OPC_ActivityBeginTime);
6273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Activity End Time", LIBMTP_PROPERTY_ActivityEndTime, PTP_OPC_ActivityEndTime);
6283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Activity Location", LIBMTP_PROPERTY_ActivityLocation, PTP_OPC_ActivityLocation);
6293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Activity Required Attendees", LIBMTP_PROPERTY_ActivityRequiredAttendees, PTP_OPC_ActivityRequiredAttendees);
6303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Optional Attendees", LIBMTP_PROPERTY_ActivityOptionalAttendees, PTP_OPC_ActivityOptionalAttendees);
6313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Activity Resources", LIBMTP_PROPERTY_ActivityResources, PTP_OPC_ActivityResources);
6323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Activity Accepted", LIBMTP_PROPERTY_ActivityAccepted, PTP_OPC_ActivityAccepted);
6333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Owner", LIBMTP_PROPERTY_Owner, PTP_OPC_Owner);
6343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Editor", LIBMTP_PROPERTY_Editor, PTP_OPC_Editor);
6353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Webmaster", LIBMTP_PROPERTY_Webmaster, PTP_OPC_Webmaster);
6363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("URL Source", LIBMTP_PROPERTY_URLSource, PTP_OPC_URLSource);
6373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("URL Destination", LIBMTP_PROPERTY_URLDestination, PTP_OPC_URLDestination);
6383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Time Bookmark", LIBMTP_PROPERTY_TimeBookmark, PTP_OPC_TimeBookmark);
6393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Object Bookmark", LIBMTP_PROPERTY_ObjectBookmark, PTP_OPC_ObjectBookmark);
6403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Byte Bookmark", LIBMTP_PROPERTY_ByteBookmark, PTP_OPC_ByteBookmark);
6413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Last Build Date", LIBMTP_PROPERTY_LastBuildDate, PTP_OPC_LastBuildDate);
6423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Time To Live", LIBMTP_PROPERTY_TimetoLive, PTP_OPC_TimetoLive);
6433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Media GUID", LIBMTP_PROPERTY_MediaGUID, PTP_OPC_MediaGUID);
6443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Total Bit Rate", LIBMTP_PROPERTY_TotalBitRate, PTP_OPC_TotalBitRate);
6453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Bit Rate Type", LIBMTP_PROPERTY_BitRateType, PTP_OPC_BitRateType);
6463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Sample Rate", LIBMTP_PROPERTY_SampleRate, PTP_OPC_SampleRate);
6473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Number Of Channels", LIBMTP_PROPERTY_NumberOfChannels, PTP_OPC_NumberOfChannels);
6483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Audio Bit Depth", LIBMTP_PROPERTY_AudioBitDepth, PTP_OPC_AudioBitDepth);
6493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Scan Depth", LIBMTP_PROPERTY_ScanDepth, PTP_OPC_ScanDepth);
6503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Audio WAVE Codec", LIBMTP_PROPERTY_AudioWAVECodec, PTP_OPC_AudioWAVECodec);
6513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Audio Bit Rate", LIBMTP_PROPERTY_AudioBitRate, PTP_OPC_AudioBitRate);
6523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Video Four CC Codec", LIBMTP_PROPERTY_VideoFourCCCodec, PTP_OPC_VideoFourCCCodec);
6533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Video Bit Rate", LIBMTP_PROPERTY_VideoBitRate, PTP_OPC_VideoBitRate);
6543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Frames Per Thousand Seconds", LIBMTP_PROPERTY_FramesPerThousandSeconds, PTP_OPC_FramesPerThousandSeconds);
6553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Key Frame Distance", LIBMTP_PROPERTY_KeyFrameDistance, PTP_OPC_KeyFrameDistance);
6563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Buffer Size", LIBMTP_PROPERTY_BufferSize, PTP_OPC_BufferSize);
6573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Encoding Quality", LIBMTP_PROPERTY_EncodingQuality, PTP_OPC_EncodingQuality);
6583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Encoding Profile", LIBMTP_PROPERTY_EncodingProfile, PTP_OPC_EncodingProfile);
6593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Buy flag", LIBMTP_PROPERTY_BuyFlag, PTP_OPC_BuyFlag);
6603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  register_property("Unknown property", LIBMTP_PROPERTY_UNKNOWN, 0);
6613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
6623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
6633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
6643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Returns the PTP property that maps to a certain libmtp internal property type.
6653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param inproperty the MTP library interface property
6663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return the PTP (libgphoto2) property type
6673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
6683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint16_t map_libmtp_property_to_ptp_property(LIBMTP_property_t inproperty)
6693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
6703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  propertymap_t *current;
6713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
6723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current = propertymap;
6733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
6743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  while (current != NULL) {
6753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(current->id == inproperty) {
6763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return current->ptp_id;
6773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
6783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    current = current->next;
6793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
6803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
6813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
6823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
6833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
6843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
6853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Returns the MTP internal interface property that maps to a certain ptp
6863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * interface property.
6873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param inproperty the PTP (libgphoto2) interface property
6883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return the MTP library interface property
6893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
6903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic LIBMTP_property_t map_ptp_property_to_libmtp_property(uint16_t inproperty)
6913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
6923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  propertymap_t *current;
6933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
6943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current = propertymap;
6953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
6963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  while (current != NULL) {
6973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(current->ptp_id == inproperty) {
6983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return current->id;
6993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
7003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    current = current->next;
7013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
7023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // printf("map_ptp_type_to_libmtp_type: unknown filetype.\n");
7033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return LIBMTP_PROPERTY_UNKNOWN;
7043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
7053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
7083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Initialize the library. You are only supposed to call this
7093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * one, before using the library for the first time in a program.
7103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Never re-initialize libmtp!
7113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
7123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * The only thing this does at the moment is to initialise the
7133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * filetype mapping table.
7143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
7153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_Init(void)
7163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
7173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  init_filemap();
7183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  init_propertymap();
7193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return;
7203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
7213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
7243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This helper function returns a textual description for a libmtp
7253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * file type to be used in dialog boxes etc.
7263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param intype the libmtp internal filetype to get a description for.
7273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a string representing the filetype, this must <b>NOT</b>
7283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         be free():ed by the caller!
7293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
7303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevchar const * LIBMTP_Get_Filetype_Description(LIBMTP_filetype_t intype)
7313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
7323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filemap_t *current;
7333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current = filemap;
7353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  while (current != NULL) {
7373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(current->id == intype) {
7383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return current->description;
7393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
7403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    current = current->next;
7413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
7423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return "Unknown filetype";
7443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
7453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
7473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This helper function returns a textual description for a libmtp
7483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * property to be used in dialog boxes etc.
7493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param inproperty the libmtp internal property to get a description for.
7503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a string representing the filetype, this must <b>NOT</b>
7513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         be free():ed by the caller!
7523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
7533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevchar const * LIBMTP_Get_Property_Description(LIBMTP_property_t inproperty)
7543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
7553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  propertymap_t *current;
7563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current = propertymap;
7583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  while (current != NULL) {
7603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(current->id == inproperty) {
7613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return current->description;
7623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
7633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    current = current->next;
7643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
7653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return "Unknown property";
7673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
7683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
7703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function will do its best to fit a 16bit
7713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * value into a PTP object property if the property
7723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * is limited in range or step sizes.
7733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
7743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint16_t adjust_u16(uint16_t val, PTPObjectPropDesc *opd)
7753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
7763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  switch (opd->FormFlag) {
7773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_DPFF_Range:
7783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (val < opd->FORM.Range.MinimumValue.u16) {
7793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return opd->FORM.Range.MinimumValue.u16;
7803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
7813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (val > opd->FORM.Range.MaximumValue.u16) {
7823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return opd->FORM.Range.MaximumValue.u16;
7833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
7843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Round down to last step.
7853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (val % opd->FORM.Range.StepSize.u16 != 0) {
7863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return val - (val % opd->FORM.Range.StepSize.u16);
7873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
7883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return val;
7893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
7903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_DPFF_Enumeration:
7913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    {
7923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      int i;
7933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      uint16_t bestfit = opd->FORM.Enum.SupportedValue[0].u16;
7943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
7953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      for (i=0; i<opd->FORM.Enum.NumberOfValues; i++) {
7963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (val == opd->FORM.Enum.SupportedValue[i].u16) {
7973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  return val;
7983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
7993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// Rough guess of best fit
8003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (opd->FORM.Enum.SupportedValue[i].u16 < val) {
8013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  bestfit = opd->FORM.Enum.SupportedValue[i].u16;
8023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
8033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
8043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Just some default that'll work.
8053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return bestfit;
8063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
8073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  default:
8083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Will accept any value
8093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
8103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
8113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return val;
8123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
8133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
8153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function will do its best to fit a 32bit
8163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * value into a PTP object property if the property
8173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * is limited in range or step sizes.
8183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
8193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint32_t adjust_u32(uint32_t val, PTPObjectPropDesc *opd)
8203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
8213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  switch (opd->FormFlag) {
8223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_DPFF_Range:
8233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (val < opd->FORM.Range.MinimumValue.u32) {
8243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return opd->FORM.Range.MinimumValue.u32;
8253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
8263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (val > opd->FORM.Range.MaximumValue.u32) {
8273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return opd->FORM.Range.MaximumValue.u32;
8283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
8293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Round down to last step.
8303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (val % opd->FORM.Range.StepSize.u32 != 0) {
8313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return val - (val % opd->FORM.Range.StepSize.u32);
8323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
8333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return val;
8343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
8353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_DPFF_Enumeration:
8363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    {
8373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      int i;
8383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      uint32_t bestfit = opd->FORM.Enum.SupportedValue[0].u32;
8393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      for (i=0; i<opd->FORM.Enum.NumberOfValues; i++) {
8413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (val == opd->FORM.Enum.SupportedValue[i].u32) {
8423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  return val;
8433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
8443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// Rough guess of best fit
8453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (opd->FORM.Enum.SupportedValue[i].u32 < val) {
8463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  bestfit = opd->FORM.Enum.SupportedValue[i].u32;
8473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
8483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
8493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Just some default that'll work.
8503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return bestfit;
8513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
8523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  default:
8533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Will accept any value
8543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
8553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
8563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return val;
8573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
8583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
8603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function returns a newly created ISO 8601 timestamp with the
8613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * current time in as high precision as possible. It even adds
8623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * the time zone if it can.
8633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
8643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic char *get_iso8601_stamp(void)
8653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
8663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  time_t curtime;
8673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  struct tm *loctime;
8683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  char tmp[64];
8693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  curtime = time(NULL);
8713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  loctime = localtime(&curtime);
8723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  strftime (tmp, sizeof(tmp), "%Y%m%dT%H%M%S.0%z", loctime);
8733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return strdup(tmp);
8743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
8753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
8773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Gets the allowed values (range or enum) for a property
8783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device
8793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param property the property to query
8803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param filetype the filetype of the object you want to set values for
8813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param allowed_vals pointer to a LIBMTP_allowed_values_t struct to
8823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        receive the allowed values.  Call LIBMTP_destroy_allowed_values_t
8833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        on this on successful completion.
8843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure
8853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
8863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Get_Allowed_Property_Values(LIBMTP_mtpdevice_t *device, LIBMTP_property_t const property,
8873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev            LIBMTP_filetype_t const filetype, LIBMTP_allowed_values_t *allowed_vals)
8883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
8893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObjectPropDesc opd;
8903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret = 0;
8913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectpropdesc(device->params, map_libmtp_property_to_ptp_property(property), map_libmtp_type_to_ptp_type(filetype), &opd);
8933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
8943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Allowed_Property_Values(): could not get property description.");
8953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
8963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
8973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
8983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (opd.FormFlag == PTP_OPFF_Enumeration) {
8993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    int i = 0;
9003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
9013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    allowed_vals->is_range = 0;
9023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    allowed_vals->num_entries = opd.FORM.Enum.NumberOfValues;
9033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
9043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    switch (opd.DataType)
9053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    {
9063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_INT8:
9073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i8vals = malloc(sizeof(int8_t) * opd.FORM.Enum.NumberOfValues);
9083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_INT8;
9093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
9103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_UINT8:
9113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u8vals = malloc(sizeof(uint8_t) * opd.FORM.Enum.NumberOfValues);
9123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_UINT8;
9133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
9143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_INT16:
9153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i16vals = malloc(sizeof(int16_t) * opd.FORM.Enum.NumberOfValues);
9163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_INT16;
9173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
9183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_UINT16:
9193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u16vals = malloc(sizeof(uint16_t) * opd.FORM.Enum.NumberOfValues);
9203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_UINT16;
9213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
9223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_INT32:
9233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i32vals = malloc(sizeof(int32_t) * opd.FORM.Enum.NumberOfValues);
9243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_INT32;
9253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
9263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_UINT32:
9273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u32vals = malloc(sizeof(uint32_t) * opd.FORM.Enum.NumberOfValues);
9283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_UINT32;
9293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
9303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_INT64:
9313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i64vals = malloc(sizeof(int64_t) * opd.FORM.Enum.NumberOfValues);
9323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_INT64;
9333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
9343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_UINT64:
9353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u64vals = malloc(sizeof(uint64_t) * opd.FORM.Enum.NumberOfValues);
9363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_UINT64;
9373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
9383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
9393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
9403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i = 0; i < opd.FORM.Enum.NumberOfValues; i++) {
9413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      switch (opd.DataType)
9423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      {
9433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        case PTP_DTC_INT8:
9443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          allowed_vals->i8vals[i] = opd.FORM.Enum.SupportedValue[i].i8;
9453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          break;
9463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        case PTP_DTC_UINT8:
9473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          allowed_vals->u8vals[i] = opd.FORM.Enum.SupportedValue[i].u8;
9483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          break;
9493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        case PTP_DTC_INT16:
9503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          allowed_vals->i16vals[i] = opd.FORM.Enum.SupportedValue[i].i16;
9513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          break;
9523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        case PTP_DTC_UINT16:
9533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          allowed_vals->u16vals[i] = opd.FORM.Enum.SupportedValue[i].u16;
9543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          break;
9553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        case PTP_DTC_INT32:
9563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          allowed_vals->i32vals[i] = opd.FORM.Enum.SupportedValue[i].i32;
9573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          break;
9583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        case PTP_DTC_UINT32:
9593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          allowed_vals->u32vals[i] = opd.FORM.Enum.SupportedValue[i].u32;
9603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          break;
9613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        case PTP_DTC_INT64:
9623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          allowed_vals->i64vals[i] = opd.FORM.Enum.SupportedValue[i].i64;
9633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          break;
9643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        case PTP_DTC_UINT64:
9653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          allowed_vals->u64vals[i] = opd.FORM.Enum.SupportedValue[i].u64;
9663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          break;
9673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
9683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
9693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_free_objectpropdesc(&opd);
9703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 0;
9713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else if (opd.FormFlag == PTP_OPFF_Range) {
9723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    allowed_vals->is_range = 1;
9733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
9743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    switch (opd.DataType)
9753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    {
9763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_INT8:
9773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i8min = opd.FORM.Range.MinimumValue.i8;
9783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i8max = opd.FORM.Range.MaximumValue.i8;
9793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i8step = opd.FORM.Range.StepSize.i8;
9803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_INT8;
9813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
9823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_UINT8:
9833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u8min = opd.FORM.Range.MinimumValue.u8;
9843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u8max = opd.FORM.Range.MaximumValue.u8;
9853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u8step = opd.FORM.Range.StepSize.u8;
9863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_UINT8;
9873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
9883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_INT16:
9893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i16min = opd.FORM.Range.MinimumValue.i16;
9903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i16max = opd.FORM.Range.MaximumValue.i16;
9913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i16step = opd.FORM.Range.StepSize.i16;
9923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_INT16;
9933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
9943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_UINT16:
9953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u16min = opd.FORM.Range.MinimumValue.u16;
9963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u16max = opd.FORM.Range.MaximumValue.u16;
9973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u16step = opd.FORM.Range.StepSize.u16;
9983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_UINT16;
9993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
10003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_INT32:
10013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i32min = opd.FORM.Range.MinimumValue.i32;
10023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i32max = opd.FORM.Range.MaximumValue.i32;
10033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i32step = opd.FORM.Range.StepSize.i32;
10043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_INT32;
10053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
10063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_UINT32:
10073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u32min = opd.FORM.Range.MinimumValue.u32;
10083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u32max = opd.FORM.Range.MaximumValue.u32;
10093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u32step = opd.FORM.Range.StepSize.u32;
10103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_UINT32;
10113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
10123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_INT64:
10133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i64min = opd.FORM.Range.MinimumValue.i64;
10143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i64max = opd.FORM.Range.MaximumValue.i64;
10153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->i64step = opd.FORM.Range.StepSize.i64;
10163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_INT64;
10173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
10183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_DTC_UINT64:
10193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u64min = opd.FORM.Range.MinimumValue.u64;
10203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u64max = opd.FORM.Range.MaximumValue.u64;
10213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->u64step = opd.FORM.Range.StepSize.u64;
10223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        allowed_vals->datatype = LIBMTP_DATATYPE_UINT64;
10233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
10243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
10253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 0;
10263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else
10273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
10283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
10293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
10313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Destroys a LIBMTP_allowed_values_t struct
10323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param allowed_vals the struct to destroy
10333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
10343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_destroy_allowed_values_t(LIBMTP_allowed_values_t *allowed_vals)
10353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
10363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!allowed_vals->is_range)
10373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  {
10383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    switch (allowed_vals->datatype)
10393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    {
10403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case LIBMTP_DATATYPE_INT8:
10413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        if (allowed_vals->i8vals)
10423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          free(allowed_vals->i8vals);
10433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
10443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case LIBMTP_DATATYPE_UINT8:
10453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        if (allowed_vals->u8vals)
10463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          free(allowed_vals->u8vals);
10473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
10483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case LIBMTP_DATATYPE_INT16:
10493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        if (allowed_vals->i16vals)
10503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          free(allowed_vals->i16vals);
10513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
10523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case LIBMTP_DATATYPE_UINT16:
10533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        if (allowed_vals->u16vals)
10543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          free(allowed_vals->u16vals);
10553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
10563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case LIBMTP_DATATYPE_INT32:
10573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        if (allowed_vals->i32vals)
10583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          free(allowed_vals->i32vals);
10593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
10603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case LIBMTP_DATATYPE_UINT32:
10613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        if (allowed_vals->u32vals)
10623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          free(allowed_vals->u32vals);
10633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
10643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case LIBMTP_DATATYPE_INT64:
10653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        if (allowed_vals->i64vals)
10663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          free(allowed_vals->i64vals);
10673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
10683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case LIBMTP_DATATYPE_UINT64:
10693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        if (allowed_vals->u64vals)
10703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          free(allowed_vals->u64vals);
10713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
10723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
10733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
10743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
10753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
10773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Determine if a property is supported for a given file type
10783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device
10793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param property the property to query
10803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param filetype the filetype of the object you want to set values for
10813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if not supported, positive if supported, negative on error
10823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
10833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Is_Property_Supported(LIBMTP_mtpdevice_t *device, LIBMTP_property_t const property,
10843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev            LIBMTP_filetype_t const filetype)
10853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
10863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t *props = NULL;
10873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t propcnt = 0;
10883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret = 0;
10893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int i = 0;
10903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int supported = 0;
10913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ptp_prop = map_libmtp_property_to_ptp_property(property);
10923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectpropssupported(device->params, map_libmtp_type_to_ptp_type(filetype), &propcnt, &props);
10943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
10953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Is_Property_Supported(): could not get properties supported.");
10963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
10973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
10983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
10993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (i = 0; i < propcnt; i++) {
11003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (props[i] == ptp_prop) {
11013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      supported = 1;
11023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
11033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
11043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
11053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(props);
11073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return supported;
11093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
11103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
11123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Retrieves a string from an object
11133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
11143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
11153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
11163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id MTP attribute ID
11173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return valid string or NULL on failure. The returned string
11183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         must bee <code>free()</code>:ed by the caller after
11193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         use.
11203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
11213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevchar *LIBMTP_Get_String_From_Object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
11223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    LIBMTP_property_t const attribute_id)
11233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
11243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return get_string_from_object(device, object_id, attribute_id);
11253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
11263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
11283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev* Retrieves an unsigned 64-bit integer from an object attribute
11293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
11303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
11313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
11323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id MTP attribute ID
11333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param value_default Default value to return on failure
11343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return the value
11353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
11363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevuint64_t LIBMTP_Get_u64_From_Object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
11373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                    LIBMTP_property_t const attribute_id, uint64_t const value_default)
11383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
11393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return get_u64_from_object(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value_default);
11403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
11413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
11433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Retrieves an unsigned 32-bit integer from an object attribute
11443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
11453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
11463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
11473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id MTP attribute ID
11483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param value_default Default value to return on failure
11493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return the value
11503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
11513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevuint32_t LIBMTP_Get_u32_From_Object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
11523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    LIBMTP_property_t const attribute_id, uint32_t const value_default)
11533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
11543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return get_u32_from_object(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value_default);
11553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
11563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
11583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Retrieves an unsigned 16-bit integer from an object attribute
11593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
11603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
11613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
11623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id MTP attribute ID
11633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param value_default Default value to return on failure
11643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a value
11653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
11663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevuint16_t LIBMTP_Get_u16_From_Object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
11673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    LIBMTP_property_t const attribute_id, uint16_t const value_default)
11683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
11693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return get_u16_from_object(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value_default);
11703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
11713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
11733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Retrieves an unsigned 8-bit integer from an object attribute
11743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
11753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
11763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
11773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id MTP attribute ID
11783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param value_default Default value to return on failure
11793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a value
11803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
11813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevuint8_t LIBMTP_Get_u8_From_Object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
11823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  LIBMTP_property_t const attribute_id, uint8_t const value_default)
11833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
11843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return get_u8_from_object(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value_default);
11853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
11863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
11873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
11883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Sets an object attribute from a string
11893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
11903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
11913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
11923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id MTP attribute ID
11933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param string string value to set
11943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure
11953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
11963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Set_Object_String(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
11973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			     LIBMTP_property_t const attribute_id, char const * const string)
11983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
11993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return set_object_string(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), string);
12003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
12013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
12043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Sets an object attribute from an unsigned 32-bit integer
12053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
12063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
12073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
12083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id MTP attribute ID
12093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param value 32-bit unsigned integer to set
12103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure
12113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
12123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Set_Object_u32(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
12133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			  LIBMTP_property_t const attribute_id, uint32_t const value)
12143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
12153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return set_object_u32(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value);
12163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
12173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
12193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Sets an object attribute from an unsigned 16-bit integer
12203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
12213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
12223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
12233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id MTP attribute ID
12243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param value 16-bit unsigned integer to set
12253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure
12263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
12273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Set_Object_u16(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
12283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			  LIBMTP_property_t const attribute_id, uint16_t const value)
12293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
12303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return set_object_u16(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value);
12313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
12323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
12343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Sets an object attribute from an unsigned 8-bit integer
12353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
12363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
12373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
12383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id MTP attribute ID
12393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param value 8-bit unsigned integer to set
12403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure
12413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
12423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Set_Object_u8(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
12433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 LIBMTP_property_t const attribute_id, uint8_t const value)
12443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
12453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return set_object_u8(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value);
12463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
12473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
12493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Retrieves a string from an object
12503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
12513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
12523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
12533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id PTP attribute ID
12543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return valid string or NULL on failure. The returned string
12553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         must bee <code>free()</code>:ed by the caller after
12563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         use.
12573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
12583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic char *get_string_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
12593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint16_t const attribute_id)
12603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
12613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
12623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  char *retstring = NULL;
12633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
12643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
12653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  MTPProperties *prop;
12663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( device == NULL || object_id == 0) {
12683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
12693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
12703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
12723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (prop) {
12733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (prop->propval.str != NULL)
12743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return strdup(prop->propval.str);
12753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else
12763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return NULL;
12773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
12783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_STR);
12803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret == PTP_RC_OK) {
12813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (propval.str != NULL) {
12823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      retstring = (char *) strdup(propval.str);
12833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      free(propval.str);
12843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
12853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
12863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "get_string_from_object(): could not get object string.");
12873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
12883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retstring;
12903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
12913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
12923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
12933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev* Retrieves an unsigned 64-bit integer from an object attribute
12943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
12953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
12963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
12973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id PTP attribute ID
12983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param value_default Default value to return on failure
12993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return the value
13003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
13013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint64_t get_u64_from_object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
13023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                    uint16_t const attribute_id, uint64_t const value_default)
13033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
13043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
13053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint64_t retval = value_default;
13063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
13073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
13083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  MTPProperties *prop;
13093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( device == NULL ) {
13113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return value_default;
13123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
13133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
13153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (prop)
13163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return prop->propval.u64;
13173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectpropvalue(params, object_id,
13193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                   attribute_id,
13203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                   &propval,
13213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                   PTP_DTC_UINT64);
13223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret == PTP_RC_OK) {
13233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retval = propval.u64;
13243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
13253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "get_u64_from_object(): could not get unsigned 64bit integer from object.");
13263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
13273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retval;
13293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
13303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
13323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Retrieves an unsigned 32-bit integer from an object attribute
13333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
13343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
13353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
13363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id PTP attribute ID
13373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param value_default Default value to return on failure
13383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return the value
13393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
13403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint32_t get_u32_from_object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
13413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint16_t const attribute_id, uint32_t const value_default)
13423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
13433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
13443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t retval = value_default;
13453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
13463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
13473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  MTPProperties *prop;
13483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( device == NULL ) {
13503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return value_default;
13513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
13523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
13543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (prop)
13553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return prop->propval.u32;
13563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectpropvalue(params, object_id,
13583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                   attribute_id,
13593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                   &propval,
13603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                   PTP_DTC_UINT32);
13613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret == PTP_RC_OK) {
13623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retval = propval.u32;
13633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
13643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "get_u32_from_object(): could not get unsigned 32bit integer from object.");
13653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
13663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retval;
13673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
13683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
13703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Retrieves an unsigned 16-bit integer from an object attribute
13713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
13723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
13733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
13743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id PTP attribute ID
13753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param value_default Default value to return on failure
13763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a value
13773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
13783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint16_t get_u16_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
13793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint16_t const attribute_id, uint16_t const value_default)
13803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
13813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
13823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t retval = value_default;
13833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
13843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
13853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  MTPProperties *prop;
13863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( device == NULL ) {
13883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return value_default;
13893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
13903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // This O(n) search should not be used so often, since code
13923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // using the cached properties don't usually call this function.
13933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
13943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (prop)
13953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return prop->propval.u16;
13963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
13973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectpropvalue(params, object_id,
13983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                   attribute_id,
13993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                   &propval,
14003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                   PTP_DTC_UINT16);
14013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret == PTP_RC_OK) {
14023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retval = propval.u16;
14033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
14043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "get_u16_from_object(): could not get unsigned 16bit integer from object.");
14053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
14063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retval;
14083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
14093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
14113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Retrieves an unsigned 8-bit integer from an object attribute
14123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
14133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
14143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
14153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id PTP attribute ID
14163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param value_default Default value to return on failure
14173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a value
14183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
14193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint8_t get_u8_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
14203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  uint16_t const attribute_id, uint8_t const value_default)
14213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
14223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
14233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint8_t retval = value_default;
14243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
14253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
14263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  MTPProperties *prop;
14273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( device == NULL ) {
14293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return value_default;
14303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
14313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // This O(n) search should not be used so often, since code
14333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // using the cached properties don't usually call this function.
14343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
14353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (prop)
14363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return prop->propval.u8;
14373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectpropvalue(params, object_id,
14393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                   attribute_id,
14403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                   &propval,
14413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                   PTP_DTC_UINT8);
14423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret == PTP_RC_OK) {
14433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retval = propval.u8;
14443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
14453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "get_u8_from_object(): could not get unsigned 8bit integer from object.");
14463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
14473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retval;
14493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
14503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
14523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Sets an object attribute from a string
14533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
14543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
14553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
14563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id PTP attribute ID
14573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param string string value to set
14583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure
14593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
14603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int set_object_string(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
14613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			     uint16_t const attribute_id, char const * const string)
14623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
14633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
14643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
14653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
14663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (device == NULL || string == NULL) {
14683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
14693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
14703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
14723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_string(): could not set object string: "
14733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				"PTP_OC_MTP_SetObjectPropValue not supported.");
14743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
14753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
14763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  propval.str = (char *) string;
14773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_STR);
14783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
14793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "set_object_string(): could not set object string.");
14803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
14813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
14823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
14843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
14853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
14873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
14883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Sets an object attribute from an unsigned 32-bit integer
14893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
14903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
14913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
14923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id PTP attribute ID
14933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param value 32-bit unsigned integer to set
14943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure
14953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
14963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int set_object_u32(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
14973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			  uint16_t const attribute_id, uint32_t const value)
14983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
14993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
15003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
15013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
15023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
15033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (device == NULL) {
15043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
15053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
15063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
15073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
15083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_u32(): could not set unsigned 32bit integer property: "
15093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				"PTP_OC_MTP_SetObjectPropValue not supported.");
15103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
15113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
15123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
15133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  propval.u32 = value;
15143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_UINT32);
15153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
15163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "set_object_u32(): could not set unsigned 32bit integer property.");
15173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
15183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
15193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
15203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
15213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
15223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
15233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
15243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Sets an object attribute from an unsigned 16-bit integer
15253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
15263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
15273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
15283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id PTP attribute ID
15293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param value 16-bit unsigned integer to set
15303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure
15313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
15323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int set_object_u16(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
15333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			  uint16_t const attribute_id, uint16_t const value)
15343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
15353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
15363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
15373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
15383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
15393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (device == NULL) {
15403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 1;
15413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
15423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
15433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
15443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_u16(): could not set unsigned 16bit integer property: "
15453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				"PTP_OC_MTP_SetObjectPropValue not supported.");
15463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
15473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
15483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  propval.u16 = value;
15493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_UINT16);
15503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
15513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "set_object_u16(): could not set unsigned 16bit integer property.");
15523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 1;
15533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
15543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
15553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
15563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
15573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
15583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
15593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Sets an object attribute from an unsigned 8-bit integer
15603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
15613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to an MTP device.
15623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id Object reference
15633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param attribute_id PTP attribute ID
15643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param value 8-bit unsigned integer to set
15653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure
15663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
15673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int set_object_u8(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
15683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 uint16_t const attribute_id, uint8_t const value)
15693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
15703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
15713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
15723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
15733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
15743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (device == NULL) {
15753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 1;
15763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
15773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
15783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
15793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_u8(): could not set unsigned 8bit integer property: "
15803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "PTP_OC_MTP_SetObjectPropValue not supported.");
15813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
15823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
15833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  propval.u8 = value;
15843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_UINT8);
15853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
15863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "set_object_u8(): could not set unsigned 8bit integer property.");
15873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 1;
15883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
15893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
15903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
15913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
15923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
15933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
15943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Get the first (as in "first in the list of") connected MTP device.
15953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a device pointer.
15963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Connected_Devices()
15973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
15983aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_mtpdevice_t *LIBMTP_Get_First_Device(void)
15993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
16003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_mtpdevice_t *first_device = NULL;
16013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_raw_device_t *devices;
16023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int numdevs;
16033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_error_number_t ret;
16043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = LIBMTP_Detect_Raw_Devices(&devices, &numdevs);
16063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != LIBMTP_ERROR_NONE) {
16073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
16083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
16093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (devices == NULL || numdevs == 0) {
16113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
16123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
16133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  first_device = LIBMTP_Open_Raw_Device(&devices[0]);
16153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(devices);
16163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return first_device;
16173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
16183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
16203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Overriding debug function.
16213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This way we can disable debug prints.
16223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
16233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void
16243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef __GNUC__
16253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev__attribute__((__format__(printf,2,0)))
16263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
16273aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_ptp_debug(void *data, const char *format, va_list args)
16283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
16293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef ENABLE_PTP_DEBUG
16303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  vfprintf (stderr, format, args);
16313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  fflush (stderr);
16323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
16333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
16343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
16363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Overriding error function.
16373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This way we can capture all error etc to our errorstack.
16383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
16393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void
16403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef __GNUC__
16413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev__attribute__((__format__(printf,2,0)))
16423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
16433aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_ptp_error(void *data, const char *format, va_list args)
16443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
16453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // if (data == NULL) {
16463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    vfprintf (stderr, format, args);
16473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    fflush (stderr);
16483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
16493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    FIXME: find out how we shall get the device here.
16503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
16513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTP_USB *ptp_usb = data;
16523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_mtpdevice_t *device = ...;
16533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    char buf[2048];
16543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    vsnprintf (buf, sizeof (buf), format, args);
16563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device,
16573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    LIBMTP_ERROR_PTP_LAYER,
16583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    buf);
16593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
16603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  */
16613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
16623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
16643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function opens a device from a raw device. It is the
16653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * preferred way to access devices in the new interface where
16663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * several devices can come and go as the library is working
16673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * on a certain device.
16683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param rawdevice the raw device to open a "real" device for.
16693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return an open device.
16703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
16713aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_mtpdevice_t *LIBMTP_Open_Raw_Device(LIBMTP_raw_device_t *rawdevice)
16723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
16733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_mtpdevice_t *mtp_device;
16743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint8_t bs = 0;
16753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *current_params;
16763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb;
16773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_error_number_t err;
16783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int i;
16793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Allocate dynamic space for our device */
16813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_device = (LIBMTP_mtpdevice_t *) malloc(sizeof(LIBMTP_mtpdevice_t));
16823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  memset(mtp_device, 0, sizeof(LIBMTP_mtpdevice_t));
16833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Check if there was a memory allocation error */
16843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(mtp_device == NULL) {
16853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* There has been an memory allocation error. We are going to ignore this
16863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev       device and attempt to continue */
16873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* TODO: This error statement could probably be a bit more robust */
16893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    fprintf(stderr, "LIBMTP PANIC: connect_usb_devices encountered a memory "
16903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    "allocation error with device %d on bus %d, trying to continue",
16913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    rawdevice->devnum, rawdevice->bus_location);
16923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
16943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
16953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
16963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Create PTP params */
16973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current_params = (PTPParams *) malloc(sizeof(PTPParams));
16983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (current_params == NULL) {
16993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(mtp_device);
17003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
17013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
17023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  memset(current_params, 0, sizeof(PTPParams));
17033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current_params->device_flags = rawdevice->device_entry.device_flags;
17043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current_params->nrofobjects = 0;
17053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current_params->objects = NULL;
17063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current_params->response_packet_size = 0;
17073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current_params->response_packet = NULL;
17083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* This will be a pointer to PTP_USB later */
17093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current_params->data = NULL;
17103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Set upp local debug and error functions */
17113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current_params->debug_func = LIBMTP_ptp_debug;
17123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current_params->error_func = LIBMTP_ptp_error;
17133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* TODO: Will this always be little endian? */
17143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current_params->byteorder = PTP_DL_LE;
17153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current_params->cd_locale_to_ucs2 = iconv_open("UCS-2LE", "UTF-8");
17163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  current_params->cd_ucs2_to_locale = iconv_open("UTF-8", "UCS-2LE");
17173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(current_params->cd_locale_to_ucs2 == (iconv_t) -1 ||
17193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     current_params->cd_ucs2_to_locale == (iconv_t) -1) {
17203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    fprintf(stderr, "LIBMTP PANIC: Cannot open iconv() converters to/from UCS-2!\n"
17213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    "Too old stdlibc, glibc and libiconv?\n");
17223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(current_params);
17233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(mtp_device);
17243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
17253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
17263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_device->params = current_params;
17273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Create usbinfo, this also opens the session */
17303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  err = configure_usb_device(rawdevice,
17313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			     current_params,
17323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			     &mtp_device->usbinfo);
17333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (err != LIBMTP_ERROR_NONE) {
17343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(current_params);
17353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(mtp_device);
17363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
17373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
17383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb = (PTP_USB*) mtp_device->usbinfo;
17393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Set pointer back to params */
17403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->params = current_params;
17413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Cache the device information for later use */
17443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ptp_getdeviceinfo(current_params,
17453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			&current_params->deviceinfo) != PTP_RC_OK) {
17463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    fprintf(stderr, "LIBMTP PANIC: Unable to read device information on device "
17473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    "%d on bus %d, trying to continue",
17483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    rawdevice->devnum, rawdevice->bus_location);
17493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* Prevent memory leaks for this device */
17513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(mtp_device->usbinfo);
17523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(mtp_device->params);
17533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    current_params = NULL;
17543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(mtp_device);
17553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
17563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
17573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Determine if the object size supported is 32 or 64 bit wide */
17593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i=0;i<current_params->deviceinfo.ImageFormats_len;i++) {
17603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTPObjectPropDesc opd;
17613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
17623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ptp_mtp_getobjectpropdesc(current_params,
17633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  PTP_OPC_ObjectSize,
17643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  current_params->deviceinfo.ImageFormats[i],
17653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  &opd) != PTP_RC_OK) {
17663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("LIBMTP PANIC: "
17673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	     "could not inspect object property descriptions!\n");
17683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
17693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (opd.DataType == PTP_DTC_UINT32) {
17703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (bs == 0) {
17713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  bs = 32;
17723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	} else if (bs != 32) {
17733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  printf("LIBMTP PANIC: "
17743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		 "different objects support different object sizes!\n");
17753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  bs = 0;
17763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
17773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
17783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      } else if (opd.DataType == PTP_DTC_UINT64) {
17793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (bs == 0) {
17803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  bs = 64;
17813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	} else if (bs != 64) {
17823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  printf("LIBMTP PANIC: "
17833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		 "different objects support different object sizes!\n");
17843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  bs = 0;
17853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
17863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
17873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      } else {
17883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// Ignore if other size.
17893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("LIBMTP PANIC: "
17903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       "awkward object size data type: %04x\n", opd.DataType);
17913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	bs = 0;
17923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
17933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
17943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
17953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
17963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (bs == 0) {
17973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Could not detect object bitsize, assume 32 bits
17983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    bs = 32;
17993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
18003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_device->object_bitsize = bs;
18013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* No Errors yet for this device */
18033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_device->errorstack = NULL;
18043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Default Max Battery Level, we will adjust this if possible */
18063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_device->maximum_battery_level = 100;
18073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Check if device supports reading maximum battery level */
18093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(!FLAG_BROKEN_BATTERY_LEVEL(ptp_usb) &&
18103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     ptp_property_issupported( current_params, PTP_DPC_BatteryLevel)) {
18113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTPDevicePropDesc dpd;
18123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* Try to read maximum battery level */
18143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(ptp_getdevicepropdesc(current_params,
18153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			     PTP_DPC_BatteryLevel,
18163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			     &dpd) != PTP_RC_OK) {
18173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_error_to_errorstack(mtp_device,
18183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      LIBMTP_ERROR_CONNECTING,
18193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      "Unable to read Maximum Battery Level for this "
18203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      "device even though the device supposedly "
18213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      "supports this functionality");
18223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
18233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* TODO: is this appropriate? */
18253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* If max battery level is 0 then leave the default, otherwise assign */
18263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (dpd.FORM.Range.MaximumValue.u8 != 0) {
18273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      mtp_device->maximum_battery_level = dpd.FORM.Range.MaximumValue.u8;
18283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
18293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_free_devicepropdesc(&dpd);
18313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
18323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Set all default folders to 0 (root directory) */
18343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_device->default_music_folder = 0;
18353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_device->default_playlist_folder = 0;
18363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_device->default_picture_folder = 0;
18373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_device->default_video_folder = 0;
18383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_device->default_organizer_folder = 0;
18393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_device->default_zencast_folder = 0;
18403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_device->default_album_folder = 0;
18413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_device->default_text_folder = 0;
18423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Set initial storage information */
18443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_device->storage = NULL;
18453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (LIBMTP_Get_Storage(mtp_device, LIBMTP_STORAGE_SORTBY_NOTSORTED) == -1) {
18463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(mtp_device,
18473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    LIBMTP_ERROR_GENERAL,
18483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "Get Storage information failed.");
18493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    mtp_device->storage = NULL;
18503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
18513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
18533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * Then get the handles and try to locate the default folders.
18543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * This has the desired side effect of caching all handles from
18553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * the device which speeds up later operations.
18563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   */
18573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  flush_handles(mtp_device);
18583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return mtp_device;
18603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
18613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
18633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Recursive function that adds MTP devices to a linked list
18643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param devices a list of raw devices to have real devices created for.
18653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a device pointer to a newly created mtpdevice (used in linked
18663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * list creation).
18673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
18683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic LIBMTP_mtpdevice_t * create_usb_mtp_devices(LIBMTP_raw_device_t *devices, int numdevs)
18693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
18703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint8_t i;
18713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_mtpdevice_t *mtp_device_list = NULL;
18723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_mtpdevice_t *current_device = NULL;
18733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i=0; i < numdevs; i++) {
18753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_mtpdevice_t *mtp_device;
18763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    mtp_device = LIBMTP_Open_Raw_Device(&devices[i]);
18773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* On error, try next device */
18793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (mtp_device == NULL)
18803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      continue;
18813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* Add the device to the list */
18833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    mtp_device->next = NULL;
18843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (mtp_device_list == NULL) {
18853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      mtp_device_list = current_device = mtp_device;
18863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
18873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      current_device->next = mtp_device;
18883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      current_device = mtp_device;
18893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
18903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
18913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return mtp_device_list;
18923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
18933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
18943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
18953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Get the number of devices that are available in the listed device list
18963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device_list Pointer to a linked list of devices
18973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return Number of devices in the device list device_list
18983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Connected_Devices()
18993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
19003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevuint32_t LIBMTP_Number_Devices_In_List(LIBMTP_mtpdevice_t *device_list)
19013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
19023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t numdevices = 0;
19033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_mtpdevice_t *iter;
19043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for(iter = device_list; iter != NULL; iter = iter->next)
19053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    numdevices++;
19063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
19073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return numdevices;
19083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
19093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
19103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
19113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Get the first connected MTP device node in the linked list of devices.
19123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Currently this only provides access to USB devices
19133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device_list A list of devices ready to be used by the caller. You
19143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        need to know how many there are.
19153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return Any error information gathered from device connections
19163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Number_Devices_In_List()
19173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
19183aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_error_number_t LIBMTP_Get_Connected_Devices(LIBMTP_mtpdevice_t **device_list)
19193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
19203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_raw_device_t *devices;
19213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int numdevs;
19223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_error_number_t ret;
19233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
19243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = LIBMTP_Detect_Raw_Devices(&devices, &numdevs);
19253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != LIBMTP_ERROR_NONE) {
19263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    *device_list = NULL;
19273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return ret;
19283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
19293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
19303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Assign linked list of devices */
19313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (devices == NULL || numdevs == 0) {
19323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    *device_list = NULL;
19333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return LIBMTP_ERROR_NO_DEVICE_ATTACHED;
19343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
19353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
19363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  *device_list = create_usb_mtp_devices(devices, numdevs);
19373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(devices);
19383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
19393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* TODO: Add wifi device access here */
19403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
19413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* We have found some devices but create failed */
19423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (*device_list == NULL)
19433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return LIBMTP_ERROR_CONNECTING;
19443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
19453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return LIBMTP_ERROR_NONE;
19463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
19473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
19483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
19493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This closes and releases an allocated MTP device.
19503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the MTP device to release.
19513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
19523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_Release_Device_List(LIBMTP_mtpdevice_t *device)
19533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
19543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(device != NULL)
19553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  {
19563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(device->next != NULL)
19573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    {
19583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      LIBMTP_Release_Device_List(device->next);
19593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
19603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
19613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_Release_Device(device);
19623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
19633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
19643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
19653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
19663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This closes and releases an allocated MTP device.
19673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the MTP device to release.
19683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
19693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_Release_Device(LIBMTP_mtpdevice_t *device)
19703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
19713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
19723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
19733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
19743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  close_device(ptp_usb, params);
19753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Clear error stack
19763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_Clear_Errorstack(device);
19773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Free iconv() converters...
19783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  iconv_close(params->cd_locale_to_ucs2);
19793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  iconv_close(params->cd_ucs2_to_locale);
19803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(ptp_usb);
19813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_free_params(params);
19823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free_storage_list(device);
19833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(device);
19843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
19853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
19863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
19873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This can be used by any libmtp-intrinsic code that
19883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * need to stack up an error on the stack. You are only
19893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * supposed to add errors to the error stack using this
19903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * function, do not create and reference error entries
19913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * directly.
19923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
19933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void add_error_to_errorstack(LIBMTP_mtpdevice_t *device,
19943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    LIBMTP_error_number_t errornumber,
19953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    char const * const error_text)
19963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
19973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_error_t *newerror;
19983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
19993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (device == NULL) {
20003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    fprintf(stderr, "LIBMTP PANIC: Trying to add error to a NULL device!\n");
20013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return;
20023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
20033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  newerror = (LIBMTP_error_t *) malloc(sizeof(LIBMTP_error_t));
20043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  newerror->errornumber = errornumber;
20053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  newerror->error_text = strdup(error_text);
20063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  newerror->next = NULL;
20073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (device->errorstack == NULL) {
20083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    device->errorstack = newerror;
20093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
20103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_error_t *tmp = device->errorstack;
20113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
20123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    while (tmp->next != NULL) {
20133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      tmp = tmp->next;
20143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
20153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    tmp->next = newerror;
20163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
20173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
20183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
20193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
20203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Adds an error from the PTP layer to the error stack.
20213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
20223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void add_ptp_error_to_errorstack(LIBMTP_mtpdevice_t *device,
20233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					uint16_t ptp_error,
20243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					char const * const error_text)
20253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
20263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (device == NULL) {
20273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    fprintf(stderr, "LIBMTP PANIC: Trying to add PTP error to a NULL device!\n");
20283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return;
20293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
20303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    char outstr[256];
20313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    snprintf(outstr, sizeof(outstr), "PTP Layer error %04x: %s", ptp_error, error_text);
20323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    outstr[sizeof(outstr)-1] = '\0';
20333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_PTP_LAYER, outstr);
20343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_PTP_LAYER, "(Look this up in ptp.h for an explanation.)");
20353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
20363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
20373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
20383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
20393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This returns the error stack for a device in case you
20403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * need to either reference the error numbers (e.g. when
20413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * creating multilingual apps with multiple-language text
20423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * representations for each error number) or when you need
20433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * to build a multi-line error text widget or something like
20443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * that. You need to call the <code>LIBMTP_Clear_Errorstack</code>
20453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * to clear it when you're finished with it.
20463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the MTP device to get the error
20473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        stack for.
20483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return the error stack or NULL if there are no errors
20493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         on the stack.
20503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Clear_Errorstack()
20513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Dump_Errorstack()
20523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
20533aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_error_t *LIBMTP_Get_Errorstack(LIBMTP_mtpdevice_t *device)
20543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
20553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (device == NULL) {
20563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    fprintf(stderr, "LIBMTP PANIC: Trying to get the error stack of a NULL device!\n");
20573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
20583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
20593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return device->errorstack;
20603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
20613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
20623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
20633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function clears the error stack of a device and frees
20643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * any memory used by it. Call this when you're finished with
20653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * using the errors.
20663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the MTP device to clear the error
20673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        stack for.
20683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
20693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_Clear_Errorstack(LIBMTP_mtpdevice_t *device)
20703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
20713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (device == NULL) {
20723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    fprintf(stderr, "LIBMTP PANIC: Trying to clear the error stack of a NULL device!\n");
20733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
20743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_error_t *tmp = device->errorstack;
20753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
20763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    while (tmp != NULL) {
20773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      LIBMTP_error_t *tmp2;
20783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
20793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (tmp->error_text != NULL) {
20803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	free(tmp->error_text);
20813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
20823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      tmp2 = tmp;
20833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      tmp = tmp->next;
20843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      free(tmp2);
20853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
20863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    device->errorstack = NULL;
20873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
20883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
20893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
20903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
20913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function dumps the error stack to <code>stderr</code>.
20923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * (You still have to clear the stack though.)
20933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the MTP device to dump the error
20943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        stack for.
20953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
20963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_Dump_Errorstack(LIBMTP_mtpdevice_t *device)
20973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
20983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (device == NULL) {
20993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    fprintf(stderr, "LIBMTP PANIC: Trying to dump the error stack of a NULL device!\n");
21003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
21013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_error_t *tmp = device->errorstack;
21023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
21033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    while (tmp != NULL) {
21043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (tmp->error_text != NULL) {
21053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	fprintf(stderr, "Error %d: %s\n", tmp->errornumber, tmp->error_text);
21063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      } else {
21073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	fprintf(stderr, "Error %d: (unknown)\n", tmp->errornumber);
21083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
21093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      tmp = tmp->next;
21103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
21113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
21123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
21133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
21143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_Set_Device_Timeout(LIBMTP_mtpdevice_t *device, int milliseconds)
21153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
21163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
21173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  set_usb_device_timeout(ptp_usb, milliseconds);
21183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
21193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
21203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_Get_Device_Timeout(LIBMTP_mtpdevice_t *device, int * milliseconds)
21213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
21223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
21233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  get_usb_device_timeout(ptp_usb, milliseconds);
21243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
21253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
21263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
21273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This command gets all handles and stuff by FAST directory retrieveal
21283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * which is available by getting all metadata for object
21293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <code>0xffffffff</code> which simply means "all metadata for all objects".
21303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This works on the vast majority of MTP devices (there ARE exceptions!)
21313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * and is quite quick. Check the error stack to see if there were
21323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * problems getting the metadata.
21333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if all was OK, -1 on failure.
21343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
21353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int get_all_metadata_fast(LIBMTP_mtpdevice_t *device,
21363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				 uint32_t storage)
21373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
21383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams      *params = (PTPParams *) device->params;
21393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int		 cnt = 0;
21403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int            i, j, nrofprops;
21413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t	 lasthandle = 0xffffffff;
21423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  MTPProperties  *props = NULL;
21433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  MTPProperties  *prop;
21443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t       ret;
21453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int            oldtimeout;
21463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
21473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
21483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* The follow request causes the device to generate
21493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * a list of very file on the device and return it
21503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * in a single response.
21513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   *
21523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * Some slow devices as well as devices with very
21533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * large file systems can easily take longer then
21543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * the standard timeout value before it is able
21553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * to return a response.
21563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   *
21573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * Temporarly set timeout to allow working with
21583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * widest range of devices.
21593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   */
21603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  get_usb_device_timeout(ptp_usb, &oldtimeout);
21613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  set_usb_device_timeout(ptp_usb, 60000);
21623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
21633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectproplist(params, 0xffffffff, &props, &nrofprops);
21643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  set_usb_device_timeout(ptp_usb, oldtimeout);
21653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
21663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret == PTP_RC_MTP_Specification_By_Group_Unsupported) {
21673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // What's the point in the device implementing this command if
21683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // you cannot use it to get all props for AT LEAST one object?
21693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Well, whatever...
21703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "get_all_metadata_fast(): "
21713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    "cannot retrieve all metadata for an object on this device.");
21723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
21733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
21743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
21753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "get_all_metadata_fast(): "
21763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    "could not get proplist of all objects.");
21773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
21783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
21793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (props == NULL && nrofprops != 0) {
21803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
21813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "get_all_metadata_fast(): "
21823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "call to ptp_mtp_getobjectproplist() returned "
21833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "inconsistent results.");
21843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
21853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
21863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
21873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * We count the number of objects by counting the ObjectHandle
21883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * references, whenever it changes we get a new object, when it's
21893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * the same, it is just different properties of the same object.
21903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   */
21913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  prop = props;
21923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i=0;i<nrofprops;i++) {
21933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (lasthandle != prop->ObjectHandle) {
21943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	cnt++;
21953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	lasthandle = prop->ObjectHandle;
21963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
21973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      prop++;
21983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
21993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  lasthandle = 0xffffffff;
22003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  params->objects = calloc (sizeof(PTPObject),cnt);
22013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  prop = props;
22023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  i = -1;
22033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (j=0;j<nrofprops;j++) {
22043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (lasthandle != prop->ObjectHandle) {
22053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (i >= 0) {
22063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        params->objects[i].flags |= PTPOBJECT_OBJECTINFO_LOADED;
22073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!params->objects[i].oi.Filename) {
22083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  /* I have one such file on my Creative (Marcus) */
22093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  params->objects[i].oi.Filename = strdup("<null>");
22103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
22113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
22123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      i++;
22133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      lasthandle = prop->ObjectHandle;
22143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      params->objects[i].oid = prop->ObjectHandle;
22153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
22163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    switch (prop->property) {
22173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case PTP_OPC_ParentObject:
22183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      params->objects[i].oi.ParentObject = prop->propval.u32;
22193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      params->objects[i].flags |= PTPOBJECT_PARENTOBJECT_LOADED;
22203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
22213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case PTP_OPC_ObjectFormat:
22223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      params->objects[i].oi.ObjectFormat = prop->propval.u16;
22233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
22243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case PTP_OPC_ObjectSize:
22253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // We loose precision here, up to 32 bits! However the commands that
22263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // retrieve metadata for files and tracks will make sure that the
22273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // PTP_OPC_ObjectSize is read in and duplicated again.
22283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (device->object_bitsize == 64) {
22293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	params->objects[i].oi.ObjectCompressedSize = (uint32_t) prop->propval.u64;
22303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      } else {
22313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	params->objects[i].oi.ObjectCompressedSize = prop->propval.u32;
22323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
22333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
22343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case PTP_OPC_StorageID:
22353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      params->objects[i].oi.StorageID = prop->propval.u32;
22363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      params->objects[i].flags |= PTPOBJECT_STORAGEID_LOADED;
22373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
22383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case PTP_OPC_ObjectFileName:
22393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (prop->propval.str != NULL)
22403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        params->objects[i].oi.Filename = strdup(prop->propval.str);
22413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
22423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    default: {
22433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      MTPProperties *newprops;
22443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
22453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      /* Copy all of the other MTP oprierties into the per-object proplist */
22463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (params->objects[i].nrofmtpprops) {
22473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        newprops = realloc(params->objects[i].mtpprops,(params->objects[i].nrofmtpprops+1)*sizeof(MTPProperties));
22483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      } else {
22493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        newprops = calloc(sizeof(MTPProperties),1);
22503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
22513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (!newprops) return 0; /* FIXME: error handling? */
22523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      params->objects[i].mtpprops = newprops;
22533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      memcpy(&params->objects[i].mtpprops[params->objects[i].nrofmtpprops],&props[j],sizeof(props[j]));
22543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      params->objects[i].nrofmtpprops++;
22553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      params->objects[i].flags |= PTPOBJECT_MTPPROPLIST_LOADED;
22563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
22573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
22583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
22593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    prop++;
22603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
22613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* mark last entry also */
22623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  params->objects[i].flags |= PTPOBJECT_OBJECTINFO_LOADED;
22633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  params->nrofobjects = i+1;
22643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* The device might not give the list in linear ascending order */
22653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_objects_sort (params);
22663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
22673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
22683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
22693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
22703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function will recurse through all the directories on the device,
22713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * starting at the root directory, gathering metadata as it moves along.
22723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * It works better on some devices that will only return data for a
22733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * certain directory and does not respect the option to get all metadata
22743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * for all objects.
22753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
22763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void get_handles_recursively(LIBMTP_mtpdevice_t *device,
22773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    PTPParams *params,
22783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint32_t storageid,
22793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint32_t parent)
22803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
22813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObjectHandles currentHandles;
22823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int i = 0;
22833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret = ptp_getobjecthandles(params,
22843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                      storageid,
22853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                      PTP_GOH_ALL_FORMATS,
22863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                      parent,
22873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                      &currentHandles);
22883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
22893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
22903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "get_handles_recursively(): could not get object handles.");
22913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return;
22923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
22933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
22943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (currentHandles.Handler == NULL || currentHandles.n == 0)
22953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return;
22963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
22973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Now descend into any subdirectories found
22983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i = 0; i < currentHandles.n; i++) {
22993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTPObject *ob;
23003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_object_want(params,currentHandles.Handler[i],PTPOBJECT_OBJECTINFO_LOADED, &ob);
23013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret == PTP_RC_OK) {
23023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ob->oi.ObjectFormat == PTP_OFC_Association)
23033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        get_handles_recursively(device, params, storageid, currentHandles.Handler[i]);
23043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
23053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_error_to_errorstack(device,
23063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      LIBMTP_ERROR_CONNECTING,
23073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      "Found a bad handle, trying to ignore it.");
23083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
23093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
23103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(currentHandles.Handler);
23113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
23123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23143aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_file_t * obj2file(LIBMTP_mtpdevice_t *device, PTPObject *ob)
23153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
23163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
23173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
23183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_file_t *file;
23193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObject *xob;
23203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
23213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ob->oi.Filename == NULL)
23243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ob->oi.Filename = strdup("<null>");
23253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ob->oi.Keywords == NULL)
23273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ob->oi.Keywords = strdup("<null>");
23283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Allocate a new file type
23303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file = LIBMTP_new_file_t();
23313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file->parent_id = ob->oi.ParentObject;
23333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file->storage_id = ob->oi.StorageID;
23343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // This is some sort of unique ID so we can keep track of the track.
23363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file->item_id = ob->oid;
23373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Set the filetype
23393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file->filetype = map_ptp_type_to_libmtp_type(ob->oi.ObjectFormat);
23403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Set the modification date
23423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file->modificationdate = ob->oi.ModificationDate;
23433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Original file-specific properties
23453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // We only have 32-bit file size here; if we find it, we use the
23463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // PTP_OPC_ObjectSize property which has 64bit precision.
23473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file->filesize = ob->oi.ObjectCompressedSize;
23483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ob->oi.Filename != NULL) {
23493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      file->filename = strdup(ob->oi.Filename);
23503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
23513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
23533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  * A special quirk for devices that doesn't quite
23543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  * remember that some files marked as "unknown" type are
23553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  * actually OGG or FLAC files. We look at the filename extension
23563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  * and see if it happens that this was atleast named "ogg" or "flac"
23573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  * and fall back on this heuristic approach in that case,
23583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  * for these bugged devices only.
23593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  */
23603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (file->filetype == LIBMTP_FILETYPE_UNKNOWN) {
23613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if ((FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) ||
23623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        FLAG_OGG_IS_UNKNOWN(ptp_usb)) &&
23633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        has_ogg_extension(file->filename))
23643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      file->filetype = LIBMTP_FILETYPE_OGG;
23663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (FLAG_FLAC_IS_UNKNOWN(ptp_usb) && has_flac_extension(file->filename))
23683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        file->filetype = LIBMTP_FILETYPE_FLAC;
23693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
23703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
23723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  * If we have a cached, large set of metadata, then use it!
23733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  */
23743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_object_want (params, ob->oid, PTPOBJECT_MTPPROPLIST_LOADED, &xob);
23753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ob->mtpprops) {
23763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    MTPProperties *prop = ob->mtpprops;
23773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    int i;
23783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i=0;i<ob->nrofmtpprops;i++) {
23803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Pick ObjectSize here...
23813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (prop->property == PTP_OPC_ObjectSize) {
23823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        if (device->object_bitsize == 64) {
23833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          file->filesize = prop->propval.u64;
23843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        } else {
23853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          file->filesize = prop->propval.u32;
23863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        }
23873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        break;
23883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
23893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      prop++;
23903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
23913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
23923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    uint16_t *props = NULL;
23933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    uint32_t propcnt = 0;
23943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
23953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // First see which properties can be retrieved for this object format
23963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_mtp_getobjectpropssupported(params, ob->oi.ObjectFormat, &propcnt, &props);
23973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
23983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_ptp_error_to_errorstack(device, ret, "obj2file(): call to ptp_mtp_getobjectpropssupported() failed.");
23993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Silently fall through.
24003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
24013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      int i;
24023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      for (i=0;i<propcnt;i++) {
24033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/*
24053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    TODO: (yavor) See what is a sensible thing to do for Folders
24063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ob->oi.ObjectFormat == PTP_OFC_Association)
24073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev*/
24083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      switch (props[i]) {
24093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        case PTP_OPC_ObjectSize:
24103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          if (device->object_bitsize == 64) {
24113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev            file->filesize = get_u64_from_object(device, file->item_id, PTP_OPC_ObjectSize, 0);
24123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          } else {
24133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev            file->filesize = get_u32_from_object(device, file->item_id, PTP_OPC_ObjectSize, 0);
24143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          }
24153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          break;
24163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        default:
24173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev            break;
24183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        }
24193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
24203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      free(props);
24213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
24223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
24233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return file;
24253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
24263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic LIBMTP_file_t * get_files(LIBMTP_mtpdevice_t *device,
24303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                        PTPParams *params,
24313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                        uint32_t storageid,
24323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                        uint32_t parentId
24333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                        )
24343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
24353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int i = 0;
24363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_file_t *curfile = NULL;
24373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_file_t *retfiles = NULL;
24383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObjectHandles currentHandles;
24393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret = ptp_getobjecthandles(params,
24413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                      storageid,
24423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                      PTP_GOH_ALL_FORMATS,
24433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                      parentId,
24443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                      &currentHandles);
24453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
24473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "get_files(): could not get object handles.");
24483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
24493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
24503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (currentHandles.Handler == NULL || currentHandles.n == 0)
24523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
24533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i = 0; i < currentHandles.n; i++) {
24553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTPObject *ob;
24563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_file_t *file;
24573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_object_want(params, currentHandles.Handler[i],PTPOBJECT_OBJECTINFO_LOADED, &ob);
24593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK)
24603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return NULL;
24613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    file = obj2file(device, ob);
24633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (file == NULL)
24653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      continue;
24663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Add track to a list that will be returned afterwards.
24683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (curfile == NULL) {
24693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curfile = file;
24703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      retfiles = file;
24713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
24723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curfile->next = file;
24733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curfile = file;
24743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
24753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev }
24763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(currentHandles.Handler);
24783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Return a pointer to the original first file
24803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // in the big list.
24813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retfiles;
24823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
24833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
24853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function controls the usage of the internal object cache.
24863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * The default configuration loads all object handles on initialization.
24873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * In order to handle large number of files turn on the on demand
24883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * loading by calling this function with parameter 1, and use
24893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * LIBMTP_Get_Files_And_Folders() to load content when needed.
24903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
24913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param flag - 0 means turn off on demand loading.
24923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             - 1 means turn on on demand loading.
24933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
24943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_Set_Load_Cache_On_Demand(int flag)
24953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
24963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    load_cache_on_demand = flag;
24973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
24983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
24993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
25003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function retrieves the content of a folder with id - parentId.
25013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * The result contains both files and folders.
25023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * NOTE: the request will always perform I/O with the device.
25033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the MTP device to report info from.
25043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @storageId the id for the storage.
25053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param parentId the parent folder id.
25063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
25073aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_file_t * LIBMTP_Get_Files_And_Folders(LIBMTP_mtpdevice_t *device, uint32_t storageId, uint32_t parentId)
25083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
25093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_file_t *retfiles = NULL;
25103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
25113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
25123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int ret;
25133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t i;
25143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
25153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#if 0
25163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  //TODO: (yavor) Try to use get_all_metadata_fast for a parendId.
25173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ptp_operation_issupported(params,PTP_OC_MTP_GetObjPropList)
25183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      && !FLAG_BROKEN_MTPGETOBJPROPLIST(ptp_usb)
25193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      && !FLAG_BROKEN_MTPGETOBJPROPLIST_ALL(ptp_usb)) {
25203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Use the fast method. Ignore return value for now.
25213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = get_all_metadata_fast(device, PTP_GOH_ALL_STORAGE);
25223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
25233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
25243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
25253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
25263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  retfiles = get_files(device, params, storageId, parentId);
25273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
25283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retfiles;
25293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
25303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
25313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
25323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function refresh the internal handle list whenever
25333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * the items stored inside the device is altered. On operations
25343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * that do not add or remove objects, this is typically not
25353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * called.
25363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the MTP device to flush handles for.
25373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
25383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void flush_handles(LIBMTP_mtpdevice_t *device)
25393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
25403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
25413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
25423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int ret;
25433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t i;
25443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
25453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (load_cache_on_demand) {
25463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return;
25473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
25483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
25493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->objects != NULL) {
25503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i=0;i<params->nrofobjects;i++)
25513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptp_free_object (&params->objects[i]);
25523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(params->objects);
25533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    params->objects = NULL;
25543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    params->nrofobjects = 0;
25553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
25563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
25573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ptp_operation_issupported(params,PTP_OC_MTP_GetObjPropList)
25583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      && !FLAG_BROKEN_MTPGETOBJPROPLIST(ptp_usb)
25593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      && !FLAG_BROKEN_MTPGETOBJPROPLIST_ALL(ptp_usb)) {
25603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Use the fast method. Ignore return value for now.
25613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = get_all_metadata_fast(device, PTP_GOH_ALL_STORAGE);
25623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
25633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
25643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // If the previous failed or returned no objects, use classic
25653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // methods instead.
25663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->nrofobjects == 0) {
25673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Get all the handles using just standard commands.
25683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (device->storage == NULL) {
25693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      get_handles_recursively(device, params,
25703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      PTP_GOH_ALL_STORAGE,
25713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      PTP_GOH_ROOT_PARENT);
25723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
25733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Get handles for each storage in turn.
25743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      LIBMTP_devicestorage_t *storage = device->storage;
25753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      while(storage != NULL) {
25763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	get_handles_recursively(device, params,
25773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				storage->id,
25783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				PTP_GOH_ROOT_PARENT);
25793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	storage = storage->next;
25803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
25813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
25823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
25833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
25843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
25853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * Loop over the handles, fix up any NULL filenames or
25863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * keywords, then attempt to locate some default folders
25873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * in the root directory of the primary storage.
25883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   */
25893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for(i = 0; i < params->nrofobjects; i++) {
25903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTPObject *ob, *xob;
25913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
25923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ob = &params->objects[i];
25933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_object_want(params,params->objects[i].oid,PTPOBJECT_OBJECTINFO_LOADED, &xob);
25943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
25953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	fprintf(stderr,"broken! %x not found\n", params->objects[i].oid);
25963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
25973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ob->oi.Filename == NULL)
25983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ob->oi.Filename = strdup("<null>");
25993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ob->oi.Keywords == NULL)
26003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ob->oi.Keywords = strdup("<null>");
26013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
26023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* Ignore handles that point to non-folders */
26033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(ob->oi.ObjectFormat != PTP_OFC_Association)
26043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      continue;
26053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* Only look in the root folder */
26063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ob->oi.ParentObject != 0x00000000U)
26073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      continue;
26083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* Only look in the primary storage */
26093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (device->storage != NULL && ob->oi.StorageID != device->storage->id)
26103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      continue;
26113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
26123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
26133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* Is this the Music Folder */
26143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (!strcasecmp(ob->oi.Filename, "My Music") ||
26153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	!strcasecmp(ob->oi.Filename, "Music")) {
26163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      device->default_music_folder = ob->oid;
26173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
26183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else if (!strcasecmp(ob->oi.Filename, "My Playlists") ||
26193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	     !strcasecmp(ob->oi.Filename, "Playlists")) {
26203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      device->default_playlist_folder = ob->oid;
26213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
26223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else if (!strcasecmp(ob->oi.Filename, "My Pictures") ||
26233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	     !strcasecmp(ob->oi.Filename, "Pictures")) {
26243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      device->default_picture_folder = ob->oid;
26253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
26263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else if (!strcasecmp(ob->oi.Filename, "My Video") ||
26273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	     !strcasecmp(ob->oi.Filename, "Video")) {
26283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	device->default_video_folder = ob->oid;
26293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
26303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else if (!strcasecmp(ob->oi.Filename, "My Organizer")) {
26313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      device->default_organizer_folder = ob->oid;
26323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
26333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else if (!strcasecmp(ob->oi.Filename, "ZENcast") ||
26343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	     !strcasecmp(ob->oi.Filename, "Datacasts")) {
26353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      device->default_zencast_folder = ob->oid;
26363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
26373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else if (!strcasecmp(ob->oi.Filename, "My Albums") ||
26383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	     !strcasecmp(ob->oi.Filename, "Albums")) {
26393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      device->default_album_folder = ob->oid;
26403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
26413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else if (!strcasecmp(ob->oi.Filename, "Text") ||
26423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	     !strcasecmp(ob->oi.Filename, "Texts")) {
26433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      device->default_text_folder = ob->oid;
26443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
26453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
26463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
26473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
26483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
26493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function traverses a devices storage list freeing up the
26503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * strings and the structs.
26513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the MTP device to free the storage
26523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * list for.
26533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
26543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void free_storage_list(LIBMTP_mtpdevice_t *device)
26553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
26563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_devicestorage_t *storage;
26573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_devicestorage_t *tmp;
26583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
26593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  storage = device->storage;
26603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  while(storage != NULL) {
26613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (storage->StorageDescription != NULL) {
26623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      free(storage->StorageDescription);
26633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
26643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (storage->VolumeIdentifier != NULL) {
26653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      free(storage->VolumeIdentifier);
26663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
26673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    tmp = storage;
26683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    storage = storage->next;
26693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(tmp);
26703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
26713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  device->storage = NULL;
26723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
26733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return;
26743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
26753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
26763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
26773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function traverses a devices storage list freeing up the
26783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * strings and the structs.
26793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the MTP device to free the storage
26803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * list for.
26813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
26823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int sort_storage_by(LIBMTP_mtpdevice_t *device,int const sortby)
26833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
26843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_devicestorage_t *oldhead, *ptr1, *ptr2, *newlist;
26853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
26863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (device->storage == NULL)
26873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
26883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (sortby == LIBMTP_STORAGE_SORTBY_NOTSORTED)
26893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 0;
26903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
26913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  oldhead = ptr1 = ptr2 = device->storage;
26923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
26933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  newlist = NULL;
26943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
26953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  while(oldhead != NULL) {
26963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptr1 = ptr2 = oldhead;
26973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    while(ptr1 != NULL) {
26983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
26993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (sortby == LIBMTP_STORAGE_SORTBY_FREESPACE && ptr1->FreeSpaceInBytes > ptr2->FreeSpaceInBytes)
27003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        ptr2 = ptr1;
27013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (sortby == LIBMTP_STORAGE_SORTBY_MAXSPACE && ptr1->FreeSpaceInBytes > ptr2->FreeSpaceInBytes)
27023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        ptr2 = ptr1;
27033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
27043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptr1 = ptr1->next;
27053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
27063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
27073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Make our previous entries next point to our next
27083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(ptr2->prev != NULL) {
27093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptr1 = ptr2->prev;
27103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptr1->next = ptr2->next;
27113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
27123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      oldhead = ptr2->next;
27133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if(oldhead != NULL)
27143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        oldhead->prev = NULL;
27153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
27163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
27173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Make our next entries previous point to our previous
27183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptr1 = ptr2->next;
27193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(ptr1 != NULL) {
27203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptr1->prev = ptr2->prev;
27213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
27223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptr1 = ptr2->prev;
27233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if(ptr1 != NULL)
27243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        ptr1->next = NULL;
27253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
27263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
27273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if(newlist == NULL) {
27283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      newlist = ptr2;
27293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      newlist->prev = NULL;
27303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
27313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptr2->prev = newlist;
27323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      newlist->next = ptr2;
27333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      newlist = newlist->next;
27343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
27353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
27363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
27373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (newlist != NULL) {
27383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    newlist->next = NULL;
27393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    while(newlist->prev != NULL)
27403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      newlist = newlist->prev;
27413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    device->storage = newlist;
27423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
27433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
27443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
27453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
27463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
27473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
27483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function grabs the first writeable storageid from the
27493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * device storage list.
27503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the MTP device to locate writeable
27513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        storage for.
27523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param fitsize a file of this file must fit on the device.
27533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
27543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint32_t get_writeable_storageid(LIBMTP_mtpdevice_t *device, uint64_t fitsize)
27553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
27563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_devicestorage_t *storage;
27573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t store = 0x00000000; //Should this be 0xffffffffu instead?
27583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int subcall_ret;
27593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
27603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // See if there is some storage we can fit this file on.
27613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  storage = device->storage;
27623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (storage == NULL) {
27633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Sometimes the storage just cannot be detected.
27643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    store = 0x00000000U;
27653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
27663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    while(storage != NULL) {
27673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // These storages cannot be used.
27683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (storage->StorageType == PTP_ST_FixedROM || storage->StorageType == PTP_ST_RemovableROM) {
27693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	storage = storage->next;
27703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	continue;
27713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
27723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Storage IDs with the lower 16 bits 0x0000 are not supposed
27733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // to be writeable.
27743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if ((storage->id & 0x0000FFFFU) == 0x00000000U) {
27753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	storage = storage->next;
27763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	continue;
27773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
27783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Also check the access capability to avoid e.g. deletable only storages
27793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (storage->AccessCapability == PTP_AC_ReadOnly || storage->AccessCapability == PTP_AC_ReadOnly_with_Object_Deletion) {
27803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	storage = storage->next;
27813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	continue;
27823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
27833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Then see if we can fit the file.
27843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      subcall_ret = check_if_file_fits(device, storage, fitsize);
27853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (subcall_ret != 0) {
27863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	storage = storage->next;
27873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      } else {
27883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// We found a storage that is writable and can fit the file!
27893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
27903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
27913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
27923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (storage == NULL) {
27933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_error_to_errorstack(device, LIBMTP_ERROR_STORAGE_FULL, "LIBMTP_Send_File_From_File_Descriptor(): "
27943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      "all device storage is full or corrupt.");
27953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return -1;
27963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
27973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    store = storage->id;
27983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
27993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
28003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return store;
28013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
28023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
28033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
28043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function grabs the freespace from a certain storage in
28053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * device storage list.
28063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the MTP device to free the storage
28073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * list for.
28083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param storageid the storage ID for the storage to flush and
28093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * get free space for.
28103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param freespace the free space on this storage will be returned
28113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * in this variable.
28123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
28133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int get_storage_freespace(LIBMTP_mtpdevice_t *device,
28143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				 LIBMTP_devicestorage_t *storage,
28153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				 uint64_t *freespace)
28163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
28173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
28183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
28193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Always query the device about this, since some models explicitly
28203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // needs that. We flush all data on queries storage here.
28213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ptp_operation_issupported(params,PTP_OC_GetStorageInfo)) {
28223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTPStorageInfo storageInfo;
28233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    uint16_t ret;
28243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
28253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_getstorageinfo(params, storage->id, &storageInfo);
28263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
28273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_ptp_error_to_errorstack(device, ret, "get_first_storage_freespace(): could not get storage info.");
28283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return -1;
28293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
28303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (storage->StorageDescription != NULL) {
28313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      free(storage->StorageDescription);
28323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
28333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (storage->VolumeIdentifier != NULL) {
28343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      free(storage->VolumeIdentifier);
28353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
28363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    storage->StorageType = storageInfo.StorageType;
28373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    storage->FilesystemType = storageInfo.FilesystemType;
28383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    storage->AccessCapability = storageInfo.AccessCapability;
28393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    storage->MaxCapacity = storageInfo.MaxCapability;
28403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    storage->FreeSpaceInBytes = storageInfo.FreeSpaceInBytes;
28413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    storage->FreeSpaceInObjects = storageInfo.FreeSpaceInImages;
28423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    storage->StorageDescription = storageInfo.StorageDescription;
28433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    storage->VolumeIdentifier = storageInfo.VolumeLabel;
28443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
28453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(storage->FreeSpaceInBytes == (uint64_t) -1)
28463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
28473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  *freespace = storage->FreeSpaceInBytes;
28483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
28493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
28503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
28513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
28523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function dumps out a large chunk of textual information
28533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * provided from the PTP protocol and additionally some extra
28543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * MTP-specific information where applicable.
28553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the MTP device to report info from.
28563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
28573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_Dump_Device_Info(LIBMTP_mtpdevice_t *device)
28583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
28593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int i;
28603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
28613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
28623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_devicestorage_t *storage = device->storage;
28633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
28643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("USB low-level info:\n");
28653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  dump_usbinfo(ptp_usb);
28663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Print out some verbose information */
28673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("Device info:\n");
28683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Manufacturer: %s\n", params->deviceinfo.Manufacturer);
28693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Model: %s\n", params->deviceinfo.Model);
28703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Device version: %s\n", params->deviceinfo.DeviceVersion);
28713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Serial number: %s\n", params->deviceinfo.SerialNumber);
28723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Vendor extension ID: 0x%08x\n", params->deviceinfo.VendorExtensionID);
28733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Vendor extension description: %s\n", params->deviceinfo.VendorExtensionDesc);
28743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Detected object size: %d bits\n", device->object_bitsize);
28753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("Supported operations:\n");
28763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i=0;i<params->deviceinfo.OperationsSupported_len;i++) {
28773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    char txt[256];
28783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
28793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    (void) ptp_render_opcode (params, params->deviceinfo.OperationsSupported[i], sizeof(txt), txt);
28803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    printf("   %04x: %s\n", params->deviceinfo.OperationsSupported[i], txt);
28813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
28823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("Events supported:\n");
28833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->deviceinfo.EventsSupported_len == 0) {
28843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    printf("   None.\n");
28853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
28863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i=0;i<params->deviceinfo.EventsSupported_len;i++) {
28873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("   0x%04x\n", params->deviceinfo.EventsSupported[i]);
28883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
28893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
28903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("Device Properties Supported:\n");
28913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i=0;i<params->deviceinfo.DevicePropertiesSupported_len;i++) {
28923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    char const *propdesc = ptp_get_property_description(params, params->deviceinfo.DevicePropertiesSupported[i]);
28933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
28943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (propdesc != NULL) {
28953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("   0x%04x: %s\n", params->deviceinfo.DevicePropertiesSupported[i], propdesc);
28963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
28973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      uint16_t prop = params->deviceinfo.DevicePropertiesSupported[i];
28983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("   0x%04x: Unknown property\n", prop);
28993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
29003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
29013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
29023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ptp_operation_issupported(params,PTP_OC_MTP_GetObjectPropsSupported)) {
29033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    printf("Playable File (Object) Types and Object Properties Supported:\n");
29043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i=0;i<params->deviceinfo.ImageFormats_len;i++) {
29053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      char txt[256];
29063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      uint16_t ret;
29073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      uint16_t *props = NULL;
29083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      uint32_t propcnt = 0;
29093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      int j;
29103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
29113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      (void) ptp_render_ofc (params, params->deviceinfo.ImageFormats[i], sizeof(txt), txt);
29123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("   %04x: %s\n", params->deviceinfo.ImageFormats[i], txt);
29133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
29143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ret = ptp_mtp_getobjectpropssupported (params, params->deviceinfo.ImageFormats[i], &propcnt, &props);
29153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret != PTP_RC_OK) {
29163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	add_ptp_error_to_errorstack(device, ret, "LIBMTP_Dump_Device_Info(): error on query for object properties.");
29173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      } else {
29183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (j=0;j<propcnt;j++) {
29193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  PTPObjectPropDesc opd;
29203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  int k;
29213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
29223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  printf("      %04x: %s", props[j], LIBMTP_Get_Property_Description(map_ptp_property_to_libmtp_property(props[j])));
29233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Get a more verbose description
29243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  ret = ptp_mtp_getobjectpropdesc(params, props[j], params->deviceinfo.ImageFormats[i], &opd);
29253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (ret != PTP_RC_OK) {
29263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Dump_Device_Info(): "
29273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    "could not get property description.");
29283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    break;
29293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
29303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
29313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (opd.DataType == PTP_DTC_STR) {
29323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    printf(" STRING data type");
29333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    switch (opd.FormFlag) {
29343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    case PTP_OPFF_DateTime:
29353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" DATETIME FORM");
29363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
29373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    case PTP_OPFF_RegularExpression:
29383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" REGULAR EXPRESSION FORM");
29393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
29403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    case PTP_OPFF_LongString:
29413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" LONG STRING FORM");
29423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
29433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    default:
29443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
29453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
29463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  } else {
29473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (opd.DataType & PTP_DTC_ARRAY_MASK) {
29483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" array of");
29493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
29503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
29513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    switch (opd.DataType & (~PTP_DTC_ARRAY_MASK)) {
29523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
29533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    case PTP_DTC_UNDEF:
29543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" UNDEFINED data type");
29553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
29563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
29573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    case PTP_DTC_INT8:
29583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" INT8 data type");
29593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      switch (opd.FormFlag) {
29603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      case PTP_OPFF_Range:
29613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" range: MIN %d, MAX %d, STEP %d",
29623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.MinimumValue.i8,
29633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.MaximumValue.i8,
29643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.StepSize.i8);
29653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
29663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      case PTP_OPFF_Enumeration:
29673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" enumeration: ");
29683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for(k=0;k<opd.FORM.Enum.NumberOfValues;k++) {
29693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		  printf("%d, ", opd.FORM.Enum.SupportedValue[k].i8);
29703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
29713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
29723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      case PTP_OPFF_ByteArray:
29733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" byte array: ");
29743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
29753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      default:
29763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" ANY 8BIT VALUE form");
29773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
29783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      }
29793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
29803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
29813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    case PTP_DTC_UINT8:
29823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" UINT8 data type");
29833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      switch (opd.FormFlag) {
29843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      case PTP_OPFF_Range:
29853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" range: MIN %d, MAX %d, STEP %d",
29863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.MinimumValue.u8,
29873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.MaximumValue.u8,
29883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.StepSize.u8);
29893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
29903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      case PTP_OPFF_Enumeration:
29913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" enumeration: ");
29923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for(k=0;k<opd.FORM.Enum.NumberOfValues;k++) {
29933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		  printf("%d, ", opd.FORM.Enum.SupportedValue[k].u8);
29943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
29953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
29963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      case PTP_OPFF_ByteArray:
29973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" byte array: ");
29983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
29993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      default:
30003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" ANY 8BIT VALUE form");
30013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
30023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      }
30033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
30043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
30053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    case PTP_DTC_INT16:
30063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" INT16 data type");
30073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      switch (opd.FormFlag) {
30083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      case PTP_OPFF_Range:
30093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" range: MIN %d, MAX %d, STEP %d",
30103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		     opd.FORM.Range.MinimumValue.i16,
30113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		     opd.FORM.Range.MaximumValue.i16,
30123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		     opd.FORM.Range.StepSize.i16);
30133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
30143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      case PTP_OPFF_Enumeration:
30153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" enumeration: ");
30163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for(k=0;k<opd.FORM.Enum.NumberOfValues;k++) {
30173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		  printf("%d, ", opd.FORM.Enum.SupportedValue[k].i16);
30183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
30193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
30203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      default:
30213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" ANY 16BIT VALUE form");
30223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
30233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      }
30243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
30253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
30263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    case PTP_DTC_UINT16:
30273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" UINT16 data type");
30283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      switch (opd.FormFlag) {
30293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      case PTP_OPFF_Range:
30303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" range: MIN %d, MAX %d, STEP %d",
30313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.MinimumValue.u16,
30323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.MaximumValue.u16,
30333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.StepSize.u16);
30343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
30353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      case PTP_OPFF_Enumeration:
30363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" enumeration: ");
30373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for(k=0;k<opd.FORM.Enum.NumberOfValues;k++) {
30383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		  printf("%d, ", opd.FORM.Enum.SupportedValue[k].u16);
30393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
30403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
30413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      default:
30423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" ANY 16BIT VALUE form");
30433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
30443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      }
30453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
30463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
30473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    case PTP_DTC_INT32:
30483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" INT32 data type");
30493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      switch (opd.FormFlag) {
30503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      case PTP_OPFF_Range:
30513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" range: MIN %d, MAX %d, STEP %d",
30523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.MinimumValue.i32,
30533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.MaximumValue.i32,
30543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.StepSize.i32);
30553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
30563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      case PTP_OPFF_Enumeration:
30573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" enumeration: ");
30583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		for(k=0;k<opd.FORM.Enum.NumberOfValues;k++) {
30593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		  printf("%d, ", opd.FORM.Enum.SupportedValue[k].i32);
30603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
30613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
30623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      default:
30633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" ANY 32BIT VALUE form");
30643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
30653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      }
30663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
30673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
30683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    case PTP_DTC_UINT32:
30693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" UINT32 data type");
30703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      switch (opd.FormFlag) {
30713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      case PTP_OPFF_Range:
30723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" range: MIN %d, MAX %d, STEP %d",
30733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.MinimumValue.u32,
30743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.MaximumValue.u32,
30753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		       opd.FORM.Range.StepSize.u32);
30763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
30773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      case PTP_OPFF_Enumeration:
30783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		// Special pretty-print for FOURCC codes
30793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		if (params->deviceinfo.ImageFormats[i] == PTP_OPC_VideoFourCCCodec) {
30803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		  printf(" enumeration of u32 casted FOURCC: ");
30813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		  for (k=0;k<opd.FORM.Enum.NumberOfValues;k++) {
30823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		    if (opd.FORM.Enum.SupportedValue[k].u32 == 0) {
30833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		      printf("ANY, ");
30843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		    } else {
30853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		      char fourcc[6];
30863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		      fourcc[0] = (opd.FORM.Enum.SupportedValue[k].u32 >> 24) & 0xFFU;
30873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		      fourcc[1] = (opd.FORM.Enum.SupportedValue[k].u32 >> 16) & 0xFFU;
30883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		      fourcc[2] = (opd.FORM.Enum.SupportedValue[k].u32 >> 8) & 0xFFU;
30893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		      fourcc[3] = opd.FORM.Enum.SupportedValue[k].u32 & 0xFFU;
30903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		      fourcc[4] = '\n';
30913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		      fourcc[5] = '\0';
30923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		      printf("\"%s\", ", fourcc);
30933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		    }
30943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		  }
30953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		} else {
30963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		  printf(" enumeration: ");
30973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		  for(k=0;k<opd.FORM.Enum.NumberOfValues;k++) {
30983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		    printf("%d, ", opd.FORM.Enum.SupportedValue[k].u32);
30993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		  }
31003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		}
31013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
31023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      default:
31033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		printf(" ANY 32BIT VALUE form");
31043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev		break;
31053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      }
31063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
31073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
31083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    case PTP_DTC_INT64:
31093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" INT64 data type");
31103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
31113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
31123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    case PTP_DTC_UINT64:
31133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" UINT64 data type");
31143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
31153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
31163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    case PTP_DTC_INT128:
31173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" INT128 data type");
31183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
31193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
31203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    case PTP_DTC_UINT128:
31213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" UINT128 data type");
31223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
31233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
31243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    default:
31253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      printf(" UNKNOWN data type");
31263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      break;
31273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
31283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
31293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (opd.GetSet) {
31303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    printf(" GET/SET");
31313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  } else {
31323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    printf(" READ ONLY");
31333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
31343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  printf("\n");
31353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  ptp_free_objectpropdesc(&opd);
31363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
31373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	free(props);
31383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
31393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
31403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
31413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
31423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(storage != NULL && ptp_operation_issupported(params,PTP_OC_GetStorageInfo)) {
31433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    printf("Storage Devices:\n");
31443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    while(storage != NULL) {
31453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("   StorageID: 0x%08x\n",storage->id);
31463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("      StorageType: 0x%04x ",storage->StorageType);
31473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      switch (storage->StorageType) {
31483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_ST_Undefined:
31493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("(undefined)\n");
31503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_ST_FixedROM:
31523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("fixed ROM storage\n");
31533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_ST_RemovableROM:
31553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("removable ROM storage\n");
31563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_ST_FixedRAM:
31583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("fixed RAM storage\n");
31593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_ST_RemovableRAM:
31613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("removable RAM storage\n");
31623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      default:
31643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("UNKNOWN storage\n");
31653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
31673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("      FilesystemType: 0x%04x ",storage->FilesystemType);
31683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      switch(storage->FilesystemType) {
31693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_FST_Undefined:
31703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("(undefined)\n");
31713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_FST_GenericFlat:
31733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("generic flat filesystem\n");
31743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_FST_GenericHierarchical:
31763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("generic hierarchical\n");
31773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_FST_DCF:
31793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("DCF\n");
31803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      default:
31823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("UNKNONWN filesystem type\n");
31833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
31853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("      AccessCapability: 0x%04x ",storage->AccessCapability);
31863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      switch(storage->AccessCapability) {
31873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_AC_ReadWrite:
31883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("read/write\n");
31893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_AC_ReadOnly:
31913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("read only\n");
31923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_AC_ReadOnly_with_Object_Deletion:
31943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("read only + object deletion\n");
31953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      default:
31973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	printf("UNKNOWN access capability\n");
31983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
31993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
32003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("      MaxCapacity: %llu\n", (long long unsigned int) storage->MaxCapacity);
32013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("      FreeSpaceInBytes: %llu\n", (long long unsigned int) storage->FreeSpaceInBytes);
32023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("      FreeSpaceInObjects: %llu\n", (long long unsigned int) storage->FreeSpaceInObjects);
32033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("      StorageDescription: %s\n",storage->StorageDescription);
32043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("      VolumeIdentifier: %s\n",storage->VolumeIdentifier);
32053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage = storage->next;
32063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
32073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
32083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
32093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("Special directories:\n");
32103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Default music folder: 0x%08x\n", device->default_music_folder);
32113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Default playlist folder: 0x%08x\n", device->default_playlist_folder);
32123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Default picture folder: 0x%08x\n", device->default_picture_folder);
32133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Default video folder: 0x%08x\n", device->default_video_folder);
32143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Default organizer folder: 0x%08x\n", device->default_organizer_folder);
32153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Default zencast folder: 0x%08x\n", device->default_zencast_folder);
32163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Default album folder: 0x%08x\n", device->default_album_folder);
32173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("   Default text folder: 0x%08x\n", device->default_text_folder);
32183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
32193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
32203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
32213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This resets a device in case it supports the <code>PTP_OC_ResetDevice</code>
32223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * operation code (0x1010).
32233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to reset.
32243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
32253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
32263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Reset_Device(LIBMTP_mtpdevice_t *device)
32273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
32283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
32293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
32303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
32313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!ptp_operation_issupported(params,PTP_OC_ResetDevice)) {
32323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
32333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "LIBMTP_Reset_Device(): device does not support resetting.");
32343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
32353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
32363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_resetdevice(params);
32373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
32383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "Error resetting.");
32393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
32403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
32413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
32423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
32433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
32443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
32453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This retrieves the manufacturer name of an MTP device.
32463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the manufacturer name for.
32473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a newly allocated UTF-8 string representing the manufacturer name.
32483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         The string must be freed by the caller after use. If the call
32493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         was unsuccessful this will contain NULL.
32503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
32513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevchar *LIBMTP_Get_Manufacturername(LIBMTP_mtpdevice_t *device)
32523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
32533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  char *retmanuf = NULL;
32543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
32553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
32563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->deviceinfo.Manufacturer != NULL) {
32573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retmanuf = strdup(params->deviceinfo.Manufacturer);
32583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
32593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retmanuf;
32603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
32613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
32623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
32633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This retrieves the model name (often equal to product name)
32643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * of an MTP device.
32653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the model name for.
32663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a newly allocated UTF-8 string representing the model name.
32673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         The string must be freed by the caller after use. If the call
32683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         was unsuccessful this will contain NULL.
32693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
32703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevchar *LIBMTP_Get_Modelname(LIBMTP_mtpdevice_t *device)
32713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
32723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  char *retmodel = NULL;
32733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
32743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
32753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->deviceinfo.Model != NULL) {
32763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retmodel = strdup(params->deviceinfo.Model);
32773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
32783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retmodel;
32793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
32803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
32813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
32823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This retrieves the serial number of an MTP device.
32833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the serial number for.
32843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a newly allocated UTF-8 string representing the serial number.
32853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         The string must be freed by the caller after use. If the call
32863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         was unsuccessful this will contain NULL.
32873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
32883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevchar *LIBMTP_Get_Serialnumber(LIBMTP_mtpdevice_t *device)
32893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
32903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  char *retnumber = NULL;
32913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
32923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
32933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->deviceinfo.SerialNumber != NULL) {
32943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retnumber = strdup(params->deviceinfo.SerialNumber);
32953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
32963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retnumber;
32973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
32983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
32993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
33003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This retrieves the device version (hardware and firmware version) of an
33013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * MTP device.
33023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the device version for.
33033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a newly allocated UTF-8 string representing the device version.
33043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         The string must be freed by the caller after use. If the call
33053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         was unsuccessful this will contain NULL.
33063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
33073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevchar *LIBMTP_Get_Deviceversion(LIBMTP_mtpdevice_t *device)
33083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
33093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  char *retversion = NULL;
33103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
33113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
33123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->deviceinfo.DeviceVersion != NULL) {
33133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retversion = strdup(params->deviceinfo.DeviceVersion);
33143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
33153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retversion;
33163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
33173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
33183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
33193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
33203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This retrieves the "friendly name" of an MTP device. Usually
33213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * this is simply the name of the owner or something like
33223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * "John Doe's Digital Audio Player". This property should be supported
33233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * by all MTP devices.
33243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the friendly name for.
33253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a newly allocated UTF-8 string representing the friendly name.
33263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         The string must be freed by the caller after use.
33273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Set_Friendlyname()
33283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
33293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevchar *LIBMTP_Get_Friendlyname(LIBMTP_mtpdevice_t *device)
33303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
33313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
33323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  char *retstring = NULL;
33333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
33343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
33353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
33363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!ptp_property_issupported(params, PTP_DPC_MTP_DeviceFriendlyName)) {
33373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
33383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
33393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
33403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_getdevicepropvalue(params,
33413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       PTP_DPC_MTP_DeviceFriendlyName,
33423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       &propval,
33433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       PTP_DTC_STR);
33443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
33453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "Error getting friendlyname.");
33463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
33473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
33483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (propval.str != NULL) {
33493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retstring = strdup(propval.str);
33503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(propval.str);
33513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
33523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retstring;
33533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
33543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
33553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
33563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Sets the "friendly name" of an MTP device.
33573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to set the friendly name for.
33583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param friendlyname the new friendly name for the device.
33593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
33603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Friendlyname()
33613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
33623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Set_Friendlyname(LIBMTP_mtpdevice_t *device,
33633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 char const * const friendlyname)
33643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
33653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
33663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
33673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
33683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
33693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!ptp_property_issupported(params, PTP_DPC_MTP_DeviceFriendlyName)) {
33703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
33713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
33723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  propval.str = (char *) friendlyname;
33733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_setdevicepropvalue(params,
33743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       PTP_DPC_MTP_DeviceFriendlyName,
33753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       &propval,
33763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       PTP_DTC_STR);
33773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
33783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "Error setting friendlyname.");
33793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
33803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
33813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
33823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
33833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
33843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
33853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This retrieves the syncronization partner of an MTP device. This
33863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * property should be supported by all MTP devices.
33873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the sync partner for.
33883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a newly allocated UTF-8 string representing the synchronization
33893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         partner. The string must be freed by the caller after use.
33903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Set_Syncpartner()
33913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
33923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevchar *LIBMTP_Get_Syncpartner(LIBMTP_mtpdevice_t *device)
33933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
33943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
33953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  char *retstring = NULL;
33963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
33973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
33983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
33993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!ptp_property_issupported(params, PTP_DPC_MTP_SynchronizationPartner)) {
34003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
34013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
34023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
34033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_getdevicepropvalue(params,
34043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       PTP_DPC_MTP_SynchronizationPartner,
34053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       &propval,
34063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       PTP_DTC_STR);
34073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
34083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "Error getting syncpartner.");
34093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
34103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
34113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (propval.str != NULL) {
34123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retstring = strdup(propval.str);
34133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(propval.str);
34143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
34153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retstring;
34163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
34173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
34183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
34193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
34203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Sets the synchronization partner of an MTP device. Note that
34213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * we have no idea what the effect of setting this to "foobar"
34223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * may be. But the general idea seems to be to tell which program
34233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * shall synchronize with this device and tell others to leave
34243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * it alone.
34253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to set the sync partner for.
34263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param syncpartner the new synchronization partner for the device.
34273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
34283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Syncpartner()
34293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
34303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Set_Syncpartner(LIBMTP_mtpdevice_t *device,
34313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 char const * const syncpartner)
34323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
34333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
34343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
34353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
34363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
34373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!ptp_property_issupported(params, PTP_DPC_MTP_SynchronizationPartner)) {
34383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
34393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
34403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  propval.str = (char *) syncpartner;
34413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_setdevicepropvalue(params,
34423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       PTP_DPC_MTP_SynchronizationPartner,
34433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       &propval,
34443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       PTP_DTC_STR);
34453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
34463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "Error setting syncpartner.");
34473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
34483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
34493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
34503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
34513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
34523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
34533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Checks if the device can stora a file of this size or
34543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * if it's too big.
34553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device.
34563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param filesize the size of the file to check whether it will fit.
34573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param storageid the ID of the storage to try to fit the file on.
34583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the file fits, any other value means failure.
34593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
34603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int check_if_file_fits(LIBMTP_mtpdevice_t *device,
34613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      LIBMTP_devicestorage_t *storage,
34623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      uint64_t const filesize) {
34633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
34643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint64_t freebytes;
34653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int ret;
34663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
34673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // If we cannot check the storage, no big deal.
34683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!ptp_operation_issupported(params,PTP_OC_GetStorageInfo)) {
34693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 0;
34703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
34713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
34723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = get_storage_freespace(device, storage, &freebytes);
34733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != 0) {
34743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
34753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "check_if_file_fits(): error checking free storage.");
34763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
34773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
34783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // See if it fits.
34793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (filesize > freebytes) {
34803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return -1;
34813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
34823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
34833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
34843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
34853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
34863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
34873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
34883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function retrieves the current battery level on the device.
34893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the battery level for.
34903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param maximum_level a pointer to a variable that will hold the
34913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        maximum level of the battery if the call was successful.
34923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param current_level a pointer to a variable that will hold the
34933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        current level of the battery if the call was successful.
34943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        A value of 0 means that the device is on external power.
34953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the storage info was successfully retrieved, any other
34963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        means failure. A typical cause of failure is that
34973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        the device does not support the battery level property.
34983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
34993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Get_Batterylevel(LIBMTP_mtpdevice_t *device,
35003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    uint8_t * const maximum_level,
35013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    uint8_t * const current_level)
35023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
35033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
35043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
35053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
35063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
35073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
35083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  *maximum_level = 0;
35093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  *current_level = 0;
35103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
35113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (FLAG_BROKEN_BATTERY_LEVEL(ptp_usb) ||
35123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      !ptp_property_issupported(params, PTP_DPC_BatteryLevel)) {
35133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
35143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
35153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
35163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_getdevicepropvalue(params, PTP_DPC_BatteryLevel, &propval, PTP_DTC_UINT8);
35173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
35183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Batterylevel(): could not get device property value.");
35193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
35203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
35213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
35223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  *maximum_level = device->maximum_battery_level;
35233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  *current_level = propval.u8;
35243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
35253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
35263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
35273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
35283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
35293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
35303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Formats device storage (if the device supports the operation).
35313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * WARNING: This WILL delete all data from the device. Make sure you've
35323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * got confirmation from the user BEFORE you call this function.
35333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
35343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device containing the storage to format.
35353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param storage the actual storage to format.
35363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
35373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
35383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Format_Storage(LIBMTP_mtpdevice_t *device, LIBMTP_devicestorage_t *storage)
35393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
35403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
35413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
35423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
35433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!ptp_operation_issupported(params,PTP_OC_FormatStore)) {
35443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
35453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "LIBMTP_Format_Storage(): device does not support formatting storage.");
35463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
35473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
35483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_formatstore(params, storage->id);
35493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
35503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Format_Storage(): failed to format storage.");
35513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
35523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
35533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
35543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
35553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
35563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
35573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Helper function to extract a unicode property off a device.
35583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This is the standard way of retrieveing unicode device
35593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * properties as described by the PTP spec.
35603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the property from.
35613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param unicstring a pointer to a pointer that will hold the
35623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        property after this call is completed.
35633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param property the property to retrieve.
35643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
35653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
35663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int get_device_unicode_property(LIBMTP_mtpdevice_t *device,
35673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				       char **unicstring, uint16_t property)
35683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
35693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
35703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
35713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t *tmp;
35723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
35733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int i;
35743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
35753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!ptp_property_issupported(params, property)) {
35763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
35773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
35783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
35793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Unicode strings are 16bit unsigned integer arrays.
35803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_getdevicepropvalue(params,
35813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       property,
35823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       &propval,
35833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       PTP_DTC_AUINT16);
35843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
35853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // TODO: add a note on WHICH property that we failed to get.
35863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    *unicstring = NULL;
35873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "get_device_unicode_property(): failed to get unicode property.");
35883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
35893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
35903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
35913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Extract the actual array.
35923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // printf("Array of %d elements\n", propval.a.count);
35933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  tmp = malloc((propval.a.count + 1)*sizeof(uint16_t));
35943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i = 0; i < propval.a.count; i++) {
35953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    tmp[i] = propval.a.v[i].u16;
35963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // printf("%04x ", tmp[i]);
35973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
35983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  tmp[propval.a.count] = 0x0000U;
35993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(propval.a.v);
36003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
36013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  *unicstring = utf16_to_utf8(device, tmp);
36023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
36033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(tmp);
36043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
36053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
36063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
36073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
36083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
36093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function returns the secure time as an XML document string from
36103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * the device.
36113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the secure time for.
36123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param sectime the secure time string as an XML document or NULL if the call
36133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         failed or the secure time property is not supported. This string
36143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         must be <code>free()</code>:ed by the caller after use.
36153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
36163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
36173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Get_Secure_Time(LIBMTP_mtpdevice_t *device, char ** const sectime)
36183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
36193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return get_device_unicode_property(device, sectime, PTP_DPC_MTP_SecureTime);
36203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
36213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
36223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
36233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function returns the device (public key) certificate as an
36243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * XML document string from the device.
36253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the device certificate for.
36263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param devcert the device certificate as an XML string or NULL if the call
36273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        failed or the device certificate property is not supported. This
36283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        string must be <code>free()</code>:ed by the caller after use.
36293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
36303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
36313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Get_Device_Certificate(LIBMTP_mtpdevice_t *device, char ** const devcert)
36323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
36333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return get_device_unicode_property(device, devcert, PTP_DPC_MTP_DeviceCertificate);
36343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
36353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
36363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
36373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function retrieves a list of supported file types, i.e. the file
36383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * types that this device claims it supports, e.g. audio file types that
36393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * the device can play etc. This list is mitigated to
36403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * inlcude the file types that libmtp can handle, i.e. it will not list
36413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * filetypes that libmtp will handle internally like playlists and folders.
36423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the filetype capabilities for.
36433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param filetypes a pointer to a pointer that will hold the list of
36443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        supported filetypes if the call was successful. This list must
36453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        be <code>free()</code>:ed by the caller after use.
36463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param length a pointer to a variable that will hold the length of the
36473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        list of supported filetypes if the call was successful.
36483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
36493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Filetype_Description()
36503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
36513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Get_Supported_Filetypes(LIBMTP_mtpdevice_t *device, uint16_t ** const filetypes,
36523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  uint16_t * const length)
36533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
36543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
36553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
36563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t *localtypes;
36573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t localtypelen;
36583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t i;
36593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
36603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // This is more memory than needed if there are unknown types, but what the heck.
36613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  localtypes = (uint16_t *) malloc(params->deviceinfo.ImageFormats_len * sizeof(uint16_t));
36623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  localtypelen = 0;
36633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
36643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i=0;i<params->deviceinfo.ImageFormats_len;i++) {
36653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    uint16_t localtype = map_ptp_type_to_libmtp_type(params->deviceinfo.ImageFormats[i]);
36663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (localtype != LIBMTP_FILETYPE_UNKNOWN) {
36673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      localtypes[localtypelen] = localtype;
36683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      localtypelen++;
36693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
36703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
36713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // The forgotten Ogg support on YP-10 and others...
36723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (FLAG_OGG_IS_UNKNOWN(ptp_usb)) {
36733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    localtypes = (uint16_t *) realloc(localtypes, (params->deviceinfo.ImageFormats_len+1) * sizeof(uint16_t));
36743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    localtypes[localtypelen] = LIBMTP_FILETYPE_OGG;
36753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    localtypelen++;
36763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
36773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // The forgotten FLAC support on Cowon iAudio S9 and others...
36783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (FLAG_FLAC_IS_UNKNOWN(ptp_usb)) {
36793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    localtypes = (uint16_t *) realloc(localtypes, (params->deviceinfo.ImageFormats_len+1) * sizeof(uint16_t));
36803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    localtypes[localtypelen] = LIBMTP_FILETYPE_FLAC;
36813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    localtypelen++;
36823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
36833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
36843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  *filetypes = localtypes;
36853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  *length = localtypelen;
36863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
36873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
36883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
36893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
36903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
36913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function updates all the storage id's of a device and their
36923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * properties, then creates a linked list and puts the list head into
36933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * the device struct. It also optionally sorts this list. If you want
36943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * to display storage information in your application you should call
36953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * this function, then dereference the device struct
36963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * (<code>device-&gt;storage</code>) to get out information on the storage.
36973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
36983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * You need to call this everytime you want to update the
36993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <code>device-&gt;storage</code> list, for example anytime you need
37003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * to check available storage somewhere.
37013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
37023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <b>WARNING:</b> since this list is dynamically updated, do not
37033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * reference its fields in external applications by pointer! E.g
37043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * do not put a reference to any <code>char *</code> field. instead
37053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <code>strncpy()</code> it!
37063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
37073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the storage for.
37083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param sortby an integer that determines the sorting of the storage list.
37093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        Valid sort methods are defined in libmtp.h with beginning with
37103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        LIBMTP_STORAGE_SORTBY_. 0 or LIBMTP_STORAGE_SORTBY_NOTSORTED to not
37113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        sort.
37123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, 1 success but only with storage id's, storage
37133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        properities could not be retrieved and -1 means failure.
37143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
37153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Get_Storage(LIBMTP_mtpdevice_t *device, int const sortby)
37163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
37173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t i = 0;
37183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPStorageInfo storageInfo;
37193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
37203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPStorageIDs storageIDs;
37213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_devicestorage_t *storage = NULL;
37223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_devicestorage_t *storageprev = NULL;
37233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
37243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (device->storage != NULL)
37253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free_storage_list(device);
37263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
37273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // if (!ptp_operation_issupported(params,PTP_OC_GetStorageIDs))
37283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  //   return -1;
37293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ptp_getstorageids (params, &storageIDs) != PTP_RC_OK)
37303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
37313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (storageIDs.n < 1)
37323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
37333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
37343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!ptp_operation_issupported(params,PTP_OC_GetStorageInfo)) {
37353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i = 0; i < storageIDs.n; i++) {
37363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
37373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage = (LIBMTP_devicestorage_t *) malloc(sizeof(LIBMTP_devicestorage_t));
37383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->prev = storageprev;
37393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (storageprev != NULL)
37403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        storageprev->next = storage;
37413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (device->storage == NULL)
37423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        device->storage = storage;
37433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
37443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->id = storageIDs.Storage[i];
37453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->StorageType = PTP_ST_Undefined;
37463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->FilesystemType = PTP_FST_Undefined;
37473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->AccessCapability = PTP_AC_ReadWrite;
37483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->MaxCapacity = (uint64_t) -1;
37493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->FreeSpaceInBytes = (uint64_t) -1;
37503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->FreeSpaceInObjects = (uint64_t) -1;
37513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->StorageDescription = strdup("Unknown storage");
37523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->VolumeIdentifier = strdup("Unknown volume");
37533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->next = NULL;
37543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
37553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storageprev = storage;
37563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
37573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(storageIDs.Storage);
37583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 1;
37593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
37603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i = 0; i < storageIDs.n; i++) {
37613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      uint16_t ret;
37623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ret = ptp_getstorageinfo(params, storageIDs.Storage[i], &storageInfo);
37633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret != PTP_RC_OK) {
37643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Storage(): Could not get storage info.");
37653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (device->storage != NULL) {
37663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          free_storage_list(device);
37673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
37683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	return -1;
37693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
37703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
37713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage = (LIBMTP_devicestorage_t *) malloc(sizeof(LIBMTP_devicestorage_t));
37723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->prev = storageprev;
37733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (storageprev != NULL)
37743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        storageprev->next = storage;
37753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (device->storage == NULL)
37763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        device->storage = storage;
37773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
37783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->id = storageIDs.Storage[i];
37793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->StorageType = storageInfo.StorageType;
37803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->FilesystemType = storageInfo.FilesystemType;
37813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->AccessCapability = storageInfo.AccessCapability;
37823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->MaxCapacity = storageInfo.MaxCapability;
37833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->FreeSpaceInBytes = storageInfo.FreeSpaceInBytes;
37843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->FreeSpaceInObjects = storageInfo.FreeSpaceInImages;
37853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->StorageDescription = storageInfo.StorageDescription;
37863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->VolumeIdentifier = storageInfo.VolumeLabel;
37873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->next = NULL;
37883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
37893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storageprev = storage;
37903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
37913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
37923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (storage != NULL)
37933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      storage->next = NULL;
37943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
37953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    sort_storage_by(device,sortby);
37963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(storageIDs.Storage);
37973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 0;
37983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
37993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
38003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
38013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
38023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This creates a new file metadata structure and allocates memory
38033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * for it. Notice that if you add strings to this structure they
38043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * will be freed by the corresponding <code>LIBMTP_destroy_file_t</code>
38053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * operation later, so be careful of using strdup() when assigning
38063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * strings, e.g.:
38073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
38083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <pre>
38093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * LIBMTP_file_t *file = LIBMTP_new_file_t();
38103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * file->filename = strdup(namestr);
38113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * ....
38123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * LIBMTP_destroy_file_t(file);
38133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * </pre>
38143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
38153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a pointer to the newly allocated metadata structure.
38163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_destroy_file_t()
38173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
38183aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_file_t *LIBMTP_new_file_t(void)
38193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
38203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_file_t *new = (LIBMTP_file_t *) malloc(sizeof(LIBMTP_file_t));
38213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (new == NULL) {
38223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
38233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
38243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->filename = NULL;
38253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->item_id = 0;
38263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->parent_id = 0;
38273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->storage_id = 0;
38283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->filesize = 0;
38293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->modificationdate = 0;
38303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->filetype = LIBMTP_FILETYPE_UNKNOWN;
38313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->next = NULL;
38323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return new;
38333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
38343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
38353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
38363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This destroys a file metadata structure and deallocates the memory
38373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * used by it, including any strings. Never use a file metadata
38383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * structure again after calling this function on it.
38393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param file the file metadata to destroy.
38403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_new_file_t()
38413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
38423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_destroy_file_t(LIBMTP_file_t *file)
38433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
38443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (file == NULL) {
38453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return;
38463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
38473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (file->filename != NULL)
38483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(file->filename);
38493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(file);
38503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return;
38513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
38523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
38533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
38543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev* THIS FUNCTION IS DEPRECATED. PLEASE UPDATE YOUR CODE IN ORDER
38553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * NOT TO USE IT.
38563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Filelisting_With_Callback()
38573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
38583aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_file_t *LIBMTP_Get_Filelisting(LIBMTP_mtpdevice_t *device)
38593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
38603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("WARNING: LIBMTP_Get_Filelisting() is deprecated.\n");
38613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("WARNING: please update your code to use LIBMTP_Get_Filelisting_With_Callback()\n");
38623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return LIBMTP_Get_Filelisting_With_Callback(device, NULL, NULL);
38633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
38643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
38653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
38663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This returns a long list of all files available
38673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * on the current MTP device. Folders will not be returned, but abstract
38683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * entities like playlists and albums will show up as "files". Typical usage:
38693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
38703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <pre>
38713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * LIBMTP_file_t *filelist;
38723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
38733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * filelist = LIBMTP_Get_Filelisting_With_Callback(device, callback, data);
38743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * while (filelist != NULL) {
38753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *   LIBMTP_file_t *tmp;
38763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
38773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *   // Do something on each element in the list here...
38783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *   tmp = filelist;
38793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *   filelist = filelist->next;
38803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *   LIBMTP_destroy_file_t(tmp);
38813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * }
38823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * </pre>
38833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
38843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * If you want to group your file listing by storage (per storage unit) or
38853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * arrange files into folders, you must dereference the <code>storage_id</code>
38863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * and/or <code>parent_id</code> field of the returned <code>LIBMTP_file_t</code>
38873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * struct. To arrange by folders or files you typically have to create the proper
38883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * trees by calls to <code>LIBMTP_Get_Storage()</code> and/or
38893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <code>LIBMTP_Get_Folder_List()</code> first.
38903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
38913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the file listing for.
38923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param callback a function to be called during the tracklisting retrieveal
38933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        for displaying progress bars etc, or NULL if you don't want
38943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        any callbacks.
38953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param data a user-defined pointer that is passed along to
38963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        the <code>progress</code> function in order to
38973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        pass along some user defined data to the progress
38983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        updates. If not used, set this to NULL.
38993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a list of files that can be followed using the <code>next</code>
39003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        field of the <code>LIBMTP_file_t</code> data structure.
39013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        Each of the metadata tags must be freed after use, and may
39023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        contain only partial metadata information, i.e. one or several
39033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        fields may be NULL or 0.
39043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Filemetadata()
39053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
39063aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_file_t *LIBMTP_Get_Filelisting_With_Callback(LIBMTP_mtpdevice_t *device,
39073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                                    LIBMTP_progressfunc_t const callback,
39083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                                    void const * const data)
39093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
39103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t i = 0;
39113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_file_t *retfiles = NULL;
39123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_file_t *curfile = NULL;
39133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
39143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
39153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
39163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
39173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Get all the handles if we haven't already done that
39183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->nrofobjects == 0) {
39193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    flush_handles(device);
39203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
39213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
39223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i = 0; i < params->nrofobjects; i++) {
39233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_file_t *file;
39243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTPObject *ob, *xob;
39253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
39263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (callback != NULL)
39273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      callback(i, params->nrofobjects, data);
39283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
39293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ob = &params->objects[i];
39303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
39313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ob->oi.ObjectFormat == PTP_OFC_Association) {
39323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // MTP use this object format for folders which means
39333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // these "files" will turn up on a folder listing instead.
39343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      continue;
39353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
39363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
39373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Allocate a new file type
39383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    file = LIBMTP_new_file_t();
39393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
39403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    file->parent_id = ob->oi.ParentObject;
39413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    file->storage_id = ob->oi.StorageID;
39423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
39433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // This is some sort of unique ID so we can keep track of the track.
39443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    file->item_id = ob->oid;
39453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
39463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Set the filetype
39473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    file->filetype = map_ptp_type_to_libmtp_type(ob->oi.ObjectFormat);
39483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
39493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Set the modification date
39503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    file->modificationdate = ob->oi.ModificationDate;
39513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
39523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Original file-specific properties
39533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // We only have 32-bit file size here; if we find it, we use the
39543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // PTP_OPC_ObjectSize property which has 64bit precision.
39553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    file->filesize = ob->oi.ObjectCompressedSize;
39563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ob->oi.Filename != NULL) {
39573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      file->filename = strdup(ob->oi.Filename);
39583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
39593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
39603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /*
39613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * A special quirk for devices that doesn't quite
39623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * remember that some files marked as "unknown" type are
39633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * actually OGG or FLAC files. We look at the filename extension
39643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * and see if it happens that this was atleast named "ogg" or "flac"
39653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * and fall back on this heuristic approach in that case,
39663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * for these bugged devices only.
39673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     */
39683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (file->filetype == LIBMTP_FILETYPE_UNKNOWN) {
39693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if ((FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) ||
39703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	   FLAG_OGG_IS_UNKNOWN(ptp_usb)) &&
39713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  has_ogg_extension(file->filename))
39723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	file->filetype = LIBMTP_FILETYPE_OGG;
39733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (FLAG_FLAC_IS_UNKNOWN(ptp_usb) &&
39743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  has_flac_extension(file->filename))
39753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	file->filetype = LIBMTP_FILETYPE_FLAC;
39763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
39773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
39783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /*
39793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * If we have a cached, large set of metadata, then use it!
39803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     */
39813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_object_want (params, ob->oid, PTPOBJECT_MTPPROPLIST_LOADED, &xob);
39823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ob->mtpprops) {
39833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      MTPProperties *prop = ob->mtpprops;
39843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      int i;
39853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
39863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      for (i=0;i<ob->nrofmtpprops;i++) {
39873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// Pick ObjectSize here...
39883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (prop->property == PTP_OPC_ObjectSize) {
39893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (device->object_bitsize == 64) {
39903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    file->filesize = prop->propval.u64;
39913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  } else {
39923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    file->filesize = prop->propval.u32;
39933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
39943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
39953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
39963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	prop++;
39973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
39983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
39993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      uint16_t *props = NULL;
40003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      uint32_t propcnt = 0;
40013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
40023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // First see which properties can be retrieved for this object format
40033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ret = ptp_mtp_getobjectpropssupported(params, ob->oi.ObjectFormat, &propcnt, &props);
40043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret != PTP_RC_OK) {
40053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Filelisting_With_Callback(): call to ptp_mtp_getobjectpropssupported() failed.");
40063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// Silently fall through.
40073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      } else {
40083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        int i;
40093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	for (i=0;i<propcnt;i++) {
40103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  switch (props[i]) {
40113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  case PTP_OPC_ObjectSize:
40123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (device->object_bitsize == 64) {
40133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      file->filesize = get_u64_from_object(device, file->item_id, PTP_OPC_ObjectSize, 0);
40143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    } else {
40153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      file->filesize = get_u32_from_object(device, file->item_id, PTP_OPC_ObjectSize, 0);
40163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
40173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    break;
40183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  default:
40193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    break;
40203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
40213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
40223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	free(props);
40233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
40243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
40253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
40263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Add track to a list that will be returned afterwards.
40273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (retfiles == NULL) {
40283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      retfiles = file;
40293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curfile = file;
40303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
40313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curfile->next = file;
40323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curfile = file;
40333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
40343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
40353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Call listing callback
40363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // double progressPercent = (double)i*(double)100.0 / (double)params->handles.n;
40373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
40383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } // Handle counting loop
40393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retfiles;
40403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
40413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
40423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
40433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function retrieves the metadata for a single file off
40443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * the device.
40453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
40463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Do not call this function repeatedly! The file handles are linearly
40473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * searched O(n) and the call may involve (slow) USB traffic, so use
40483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <code>LIBMTP_Get_Filelisting()</code> and cache the file, preferably
40493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * as an efficient data structure such as a hash list.
40503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
40513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Incidentally this function will return metadata for
40523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * a folder (association) as well, but this is not a proper use
40533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * of it, it is intended for file manipulation, not folder manipulation.
40543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
40553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the file metadata from.
40563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param fileid the object ID of the file that you want the metadata for.
40573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a metadata entry on success or NULL on failure.
40583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Filelisting()
40593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
40603aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_file_t *LIBMTP_Get_Filemetadata(LIBMTP_mtpdevice_t *device, uint32_t const fileid)
40613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
40623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t i = 0;
40633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
40643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
40653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObject *ob;
40663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_file_t *file;
40673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
40683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Get all the handles if we haven't already done that
40693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->nrofobjects == 0) {
40703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    flush_handles(device);
40713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
40723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
40733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_object_want (params, fileid, PTPOBJECT_OBJECTINFO_LOADED|PTPOBJECT_MTPPROPLIST_LOADED, &ob);
40743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK)
40753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
40763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
40773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Allocate a new file type
40783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file = LIBMTP_new_file_t();
40793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
40803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file->parent_id = ob->oi.ParentObject;
40813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file->storage_id = ob->oi.StorageID;
40823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
40833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Set the filetype
40843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file->filetype = map_ptp_type_to_libmtp_type(ob->oi.ObjectFormat);
40853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
40863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Original file-specific properties
40873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
40883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // We only have 32-bit file size here; later we use the PTP_OPC_ObjectSize property
40893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file->filesize = ob->oi.ObjectCompressedSize;
40903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ob->oi.Filename != NULL) {
40913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    file->filename = strdup(ob->oi.Filename);
40923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
40933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
40943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // This is some sort of unique ID so we can keep track of the file.
40953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file->item_id = fileid;
40963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
40973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
40983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * If we have a cached, large set of metadata, then use it!
40993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   */
41003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ob->mtpprops) {
41013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    MTPProperties *prop = ob->mtpprops;
41023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
41033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i=0;i<ob->nrofmtpprops;i++,prop++) {
41043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Pick ObjectSize here...
41053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (prop->property == PTP_OPC_ObjectSize) {
41063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// This may already be set, but this 64bit precision value
41073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// is better than the PTP 32bit value, so let it override.
41083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (device->object_bitsize == 64) {
41093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  file->filesize = prop->propval.u64;
41103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	} else {
41113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  file->filesize = prop->propval.u32;
41123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
41133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
41143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
41153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
41163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
41173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    uint16_t *props = NULL;
41183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    uint32_t propcnt = 0;
41193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
41203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // First see which properties can be retrieved for this object format
41213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_mtp_getobjectpropssupported(params, map_libmtp_type_to_ptp_type(file->filetype), &propcnt, &props);
41223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
41233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Filemetadata(): call to ptp_mtp_getobjectpropssupported() failed.");
41243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Silently fall through.
41253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
41263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      for (i=0;i<propcnt;i++) {
41273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	switch (props[i]) {
41283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_ObjectSize:
41293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (device->object_bitsize == 64) {
41303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    file->filesize = get_u64_from_object(device, file->item_id, PTP_OPC_ObjectSize, 0);
41313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  } else {
41323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    file->filesize = get_u32_from_object(device, file->item_id, PTP_OPC_ObjectSize, 0);
41333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
41343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
41353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	default:
41363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
41373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
41383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
41393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      free(props);
41403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
41413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
41423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
41433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return file;
41443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
41453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
41463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
41473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This creates a new track metadata structure and allocates memory
41483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * for it. Notice that if you add strings to this structure they
41493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * will be freed by the corresponding <code>LIBMTP_destroy_track_t</code>
41503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * operation later, so be careful of using strdup() when assigning
41513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * strings, e.g.:
41523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
41533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <pre>
41543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * LIBMTP_track_t *track = LIBMTP_new_track_t();
41553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * track->title = strdup(titlestr);
41563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * ....
41573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * LIBMTP_destroy_track_t(track);
41583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * </pre>
41593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
41603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a pointer to the newly allocated metadata structure.
41613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_destroy_track_t()
41623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
41633aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_track_t *LIBMTP_new_track_t(void)
41643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
41653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_track_t *new = (LIBMTP_track_t *) malloc(sizeof(LIBMTP_track_t));
41663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (new == NULL) {
41673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
41683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
41693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->item_id = 0;
41703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->parent_id = 0;
41713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->storage_id = 0;
41723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->title = NULL;
41733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->artist = NULL;
41743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->composer = NULL;
41753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->album = NULL;
41763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->genre = NULL;
41773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->date = NULL;
41783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->filename = NULL;
41793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->duration = 0;
41803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->tracknumber = 0;
41813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->filesize = 0;
41823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->filetype = LIBMTP_FILETYPE_UNKNOWN;
41833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->samplerate = 0;
41843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->nochannels = 0;
41853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->wavecodec = 0;
41863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->bitrate = 0;
41873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->bitratetype = 0;
41883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->rating = 0;
41893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->usecount = 0;
41903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->modificationdate = 0;
41913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->next = NULL;
41923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return new;
41933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
41943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
41953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
41963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This destroys a track metadata structure and deallocates the memory
41973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * used by it, including any strings. Never use a track metadata
41983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * structure again after calling this function on it.
41993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param track the track metadata to destroy.
42003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_new_track_t()
42013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
42023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_destroy_track_t(LIBMTP_track_t *track)
42033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
42043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (track == NULL) {
42053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return;
42063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
42073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (track->title != NULL)
42083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(track->title);
42093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (track->artist != NULL)
42103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(track->artist);
42113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (track->composer != NULL)
42123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(track->composer);
42133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (track->album != NULL)
42143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(track->album);
42153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (track->genre != NULL)
42163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(track->genre);
42173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (track->date != NULL)
42183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(track->date);
42193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (track->filename != NULL)
42203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(track->filename);
42213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(track);
42223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return;
42233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
42243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
42253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
42263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function maps and copies a property onto the track metadata if applicable.
42273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
42283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void pick_property_to_track_metadata(LIBMTP_mtpdevice_t *device, MTPProperties *prop, LIBMTP_track_t *track)
42293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
42303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  switch (prop->property) {
42313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_Name:
42323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (prop->propval.str != NULL)
42333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->title = strdup(prop->propval.str);
42343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else
42353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->title = NULL;
42363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_Artist:
42383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (prop->propval.str != NULL)
42393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->artist = strdup(prop->propval.str);
42403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else
42413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->artist = NULL;
42423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_Composer:
42443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (prop->propval.str != NULL)
42453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->composer = strdup(prop->propval.str);
42463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else
42473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->composer = NULL;
42483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_Duration:
42503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->duration = prop->propval.u32;
42513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_Track:
42533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->tracknumber = prop->propval.u16;
42543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_Genre:
42563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (prop->propval.str != NULL)
42573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->genre = strdup(prop->propval.str);
42583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else
42593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->genre = NULL;
42603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_AlbumName:
42623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (prop->propval.str != NULL)
42633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->album = strdup(prop->propval.str);
42643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else
42653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->album = NULL;
42663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_OriginalReleaseDate:
42683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (prop->propval.str != NULL)
42693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->date = strdup(prop->propval.str);
42703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else
42713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->date = NULL;
42723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // These are, well not so important.
42743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_SampleRate:
42753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->samplerate = prop->propval.u32;
42763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_NumberOfChannels:
42783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->nochannels = prop->propval.u16;
42793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_AudioWAVECodec:
42813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->wavecodec = prop->propval.u32;
42823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_AudioBitRate:
42843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->bitrate = prop->propval.u32;
42853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_BitRateType:
42873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->bitratetype = prop->propval.u16;
42883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_Rating:
42903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->rating = prop->propval.u16;
42913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_UseCount:
42933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->usecount = prop->propval.u32;
42943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
42953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_ObjectSize:
42963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (device->object_bitsize == 64) {
42973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->filesize = prop->propval.u64;
42983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
42993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->filesize = prop->propval.u32;
43003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
43013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
43023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  default:
43033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
43043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
43053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
43063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
43073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
43083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function retrieves the track metadata for a track
43093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * given by a unique ID.
43103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the track metadata off.
43113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param trackid the unique ID of the track.
43123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param objectformat the object format of this track, so we know what it supports.
43133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param track a metadata set to fill in.
43143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
43153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void get_track_metadata(LIBMTP_mtpdevice_t *device, uint16_t objectformat,
43163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       LIBMTP_track_t *track)
43173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
43183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
43193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
43203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t i;
43213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  MTPProperties *prop;
43223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObject *ob;
43233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
43243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
43253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * If we have a cached, large set of metadata, then use it!
43263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   */
43273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_object_want(params, track->item_id, PTPOBJECT_MTPPROPLIST_LOADED, &ob);
43283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ob->mtpprops) {
43293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    prop = ob->mtpprops;
43303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i=0;i<ob->nrofmtpprops;i++,prop++)
43313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      pick_property_to_track_metadata(device, prop, track);
43323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
43333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    uint16_t *props = NULL;
43343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    uint32_t propcnt = 0;
43353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
43363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // First see which properties can be retrieved for this object format
43373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_mtp_getobjectpropssupported(params, map_libmtp_type_to_ptp_type(track->filetype), &propcnt, &props);
43383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
43393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_ptp_error_to_errorstack(device, ret, "get_track_metadata(): call to ptp_mtp_getobjectpropssupported() failed.");
43403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Just bail out for now, nothing is ever set.
43413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return;
43423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
43433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      for (i=0;i<propcnt;i++) {
43443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	switch (props[i]) {
43453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Name:
43463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->title = get_string_from_object(device, track->item_id, PTP_OPC_Name);
43473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Artist:
43493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->artist = get_string_from_object(device, track->item_id, PTP_OPC_Artist);
43503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Composer:
43523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->composer = get_string_from_object(device, track->item_id, PTP_OPC_Composer);
43533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Duration:
43553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->duration = get_u32_from_object(device, track->item_id, PTP_OPC_Duration, 0);
43563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Track:
43583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->tracknumber = get_u16_from_object(device, track->item_id, PTP_OPC_Track, 0);
43593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Genre:
43613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->genre = get_string_from_object(device, track->item_id, PTP_OPC_Genre);
43623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_AlbumName:
43643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->album = get_string_from_object(device, track->item_id, PTP_OPC_AlbumName);
43653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_OriginalReleaseDate:
43673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->date = get_string_from_object(device, track->item_id, PTP_OPC_OriginalReleaseDate);
43683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // These are, well not so important.
43703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_SampleRate:
43713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->samplerate = get_u32_from_object(device, track->item_id, PTP_OPC_SampleRate, 0);
43723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_NumberOfChannels:
43743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->nochannels = get_u16_from_object(device, track->item_id, PTP_OPC_NumberOfChannels, 0);
43753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_AudioWAVECodec:
43773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->wavecodec = get_u32_from_object(device, track->item_id, PTP_OPC_AudioWAVECodec, 0);
43783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_AudioBitRate:
43803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->bitrate = get_u32_from_object(device, track->item_id, PTP_OPC_AudioBitRate, 0);
43813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_BitRateType:
43833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->bitratetype = get_u16_from_object(device, track->item_id, PTP_OPC_BitRateType, 0);
43843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Rating:
43863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->rating = get_u16_from_object(device, track->item_id, PTP_OPC_Rating, 0);
43873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_UseCount:
43893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  track->usecount = get_u32_from_object(device, track->item_id, PTP_OPC_UseCount, 0);
43903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_ObjectSize:
43923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (device->object_bitsize == 64) {
43933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    track->filesize = get_u64_from_object(device, track->item_id, PTP_OPC_ObjectSize, 0);
43943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  } else {
43953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    track->filesize = (uint64_t) get_u32_from_object(device, track->item_id, PTP_OPC_ObjectSize, 0);
43963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
43973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
43983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
43993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
44003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      free(props);
44013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
44023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
44033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
44043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
44053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
44063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * THIS FUNCTION IS DEPRECATED. PLEASE UPDATE YOUR CODE IN ORDER
44073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * NOT TO USE IT.
44083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Tracklisting_With_Callback()
44093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
44103aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_track_t *LIBMTP_Get_Tracklisting(LIBMTP_mtpdevice_t *device)
44113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
44123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("WARNING: LIBMTP_Get_Tracklisting() is deprecated.\n");
44133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  printf("WARNING: please update your code to use LIBMTP_Get_Tracklisting_With_Callback()\n");
44143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return LIBMTP_Get_Tracklisting_With_Callback(device, NULL, NULL);
44153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
44163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
44173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
44183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This returns a long list of all tracks available on the current MTP device.
44193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Tracks include multimedia objects, both music tracks and video tracks.
44203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Typical usage:
44213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
44223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <pre>
44233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * LIBMTP_track_t *tracklist;
44243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
44253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * tracklist = LIBMTP_Get_Tracklisting_With_Callback(device, callback, data);
44263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * while (tracklist != NULL) {
44273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *   LIBMTP_track_t *tmp;
44283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
44293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *   // Do something on each element in the list here...
44303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *   tmp = tracklist;
44313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *   tracklist = tracklist->next;
44323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *   LIBMTP_destroy_track_t(tmp);
44333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * }
44343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * </pre>
44353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
44363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * If you want to group your track listing by storage (per storage unit) or
44373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * arrange tracks into folders, you must dereference the <code>storage_id</code>
44383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * and/or <code>parent_id</code> field of the returned <code>LIBMTP_track_t</code>
44393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * struct. To arrange by folders or files you typically have to create the proper
44403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * trees by calls to <code>LIBMTP_Get_Storage()</code> and/or
44413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <code>LIBMTP_Get_Folder_List()</code> first.
44423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
44433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the track listing for.
44443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param callback a function to be called during the tracklisting retrieveal
44453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        for displaying progress bars etc, or NULL if you don't want
44463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        any callbacks.
44473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param data a user-defined pointer that is passed along to
44483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        the <code>progress</code> function in order to
44493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        pass along some user defined data to the progress
44503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        updates. If not used, set this to NULL.
44513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a list of tracks that can be followed using the <code>next</code>
44523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        field of the <code>LIBMTP_track_t</code> data structure.
44533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        Each of the metadata tags must be freed after use, and may
44543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        contain only partial metadata information, i.e. one or several
44553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        fields may be NULL or 0.
44563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Trackmetadata()
44573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
44583aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_track_t *LIBMTP_Get_Tracklisting_With_Callback(LIBMTP_mtpdevice_t *device,
44593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                                      LIBMTP_progressfunc_t const callback,
44603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                                      void const * const data)
44613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
44623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t i = 0;
44633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_track_t *retracks = NULL;
44643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_track_t *curtrack = NULL;
44653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
44663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
44673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
44683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Get all the handles if we haven't already done that
44693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->nrofobjects == 0) {
44703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    flush_handles(device);
44713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
44723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
44733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i = 0; i < params->nrofobjects; i++) {
44743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_track_t *track;
44753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTPObject *ob;
44763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_filetype_t mtptype;
44773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
44783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (callback != NULL)
44793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      callback(i, params->nrofobjects, data);
44803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
44813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ob = &params->objects[i];
44823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    mtptype = map_ptp_type_to_libmtp_type(ob->oi.ObjectFormat);
44833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
44843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Ignore stuff we don't know how to handle...
44853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // TODO: get this list as an intersection of the sets
44863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // supported by the device and the from the device and
44873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // all known track files?
44883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (!LIBMTP_FILETYPE_IS_TRACK(mtptype) &&
44893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// This row lets through undefined files for examination since they may be forgotten OGG files.
44903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	(ob->oi.ObjectFormat != PTP_OFC_Undefined ||
44913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 (!FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) &&
44923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  !FLAG_OGG_IS_UNKNOWN(ptp_usb) &&
44933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  !FLAG_FLAC_IS_UNKNOWN(ptp_usb)))
44943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	) {
44953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      //printf("Not a music track (name: %s format: %d), skipping...\n", oi->Filename, oi->ObjectFormat);
44963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      continue;
44973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
44983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
44993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Allocate a new track type
45003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track = LIBMTP_new_track_t();
45013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
45023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // This is some sort of unique ID so we can keep track of the track.
45033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->item_id = ob->oid;
45043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->parent_id = ob->oi.ParentObject;
45053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->storage_id = ob->oi.StorageID;
45063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->modificationdate = ob->oi.ModificationDate;
45073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
45083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->filetype = mtptype;
45093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
45103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Original file-specific properties
45113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->filesize = ob->oi.ObjectCompressedSize;
45123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ob->oi.Filename != NULL) {
45133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->filename = strdup(ob->oi.Filename);
45143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
45153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
45163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    get_track_metadata(device, ob->oi.ObjectFormat, track);
45173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
45183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /*
45193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * A special quirk for iriver devices that doesn't quite
45203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * remember that some files marked as "unknown" type are
45213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * actually OGG or FLAC files. We look at the filename extension
45223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * and see if it happens that this was atleast named "ogg" or "flac"
45233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * and fall back on this heuristic approach in that case,
45243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * for these bugged devices only.
45253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     */
45263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (track->filetype == LIBMTP_FILETYPE_UNKNOWN &&
45273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	track->filename != NULL) {
45283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if ((FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) ||
45293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	   FLAG_OGG_IS_UNKNOWN(ptp_usb)) &&
45303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  has_ogg_extension(track->filename))
45313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	track->filetype = LIBMTP_FILETYPE_OGG;
45323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      else if (FLAG_FLAC_IS_UNKNOWN(ptp_usb) &&
45333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       has_flac_extension(track->filename))
45343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	track->filetype = LIBMTP_FILETYPE_FLAC;
45353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      else {
45363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// This was not an OGG/FLAC file so discard it and continue
45373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	LIBMTP_destroy_track_t(track);
45383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	continue;
45393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
45403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
45413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
45423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Add track to a list that will be returned afterwards.
45433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (retracks == NULL) {
45443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      retracks = track;
45453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curtrack = track;
45463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
45473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curtrack->next = track;
45483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curtrack = track;
45493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
45503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
45513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Call listing callback
45523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // double progressPercent = (double)i*(double)100.0 / (double)params->handles.n;
45533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
45543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
45553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } // Handle counting loop
45563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retracks;
45573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
45583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
45593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
45603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function retrieves the metadata for a single track off
45613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * the device.
45623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
45633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Do not call this function repeatedly! The track handles are linearly
45643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * searched O(n) and the call may involve (slow) USB traffic, so use
45653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <code>LIBMTP_Get_Tracklisting()</code> and cache the tracks, preferably
45663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * as an efficient data structure such as a hash list.
45673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
45683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the track metadata from.
45693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param trackid the object ID of the track that you want the metadata for.
45703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a track metadata entry on success or NULL on failure.
45713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Tracklisting()
45723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
45733aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_track_t *LIBMTP_Get_Trackmetadata(LIBMTP_mtpdevice_t *device, uint32_t const trackid)
45743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
45753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
45763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
45773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObject *ob;
45783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_track_t *track;
45793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_filetype_t mtptype;
45803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
45813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
45823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Get all the handles if we haven't already done that
45833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->nrofobjects == 0)
45843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    flush_handles(device);
45853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
45863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_object_want (params, trackid, PTPOBJECT_OBJECTINFO_LOADED, &ob);
45873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK)
45883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
45893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
45903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtptype = map_ptp_type_to_libmtp_type(ob->oi.ObjectFormat);
45913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
45923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Ignore stuff we don't know how to handle...
45933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!LIBMTP_FILETYPE_IS_TRACK(mtptype) &&
45943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      /*
45953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev       * This row lets through undefined files for examination
45963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev       * since they may be forgotten OGG or FLAC files.
45973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev       */
45983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      (ob->oi.ObjectFormat != PTP_OFC_Undefined ||
45993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev       (!FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) &&
46003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	!FLAG_OGG_IS_UNKNOWN(ptp_usb) &&
46013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	!FLAG_FLAC_IS_UNKNOWN(ptp_usb)))
46023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ) {
46033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    //printf("Not a music track (name: %s format: %d), skipping...\n", oi->Filename, oi->ObjectFormat);
46043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
46053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
46063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
46073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Allocate a new track type
46083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  track = LIBMTP_new_track_t();
46093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
46103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // This is some sort of unique ID so we can keep track of the track.
46113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  track->item_id = ob->oid;
46123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  track->parent_id = ob->oi.ParentObject;
46133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  track->storage_id = ob->oi.StorageID;
46143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  track->modificationdate = ob->oi.ModificationDate;
46153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
46163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  track->filetype = mtptype;
46173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
46183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Original file-specific properties
46193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  track->filesize = ob->oi.ObjectCompressedSize;
46203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ob->oi.Filename != NULL) {
46213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    track->filename = strdup(ob->oi.Filename);
46223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
46233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
46243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
46253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * A special quirk for devices that doesn't quite
46263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * remember that some files marked as "unknown" type are
46273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * actually OGG or FLAC files. We look at the filename extension
46283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * and see if it happens that this was atleast named "ogg"
46293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * and fall back on this heuristic approach in that case,
46303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * for these bugged devices only.
46313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   */
46323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (track->filetype == LIBMTP_FILETYPE_UNKNOWN &&
46333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->filename != NULL) {
46343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if ((FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) ||
46353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	 FLAG_OGG_IS_UNKNOWN(ptp_usb)) &&
46363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	has_ogg_extension(track->filename))
46373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->filetype = LIBMTP_FILETYPE_OGG;
46383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else if (FLAG_FLAC_IS_UNKNOWN(ptp_usb) &&
46393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	     has_flac_extension(track->filename))
46403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      track->filetype = LIBMTP_FILETYPE_FLAC;
46413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else {
46423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // This was not an OGG/FLAC file so discard it
46433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      LIBMTP_destroy_track_t(track);
46443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return NULL;
46453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
46463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
46473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  get_track_metadata(device, ob->oi.ObjectFormat, track);
46483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return track;
46493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
46503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
46513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
46523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This is a manual conversion from MTPDataGetFunc to PTPDataGetFunc
46533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * to isolate the internal type.
46543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
46553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint16_t get_func_wrapper(PTPParams* params, void* priv, unsigned long wantlen, unsigned char *data, unsigned long *gotlen)
46563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
46573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  MTPDataHandler *handler = (MTPDataHandler *)priv;
46583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
46593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t local_gotlen = 0;
46603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = handler->getfunc(params, handler->priv, wantlen, data, &local_gotlen);
46613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  *gotlen = local_gotlen;
46623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  switch (ret)
46633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  {
46643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case LIBMTP_HANDLER_RETURN_OK:
46653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return PTP_RC_OK;
46663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case LIBMTP_HANDLER_RETURN_ERROR:
46673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return PTP_ERROR_IO;
46683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case LIBMTP_HANDLER_RETURN_CANCEL:
46693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return PTP_ERROR_CANCEL;
46703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    default:
46713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return PTP_ERROR_IO;
46723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
46733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
46743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
46753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
46763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This is a manual conversion from MTPDataPutFunc to PTPDataPutFunc
46773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * to isolate the internal type.
46783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
46793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic uint16_t put_func_wrapper(PTPParams* params, void* priv, unsigned long sendlen, unsigned char *data, unsigned long *putlen)
46803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
46813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  MTPDataHandler *handler = (MTPDataHandler *)priv;
46823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
46833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t local_putlen = 0;
46843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = handler->putfunc(params, handler->priv, sendlen, data, &local_putlen);
46853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  *putlen = local_putlen;
46863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  switch (ret)
46873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  {
46883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case LIBMTP_HANDLER_RETURN_OK:
46893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return PTP_RC_OK;
46903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case LIBMTP_HANDLER_RETURN_ERROR:
46913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return PTP_ERROR_IO;
46923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case LIBMTP_HANDLER_RETURN_CANCEL:
46933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return PTP_ERROR_CANCEL;
46943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    default:
46953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return PTP_ERROR_IO;
46963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
46973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
46983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
46993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
47003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This gets a file off the device to a local file identified
47013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * by a filename.
47023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the track from.
47033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param id the file ID of the file to retrieve.
47043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param path a filename to use for the retrieved file.
47053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param callback a progress indicator function or NULL to ignore.
47063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param data a user-defined pointer that is passed along to
47073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             the <code>progress</code> function in order to
47083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             pass along some user defined data to the progress
47093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             updates. If not used, set this to NULL.
47103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the transfer was successful, any other value means
47113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *           failure.
47123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_File_To_File_Descriptor()
47133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
47143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Get_File_To_File(LIBMTP_mtpdevice_t *device, uint32_t const id,
47153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 char const * const path, LIBMTP_progressfunc_t const callback,
47163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 void const * const data)
47173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
47183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int fd = -1;
4719bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev  struct utimbuf mtime;
47203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int ret;
47213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
47223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Sanity check
47233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (path == NULL) {
47243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_File_To_File(): Bad arguments, path was NULL.");
47253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
47263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
47273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
47283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Open file
47293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef __WIN32__
47303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef USE_WINDOWS_IO_H
47313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( (fd = _open(path, O_RDWR|O_CREAT|O_TRUNC|O_BINARY,_S_IREAD)) == -1 ) {
47323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#else
47333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( (fd = open(path, O_RDWR|O_CREAT|O_TRUNC|O_BINARY,S_IRWXU)) == -1 ) {
47343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
47353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#else
47363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( (fd = open(path, O_RDWR|O_CREAT|O_TRUNC,S_IRWXU|S_IRGRP)) == -1) {
47373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
47383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_File_To_File(): Could not create file.");
47393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
47403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
47413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4742bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev  ret = LIBMTP_Get_File_To_File_Descriptor(device, id, fd, callback, data, &mtime);
47433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
47443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Close file
47453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  close(fd);
47463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
47473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Delete partial file.
47483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret == -1) {
47493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    unlink(path);
4750bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev  } else {
4751bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev      utime(path, &mtime);
47523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
47533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return ret;
47543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
47553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
47563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
47573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This gets a file off the device to a file identified
47583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * by a file descriptor.
47593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
47603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function can potentially be used for streaming
47613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * files off the device for playback or broadcast for example,
47623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * by downloading the file into a stream sink e.g. a socket.
47633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
47643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the file from.
47653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param id the file ID of the file to retrieve.
47663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param fd a local file descriptor to write the file to.
47673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param callback a progress indicator function or NULL to ignore.
47683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param data a user-defined pointer that is passed along to
47693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             the <code>progress</code> function in order to
47703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             pass along some user defined data to the progress
47713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             updates. If not used, set this to NULL.
4772bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev * @param mtime out parameter to return the timestamp for file on
4773bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev *             the device.
47743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the transfer was successful, any other value means
4775bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev *             failure.
47763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_File_To_File()
47773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
47783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Get_File_To_File_Descriptor(LIBMTP_mtpdevice_t *device,
47793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					uint32_t const id,
47803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					int const fd,
47813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					LIBMTP_progressfunc_t const callback,
4782bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev					void const * const data,
4783bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev                    struct utimbuf * mtime)
47843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
47853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
47863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
47873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
47883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObject *ob;
47893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
47903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_object_want (params, id, PTPOBJECT_OBJECTINFO_LOADED, &ob);
47913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
47923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_File_To_File_Descriptor(): Could not get object info.");
47933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
47943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
47953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ob->oi.ObjectFormat == PTP_OFC_Association) {
47963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_File_To_File_Descriptor(): Bad object format.");
47973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
47983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
47993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
4800bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev  if (mtime != NULL) {
4801bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev    mtime->actime = ob->oi.CaptureDate;
4802bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev    mtime->modtime = ob->oi.ModificationDate;
4803bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev  }
4804bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev
48053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Callbacks
48063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->callback_active = 1;
48073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_total = ob->oi.ObjectCompressedSize+
48083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTP_USB_BULK_HDR_LEN+sizeof(uint32_t); // Request length, one parameter
48093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_complete = 0;
48103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback = callback;
48113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback_data = data;
48123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
48133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_getobject_tofd(params, id, fd);
48143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
48153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->callback_active = 0;
48163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback = NULL;
48173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback_data = NULL;
48183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
48193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret == PTP_ERROR_CANCEL) {
48203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_CANCELLED, "LIBMTP_Get_File_From_File_Descriptor(): Cancelled transfer.");
48213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
48223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
48233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
48243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_File_To_File_Descriptor(): Could not get file from device.");
48253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
48263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
48273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
48283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
48293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
48303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
48313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
48323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This gets a file off the device and calls put_func
48333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * with chunks of data
48343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
48353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the file from.
48363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param id the file ID of the file to retrieve.
48373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param put_func the function to call when we have data.
48383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param priv the user-defined pointer that is passed to
48393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             <code>put_func</code>.
48403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param callback a progress indicator function or NULL to ignore.
48413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param data a user-defined pointer that is passed along to
48423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             the <code>progress</code> function in order to
48433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             pass along some user defined data to the progress
48443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             updates. If not used, set this to NULL.
48453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the transfer was successful, any other value means
48463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *           failure.
48473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
48483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Get_File_To_Handler(LIBMTP_mtpdevice_t *device,
48493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					uint32_t const id,
48503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					MTPDataPutFunc put_func,
48513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          void * priv,
48523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					LIBMTP_progressfunc_t const callback,
48533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					void const * const data)
48543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
48553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObject *ob;
48563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
48573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
48583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
48593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
48603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_object_want (params, id, PTPOBJECT_OBJECTINFO_LOADED, &ob);
48613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
48623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_File_To_File_Descriptor(): Could not get object info.");
48633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
48643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
48653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ob->oi.ObjectFormat == PTP_OFC_Association) {
48663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_File_To_File_Descriptor(): Bad object format.");
48673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
48683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
48693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
48703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Callbacks
48713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->callback_active = 1;
48723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_total = ob->oi.ObjectCompressedSize+
48733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTP_USB_BULK_HDR_LEN+sizeof(uint32_t); // Request length, one parameter
48743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_complete = 0;
48753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback = callback;
48763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback_data = data;
48773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
48783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  MTPDataHandler mtp_handler;
48793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_handler.getfunc = NULL;
48803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_handler.putfunc = put_func;
48813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_handler.priv = priv;
48823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
48833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPDataHandler handler;
48843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  handler.getfunc = NULL;
48853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  handler.putfunc = put_func_wrapper;
48863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  handler.priv = &mtp_handler;
48873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
48883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_getobject_to_handler(params, id, &handler);
48893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
48903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->callback_active = 0;
48913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback = NULL;
48923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback_data = NULL;
48933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
48943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret == PTP_ERROR_CANCEL) {
48953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_CANCELLED, "LIBMTP_Get_File_From_File_Descriptor(): Cancelled transfer.");
48963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
48973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
48983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
48993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_File_To_File_Descriptor(): Could not get file from device.");
49003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
49013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
49023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
49033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
49043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
49053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
49063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
49073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
49083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This gets a track off the device to a file identified
49093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * by a filename. This is actually just a wrapper for the
49103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * \c LIBMTP_Get_Track_To_File() function.
49113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the track from.
49123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param id the track ID of the track to retrieve.
49133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param path a filename to use for the retrieved track.
49143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param callback a progress indicator function or NULL to ignore.
49153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param data a user-defined pointer that is passed along to
49163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             the <code>progress</code> function in order to
49173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             pass along some user defined data to the progress
49183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             updates. If not used, set this to NULL.
49193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the transfer was successful, any other value means
49203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *           failure.
49213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Track_To_File_Descriptor()
49223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
49233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Get_Track_To_File(LIBMTP_mtpdevice_t *device, uint32_t const id,
49243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 char const * const path, LIBMTP_progressfunc_t const callback,
49253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 void const * const data)
49263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
49273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // This is just a wrapper
49283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return LIBMTP_Get_File_To_File(device, id, path, callback, data);
49293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
49303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
49313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
49323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This gets a track off the device to a file identified
49333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * by a file descriptor. This is actually just a wrapper for
49343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * the \c LIBMTP_Get_File_To_File_Descriptor() function.
49353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the track from.
49363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param id the track ID of the track to retrieve.
49373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param fd a file descriptor to write the track to.
49383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param callback a progress indicator function or NULL to ignore.
49393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param data a user-defined pointer that is passed along to
49403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             the <code>progress</code> function in order to
49413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             pass along some user defined data to the progress
49423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             updates. If not used, set this to NULL.
4943bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev * @param mtime out parameter to return the timestamp for file on
4944bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev *             the device.
49453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the transfer was successful, any other value means
49463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *           failure.
49473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Track_To_File()
49483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
49493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Get_Track_To_File_Descriptor(LIBMTP_mtpdevice_t *device,
49503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					uint32_t const id,
49513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					int const fd,
49523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					LIBMTP_progressfunc_t const callback,
4953bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev					void const * const data,
4954bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev                    struct utimbuf * mtime)
49553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
49563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // This is just a wrapper
4957bf992f9881b17ef13f0877b128001e4d001d7c56Yavor Goulishev  return LIBMTP_Get_File_To_File_Descriptor(device, id, fd, callback, data, mtime);
49583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
49593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
49603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
49613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This gets a track off the device to a handler function.
49623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This is actually just a wrapper for
49633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * the \c LIBMTP_Get_File_To_Handler() function.
49643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the track from.
49653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param id the track ID of the track to retrieve.
49663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param put_func the function to call when we have data.
49673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param priv the user-defined pointer that is passed to
49683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             <code>put_func</code>.
49693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param callback a progress indicator function or NULL to ignore.
49703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param data a user-defined pointer that is passed along to
49713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             the <code>progress</code> function in order to
49723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             pass along some user defined data to the progress
49733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             updates. If not used, set this to NULL.
49743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the transfer was successful, any other value means
49753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *           failure.
49763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
49773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Get_Track_To_Handler(LIBMTP_mtpdevice_t *device,
49783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					uint32_t const id,
49793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					MTPDataPutFunc put_func,
49803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev          void * priv,
49813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					LIBMTP_progressfunc_t const callback,
49823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					void const * const data)
49833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
49843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // This is just a wrapper
49853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return LIBMTP_Get_File_To_Handler(device, id, put_func, priv, callback, data);
49863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
49873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
49883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
49893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function sends a track from a local file to an
49903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * MTP device. A filename and a set of metadata must be
49913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * given as input.
49923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to send the track to.
49933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param path the filename of a local file which will be sent.
49943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param metadata a track metadata set to be written along with the file.
49953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        After this call the field <code>metadata-&gt;item_id</code>
49963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        will contain the new track ID. Other fields such
49973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        as the <code>metadata-&gt;filename</code>, <code>metadata-&gt;parent_id</code>
49983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        or <code>metadata-&gt;storage_id</code> may also change during this
49993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        operation due to device restrictions, so do not rely on the
50003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        contents of this struct to be preserved in any way.
50013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <ul>
50023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>metadata-&gt;parent_id</code> should be set to the parent
50033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        (e.g. folder) to store this track in. Since some
50043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        devices are a bit picky about where files
50053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        are placed, a default folder will be chosen if libmtp
50063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        has detected one for the current filetype and this
50073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        parameter is set to 0. If this is 0 and no default folder
50083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        can be found, the file will be stored in the root folder.
50093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>metadata-&gt;storage_id</code> should be set to the
50103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        desired storage (e.g. memory card or whatever your device
50113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        presents) to store this track in. Setting this to 0 will store
50123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        the track on the primary storage.
50133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        </ul>
50143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param callback a progress indicator function or NULL to ignore.
50153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param data a user-defined pointer that is passed along to
50163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             the <code>progress</code> function in order to
50173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             pass along some user defined data to the progress
50183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             updates. If not used, set this to NULL.
50193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the transfer was successful, any other value means
50203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *           failure.
50213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Send_Track_From_File_Descriptor()
50223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Send_File_From_File()
50233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Delete_Object()
50243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
50253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Send_Track_From_File(LIBMTP_mtpdevice_t *device,
50263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 char const * const path, LIBMTP_track_t * const metadata,
50273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                         LIBMTP_progressfunc_t const callback,
50283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 void const * const data)
50293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
50303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int fd;
50313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int ret;
50323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
50333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Sanity check
50343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (path == NULL) {
50353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Send_Track_From_File(): Bad arguments, path was NULL.");
50363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
50373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
50383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
50393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Open file
50403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef __WIN32__
50413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef USE_WINDOWS_IO_H
50423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( (fd = _open(path, O_RDONLY|O_BINARY) == -1) ) {
50433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#else
50443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( (fd = open(path, O_RDONLY|O_BINARY) == -1) ) {
50453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
50463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#else
50473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( (fd = open(path, O_RDONLY)) == -1) {
50483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
50493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    printf("LIBMTP_Send_Track_From_File(): Could not open source file \"%s\"\n", path);
50503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
50513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
50523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
50533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = LIBMTP_Send_Track_From_File_Descriptor(device, fd, metadata, callback, data);
50543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
50553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Close file.
50563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef USE_WINDOWS_IO_H
50573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  _close(fd);
50583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#else
50593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  close(fd);
50603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
50613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
50623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return ret;
50633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
50643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
50653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
50663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function sends a track from a file descriptor to an
50673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * MTP device. A filename and a set of metadata must be
50683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * given as input.
50693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to send the track to.
50703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param fd the filedescriptor for a local file which will be sent.
50713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param metadata a track metadata set to be written along with the file.
50723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        After this call the field <code>metadata-&gt;item_id</code>
50733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        will contain the new track ID. Other fields such
50743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        as the <code>metadata-&gt;filename</code>, <code>metadata-&gt;parent_id</code>
50753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        or <code>metadata-&gt;storage_id</code> may also change during this
50763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        operation due to device restrictions, so do not rely on the
50773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        contents of this struct to be preserved in any way.
50783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <ul>
50793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>metadata-&gt;parent_id</code> should be set to the parent
50803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        (e.g. folder) to store this track in. Since some
50813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        devices are a bit picky about where files
50823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        are placed, a default folder will be chosen if libmtp
50833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        has detected one for the current filetype and this
50843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        parameter is set to 0. If this is 0 and no default folder
50853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        can be found, the file will be stored in the root folder.
50863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>metadata-&gt;storage_id</code> should be set to the
50873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        desired storage (e.g. memory card or whatever your device
50883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        presents) to store this track in. Setting this to 0 will store
50893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        the track on the primary storage.
50903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        </ul>
50913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param callback a progress indicator function or NULL to ignore.
50923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param data a user-defined pointer that is passed along to
50933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             the <code>progress</code> function in order to
50943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             pass along some user defined data to the progress
50953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             updates. If not used, set this to NULL.
50963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the transfer was successful, any other value means
50973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *           failure.
50983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Send_Track_From_File()
50993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Delete_Object()
51003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
51013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Send_Track_From_File_Descriptor(LIBMTP_mtpdevice_t *device,
51023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 int const fd, LIBMTP_track_t * const metadata,
51033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                         LIBMTP_progressfunc_t const callback,
51043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 void const * const data)
51053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
51063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int subcall_ret;
51073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_file_t filedata;
51083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
51093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Sanity check, is this really a track?
51103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!LIBMTP_FILETYPE_IS_TRACK(metadata->filetype)) {
51113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
51123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "LIBMTP_Send_Track_From_File_Descriptor(): "
51133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "I don't think this is actually a track, strange filetype...");
51143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
51153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
51163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Wrap around the file transfer function
51173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata.item_id = metadata->item_id;
51183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata.parent_id = metadata->parent_id;
51193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata.storage_id = metadata->storage_id;
51203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata.filename = metadata->filename;
51213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata.filesize = metadata->filesize;
51223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata.filetype = metadata->filetype;
51233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata.next = NULL;
51243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
51253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  subcall_ret = LIBMTP_Send_File_From_File_Descriptor(device,
51263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						      fd,
51273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						      &filedata,
51283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						      callback,
51293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						      data);
51303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
51313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (subcall_ret != 0) {
51323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
51333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "LIBMTP_Send_Track_From_File_Descriptor(): "
51343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "subcall to LIBMTP_Send_File_From_File_Descriptor failed.");
51353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // We used to delete the file here, but don't... It might be OK after all.
51363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // (void) LIBMTP_Delete_Object(device, metadata->item_id);
51373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
51383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
51393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
51403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Pick up new item (and parent, storage) ID
51413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  metadata->item_id = filedata.item_id;
51423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  metadata->parent_id = filedata.parent_id;
51433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  metadata->storage_id = filedata.storage_id;
51443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
51453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Set track metadata for the new fine track
51463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  subcall_ret = LIBMTP_Update_Track_Metadata(device, metadata);
51473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (subcall_ret != 0) {
51483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Subcall will add error to errorstack
51493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // We used to delete the file here, but don't... It might be OK after all.
51503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // (void) LIBMTP_Delete_Object(device, metadata->item_id);
51513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
51523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
51533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
51543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // note we don't need to update the cache here because LIBMTP_Send_File_From_File_Descriptor
51553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // has added the object handle and LIBMTP_Update_Track_Metadata has added the metadata.
51563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
51573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
51583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
51593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
51603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
51613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function sends a track from a handler function to an
51623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * MTP device. A filename and a set of metadata must be
51633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * given as input.
51643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to send the track to.
51653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param get_func the function to call when we have data.
51663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param priv the user-defined pointer that is passed to
51673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             <code>get_func</code>.
51683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param metadata a track metadata set to be written along with the file.
51693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        After this call the field <code>metadata-&gt;item_id</code>
51703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        will contain the new track ID. Other fields such
51713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        as the <code>metadata-&gt;filename</code>, <code>metadata-&gt;parent_id</code>
51723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        or <code>metadata-&gt;storage_id</code> may also change during this
51733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        operation due to device restrictions, so do not rely on the
51743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        contents of this struct to be preserved in any way.
51753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <ul>
51763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>metadata-&gt;parent_id</code> should be set to the parent
51773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        (e.g. folder) to store this track in. Since some
51783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        devices are a bit picky about where files
51793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        are placed, a default folder will be chosen if libmtp
51803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        has detected one for the current filetype and this
51813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        parameter is set to 0. If this is 0 and no default folder
51823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        can be found, the file will be stored in the root folder.
51833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>metadata-&gt;storage_id</code> should be set to the
51843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        desired storage (e.g. memory card or whatever your device
51853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        presents) to store this track in. Setting this to 0 will store
51863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        the track on the primary storage.
51873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        </ul>
51883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param callback a progress indicator function or NULL to ignore.
51893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param data a user-defined pointer that is passed along to
51903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             the <code>progress</code> function in order to
51913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             pass along some user defined data to the progress
51923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             updates. If not used, set this to NULL.
51933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the transfer was successful, any other value means
51943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *           failure.
51953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Send_Track_From_File()
51963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Delete_Object()
51973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
51983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Send_Track_From_Handler(LIBMTP_mtpdevice_t *device,
51993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 MTPDataGetFunc get_func, void * priv, LIBMTP_track_t * const metadata,
52003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                         LIBMTP_progressfunc_t const callback,
52013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 void const * const data)
52023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
52033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int subcall_ret;
52043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_file_t filedata;
52053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
52063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Sanity check, is this really a track?
52073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!LIBMTP_FILETYPE_IS_TRACK(metadata->filetype)) {
52083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
52093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "LIBMTP_Send_Track_From_Handler(): "
52103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "I don't think this is actually a track, strange filetype...");
52113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
52123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
52133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Wrap around the file transfer function
52143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata.item_id = metadata->item_id;
52153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata.parent_id = metadata->parent_id;
52163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata.storage_id = metadata->storage_id;
52173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata.filename = metadata->filename;
52183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata.filesize = metadata->filesize;
52193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata.filetype = metadata->filetype;
52203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata.next = NULL;
52213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
52223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  subcall_ret = LIBMTP_Send_File_From_Handler(device,
52233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						      get_func,
52243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                  priv,
52253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						      &filedata,
52263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						      callback,
52273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev						      data);
52283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
52293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (subcall_ret != 0) {
52303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
52313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "LIBMTP_Send_Track_From_Handler(): "
52323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "subcall to LIBMTP_Send_File_From_Handler failed.");
52333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // We used to delete the file here, but don't... It might be OK after all.
52343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // (void) LIBMTP_Delete_Object(device, metadata->item_id);
52353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
52363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
52373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
52383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Pick up new item (and parent, storage) ID
52393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  metadata->item_id = filedata.item_id;
52403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  metadata->parent_id = filedata.parent_id;
52413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  metadata->storage_id = filedata.storage_id;
52423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
52433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Set track metadata for the new fine track
52443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  subcall_ret = LIBMTP_Update_Track_Metadata(device, metadata);
52453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (subcall_ret != 0) {
52463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Subcall will add error to errorstack
52473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // We used to delete the file here, but don't... It might be OK after all.
52483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // (void) LIBMTP_Delete_Object(device, metadata->item_id);
52493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
52503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
52513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
52523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // note we don't need to update the cache here because LIBMTP_Send_File_From_File_Descriptor
52533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // has added the object handle and LIBMTP_Update_Track_Metadata has added the metadata.
52543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
52553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
52563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
52573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
52583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
52593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function sends a local file to an MTP device.
52603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * A filename and a set of metadata must be
52613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * given as input.
52623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to send the track to.
52633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param path the filename of a local file which will be sent.
52643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param filedata a file metadata set to be written along with the file.
52653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        After this call the field <code>filedata-&gt;item_id</code>
52663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        will contain the new file ID. Other fields such
52673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        as the <code>filedata-&gt;filename</code>, <code>filedata-&gt;parent_id</code>
52683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        or <code>filedata-&gt;storage_id</code> may also change during this
52693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        operation due to device restrictions, so do not rely on the
52703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        contents of this struct to be preserved in any way.
52713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <ul>
52723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>filedata-&gt;parent_id</code> should be set to the parent
52733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        (e.g. folder) to store this file in. If this is 0,
52743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        the file will be stored in the root folder.
52753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>filedata-&gt;storage_id</code> should be set to the
52763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        desired storage (e.g. memory card or whatever your device
52773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        presents) to store this file in. Setting this to 0 will store
52783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        the file on the primary storage.
52793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        </ul>
52803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param callback a progress indicator function or NULL to ignore.
52813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param data a user-defined pointer that is passed along to
52823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             the <code>progress</code> function in order to
52833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             pass along some user defined data to the progress
52843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             updates. If not used, set this to NULL.
52853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the transfer was successful, any other value means
52863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *           failure.
52873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Send_File_From_File_Descriptor()
52883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Delete_Object()
52893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
52903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Send_File_From_File(LIBMTP_mtpdevice_t *device,
52913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       char const * const path, LIBMTP_file_t * const filedata,
52923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       LIBMTP_progressfunc_t const callback,
52933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       void const * const data)
52943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
52953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int fd;
52963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int ret;
52973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
52983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Sanity check
52993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (path == NULL) {
53003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Send_File_From_File(): Bad arguments, path was NULL.");
53013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
53023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
53033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
53043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Open file
53053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef __WIN32__
53063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef USE_WINDOWS_IO_H
53073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( (fd = _open(path, O_RDONLY|O_BINARY) == -1) ) {
53083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#else
53093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( (fd = open(path, O_RDONLY|O_BINARY) == -1) ) {
53103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
53113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#else
53123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( (fd = open(path, O_RDONLY)) == -1) {
53133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
53143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Send_File_From_File(): Could not open source file.");
53153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
53163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
53173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
53183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = LIBMTP_Send_File_From_File_Descriptor(device, fd, filedata, callback, data);
53193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
53203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Close file.
53213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#ifdef USE_WINDOWS_IO_H
53223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  _close(fd);
53233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#else
53243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  close(fd);
53253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#endif
53263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
53273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return ret;
53283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
53293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
53303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
53313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function sends a generic file from a file descriptor to an
53323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * MTP device. A filename and a set of metadata must be
53333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * given as input.
53343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
53353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This can potentially be used for sending in a stream of unknown
53363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * length. Send music files with
53373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <code>LIBMTP_Send_Track_From_File_Descriptor()</code>
53383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
53393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to send the file to.
53403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param fd the filedescriptor for a local file which will be sent.
53413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param filedata a file metadata set to be written along with the file.
53423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        After this call the field <code>filedata-&gt;item_id</code>
53433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        will contain the new file ID. Other fields such
53443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        as the <code>filedata-&gt;filename</code>, <code>filedata-&gt;parent_id</code>
53453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        or <code>filedata-&gt;storage_id</code> may also change during this
53463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        operation due to device restrictions, so do not rely on the
53473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        contents of this struct to be preserved in any way.
53483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <ul>
53493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>filedata-&gt;parent_id</code> should be set to the parent
53503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        (e.g. folder) to store this file in. If this is 0,
53513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        the file will be stored in the root folder.
53523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>filedata-&gt;storage_id</code> should be set to the
53533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        desired storage (e.g. memory card or whatever your device
53543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        presents) to store this file in. Setting this to 0 will store
53553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        the file on the primary storage.
53563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        </ul>
53573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param callback a progress indicator function or NULL to ignore.
53583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param data a user-defined pointer that is passed along to
53593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             the <code>progress</code> function in order to
53603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             pass along some user defined data to the progress
53613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             updates. If not used, set this to NULL.
53623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the transfer was successful, any other value means
53633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *           failure.
53643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Send_File_From_File()
53653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Send_Track_From_File_Descriptor()
53663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Delete_Object()
53673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
53683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Send_File_From_File_Descriptor(LIBMTP_mtpdevice_t *device,
53693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 int const fd, LIBMTP_file_t * const filedata,
53703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                         LIBMTP_progressfunc_t const callback,
53713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 void const * const data)
53723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
53733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
53743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
53753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
53763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_file_t *newfilemeta;
53773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
53783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (send_file_object_info(device, filedata))
53793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  {
53803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // no need to output an error since send_file_object_info will already have done so
53813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
53823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
53833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
53843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Callbacks
53853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->callback_active = 1;
53863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // The callback will deactivate itself after this amount of data has been sent
53873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // One BULK header for the request, one for the data phase. No parameters to the request.
53883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_total = filedata->filesize+PTP_USB_BULK_HDR_LEN*2;
53893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_complete = 0;
53903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback = callback;
53913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback_data = data;
53923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
53933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_sendobject_fromfd(params, fd, filedata->filesize);
53943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
53953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->callback_active = 0;
53963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback = NULL;
53973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback_data = NULL;
53983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
53993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret == PTP_ERROR_CANCEL) {
54003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_CANCELLED, "LIBMTP_Send_File_From_File_Descriptor(): Cancelled transfer.");
54013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
54023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
54033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
54043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Send_File_From_File_Descriptor(): "
54053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				"Could not send object.");
54063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
54073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
54083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
54093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  add_object_to_cache(device, filedata->item_id);
54103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
54113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
54123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * Get the device-assined parent_id from the cache.
54133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * The operation that adds it to the cache will
54143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * look it up from the device, so we get the new
54153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * parent_id from the cache.
54163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   */
54173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  newfilemeta = LIBMTP_Get_Filemetadata(device, filedata->item_id);
54183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (newfilemeta != NULL) {
54193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    filedata->parent_id = newfilemeta->parent_id;
54203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    filedata->storage_id = newfilemeta->storage_id;
54213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_destroy_file_t(newfilemeta);
54223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
54233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
54243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "LIBMTP_Send_File_From_File_Descriptor(): "
54253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "Could not retrieve updated metadata.");
54263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
54273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
54283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
54293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
54303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
54313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
54323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
54333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function sends a generic file from a handler function to an
54343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * MTP device. A filename and a set of metadata must be
54353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * given as input.
54363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
54373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This can potentially be used for sending in a stream of unknown
54383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * length. Send music files with
54393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <code>LIBMTP_Send_Track_From_Handler()</code>
54403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
54413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to send the file to.
54423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param get_func the function to call to get data to write
54433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param priv a user-defined pointer that is passed along to
54443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <code>get_func</code>. If not used, this is set to NULL.
54453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param filedata a file metadata set to be written along with the file.
54463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        After this call the field <code>filedata-&gt;item_id</code>
54473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        will contain the new file ID. Other fields such
54483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        as the <code>filedata-&gt;filename</code>, <code>filedata-&gt;parent_id</code>
54493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        or <code>filedata-&gt;storage_id</code> may also change during this
54503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        operation due to device restrictions, so do not rely on the
54513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        contents of this struct to be preserved in any way.
54523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <ul>
54533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>filedata-&gt;parent_id</code> should be set to the parent
54543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        (e.g. folder) to store this file in. If this is 0,
54553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        the file will be stored in the root folder.
54563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>filedata-&gt;storage_id</code> should be set to the
54573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        desired storage (e.g. memory card or whatever your device
54583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        presents) to store this file in. Setting this to 0 will store
54593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        the file on the primary storage.
54603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        </ul>
54613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param callback a progress indicator function or NULL to ignore.
54623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param data a user-defined pointer that is passed along to
54633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             the <code>progress</code> function in order to
54643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             pass along some user defined data to the progress
54653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *             updates. If not used, set this to NULL.
54663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the transfer was successful, any other value means
54673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *           failure.
54683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Send_File_From_File()
54693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Send_Track_From_File_Descriptor()
54703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Delete_Object()
54713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
54723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Send_File_From_Handler(LIBMTP_mtpdevice_t *device,
54733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 MTPDataGetFunc get_func, void * priv, LIBMTP_file_t * const filedata,
54743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev       LIBMTP_progressfunc_t const callback, void const * const data)
54753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
54763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
54773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
54783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
54793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_file_t *newfilemeta;
54803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
54813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (send_file_object_info(device, filedata))
54823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  {
54833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // no need to output an error since send_file_object_info will already have done so
54843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
54853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
54863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
54873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Callbacks
54883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->callback_active = 1;
54893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // The callback will deactivate itself after this amount of data has been sent
54903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // One BULK header for the request, one for the data phase. No parameters to the request.
54913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_total = filedata->filesize+PTP_USB_BULK_HDR_LEN*2;
54923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_complete = 0;
54933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback = callback;
54943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback_data = data;
54953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
54963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  MTPDataHandler mtp_handler;
54973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_handler.getfunc = get_func;
54983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_handler.putfunc = NULL;
54993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  mtp_handler.priv = priv;
55003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
55013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPDataHandler handler;
55023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  handler.getfunc = get_func_wrapper;
55033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  handler.putfunc = NULL;
55043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  handler.priv = &mtp_handler;
55053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
55063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_sendobject_from_handler(params, &handler, filedata->filesize);
55073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
55083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->callback_active = 0;
55093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback = NULL;
55103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_usb->current_transfer_callback_data = NULL;
55113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
55123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret == PTP_ERROR_CANCEL) {
55133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_CANCELLED, "LIBMTP_Send_File_From_Handler(): Cancelled transfer.");
55143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
55153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
55163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
55173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Send_File_From_Handler(): "
55183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				"Could not send object.");
55193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
55203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
55213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
55223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  add_object_to_cache(device, filedata->item_id);
55233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
55243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
55253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * Get the device-assined parent_id from the cache.
55263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * The operation that adds it to the cache will
55273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * look it up from the device, so we get the new
55283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * parent_id from the cache.
55293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   */
55303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  newfilemeta = LIBMTP_Get_Filemetadata(device, filedata->item_id);
55313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (newfilemeta != NULL) {
55323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    filedata->parent_id = newfilemeta->parent_id;
55333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    filedata->storage_id = newfilemeta->storage_id;
55343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_destroy_file_t(newfilemeta);
55353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
55363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
55373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "LIBMTP_Send_File_From_Handler(): "
55383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "Could not retrieve updated metadata.");
55393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
55403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
55413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
55423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
55433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
55443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
55453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
55463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function sends the file object info, ready for sendobject
55473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to send the file to.
55483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param filedata a file metadata set to be written along with the file.
55493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 if the transfer was successful, any other value means
55503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *           failure.
55513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
55523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int send_file_object_info(LIBMTP_mtpdevice_t *device, LIBMTP_file_t *filedata)
55533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
55543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
55553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
55563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t store;
5557ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev
5558ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev#ifdef _AFT_BUILD
5559ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev  int use_primary_storage = 0;
5560ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev#else
55613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int use_primary_storage = 1;
5562ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev#endif
5563ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev
55643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t of = map_libmtp_type_to_ptp_type(filedata->filetype);
55653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_devicestorage_t *storage;
55663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t localph = filedata->parent_id;
55673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
55683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int i;
55693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
55703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (filedata->storage_id != 0) {
55713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    store = filedata->storage_id;
55723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
55733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    store = get_writeable_storageid(device, filedata->filesize);
55743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
55753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Detect if something non-primary is in use.
55763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  storage = device->storage;
55773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (storage != NULL && store != storage->id) {
55783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    use_primary_storage = 0;
55793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
55803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
55813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
55823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * If no destination folder was given, look up a default
55833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * folder if possible. Perhaps there is some way of retrieveing
55843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * the default folder for different forms of content, what
55853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * do I know, we use a fixed list in lack of any better method.
55863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * Some devices obviously need to have their files in certain
55873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * folders in order to find/display them at all (hello Creative),
55883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * so we have to have a method for this. We only do this if the
55893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * primary storage is in use.
55903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   */
55913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
55923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (localph == 0 && use_primary_storage) {
55933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (LIBMTP_FILETYPE_IS_AUDIO(filedata->filetype)) {
55943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      localph = device->default_music_folder;
55953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else if (LIBMTP_FILETYPE_IS_VIDEO(filedata->filetype)) {
55963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      localph = device->default_video_folder;
55973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else if (of == PTP_OFC_EXIF_JPEG ||
55983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_JP2 ||
55993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_JPX ||
56003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_JFIF ||
56013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_TIFF ||
56023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_TIFF_IT ||
56033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_BMP ||
56043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_GIF ||
56053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_PICT ||
56063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_PNG ||
56073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_MTP_WindowsImageFormat) {
56083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      localph = device->default_picture_folder;
56093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else if (of == PTP_OFC_MTP_vCalendar1 ||
56103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_MTP_vCalendar2 ||
56113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_MTP_UndefinedContact ||
56123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_MTP_vCard2 ||
56133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_MTP_vCard3 ||
56143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	       of == PTP_OFC_MTP_UndefinedCalendarItem) {
56153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      localph = device->default_organizer_folder;
56163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else if (of == PTP_OFC_Text) {
56173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      localph = device->default_text_folder;
56183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
56193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
56203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
5621ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev  // default parent handle
5622ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev  if (localph == 0) {
5623ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev    localph = 0xFFFFFFFFU; // Set to -1
5624ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev  }
5625ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev
56263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Here we wire the type to unknown on bugged, but
56273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Ogg or FLAC-supportive devices.
56283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (FLAG_OGG_IS_UNKNOWN(ptp_usb) && of == PTP_OFC_MTP_OGG) {
56293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    of = PTP_OFC_Undefined;
56303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
56313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (FLAG_FLAC_IS_UNKNOWN(ptp_usb) && of == PTP_OFC_MTP_FLAC) {
56323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    of = PTP_OFC_Undefined;
56333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
56343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
56353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ptp_operation_issupported(params, PTP_OC_MTP_SendObjectPropList) &&
56363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      !FLAG_BROKEN_SEND_OBJECT_PROPLIST(ptp_usb)) {
56373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /*
56383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * MTP enhanched does it this way (from a sniff):
56393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * -> PTP_OC_MTP_SendObjectPropList (0x9808):
56403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    20 00 00 00 01 00 08 98 1B 00 00 00 01 00 01 00
56413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    FF FF FF FF 00 30 00 00 00 00 00 00 12 5E 00 00
56423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Length: 0x00000020
56433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Type:   0x0001 PTP_USB_CONTAINER_COMMAND
56443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Code:   0x9808
56453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Transaction ID: 0x0000001B
56463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Param1: 0x00010001 <- store
56473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Param2: 0xffffffff <- parent handle (-1 ?)
56483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Param3: 0x00003000 <- file type PTP_OFC_Undefined - we don't know about PDF files
56493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Param4: 0x00000000 <- file length MSB (-0x0c header len)
56503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Param5: 0x00005e12 <- file length LSB (-0x0c header len)
56513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *
56523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * -> PTP_OC_MTP_SendObjectPropList (0x9808):
56533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    46 00 00 00 02 00 08 98 1B 00 00 00 03 00 00 00
56543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    00 00 00 00 07 DC FF FF 0D 4B 00 53 00 30 00 36 - dc07 = file name
56553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    00 30 00 33 00 30 00 36 00 2E 00 70 00 64 00 66
56563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    00 00 00 00 00 00 00 03 DC 04 00 00 00 00 00 00 - dc03 = protection status
56573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    00 4F DC 02 00 01                               - dc4f = non consumable
56583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Length: 0x00000046
56593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Type:   0x0002 PTP_USB_CONTAINER_DATA
56603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Code:   0x9808
56613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Transaction ID: 0x0000001B
56623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Metadata....
56633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0x00000003 <- Number of metadata items
56643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0x00000000 <- Object handle, set to 0x00000000 since it is unknown!
56653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0xdc07     <- metadata type: file name
56663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0xffff     <- metadata type: string
56673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0x0d       <- number of (uint16_t) characters
56683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    4b 53 30 36 30 33 30 36 2e 50 64 66 00 "KS060306.pdf", null terminated
56693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0x00000000 <- Object handle, set to 0x00000000 since it is unknown!
56703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0xdc03     <- metadata type: protection status
56713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0x0004     <- metadata type: uint16_t
56723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0x0000     <- not protected
56733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0x00000000 <- Object handle, set to 0x00000000 since it is unknown!
56743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0xdc4f     <- non consumable
56753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0x0002     <- metadata type: uint8_t
56763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0x01       <- non-consumable (this device cannot display PDF)
56773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *
56783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * <- Read 0x18 bytes back
56793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    18 00 00 00 03 00 01 20 1B 00 00 00 01 00 01 00
56803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    00 00 00 00 01 40 00 00
56813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Length: 0x000000018
56823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Type:   0x0003 PTP_USB_CONTAINER_RESPONSE
56833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Code:   0x2001 PTP_OK
56843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Transaction ID: 0x0000001B
56853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Param1: 0x00010001 <- store
56863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Param2: 0x00000000 <- parent handle
56873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    Param3: 0x00004001 <- new file/object ID
56883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *
56893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * -> PTP_OC_SendObject (0x100d)
56903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0C 00 00 00 01 00 0D 10 1C 00 00 00
56913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * -> ... all the bytes ...
56923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * <- Read 0x0c bytes back
56933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    0C 00 00 00 03 00 01 20 1C 00 00 00
56943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *    ... Then update metadata one-by one, actually (instead of sending it first!) ...
56953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     */
56963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    MTPProperties *props = NULL;
56973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    int nrofprops = 0;
56983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    MTPProperties *prop = NULL;
56993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    uint16_t *properties = NULL;
57003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    uint32_t propcnt = 0;
57013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
57023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Must be 0x00000000U for new objects
57033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    filedata->item_id = 0x00000000U;
57043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
57053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_mtp_getobjectpropssupported(params, of, &propcnt, &properties);
57063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
57073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i=0;i<propcnt;i++) {
57083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      PTPObjectPropDesc opd;
57093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
57103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ret = ptp_mtp_getobjectpropdesc(params, properties[i], of, &opd);
57113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret != PTP_RC_OK) {
57123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	add_ptp_error_to_errorstack(device, ret, "send_file_object_info(): "
57133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				"could not get property description.");
57143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      } else if (opd.GetSet) {
57153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	switch (properties[i]) {
57163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_ObjectFileName:
57173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
57183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = filedata->item_id;
57193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_ObjectFileName;
57203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_STR;
57213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (filedata->filename != NULL) {
57223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = strdup(filedata->filename);
57233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) {
57243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      strip_7bit_from_utf8(prop->propval.str);
57253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
57263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
57273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
57283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_ProtectionStatus:
57293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
57303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = filedata->item_id;
57313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_ProtectionStatus;
57323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_UINT16;
57333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.u16 = 0x0000U; /* Not protected */
57343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
57353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_NonConsumable:
57363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
57373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = filedata->item_id;
57383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_NonConsumable;
57393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_UINT8;
57403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.u8 = 0x00; /* It is supported, then it is consumable */
57413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
57423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Name:
57433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
57443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = filedata->item_id;
57453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_Name;
57463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_STR;
57473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (filedata->filename != NULL)
57483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = strdup(filedata->filename);
57493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
57503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_DateModified:
57513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Tag with current time if that is supported
57523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
57533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
57543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->ObjectHandle = filedata->item_id;
57553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->property = PTP_OPC_DateModified;
57563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->datatype = PTP_DTC_STR;
57573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = get_iso8601_stamp();
57583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    filedata->modificationdate = time(NULL);
57593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
57603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
57613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
57623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
57633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptp_free_objectpropdesc(&opd);
57643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
57653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(properties);
57663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
57673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_mtp_sendobjectproplist(params, &store, &localph, &filedata->item_id,
57683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				     of, filedata->filesize, props, nrofprops);
57693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
57703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* Free property list */
57713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_destroy_object_prop_list(props, nrofprops);
57723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
57733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
57743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_ptp_error_to_errorstack(device, ret, "send_file_object_info():"
57753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  "Could not send object property list.");
57763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret == PTP_RC_AccessDenied) {
57773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	add_ptp_error_to_errorstack(device, ret, "ACCESS DENIED.");
57783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
57793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return -1;
57803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
57813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else if (ptp_operation_issupported(params,PTP_OC_SendObjectInfo)) {
57823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTPObjectInfo new_file;
57833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
57843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    memset(&new_file, 0, sizeof(PTPObjectInfo));
57853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
57863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new_file.Filename = filedata->filename;
57873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) {
57883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      strip_7bit_from_utf8(new_file.Filename);
57893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
57903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // We lose precision here.
57913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new_file.ObjectCompressedSize = (uint32_t) filedata->filesize;
57923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new_file.ObjectFormat = of;
57933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new_file.StorageID = store;
57943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new_file.ParentObject = localph;
57953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new_file.ModificationDate = time(NULL);
57963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Create the object
5797ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev
57983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_sendobjectinfo(params, &store, &localph, &filedata->item_id, &new_file);
57993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
58003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
58013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_ptp_error_to_errorstack(device, ret, "send_file_object_info(): "
58023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  "Could not send object info.");
58033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret == PTP_RC_AccessDenied) {
58043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	add_ptp_error_to_errorstack(device, ret, "ACCESS DENIED.");
58053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
58063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return -1;
58073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
58083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // NOTE: the char* pointers inside new_file are not copies so don't
58093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // try to destroy this objectinfo!
58103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
58113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
58123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Now there IS an object with this parent handle.
58133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  filedata->parent_id = localph;
58143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
58153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
58163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
58173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
58183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
58193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function updates the MTP track object metadata on a
58203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * single file identified by an object ID.
58213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to update the track
58223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        metadata on.
58233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param metadata a track metadata set to be written to the file.
58243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        notice that the <code>track_id</code> field of the
58253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        metadata structure must be correct so that the
58263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        function can update the right file. If some properties
58273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        of this metadata are set to NULL (strings) or 0
58283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        (numerical values) they will be discarded and the
58293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        track will not be tagged with these blank values.
58303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure. If some
58313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        or all of the properties fail to update we will still
58323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        return success. On some devices (notably iRiver T30)
58333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        properties that exist cannot be updated.
58343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
58353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Update_Track_Metadata(LIBMTP_mtpdevice_t *device,
58363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				 LIBMTP_track_t const * const metadata)
58373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
58383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
58393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
58403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
58413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t i;
58423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t *properties = NULL;
58433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t propcnt = 0;
58443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
58453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // First see which properties can be set on this file format and apply accordingly
58463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // i.e only try to update this metadata for object tags that exist on the current player.
58473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectpropssupported(params, map_libmtp_type_to_ptp_type(metadata->filetype), &propcnt, &properties);
58483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
58493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Just bail out for now, nothing is ever set.
58503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
58513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "could not retrieve supported object properties.");
58523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
58533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
58543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ptp_operation_issupported(params, PTP_OC_MTP_SetObjPropList) &&
58553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      !FLAG_BROKEN_SET_OBJECT_PROPLIST(ptp_usb)) {
58563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    MTPProperties *props = NULL;
58573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    MTPProperties *prop = NULL;
58583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    int nrofprops = 0;
58593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
58603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i=0;i<propcnt;i++) {
58613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      PTPObjectPropDesc opd;
58623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
58633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ret = ptp_mtp_getobjectpropdesc(params, properties[i], map_libmtp_type_to_ptp_type(metadata->filetype), &opd);
58643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret != PTP_RC_OK) {
58653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
58663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				"could not get property description.");
58673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      } else if (opd.GetSet) {
58683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	switch (properties[i]) {
58693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Name:
58703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->title == NULL)
58713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    break;
58723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
58733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
58743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_Name;
58753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_STR;
58763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.str = strdup(metadata->title);
58773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
58783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_AlbumName:
58793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->album == NULL)
58803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    break;
58813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
58823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
58833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_AlbumName;
58843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_STR;
58853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.str = strdup(metadata->album);
58863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
58873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Artist:
58883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->artist == NULL)
58893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    break;
58903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
58913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
58923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_Artist;
58933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_STR;
58943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.str = strdup(metadata->artist);
58953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
58963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Composer:
58973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->composer == NULL)
58983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    break;
58993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
59003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
59013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_Composer;
59023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_STR;
59033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.str = strdup(metadata->composer);
59043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
59053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Genre:
59063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->genre == NULL)
59073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    break;
59083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
59093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
59103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_Genre;
59113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_STR;
59123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.str = strdup(metadata->genre);
59133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
59143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Duration:
59153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
59163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
59173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_Duration;
59183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_UINT32;
59193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.u32 = adjust_u32(metadata->duration, &opd);
59203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
59213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Track:
59223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
59233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
59243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_Track;
59253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_UINT16;
59263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.u16 = adjust_u16(metadata->tracknumber, &opd);
59273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
59283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_OriginalReleaseDate:
59293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->date == NULL)
59303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    break;
59313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
59323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
59333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_OriginalReleaseDate;
59343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_STR;
59353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.str = strdup(metadata->date);
59363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
59373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_SampleRate:
59383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
59393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
59403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_SampleRate;
59413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_UINT32;
59423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.u32 = adjust_u32(metadata->samplerate, &opd);
59433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
59443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_NumberOfChannels:
59453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
59463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
59473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_NumberOfChannels;
59483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_UINT16;
59493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.u16 = adjust_u16(metadata->nochannels, &opd);
59503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
59513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_AudioWAVECodec:
59523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
59533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
59543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_AudioWAVECodec;
59553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_UINT32;
59563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.u32 = adjust_u32(metadata->wavecodec, &opd);
59573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
59583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_AudioBitRate:
59593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
59603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
59613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_AudioBitRate;
59623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_UINT32;
59633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.u32 = adjust_u32(metadata->bitrate, &opd);
59643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
59653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_BitRateType:
59663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
59673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
59683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_BitRateType;
59693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_UINT16;
59703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.u16 = adjust_u16(metadata->bitratetype, &opd);
59713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
59723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Rating:
59733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // TODO: shall this be set for rating 0?
59743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->rating == 0)
59753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    break;
59763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
59773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
59783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_Rating;
59793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_UINT16;
59803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.u16 = adjust_u16(metadata->rating, &opd);
59813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
59823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_UseCount:
59833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
59843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = metadata->item_id;
59853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_UseCount;
59863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_UINT32;
59873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.u32 = adjust_u32(metadata->usecount, &opd);
59883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
59893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_DateModified:
59903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
59913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    // Tag with current time if that is supported
59923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
59933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->ObjectHandle = metadata->item_id;
59943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->property = PTP_OPC_DateModified;
59953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->datatype = PTP_DTC_STR;
59963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = get_iso8601_stamp();
59973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
59983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
59993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	default:
60003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
60013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
60023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
60033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptp_free_objectpropdesc(&opd);
60043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
60053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
60063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // NOTE: File size is not updated, this should not change anyway.
60073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // neither will we change the filename.
60083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
60093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_mtp_setobjectproplist(params, props, nrofprops);
60103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
60113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_destroy_object_prop_list(props, nrofprops);
60123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
60133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
60143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // TODO: return error of which property we couldn't set
60153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
60163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      "could not set object property list.");
60173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      free(properties);
60183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return -1;
60193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
60203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
60213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else if (ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
60223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i=0;i<propcnt;i++) {
60233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      PTPObjectPropDesc opd;
60243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
60253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ret = ptp_mtp_getobjectpropdesc(params, properties[i], map_libmtp_type_to_ptp_type(metadata->filetype), &opd);
60263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret != PTP_RC_OK) {
60273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
60283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				"could not get property description.");
60293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      } else if (opd.GetSet) {
60303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	switch (properties[i]) {
60313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Name:
60323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update title
60333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  ret = set_object_string(device, metadata->item_id, PTP_OPC_Name, metadata->title);
60343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (ret != 0) {
60353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
60363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    "could not set track title.");
60373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
60383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
60393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_AlbumName:
60403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update album
60413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  ret = set_object_string(device, metadata->item_id, PTP_OPC_AlbumName, metadata->album);
60423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (ret != 0) {
60433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
60443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    "could not set track album name.");
60453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
60463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
60473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Artist:
60483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update artist
60493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  ret = set_object_string(device, metadata->item_id, PTP_OPC_Artist, metadata->artist);
60503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (ret != 0) {
60513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
60523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    "could not set track artist name.");
60533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
60543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
60553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Composer:
60563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update composer
60573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  ret = set_object_string(device, metadata->item_id, PTP_OPC_Composer, metadata->composer);
60583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (ret != 0) {
60593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
60603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    "could not set track composer name.");
60613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
60623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
60633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Genre:
60643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update genre
60653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  ret = set_object_string(device, metadata->item_id, PTP_OPC_Genre, metadata->genre);
60663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (ret != 0) {
60673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
60683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    "could not set track genre name.");
60693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
60703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
60713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Duration:
60723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update duration
60733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->duration != 0) {
60743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_u32(device, metadata->item_id, PTP_OPC_Duration, adjust_u32(metadata->duration, &opd));
60753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (ret != 0) {
60763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
60773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				      "could not set track duration.");
60783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
60793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
60803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
60813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Track:
60823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update track number.
60833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->tracknumber != 0) {
60843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_u16(device, metadata->item_id, PTP_OPC_Track, adjust_u16(metadata->tracknumber, &opd));
60853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (ret != 0) {
60863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
60873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				      "could not set track tracknumber.");
60883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
60893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
60903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
60913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_OriginalReleaseDate:
60923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update creation datetime
60933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  ret = set_object_string(device, metadata->item_id, PTP_OPC_OriginalReleaseDate, metadata->date);
60943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (ret != 0) {
60953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
60963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    "could not set track release date.");
60973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
60983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
60993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // These are, well not so important.
61003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_SampleRate:
61013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update sample rate
61023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->samplerate != 0) {
61033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_u32(device, metadata->item_id, PTP_OPC_SampleRate, adjust_u32(metadata->samplerate, &opd));
61043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (ret != 0) {
61053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
61063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				      "could not set samplerate.");
61073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
61083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
61093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
61103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_NumberOfChannels:
61113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update number of channels
61123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->nochannels != 0) {
61133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_u16(device, metadata->item_id, PTP_OPC_NumberOfChannels, adjust_u16(metadata->nochannels, &opd));
61143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (ret != 0) {
61153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
61163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    "could not set number of channels.");
61173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
61183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
61193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
61203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_AudioWAVECodec:
61213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update WAVE codec
61223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->wavecodec != 0) {
61233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_u32(device, metadata->item_id, PTP_OPC_AudioWAVECodec, adjust_u32(metadata->wavecodec, &opd));
61243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (ret != 0) {
61253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
61263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				      "could not set WAVE codec.");
61273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
61283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
61293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
61303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_AudioBitRate:
61313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update bitrate
61323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->bitrate != 0) {
61333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_u32(device, metadata->item_id, PTP_OPC_AudioBitRate, adjust_u32(metadata->bitrate, &opd));
61343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (ret != 0) {
61353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
61363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				      "could not set bitrate.");
61373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
61383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
61393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
61403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_BitRateType:
61413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update bitrate type
61423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->bitratetype != 0) {
61433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_u16(device, metadata->item_id, PTP_OPC_BitRateType, adjust_u16(metadata->bitratetype, &opd));
61443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (ret != 0) {
61453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
61463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				      "could not set bitratetype.");
61473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
61483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
61493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
61503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Rating:
61513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update user rating
61523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // TODO: shall this be set for rating 0?
61533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (metadata->rating != 0) {
61543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_u16(device, metadata->item_id, PTP_OPC_Rating, adjust_u16(metadata->rating, &opd));
61553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (ret != 0) {
61563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
61573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				      "could not set user rating.");
61583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
61593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
61603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
61613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_UseCount:
61623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Update use count, set even to zero if desired.
61633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  ret = set_object_u32(device, metadata->item_id, PTP_OPC_UseCount, adjust_u32(metadata->usecount, &opd));
61643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (ret != 0) {
61653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
61663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  "could not set use count.");
61673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
61683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
61693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_DateModified:
61703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
61713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    // Update modification time if supported
61723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    char *tmpstamp = get_iso8601_stamp();
61733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_string(device, metadata->item_id, PTP_OPC_DateModified, tmpstamp);
61743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (ret != 0) {
61753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
61763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				      "could not set modification date.");
61773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
61783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    free(tmpstamp);
61793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
61803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
61813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
61823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // NOTE: File size is not updated, this should not change anyway.
61833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // neither will we change the filename.
61843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	default:
61853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
61863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
61873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
61883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptp_free_objectpropdesc(&opd);
61893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
61903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
61913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
61923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                            "Your device doesn't seem to support any known way of setting metadata.");
61933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(properties);
61943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
61953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
61963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
61973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // update cached object properties if metadata cache exists
61983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  update_metadata_cache(device, metadata->item_id);
61993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(properties);
62013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
62033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
62043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
62063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function deletes a single file, track, playlist, folder or
62073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * any other object off the MTP device, identified by the object ID.
62083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
62093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * If you delete a folder, there is no guarantee that the device will
62103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * really delete all the files that were in that folder, rather it is
62113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * expected that they will not be deleted, and will turn up in object
62123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * listings with parent set to a non-existant object ID. The safe way
62133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * to do this is to recursively delete all files (and folders) contained
62143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * in the folder, then the folder itself.
62153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
62163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to delete the object from.
62173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id the object to delete.
62183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
62193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
62203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Delete_Object(LIBMTP_mtpdevice_t *device,
62213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			 uint32_t object_id)
62223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
62233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
62243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
62253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_deleteobject(params, object_id, 0);
62273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
62283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Delete_Object(): could not delete object.");
62293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
62303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
62313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
62333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
62343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
62363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Internal function to update an object filename property.
62373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
62383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int set_object_filename(LIBMTP_mtpdevice_t *device,
62393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       uint32_t object_id, uint16_t ptp_type,
62403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       const char **newname_ptr)
62413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
62423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams             *params = (PTPParams *) device->params;
62433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB               *ptp_usb = (PTP_USB*) device->usbinfo;
62443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObjectPropDesc     opd;
62453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t              ret;
62463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  char                  *newname;
62473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // See if we can modify the filename on this kind of files.
62493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectpropdesc(params, PTP_OPC_ObjectFileName, ptp_type, &opd);
62503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
62513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_filename(): "
62523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "could not get property description.");
62533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
62543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
62553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!opd.GetSet) {
62573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_free_objectpropdesc(&opd);
62583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_filename(): "
62593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev            " property is not settable.");
62603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // TODO: we COULD actually upload/download the object here, if we feel
62613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    //       like wasting time for the user.
62623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
62633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
62643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  newname = strdup(*newname_ptr);
62663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) {
62683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    strip_7bit_from_utf8(newname);
62693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
62703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ptp_operation_issupported(params, PTP_OC_MTP_SetObjPropList) &&
62723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      !FLAG_BROKEN_SET_OBJECT_PROPLIST(ptp_usb)) {
62733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    MTPProperties *props = NULL;
62743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    MTPProperties *prop = NULL;
62753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    int nrofprops = 0;
62763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
62783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    prop->ObjectHandle = object_id;
62793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    prop->property = PTP_OPC_ObjectFileName;
62803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    prop->datatype = PTP_DTC_STR;
62813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    prop->propval.str = newname;
62823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_mtp_setobjectproplist(params, props, nrofprops);
62843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_destroy_object_prop_list(props, nrofprops);
62863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
62873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
62883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_filename(): "
62893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev              " could not set object property list.");
62903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        ptp_free_objectpropdesc(&opd);
62913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        return -1;
62923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
62933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else if (ptp_operation_issupported(params, PTP_OC_MTP_SetObjectPropValue)) {
62943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = set_object_string(device, object_id, PTP_OPC_ObjectFileName, newname);
62953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != 0) {
62963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_filename(): "
62973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev              " could not set object filename.");
62983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptp_free_objectpropdesc(&opd);
62993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return -1;
63003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
63013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
63023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(newname);
63033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_filename(): "
63043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev              " your device doesn't seem to support any known way of setting metadata.");
63053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_free_objectpropdesc(&opd);
63063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
63073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
63083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
63093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_free_objectpropdesc(&opd);
63103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
63113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // update cached object properties if metadata cache exists
63123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  update_metadata_cache(device, object_id);
63133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
63143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
63153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
63163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
63173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
63183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function renames a single file.
63193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This simply means that the PTP_OPC_ObjectFileName property
63203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * is updated, if this is supported by the device.
63213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
63223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device that contains the file.
63233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param file the file metadata of the file to rename.
63243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        On success, the filename member is updated. Be aware, that
63253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        this name can be different than newname depending of device restrictions.
63263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param newname the new filename for this object.
63273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
63283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
63293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Set_File_Name(LIBMTP_mtpdevice_t *device,
63303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                   LIBMTP_file_t *file, const char *newname)
63313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
63323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int         ret;
63333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
63343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = set_object_filename(device, file->item_id,
63353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    map_libmtp_type_to_ptp_type(file->filetype),
63363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    &newname);
63373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
63383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != 0) {
63393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return ret;
63403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
63413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
63423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(file->filename);
63433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file->filename = strdup(newname);
63443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return ret;
63453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
63463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
63473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
63483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function renames a single folder.
63493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This simply means that the PTP_OPC_ObjectFileName property
63503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * is updated, if this is supported by the device.
63513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
63523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device that contains the file.
63533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param folder the folder metadata of the folder to rename.
63543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        On success, the name member is updated. Be aware, that
63553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        this name can be different than newname depending of device restrictions.
63563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param newname the new name for this object.
63573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
63583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
63593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Set_Folder_Name(LIBMTP_mtpdevice_t *device,
63603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                   LIBMTP_folder_t *folder, const char* newname)
63613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
63623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int ret;
63633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
63643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = set_object_filename(device, folder->folder_id,
63653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    PTP_OFC_Association,
63663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    &newname);
63673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
63683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != 0) {
63693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return ret;
63703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
63713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
63723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(folder->name);
63733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  folder->name = strdup(newname);
63743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return ret;
63753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
63763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
63773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
63783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function renames a single track.
63793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This simply means that the PTP_OPC_ObjectFileName property
63803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * is updated, if this is supported by the device.
63813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
63823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device that contains the file.
63833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param track the track metadata of the track to rename.
63843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        On success, the filename member is updated. Be aware, that
63853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        this name can be different than newname depending of device restrictions.
63863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param newname the new filename for this object.
63873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
63883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
63893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Set_Track_Name(LIBMTP_mtpdevice_t *device,
63903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                   LIBMTP_track_t *track, const char* newname)
63913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
63923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int         ret;
63933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
63943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = set_object_filename(device, track->item_id,
63953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    map_libmtp_type_to_ptp_type(track->filetype),
63963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    &newname);
63973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
63983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != 0) {
63993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return ret;
64003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
64013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
64023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(track->filename);
64033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  track->filename = strdup(newname);
64043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return ret;
64053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
64063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
64073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
64083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function renames a single playlist object file holder.
64093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This simply means that the <code>PTP_OPC_ObjectFileName</code>
64103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * property is updated, if this is supported by the device.
64113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * The playlist filename should nominally end with an extension
64123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * like ".pla".
64133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
64143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * NOTE: if you want to change the metadata the device display
64153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * about a playlist you must <i>not</i> use this function,
64163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * use <code>LIBMTP_Update_Playlist()</code> instead!
64173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
64183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device that contains the file.
64193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param playlist the playlist metadata of the playlist to rename.
64203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        On success, the name member is updated. Be aware, that
64213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        this name can be different than newname depending of device restrictions.
64223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param newname the new name for this object.
64233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
64243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Update_Playlist()
64253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
64263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Set_Playlist_Name(LIBMTP_mtpdevice_t *device,
64273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                   LIBMTP_playlist_t *playlist, const char* newname)
64283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
64293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int ret;
64303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
64313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = set_object_filename(device, playlist->playlist_id,
64323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    PTP_OFC_MTP_AbstractAudioVideoPlaylist,
64333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    &newname);
64343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
64353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != 0) {
64363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return ret;
64373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
64383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
64393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(playlist->name);
64403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  playlist->name = strdup(newname);
64413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return ret;
64423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
64433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
64443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
64453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function renames a single album.
64463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This simply means that the <code>PTP_OPC_ObjectFileName</code>
64473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * property is updated, if this is supported by the device.
64483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * The album filename should nominally end with an extension
64493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * like ".alb".
64503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
64513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * NOTE: if you want to change the metadata the device display
64523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * about a playlist you must <i>not</i> use this function,
64533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * use <code>LIBMTP_Update_Album()</code> instead!
64543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
64553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device that contains the file.
64563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param album the album metadata of the album to rename.
64573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        On success, the name member is updated. Be aware, that
64583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        this name can be different than newname depending of device restrictions.
64593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param newname the new name for this object.
64603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
64613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Update_Album()
64623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
64633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Set_Album_Name(LIBMTP_mtpdevice_t *device,
64643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                   LIBMTP_album_t *album, const char* newname)
64653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
64663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int ret;
64673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
64683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = set_object_filename(device, album->album_id,
64693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    PTP_OFC_MTP_AbstractAudioAlbum,
64703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    &newname);
64713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
64723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != 0) {
64733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return ret;
64743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
64753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
64763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(album->name);
64773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  album->name = strdup(newname);
64783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return ret;
64793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
64803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
64813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
64823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * THIS FUNCTION IS DEPRECATED. PLEASE UPDATE YOUR CODE IN ORDER
64833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * NOT TO USE IT.
64843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
64853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Set_File_Name()
64863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Set_Track_Name()
64873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Set_Folder_Name()
64883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Set_Playlist_Name()
64893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Set_Album_Name()
64903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
64913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Set_Object_Filename(LIBMTP_mtpdevice_t *device,
64923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                   uint32_t object_id, char* newname)
64933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
64943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int             ret;
64953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_file_t   *file;
64963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
64973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  file = LIBMTP_Get_Filemetadata(device, object_id);
64983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
64993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (file == NULL) {
65003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Set_Object_Filename(): "
65013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "could not get file metadata for target object.");
65023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
65033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
65043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
65053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = set_object_filename(device, object_id, map_libmtp_type_to_ptp_type(file->filetype), (const char **) &newname);
65063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
65073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(file);
65083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
65093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return ret;
65103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
65113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
65123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
65133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Helper function. This indicates if a track exists on the device
65143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the track from.
65153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param id the track ID of the track to retrieve.
65163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return TRUE (!=0) if the track exists, FALSE (0) if not
65173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
65183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Track_Exists(LIBMTP_mtpdevice_t *device,
65193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev           uint32_t const id)
65203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
65213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
65223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
65233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObject *ob;
65243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
65253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_object_want (params, id, 0, &ob);
65263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret == PTP_RC_OK)
65273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return -1;
65283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
65293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
65303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
65313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
65323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This creates a new folder structure and allocates memory
65333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * for it. Notice that if you add strings to this structure they
65343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * will be freed by the corresponding <code>LIBMTP_folder_track_t</code>
65353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * operation later, so be careful of using strdup() when assigning
65363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * strings, e.g.:
65373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
65383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a pointer to the newly allocated folder structure.
65393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_destroy_folder_t()
65403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
65413aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_folder_t *LIBMTP_new_folder_t(void)
65423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
65433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_folder_t *new = (LIBMTP_folder_t *) malloc(sizeof(LIBMTP_folder_t));
65443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (new == NULL) {
65453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
65463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
65473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->folder_id = 0;
65483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->parent_id = 0;
65493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->storage_id = 0;
65503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->name = NULL;
65513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->sibling = NULL;
65523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->child = NULL;
65533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return new;
65543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
65553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
65563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
65573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This recursively deletes the memory for a folder structure.
65583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This shall typically be called on a top-level folder list to
65593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * detsroy the entire folder tree.
65603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
65613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param folder folder structure to destroy
65623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_new_folder_t()
65633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
65643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_destroy_folder_t(LIBMTP_folder_t *folder)
65653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
65663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
65673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(folder == NULL) {
65683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     return;
65693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
65703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
65713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  //Destroy from the bottom up
65723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(folder->child != NULL) {
65733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     LIBMTP_destroy_folder_t(folder->child);
65743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
65753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
65763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(folder->sibling != NULL) {
65773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_destroy_folder_t(folder->sibling);
65783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
65793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
65803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(folder->name != NULL) {
65813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(folder->name);
65823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
65833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
65843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(folder);
65853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
65863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
65873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
65883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Helper function. Returns a folder structure for a
65893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * specified id.
65903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
65913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param folderlist list of folders to search
65923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @id id of folder to look for
65933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a folder or NULL if not found
65943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
65953aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_folder_t *LIBMTP_Find_Folder(LIBMTP_folder_t *folderlist, uint32_t id)
65963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
65973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_folder_t *ret = NULL;
65983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
65993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(folderlist == NULL) {
66003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
66013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
66023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(folderlist->folder_id == id) {
66043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return folderlist;
66053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
66063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(folderlist->sibling) {
66083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = LIBMTP_Find_Folder(folderlist->sibling, id);
66093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
66103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(folderlist->child && ret == NULL) {
66123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = LIBMTP_Find_Folder(folderlist->child, id);
66133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
66143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return ret;
66163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
66173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
66193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Function used to recursively get subfolders from params.
66203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
66213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic LIBMTP_folder_t *get_subfolders_for_folder(LIBMTP_folder_t *list, uint32_t parent)
66223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
66233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_folder_t *retfolders = NULL, *children, *iter, *curr;
66243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  iter = list->sibling;
66263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  while(iter != list) {
66273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (iter->parent_id != parent) {
66283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      iter = iter->sibling;
66293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      continue;
66303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
66313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* We know that iter is a child of 'parent', therefore we can safely
66333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * hold on to 'iter' locally since no one else will steal it
66343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * from the 'list' as we recurse. */
66353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    children = get_subfolders_for_folder(list, iter->folder_id);
66363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    curr = iter;
66383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    iter = iter->sibling;
66393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Remove curr from the list.
66413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    curr->child->sibling = curr->sibling;
66423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    curr->sibling->child = curr->child;
66433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Attach the children to curr.
66453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    curr->child = children;
66463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Put this folder into the list of siblings.
66483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    curr->sibling = retfolders;
66493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retfolders = curr;
66503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
66513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retfolders;
66533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
66543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
66563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This returns a list of all folders available
66573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * on the current MTP device.
66583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
66593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the folder listing for.
66603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a list of folders
66613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
66623aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_folder_t *LIBMTP_Get_Folder_List(LIBMTP_mtpdevice_t *device)
66633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
66643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
66653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_folder_t head, *rv;
66663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int i;
66673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Get all the handles if we haven't already done that
66693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->nrofobjects == 0) {
66703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    flush_handles(device);
66713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
66723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
66743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * This creates a temporary list of the folders, this is in a
66753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * reverse order and uses the Folder pointers that are already
66763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * in the Folder structure. From this we can then build up the
66773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * folder hierarchy with only looking at this temporary list,
66783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * and removing the folders from this temporary list as we go.
66793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * This significantly reduces the number of operations that we
66803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * have to do in building the folder hierarchy. Also since the
66813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * temp list is in reverse order, when we prepend to the sibling
66823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * list things are in the same order as they were originally
66833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * in the handle list.
66843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   */
66853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  head.sibling = &head;
66863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  head.child = &head;
66873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i = 0; i < params->nrofobjects; i++) {
66883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_folder_t *folder;
66893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTPObject *ob;
66903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
66913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ob = &params->objects[i];
66923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ob->oi.ObjectFormat != PTP_OFC_Association) {
66933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      continue;
66943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
66953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /*
66963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * Do we know how to handle these? They are part
66973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * of the MTP 1.0 specification paragraph 3.6.4.
66983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * For AssociationDesc 0x00000001U ptp_mtp_getobjectreferences()
66993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * should be called on these to get the contained objects, but
67003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * we basically don't care. Hopefully parent_id is maintained for all
67013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * children, because we rely on that instead.
67023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     */
67033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ob->oi.AssociationDesc != 0x00000000U) {
67043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      printf("MTP extended association type 0x%08x encountered\n", ob->oi.AssociationDesc);
67053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
67063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
67073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Create a folder struct...
67083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    folder = LIBMTP_new_folder_t();
67093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (folder == NULL) {
67103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // malloc failure or so.
67113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return NULL;
67123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
67133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    folder->folder_id = ob->oid;
67143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    folder->parent_id = ob->oi.ParentObject;
67153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    folder->storage_id = ob->oi.StorageID;
67163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    folder->name = (ob->oi.Filename) ? (char *)strdup(ob->oi.Filename) : NULL;
67173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
67183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // pretend sibling says next, and child says prev.
67193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    folder->sibling = head.sibling;
67203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    folder->child = &head;
67213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    head.sibling->child = folder;
67223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    head.sibling = folder;
67233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
67243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
67253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // We begin at the root folder and get them all recursively
67263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  rv = get_subfolders_for_folder(&head, 0x00000000);
67273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
67283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // The temp list should be empty. Clean up any orphans just in case.
67293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  while(head.sibling != &head) {
67303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_folder_t *curr = head.sibling;
67313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
67323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    printf("Orphan folder with ID: 0x%08x name: \"%s\" encountered.\n",
67333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	   curr->folder_id,
67343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	   curr->name);
67353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    curr->sibling->child = curr->child;
67363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    curr->child->sibling = curr->sibling;
67373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    curr->child = NULL;
67383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    curr->sibling = NULL;
67393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_destroy_folder_t(curr);
67403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
67413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
67423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return rv;
67433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
67443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
67453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
67463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This create a folder on the current MTP device. The PTP name
67473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * for a folder is "association". The PTP/MTP devices does not
67483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * have an internal "folder" concept really, it contains a flat
67493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * list of all files and some file are "associations" that other
67503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * files and folders may refer to as its "parent".
67513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
67523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to create the folder on.
67533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param name the name of the new folder. Note this can be modified
67543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        if the device does not support all the characters in the
67553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        name.
67563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param parent_id id of parent folder to add the new folder to,
67573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        or 0 to put it in the root directory.
67583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param storage_id id of the storage to add this new folder to.
67593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        notice that you cannot mismatch storage id and parent id:
67603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        they must both be on the same storage! Pass in 0 if you
67613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        want to create this folder on the default storage.
67623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return id to new folder or 0 if an error occured
67633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
67643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevuint32_t LIBMTP_Create_Folder(LIBMTP_mtpdevice_t *device, char *name,
67653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      uint32_t parent_id, uint32_t storage_id)
67663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
67673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
67683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
67693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t parenthandle = 0;
67703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t store;
67713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObjectInfo new_folder;
67723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
67733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t new_id = 0;
67743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
67753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (storage_id == 0) {
67763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // I'm just guessing that a folder may require 512 bytes
67773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    store = get_writeable_storageid(device, 512);
67783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
67793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    store = storage_id;
67803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
6781ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev
6782ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev  if (parent_id == 0) {
6783ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev    parent_id = 0xFFFFFFFFU; // Set to -1
6784ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev  }
6785ad8fdfb856407f0c1f2c2b0305c8fa0a062736b1Yavor Goulishev
67863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  parenthandle = parent_id;
67873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
67883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  memset(&new_folder, 0, sizeof(new_folder));
67893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new_folder.Filename = name;
67903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) {
67913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    strip_7bit_from_utf8(new_folder.Filename);
67923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
67933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new_folder.ObjectCompressedSize = 1;
67943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new_folder.ObjectFormat = PTP_OFC_Association;
67953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new_folder.ProtectionStatus = PTP_PS_NoProtection;
67963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new_folder.AssociationType = PTP_AT_GenericFolder;
67973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new_folder.ParentObject = parent_id;
67983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new_folder.StorageID = store;
67993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
68003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Create the object
68013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // FIXME: use send list here if available.
68023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_sendobjectinfo(params, &store, &parenthandle, &new_id, &new_folder);
68033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
68043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Create_Folder: Could not send object info.");
68053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret == PTP_RC_AccessDenied) {
68063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_ptp_error_to_errorstack(device, ret, "ACCESS DENIED.");
68073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
68083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return 0;
68093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
68103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // NOTE: don't destroy the new_folder objectinfo, because it is statically referencing
68113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // several strings.
68123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
68133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  add_object_to_cache(device, new_id);
68143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
68153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return new_id;
68163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
68173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
68183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
68193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This creates a new playlist metadata structure and allocates memory
68203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * for it. Notice that if you add strings to this structure they
68213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * will be freed by the corresponding <code>LIBMTP_destroy_playlist_t</code>
68223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * operation later, so be careful of using strdup() when assigning
68233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * strings, e.g.:
68243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
68253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <pre>
68263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * LIBMTP_playlist_t *pl = LIBMTP_new_playlist_t();
68273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * pl->name = strdup(str);
68283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * ....
68293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * LIBMTP_destroy_playlist_t(pl);
68303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * </pre>
68313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
68323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a pointer to the newly allocated metadata structure.
68333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_destroy_playlist_t()
68343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
68353aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_playlist_t *LIBMTP_new_playlist_t(void)
68363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
68373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_playlist_t *new = (LIBMTP_playlist_t *) malloc(sizeof(LIBMTP_playlist_t));
68383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (new == NULL) {
68393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
68403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
68413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->playlist_id = 0;
68423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->parent_id = 0;
68433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->storage_id = 0;
68443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->name = NULL;
68453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->tracks = NULL;
68463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->no_tracks = 0;
68473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->next = NULL;
68483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return new;
68493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
68503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
68513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
68523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This destroys a playlist metadata structure and deallocates the memory
68533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * used by it, including any strings. Never use a track metadata
68543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * structure again after calling this function on it.
68553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param playlist the playlist metadata to destroy.
68563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_new_playlist_t()
68573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
68583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_destroy_playlist_t(LIBMTP_playlist_t *playlist)
68593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
68603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (playlist == NULL) {
68613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return;
68623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
68633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (playlist->name != NULL)
68643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(playlist->name);
68653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (playlist->tracks != NULL)
68663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(playlist->tracks);
68673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(playlist);
68683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return;
68693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
68703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
68713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
68723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function returns a list of the playlists available on the
68733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * device. Typical usage:
68743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
68753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * <pre>
68763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * </pre>
68773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
68783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the playlist listing from.
68793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a playlist list on success, else NULL. If there are no playlists
68803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         on the device, NULL will be returned as well.
68813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Playlist()
68823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
68833aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_playlist_t *LIBMTP_Get_Playlist_List(LIBMTP_mtpdevice_t *device)
68843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
68853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
68863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  const int REQ_SPL = FLAG_PLAYLIST_SPL(ptp_usb);
68873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
68883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_playlist_t *retlists = NULL;
68893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_playlist_t *curlist = NULL;
68903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t i;
68913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
68923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Get all the handles if we haven't already done that
68933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->nrofobjects == 0) {
68943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    flush_handles(device);
68953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
68963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
68973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i = 0; i < params->nrofobjects; i++) {
68983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_playlist_t *pl;
68993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTPObject *ob;
69003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    uint16_t ret;
69013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ob = &params->objects[i];
69033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Ignore stuff that isn't playlists
69053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // For Samsung players we must look for the .spl extension explicitly since
69073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // playlists are not stored as playlist objects.
69083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if ( REQ_SPL && is_spl_playlist(&ob->oi) ) {
69093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Allocate a new playlist type
69103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      pl = LIBMTP_new_playlist_t();
69113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      spl_to_playlist_t(device, &ob->oi, ob->oid, pl);
69123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
69133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else if ( ob->oi.ObjectFormat != PTP_OFC_MTP_AbstractAudioVideoPlaylist ) {
69143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      continue;
69153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
69163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else {
69173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Allocate a new playlist type
69183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      pl = LIBMTP_new_playlist_t();
69193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Try to look up proper name, else use the oi->Filename field.
69213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      pl->name = get_string_from_object(device, ob->oid, PTP_OPC_Name);
69223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (pl->name == NULL) {
69233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	pl->name = strdup(ob->oi.Filename);
69243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
69253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      pl->playlist_id = ob->oid;
69263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      pl->parent_id = ob->oi.ParentObject;
69273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      pl->storage_id = ob->oi.StorageID;
69283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Then get the track listing for this playlist
69303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ret = ptp_mtp_getobjectreferences(params, pl->playlist_id, &pl->tracks, &pl->no_tracks);
69313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret != PTP_RC_OK) {
69323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Playlist_List(): "
69333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    "could not get object references.");
69343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        pl->tracks = NULL;
69353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        pl->no_tracks = 0;
69363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
69373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
69383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Add playlist to a list that will be returned afterwards.
69403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (retlists == NULL) {
69413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      retlists = pl;
69423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curlist = pl;
69433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
69443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curlist->next = pl;
69453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curlist = pl;
69463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
69473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Call callback here if we decide to add that possibility...
69493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
69503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retlists;
69513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
69523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
69553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function retrieves an individual playlist from the device.
69563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the playlist from.
69573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param plid the unique ID of the playlist to retrieve.
69583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a valid playlist metadata post or NULL on failure.
69593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Playlist_List()
69603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
69613aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_playlist_t *LIBMTP_Get_Playlist(LIBMTP_mtpdevice_t *device, uint32_t const plid)
69623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
69633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
69643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  const int REQ_SPL = FLAG_PLAYLIST_SPL(ptp_usb);
69653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
69663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObject *ob;
69673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_playlist_t *pl;
69683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
69693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Get all the handles if we haven't already done that
69713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->nrofobjects == 0) {
69723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    flush_handles(device);
69733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
69743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_object_want (params, plid, PTPOBJECT_OBJECTINFO_LOADED, &ob);
69763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK)
69773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
69783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // For Samsung players we must look for the .spl extension explicitly since
69803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // playlists are not stored as playlist objects.
69813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if ( REQ_SPL && is_spl_playlist(&ob->oi) ) {
69823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Allocate a new playlist type
69833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    pl = LIBMTP_new_playlist_t();
69843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    spl_to_playlist_t(device, &ob->oi, ob->oid, pl);
69853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return pl;
69863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
69873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Ignore stuff that isn't playlists
69893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  else if ( ob->oi.ObjectFormat != PTP_OFC_MTP_AbstractAudioVideoPlaylist ) {
69903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
69913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
69923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Allocate a new playlist type
69943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  pl = LIBMTP_new_playlist_t();
69953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
69963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  pl->name = get_string_from_object(device, ob->oid, PTP_OPC_Name);
69973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (pl->name == NULL) {
69983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    pl->name = strdup(ob->oi.Filename);
69993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
70003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  pl->playlist_id = ob->oid;
70013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  pl->parent_id = ob->oi.ParentObject;
70023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  pl->storage_id = ob->oi.StorageID;
70033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
70043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Then get the track listing for this playlist
70053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectreferences(params, pl->playlist_id, &pl->tracks, &pl->no_tracks);
70063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
70073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Playlist(): Could not get object references.");
70083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    pl->tracks = NULL;
70093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    pl->no_tracks = 0;
70103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
70113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
70123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return pl;
70133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
70143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
70153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
70163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function creates a new abstract list such as a playlist
70173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * or an album.
70183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
70193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to create the new abstract list
70203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        on.
70213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param name the name of the new abstract list.
70223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param artist the artist of the new abstract list or NULL.
70233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param genre the genre of the new abstract list or NULL.
70243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param parenthandle the handle of the parent or 0 for no parent
70253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        i.e. the root folder.
70263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param objectformat the abstract list type to create.
70273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param suffix the ".foo" (4 characters) suffix to use for the virtual
70283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        "file" created by this operation.
70293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param newid a pointer to a variable that will hold the new object
70303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        ID if this call is successful.
70313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param tracks an array of tracks to associate with this list.
70323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param no_tracks the number of tracks in the list.
70333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
70343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
70353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int create_new_abstract_list(LIBMTP_mtpdevice_t *device,
70363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    char const * const name,
70373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    char const * const artist,
70383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    char const * const composer,
70393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    char const * const genre,
70403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint32_t const parenthandle,
70413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint32_t const storageid,
70423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint16_t const objectformat,
70433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    char const * const suffix,
70443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint32_t * const newid,
70453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint32_t const * const tracks,
70463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    uint32_t const no_tracks)
70473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
70483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
70493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int i;
70503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int supported = 0;
70513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
70523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t *properties = NULL;
70533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t propcnt = 0;
70543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t store;
70553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t localph = parenthandle;
70563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint8_t nonconsumable = 0x00U; /* By default it is consumable */
70573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
70583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
70593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  char fname[256];
70603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint8_t data[2];
70613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
70623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (storageid == 0) {
70633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // I'm just guessing that an abstract list may require 512 bytes
70643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    store = get_writeable_storageid(device, 512);
70653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
70663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    store = storageid;
70673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
70683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
70693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Check if we can create an object of this type
70703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for ( i=0; i < params->deviceinfo.ImageFormats_len; i++ ) {
70713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (params->deviceinfo.ImageFormats[i] == objectformat) {
70723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      supported = 1;
70733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
70743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
70753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
70763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!supported) {
70773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): player does not support this abstract type.");
70783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    printf("Unsupported abstract list type: %04x\n", objectformat);
70793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
70803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
70813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
70823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // add the new suffix if it isn't there
70833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  fname[0] = '\0';
70843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (strlen(name) > strlen(suffix)) {
70853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    char const * const suff = &name[strlen(name)-strlen(suffix)];
70863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (!strcmp(suff, suffix)) {
70873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Home free.
70883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      strncpy(fname, name, sizeof(fname));
70893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
70903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
70913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // If it didn't end with "<suffix>" then add that here.
70923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (fname[0] == '\0') {
70933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    strncpy(fname, name, sizeof(fname)-strlen(suffix)-1);
70943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    strcat(fname, suffix);
70953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    fname[sizeof(fname)-1] = '\0';
70963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
70973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
70983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ptp_operation_issupported(params, PTP_OC_MTP_SendObjectPropList) &&
70993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      !FLAG_BROKEN_SEND_OBJECT_PROPLIST(ptp_usb)) {
71003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    MTPProperties *props = NULL;
71013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    MTPProperties *prop = NULL;
71023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    int nrofprops = 0;
71033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
71043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    *newid = 0x00000000U;
71053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
71063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_mtp_getobjectpropssupported(params, objectformat, &propcnt, &properties);
71073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
71083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i=0;i<propcnt;i++) {
71093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      PTPObjectPropDesc opd;
71103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
71113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ret = ptp_mtp_getobjectpropdesc(params, properties[i], objectformat, &opd);
71123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret != PTP_RC_OK) {
71133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): "
71143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				"could not get property description.");
71153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      } else if (opd.GetSet) {
71163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	switch (properties[i]) {
71173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_ObjectFileName:
71183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
71193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = *newid;
71203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_ObjectFileName;
71213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_STR;
71223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.str = strdup(fname);
71233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) {
71243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    strip_7bit_from_utf8(prop->propval.str);
71253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
71263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
71273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_ProtectionStatus:
71283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
71293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = *newid;
71303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_ProtectionStatus;
71313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_UINT16;
71323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.u16 = 0x0000U; /* Not protected */
71333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
71343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_NonConsumable:
71353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
71363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = *newid;
71373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_NonConsumable;
71383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_UINT8;
71393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->propval.u8 = nonconsumable;
71403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
71413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Name:
71423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (name != NULL) {
71433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
71443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->ObjectHandle = *newid;
71453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->property = PTP_OPC_Name;
71463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->datatype = PTP_DTC_STR;
71473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = strdup(name);
71483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
71493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
71503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_AlbumArtist:
71513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (artist != NULL) {
71523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
71533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->ObjectHandle = *newid;
71543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->property = PTP_OPC_AlbumArtist;
71553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->datatype = PTP_DTC_STR;
71563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = strdup(artist);
71573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
71583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
71593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Artist:
71603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (artist != NULL) {
71613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
71623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->ObjectHandle = *newid;
71633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->property = PTP_OPC_Artist;
71643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->datatype = PTP_DTC_STR;
71653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = strdup(artist);
71663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
71673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
71683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Composer:
71693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (composer != NULL) {
71703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
71713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->ObjectHandle = *newid;
71723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->property = PTP_OPC_Composer;
71733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->datatype = PTP_DTC_STR;
71743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = strdup(composer);
71753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
71763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
71773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Genre:
71783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (genre != NULL) {
71793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
71803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->ObjectHandle = *newid;
71813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->property = PTP_OPC_Genre;
71823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->datatype = PTP_DTC_STR;
71833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = strdup(genre);
71843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
71853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
71863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 	case PTP_OPC_DateModified:
71873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  // Tag with current time if that is supported
71883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
71893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
71903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->ObjectHandle = *newid;
71913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->property = PTP_OPC_DateModified;
71923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->datatype = PTP_DTC_STR;
71933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = get_iso8601_stamp();
71943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
71953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
71963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
71973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
71983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptp_free_objectpropdesc(&opd);
71993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
72003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(properties);
72013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
72023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_mtp_sendobjectproplist(params, &store, &localph, newid,
72033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				     objectformat, 0, props, nrofprops);
72043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
72053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* Free property list */
72063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_destroy_object_prop_list(props, nrofprops);
72073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
72083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
72093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_ptp_error_to_errorstack(device, ret, "create_new_abstract_list(): Could not send object property list.");
72103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret == PTP_RC_AccessDenied) {
72113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	add_ptp_error_to_errorstack(device, ret, "ACCESS DENIED.");
72123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
72133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return -1;
72143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
72153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
72163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // now send the blank object
72173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_sendobject(params, NULL, 0);
72183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
72193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_ptp_error_to_errorstack(device, ret, "create_new_abstract_list(): Could not send blank object data.");
72203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return -1;
72213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
72223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
72233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else if (ptp_operation_issupported(params,PTP_OC_SendObjectInfo)) {
72243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTPObjectInfo new_object;
72253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
72263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new_object.Filename = fname;
72273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) {
72283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      strip_7bit_from_utf8(new_object.Filename);
72293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
72303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new_object.ObjectCompressedSize = 1;
72313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    new_object.ObjectFormat = objectformat;
72323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
72333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Create the object
72343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_sendobjectinfo(params, &store, &localph, newid, &new_object);
72353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
72363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_ptp_error_to_errorstack(device, ret, "create_new_abstract_list(): Could not send object info (the playlist itself).");
72373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret == PTP_RC_AccessDenied) {
72383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	add_ptp_error_to_errorstack(device, ret, "ACCESS DENIED.");
72393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
72403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return -1;
72413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
72423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // NOTE: don't destroy new_object objectinfo afterwards - the strings it contains are
72433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // not copies.
72443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /*
72453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * We have to send this one blank data byte.
72463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * If we don't, the handle will not be created and thus there is no playlist.
72473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     */
72483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    data[0] = '\0';
72493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    data[1] = '\0';
72503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_sendobject(params, data, 1);
72513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
72523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_ptp_error_to_errorstack(device, ret, "create_new_abstract_list(): Could not send blank object data.");
72533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return -1;
72543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
72553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
72563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // set the properties one by one
72573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_mtp_getobjectpropssupported(params, objectformat, &propcnt, &properties);
72583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
72593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i=0;i<propcnt;i++) {
72603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      PTPObjectPropDesc opd;
72613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
72623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ret = ptp_mtp_getobjectpropdesc(params, properties[i], objectformat, &opd);
72633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret != PTP_RC_OK) {
72643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): "
72653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				"could not get property description.");
72663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      } else if (opd.GetSet) {
72673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	switch (properties[i]) {
72683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Name:
72693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (name != NULL) {
72703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_string(device, *newid, PTP_OPC_Name, name);
72713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (ret != 0) {
72723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): could not set entity name.");
72733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      return -1;
72743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
72753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
72763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
72773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_AlbumArtist:
72783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (artist != NULL) {
72793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_string(device, *newid, PTP_OPC_AlbumArtist, artist);
72803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (ret != 0) {
72813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): could not set entity album artist.");
72823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      return -1;
72833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
72843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
72853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
72863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Artist:
72873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (artist != NULL) {
72883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_string(device, *newid, PTP_OPC_Artist, artist);
72893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (ret != 0) {
72903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): could not set entity artist.");
72913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      return -1;
72923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
72933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
72943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
72953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Composer:
72963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (composer != NULL) {
72973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_string(device, *newid, PTP_OPC_Composer, composer);
72983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (ret != 0) {
72993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): could not set entity composer.");
73003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      return -1;
73013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
73023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
73033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
73043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Genre:
73053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (genre != NULL) {
73063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_string(device, *newid, PTP_OPC_Genre, genre);
73073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (ret != 0) {
73083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): could not set entity genre.");
73093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      return -1;
73103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
73113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
73123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
73133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 	case PTP_OPC_DateModified:
73143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
73153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    ret = set_object_string(device, *newid, PTP_OPC_DateModified, get_iso8601_stamp());
73163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    if (ret != 0) {
73173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): could not set date modified.");
73183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	      return -1;
73193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    }
73203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
73213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
73223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
73233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
73243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptp_free_objectpropdesc(&opd);
73253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
73263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(properties);
73273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
73283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
73293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (no_tracks > 0) {
73303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Add tracks to the list as object references.
73313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_mtp_setobjectreferences (params, *newid, (uint32_t *) tracks, no_tracks);
73323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
73333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_ptp_error_to_errorstack(device, ret, "create_new_abstract_list(): could not add tracks as object references.");
73343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return -1;
73353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
73363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
73373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
73383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  add_object_to_cache(device, *newid);
73393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
73403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
73413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
73423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
73433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
73443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This updates the metadata and track listing
73453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * for an abstract list.
73463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device that the abstract list
73473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        resides on.
73483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param name the name of the abstract list.
73493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param artist the artist of the abstract list or NULL.
73503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param genre the genre of the abstract list or NULL.
73513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param objecthandle the object to be updated.
73523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param objectformat the abstract list type to update.
73533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param tracks an array of tracks to associate with this list.
73543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param no_tracks the number of tracks in the list.
73553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
73563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
73573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic int update_abstract_list(LIBMTP_mtpdevice_t *device,
73583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				char const * const name,
73593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				char const * const artist,
73603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				char const * const composer,
73613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				char const * const genre,
73623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				uint32_t const objecthandle,
73633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				uint16_t const objectformat,
73643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				uint32_t const * const tracks,
73653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				uint32_t const no_tracks)
73663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
73673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
73683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
73693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
73703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t *properties = NULL;
73713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t propcnt = 0;
73723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int i;
73733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
73743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // First see which properties can be set
73753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // i.e only try to update this metadata for object tags that exist on the current player.
73763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectpropssupported(params, objectformat, &propcnt, &properties);
73773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
73783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Just bail out for now, nothing is ever set.
73793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
73803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    "could not retrieve supported object properties.");
73813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
73823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
73833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ptp_operation_issupported(params,PTP_OC_MTP_SetObjPropList) &&
73843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      !FLAG_BROKEN_SET_OBJECT_PROPLIST(ptp_usb)) {
73853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    MTPProperties *props = NULL;
73863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    MTPProperties *prop = NULL;
73873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    int nrofprops = 0;
73883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
73893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i=0;i<propcnt;i++) {
73903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      PTPObjectPropDesc opd;
73913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
73923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ret = ptp_mtp_getobjectpropdesc(params, properties[i], objectformat, &opd);
73933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret != PTP_RC_OK) {
73943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
73953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				"could not get property description.");
73963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      } else if (opd.GetSet) {
73973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	switch (properties[i]) {
73983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Name:
73993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
74003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->ObjectHandle = objecthandle;
74013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->property = PTP_OPC_Name;
74023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  prop->datatype = PTP_DTC_STR;
74033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (name != NULL)
74043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = strdup(name);
74053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
74063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_AlbumArtist:
74073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (artist != NULL) {
74083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
74093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->ObjectHandle = objecthandle;
74103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->property = PTP_OPC_AlbumArtist;
74113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->datatype = PTP_DTC_STR;
74123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = strdup(artist);
74133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
74143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
74153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Artist:
74163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (artist != NULL) {
74173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
74183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->ObjectHandle = objecthandle;
74193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->property = PTP_OPC_Artist;
74203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->datatype = PTP_DTC_STR;
74213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = strdup(artist);
74223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
74233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
74243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Composer:
74253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (composer != NULL) {
74263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
74273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->ObjectHandle = objecthandle;
74283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->property = PTP_OPC_Composer;
74293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->datatype = PTP_DTC_STR;
74303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = strdup(composer);
74313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
74323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
74333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Genre:
74343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (genre != NULL) {
74353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
74363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->ObjectHandle = objecthandle;
74373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->property = PTP_OPC_Genre;
74383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->datatype = PTP_DTC_STR;
74393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = strdup(genre);
74403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
74413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
74423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 	case PTP_OPC_DateModified:
74433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
74443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    // Tag with current time if that is supported
74453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
74463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->ObjectHandle = objecthandle;
74473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->property = PTP_OPC_DateModified;
74483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->datatype = PTP_DTC_STR;
74493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    prop->propval.str = get_iso8601_stamp();
74503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
74513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
74523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	default:
74533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
74543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
74553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
74563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptp_free_objectpropdesc(&opd);
74573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
74583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
74593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // proplist could be NULL if we can't write any properties
74603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (props != NULL) {
74613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ret = ptp_mtp_setobjectproplist(params, props, nrofprops);
74623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
74633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptp_destroy_object_prop_list(props, nrofprops);
74643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
74653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (ret != PTP_RC_OK) {
74663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        // TODO: return error of which property we couldn't set
74673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
74683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                                "could not set object property list.");
74693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        free(properties);
74703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        return -1;
74713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
74723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
74733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
74743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else if (ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
74753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i=0;i<propcnt;i++) {
74763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      switch (properties[i]) {
74773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_OPC_Name:
74783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// Update title
74793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ret = set_object_string(device, objecthandle, PTP_OPC_Name, name);
74803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (ret != 0) {
74813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
74823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  "could not set title.");
74833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
74843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
74853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_OPC_AlbumArtist:
74863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// Update album artist
74873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ret = set_object_string(device, objecthandle, PTP_OPC_AlbumArtist, artist);
74883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (ret != 0) {
74893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
74903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  "could not set album artist name.");
74913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
74923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
74933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_OPC_Artist:
74943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// Update artist
74953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ret = set_object_string(device, objecthandle, PTP_OPC_Artist, artist);
74963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (ret != 0) {
74973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
74983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  "could not set artist name.");
74993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
75003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_OPC_Composer:
75013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// Update composer
75023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ret = set_object_string(device, objecthandle, PTP_OPC_Composer, composer);
75033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (ret != 0) {
75043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
75053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  "could not set composer name.");
75063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
75073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
75083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_OPC_Genre:
75093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// Update genre
75103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	ret = set_object_string(device, objecthandle, PTP_OPC_Genre, genre);
75113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (ret != 0) {
75123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
75133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  "could not set genre.");
75143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
75153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
75163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      case PTP_OPC_DateModified:
75173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	// Update date modified
75183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
75193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  char *tmpdate = get_iso8601_stamp();
75203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  ret = set_object_string(device, objecthandle, PTP_OPC_DateModified, tmpdate);
75213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (ret != 0) {
75223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
75233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				    "could not set modification date.");
75243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  }
75253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  free(tmpdate);
75263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
75273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      default:
75283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	break;
75293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
75303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
75313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
75323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
75333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                            "Your device doesn't seem to support any known way of setting metadata.");
75343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(properties);
75353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
75363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
75373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
75383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Then the object references...
75393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_setobjectreferences (params, objecthandle, (uint32_t *) tracks, no_tracks);
75403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
75413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "update_abstract_list(): could not add tracks as object references.");
75423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(properties);
75433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
75443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
75453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
75463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(properties);
75473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
75483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  update_metadata_cache(device, objecthandle);
75493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
75503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
75513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
75523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
75533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
75543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
75553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This routine creates a new playlist based on the metadata
75563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * supplied. If the <code>tracks</code> field of the metadata
75573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * contains a track listing, these tracks will be added to the
75583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * playlist.
75593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to create the new playlist on.
75603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param metadata the metadata for the new playlist. If the function
75613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        exits with success, the <code>playlist_id</code> field of this
75623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        struct will contain the new playlist ID of the playlist.
75633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <ul>
75643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>metadata-&gt;parent_id</code> should be set to the parent
75653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        (e.g. folder) to store this track in. Since some
75663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        devices are a bit picky about where files
75673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        are placed, a default folder will be chosen if libmtp
75683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        has detected one for the current filetype and this
75693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        parameter is set to 0. If this is 0 and no default folder
75703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        can be found, the file will be stored in the root folder.
75713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>metadata-&gt;storage_id</code> should be set to the
75723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        desired storage (e.g. memory card or whatever your device
75733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        presents) to store this track in. Setting this to 0 will store
75743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        the track on the primary storage.
75753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        </ul>
75763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
75773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Update_Playlist()
75783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Delete_Object()
75793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
75803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Create_New_Playlist(LIBMTP_mtpdevice_t *device,
75813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       LIBMTP_playlist_t * const metadata)
75823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
75833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
75843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t localph = metadata->parent_id;
75853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
75863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Use a default folder if none given
75873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (localph == 0) {
75883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (device->default_playlist_folder != 0)
75893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      localph = device->default_playlist_folder;
75903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else
75913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      localph = device->default_music_folder;
75923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
75933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  metadata->parent_id = localph;
75943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
75953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Samsung needs its own special type of playlists
75963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(FLAG_PLAYLIST_SPL(ptp_usb)) {
75973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return playlist_t_to_spl(device, metadata);
75983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
75993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
76003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Just create a new abstract audio/video playlist...
76013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return create_new_abstract_list(device,
76023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  metadata->name,
76033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  NULL,
76043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  NULL,
76053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  NULL,
76063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  localph,
76073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  metadata->storage_id,
76083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  PTP_OFC_MTP_AbstractAudioVideoPlaylist,
76093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  get_playlist_extension(ptp_usb),
76103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  &metadata->playlist_id,
76113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  metadata->tracks,
76123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  metadata->no_tracks);
76133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
76143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
76153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
76163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This routine updates a playlist based on the metadata
76173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * supplied. If the <code>tracks</code> field of the metadata
76183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * contains a track listing, these tracks will be added to the
76193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * playlist in place of those already present, i.e. the
76203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * previous track listing will be deleted. For Samsung devices the
76213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * playlist id (metadata->playlist_id) is likely to change.
76223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to create the new playlist on.
76233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param metadata the metadata for the playlist to be updated.
76243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *                 notice that the field <code>playlist_id</code>
76253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *                 must contain the apropriate playlist ID. Playlist ID
76263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *                 be modified to a new playlist ID by the time the
76273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *                 function returns since edit-in-place is not always possible.
76283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
76293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Create_New_Playlist()
76303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Delete_Object()
76313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
76323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Update_Playlist(LIBMTP_mtpdevice_t *device,
76333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			   LIBMTP_playlist_t * const metadata)
76343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
76353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
76363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Samsung needs its own special type of playlists
76373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
76383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if(FLAG_PLAYLIST_SPL(ptp_usb)) {
76393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return update_spl_playlist(device, metadata);
76403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
76413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
76423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return update_abstract_list(device,
76433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      metadata->name,
76443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      NULL,
76453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      NULL,
76463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      NULL,
76473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      metadata->playlist_id,
76483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      PTP_OFC_MTP_AbstractAudioVideoPlaylist,
76493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      metadata->tracks,
76503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      metadata->no_tracks);
76513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
76523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
76533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
76543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This creates a new album metadata structure and allocates memory
76553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * for it. Notice that if you add strings to this structure they
76563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * will be freed by the corresponding <code>LIBMTP_destroy_album_t</code>
76573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * operation later, so be careful of using strdup() when assigning
76583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * strings.
76593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
76603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a pointer to the newly allocated metadata structure.
76613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_destroy_album_t()
76623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
76633aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_album_t *LIBMTP_new_album_t(void)
76643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
76653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_album_t *new = (LIBMTP_album_t *) malloc(sizeof(LIBMTP_album_t));
76663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (new == NULL) {
76673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
76683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
76693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->album_id = 0;
76703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->parent_id = 0;
76713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->storage_id = 0;
76723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->name = NULL;
76733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->artist = NULL;
76743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->composer = NULL;
76753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->genre = NULL;
76763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->tracks = NULL;
76773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->no_tracks = 0;
76783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->next = NULL;
76793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return new;
76803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
76813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
76823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
76833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This recursively deletes the memory for an album structure
76843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
76853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param album structure to destroy
76863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_new_album_t()
76873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
76883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_destroy_album_t(LIBMTP_album_t *album)
76893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
76903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (album == NULL) {
76913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return;
76923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
76933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (album->name != NULL)
76943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(album->name);
76953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (album->artist != NULL)
76963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(album->artist);
76973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (album->composer != NULL)
76983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(album->composer);
76993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (album->genre != NULL)
77003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(album->genre);
77013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (album->tracks != NULL)
77023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(album->tracks);
77033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(album);
77043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return;
77053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
77063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
77073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
77083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function maps and copies a property onto the album metadata if applicable.
77093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
77103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void pick_property_to_album_metadata(LIBMTP_mtpdevice_t *device,
77113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					    MTPProperties *prop, LIBMTP_album_t *alb)
77123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
77133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  switch (prop->property) {
77143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_Name:
77153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (prop->propval.str != NULL)
77163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      alb->name = strdup(prop->propval.str);
77173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else
77183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      alb->name = NULL;
77193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
77203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_AlbumArtist:
77213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (prop->propval.str != NULL) {
77223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // This should take precedence over plain "Artist"
77233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (alb->artist != NULL)
77243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	free(alb->artist);
77253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      alb->artist = strdup(prop->propval.str);
77263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else
77273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      alb->artist = NULL;
77283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
77293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_Artist:
77303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (prop->propval.str != NULL) {
77313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Only use of AlbumArtist is not set
77323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      if (alb->artist == NULL)
77333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	alb->artist = strdup(prop->propval.str);
77343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else
77353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      alb->artist = NULL;
77363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
77373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_Composer:
77383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (prop->propval.str != NULL)
77393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      alb->composer = strdup(prop->propval.str);
77403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else
77413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      alb->composer = NULL;
77423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
77433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case PTP_OPC_Genre:
77443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (prop->propval.str != NULL)
77453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      alb->genre = strdup(prop->propval.str);
77463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else
77473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      alb->genre = NULL;
77483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
77493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
77503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
77513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
77523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
77533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function retrieves the album metadata for an album
77543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * given by a unique ID.
77553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the track metadata off.
77563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param alb an album metadata metadata set to fill in.
77573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
77583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void get_album_metadata(LIBMTP_mtpdevice_t *device,
77593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			       LIBMTP_album_t *alb)
77603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
77613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
77623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
77633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t i;
77643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  MTPProperties *prop;
77653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObject *ob;
77663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
77673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
77683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * If we have a cached, large set of metadata, then use it!
77693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   */
77703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_object_want(params, alb->album_id, PTPOBJECT_MTPPROPLIST_LOADED, &ob);
77713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ob->mtpprops) {
77723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    prop = ob->mtpprops;
77733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    for (i=0;i<ob->nrofmtpprops;i++,prop++)
77743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      pick_property_to_album_metadata(device, prop, alb);
77753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else {
77763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    uint16_t *props = NULL;
77773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    uint32_t propcnt = 0;
77783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
77793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // First see which properties can be retrieved for albums
77803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_mtp_getobjectpropssupported(params, PTP_OFC_MTP_AbstractAudioAlbum, &propcnt, &props);
77813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
77823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_ptp_error_to_errorstack(device, ret, "get_album_metadata(): call to ptp_mtp_getobjectpropssupported() failed.");
77833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // Just bail out for now, nothing is ever set.
77843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      return;
77853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
77863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      for (i=0;i<propcnt;i++) {
77873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	switch (props[i]) {
77883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Name:
77893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  alb->name = get_string_from_object(device, ob->oid, PTP_OPC_Name);
77903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
77913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_AlbumArtist:
77923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (alb->artist != NULL)
77933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    free(alb->artist);
77943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  alb->artist = get_string_from_object(device, ob->oid, PTP_OPC_AlbumArtist);
77953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
77963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Artist:
77973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  if (alb->artist == NULL)
77983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	    alb->artist = get_string_from_object(device, ob->oid, PTP_OPC_Artist);
77993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
78003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Composer:
78013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  alb->composer = get_string_from_object(device, ob->oid, PTP_OPC_Composer);
78023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
78033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	case PTP_OPC_Genre:
78043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  alb->genre = get_string_from_object(device, ob->oid, PTP_OPC_Genre);
78053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
78063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	default:
78073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	  break;
78083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev	}
78093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      }
78103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      free(props);
78113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
78123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
78133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
78143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
78153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
78163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function returns a list of the albums available on the
78173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * device.
78183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
78193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the album listing from.
78203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return an album list on success, else NULL. If there are no albums
78213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *         on the device, NULL will be returned as well.
78223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Album()
78233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
78243aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_album_t *LIBMTP_Get_Album_List(LIBMTP_mtpdevice_t *device)
78253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
78263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
78273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_album_t *retalbums = NULL;
78283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_album_t *curalbum = NULL;
78293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t i;
78303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
78313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Get all the handles if we haven't already done that
78323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->nrofobjects == 0)
78333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    flush_handles(device);
78343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
78353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i = 0; i < params->nrofobjects; i++) {
78363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_album_t *alb;
78373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    PTPObject *ob;
78383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    uint16_t ret;
78393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
78403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ob = &params->objects[i];
78413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
78423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Ignore stuff that isn't an album
78433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if ( ob->oi.ObjectFormat != PTP_OFC_MTP_AbstractAudioAlbum )
78443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      continue;
78453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
78463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Allocate a new album type
78473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    alb = LIBMTP_new_album_t();
78483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    alb->album_id = ob->oid;
78493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    alb->parent_id = ob->oi.ParentObject;
78503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    alb->storage_id = ob->oi.StorageID;
78513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
78523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Fetch supported metadata
78533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    get_album_metadata(device, alb);
78543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
78553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Then get the track listing for this album
78563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ret = ptp_mtp_getobjectreferences(params, alb->album_id, &alb->tracks, &alb->no_tracks);
78573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (ret != PTP_RC_OK) {
78583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Album_List(): Could not get object references.");
78593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      alb->tracks = NULL;
78603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      alb->no_tracks = 0;
78613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
78623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
78633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Add album to a list that will be returned afterwards.
78643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (retalbums == NULL) {
78653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      retalbums = alb;
78663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curalbum = alb;
78673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    } else {
78683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curalbum->next = alb;
78693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      curalbum = alb;
78703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
78713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
78723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
78733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return retalbums;
78743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
78753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
78763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
78773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This function retrieves an individual album from the device.
78783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to get the album from.
78793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param albid the unique ID of the album to retrieve.
78803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a valid album metadata or NULL on failure.
78813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Album_List()
78823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
78833aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_album_t *LIBMTP_Get_Album(LIBMTP_mtpdevice_t *device, uint32_t const albid)
78843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
78853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
78863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
78873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObject *ob;
78883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_album_t *alb;
78893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
78903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Get all the handles if we haven't already done that
78913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (params->nrofobjects == 0)
78923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    flush_handles(device);
78933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
78943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_object_want(params, albid, PTPOBJECT_OBJECTINFO_LOADED, &ob);
78953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK)
78963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
78973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
78983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Ignore stuff that isn't an album
78993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ob->oi.ObjectFormat != PTP_OFC_MTP_AbstractAudioAlbum)
79003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
79013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
79023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Allocate a new album type
79033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  alb = LIBMTP_new_album_t();
79043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  alb->album_id = ob->oid;
79053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  alb->parent_id = ob->oi.ParentObject;
79063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  alb->storage_id = ob->oi.StorageID;
79073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
79083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Fetch supported metadata
79093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  get_album_metadata(device, alb);
79103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
79113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Then get the track listing for this album
79123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectreferences(params, alb->album_id, &alb->tracks, &alb->no_tracks);
79133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
79143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Album: Could not get object references.");
79153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    alb->tracks = NULL;
79163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    alb->no_tracks = 0;
79173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
79183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
79193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return alb;
79203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
79213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
79223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
79233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This routine creates a new album based on the metadata
79243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * supplied. If the <code>tracks</code> field of the metadata
79253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * contains a track listing, these tracks will be added to the
79263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * album.
79273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to create the new album on.
79283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param metadata the metadata for the new album. If the function
79293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        exits with success, the <code>album_id</code> field of this
79303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        struct will contain the new ID of the album.
79313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <ul>
79323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>metadata-&gt;parent_id</code> should be set to the parent
79333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        (e.g. folder) to store this track in. Since some
79343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        devices are a bit picky about where files
79353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        are placed, a default folder will be chosen if libmtp
79363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        has detected one for the current filetype and this
79373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        parameter is set to 0. If this is 0 and no default folder
79383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        can be found, the file will be stored in the root folder.
79393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        <li><code>metadata-&gt;storage_id</code> should be set to the
79403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        desired storage (e.g. memory card or whatever your device
79413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        presents) to store this track in. Setting this to 0 will store
79423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        the track on the primary storage.
79433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        </ul>
79443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
79453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Update_Album()
79463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Delete_Object()
79473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
79483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Create_New_Album(LIBMTP_mtpdevice_t *device,
79493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			    LIBMTP_album_t * const metadata)
79503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
79513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t localph = metadata->parent_id;
79523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
79533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Use a default folder if none given
79543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (localph == 0) {
79553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (device->default_album_folder != 0)
79563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      localph = device->default_album_folder;
79573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    else
79583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      localph = device->default_music_folder;
79593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
79603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  metadata->parent_id = localph;
79613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
79623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Just create a new abstract album...
79633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return create_new_abstract_list(device,
79643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  metadata->name,
79653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  metadata->artist,
79663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  metadata->composer,
79673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  metadata->genre,
79683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  localph,
79693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  metadata->storage_id,
79703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  PTP_OFC_MTP_AbstractAudioAlbum,
79713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  ".alb",
79723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  &metadata->album_id,
79733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  metadata->tracks,
79743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				  metadata->no_tracks);
79753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
79763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
79773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
79783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This creates a new sample data metadata structure and allocates memory
79793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * for it. Notice that if you add strings to this structure they
79803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * will be freed by the corresponding <code>LIBMTP_destroy_sampledata_t</code>
79813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * operation later, so be careful of using strdup() when assigning
79823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * strings.
79833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *
79843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return a pointer to the newly allocated metadata structure.
79853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_destroy_sampledata_t()
79863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
79873aa430dc5437a98734b36f996f9b17081a589143Yavor GoulishevLIBMTP_filesampledata_t *LIBMTP_new_filesampledata_t(void)
79883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
79893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  LIBMTP_filesampledata_t *new = (LIBMTP_filesampledata_t *) malloc(sizeof(LIBMTP_filesampledata_t));
79903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (new == NULL) {
79913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return NULL;
79923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
79933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->height=0;
79943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->width = 0;
79953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->data = NULL;
79963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->duration = 0;
79973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  new->size = 0;
79983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return new;
79993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
80003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
80013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
80023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This destroys a file sample metadata type.
80033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param sample the file sample metadata to be destroyed.
80043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
80053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid LIBMTP_destroy_filesampledata_t(LIBMTP_filesampledata_t * sample)
80063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
80073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (sample == NULL) {
80083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return;
80093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
80103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (sample->data != NULL) {
80113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(sample->data);
80123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
80133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(sample);
80143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
80153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
80163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
80173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This routine figures out whether a certain filetype supports
80183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * representative samples (small thumbnail images) or not. This
80193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * typically applies to JPEG files, MP3 files and Album abstract
80203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * playlists, but in theory any filetype could support representative
80213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * samples.
80223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device which is to be examined.
80233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param filetype the fileype to examine, and return the representative sample
80243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        properties for.
80253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param sample this will contain a new sample type with the fields
80263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        filled in with suitable default values. For example, the
80273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        supported sample type will be set, the supported height and
80283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        width will be set to max values if it is an image sample,
80293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        and duration will also be given some suitable default value
80303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        which should not be exceeded on audio samples. If the
80313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        device does not support samples for this filetype, this
80323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        pointer will be NULL. If it is not NULL, the user must
80333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        destroy this struct with <code>LIBMTP_destroy_filesampledata_t()</code>
80343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *        after use.
80353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
80363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Send_Representative_Sample()
80373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Create_New_Album()
80383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
80393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Get_Representative_Sample_Format(LIBMTP_mtpdevice_t *device,
80403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					    LIBMTP_filetype_t const filetype,
80413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev					    LIBMTP_filesampledata_t ** sample)
80423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
80433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
80443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
80453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t *props = NULL;
80463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t propcnt = 0;
80473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int i;
80483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // TODO: Get rid of these when we can properly query the device.
80493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int support_data = 0;
80503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int support_format = 0;
80513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int support_height = 0;
80523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int support_width = 0;
80533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int support_duration = 0;
80543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int support_size = 0;
80553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
80563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObjectPropDesc opd_height;
80573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObjectPropDesc opd_width;
80583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObjectPropDesc opd_format;
80593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObjectPropDesc opd_duration;
80603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObjectPropDesc opd_size;
80613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
80623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Default to no type supported.
80633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  *sample = NULL;
80643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
80653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectpropssupported(params, map_libmtp_type_to_ptp_type(filetype), &propcnt, &props);
80663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
80673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Representative_Sample_Format(): could not get object properties.");
80683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
80693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
80703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /*
80713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * TODO: when walking through these object properties, make calls to
80723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * a new function in ptp.h/ptp.c that can send the command
80733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * PTP_OC_MTP_GetObjectPropDesc to get max/min values of the properties
80743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * supported.
80753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   */
80763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i = 0; i < propcnt; i++) {
80773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    switch(props[i]) {
80783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case PTP_OPC_RepresentativeSampleData:
80793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      support_data = 1;
80803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
80813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case PTP_OPC_RepresentativeSampleFormat:
80823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      support_format = 1;
80833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
80843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case PTP_OPC_RepresentativeSampleSize:
80853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      support_size = 1;
80863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
80873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case PTP_OPC_RepresentativeSampleHeight:
80883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      support_height = 1;
80893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
80903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case PTP_OPC_RepresentativeSampleWidth:
80913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      support_width = 1;
80923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
80933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    case PTP_OPC_RepresentativeSampleDuration:
80943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      support_duration = 1;
80953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
80963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    default:
80973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
80983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
80993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
81003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(props);
81013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
81023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (support_data && support_format && support_height && support_width && !support_duration) {
81033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Something that supports height and width and not duration is likely to be JPEG
81043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_filesampledata_t *retsam = LIBMTP_new_filesampledata_t();
81053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /*
81063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * Populate the sample format with the first supported format
81073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *
81083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * TODO: figure out how to pass back more than one format if more are
81093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * supported by the device.
81103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     */
81113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_mtp_getobjectpropdesc (params, PTP_OPC_RepresentativeSampleFormat, map_libmtp_type_to_ptp_type(filetype), &opd_format);
81123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retsam->filetype = map_ptp_type_to_libmtp_type(opd_format.FORM.Enum.SupportedValue[0].u16);
81133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_free_objectpropdesc(&opd_format);
81143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* Populate the maximum image height */
81153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_mtp_getobjectpropdesc (params, PTP_OPC_RepresentativeSampleWidth, map_libmtp_type_to_ptp_type(filetype), &opd_width);
81163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retsam->width = opd_width.FORM.Range.MaximumValue.u32;
81173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_free_objectpropdesc(&opd_width);
81183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* Populate the maximum image width */
81193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_mtp_getobjectpropdesc (params, PTP_OPC_RepresentativeSampleHeight, map_libmtp_type_to_ptp_type(filetype), &opd_height);
81203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retsam->height = opd_height.FORM.Range.MaximumValue.u32;
81213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_free_objectpropdesc(&opd_height);
81223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* Populate the maximum size */
81233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (support_size) {
81243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptp_mtp_getobjectpropdesc (params, PTP_OPC_RepresentativeSampleSize, map_libmtp_type_to_ptp_type(filetype), &opd_size);
81253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      retsam->size = opd_size.FORM.Range.MaximumValue.u32;
81263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptp_free_objectpropdesc(&opd_size);
81273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
81283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    *sample = retsam;
81293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  } else if (support_data && support_format && !support_height && !support_width && support_duration) {
81303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // Another qualified guess
81313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    LIBMTP_filesampledata_t *retsam = LIBMTP_new_filesampledata_t();
81323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /*
81333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * Populate the sample format with the first supported format
81343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     *
81353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * TODO: figure out how to pass back more than one format if more are
81363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     * supported by the device.
81373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev     */
81383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_mtp_getobjectpropdesc (params, PTP_OPC_RepresentativeSampleFormat, map_libmtp_type_to_ptp_type(filetype), &opd_format);
81393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retsam->filetype = map_ptp_type_to_libmtp_type(opd_format.FORM.Enum.SupportedValue[0].u16);
81403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_free_objectpropdesc(&opd_format);
81413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* Populate the maximum duration */
81423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_mtp_getobjectpropdesc (params, PTP_OPC_RepresentativeSampleDuration, map_libmtp_type_to_ptp_type(filetype), &opd_duration);
81433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    retsam->duration = opd_duration.FORM.Range.MaximumValue.u32;
81443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    ptp_free_objectpropdesc(&opd_duration);
81453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    /* Populate the maximum size */
81463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (support_size) {
81473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptp_mtp_getobjectpropdesc (params, PTP_OPC_RepresentativeSampleSize, map_libmtp_type_to_ptp_type(filetype), &opd_size);
81483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      retsam->size = opd_size.FORM.Range.MaximumValue.u32;
81493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      ptp_free_objectpropdesc(&opd_size);
81503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
81513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    *sample = retsam;
81523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
81533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
81543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
81553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
81563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
81573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This routine sends representative sample data for an object.
81583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This uses the RepresentativeSampleData property of the album,
81593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * if the device supports it. The data should be of a format acceptable
81603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * to the player (for iRiver and Creative, this seems to be JPEG) and
81613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * must not be too large. (for a Creative, max seems to be about 20KB.)
81623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Check by calling LIBMTP_Get_Representative_Sample_Format() to get
81633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * maximum size, dimensions, etc..
81643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device which the object is on.
81653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param id unique id of the object to set artwork for.
81663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param pointer to LIBMTP_filesampledata_t struct containing data
81673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
81683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Representative_Sample()
81693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Representative_Sample_Format()
81703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Create_New_Album()
81713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
81723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Send_Representative_Sample(LIBMTP_mtpdevice_t *device,
81733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                          uint32_t const id,
81743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                          LIBMTP_filesampledata_t *sampledata)
81753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
81763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
81773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
81783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
81793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
81803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObject *ob;
81813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t i;
81823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t *props = NULL;
81833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t propcnt = 0;
81843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int supported = 0;
81853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
81863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // get the file format for the object we're going to send representative data for
81873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_object_want (params, id, PTPOBJECT_OBJECTINFO_LOADED, &ob);
81883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
81893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Send_Representative_Sample(): could not get object info.");
81903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
81913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
81923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
81933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // check that we can send representative sample data for this object format
81943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectpropssupported(params, ob->oi.ObjectFormat, &propcnt, &props);
81953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
81963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Send_Representative_Sample(): could not get object properties.");
81973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
81983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
81993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
82003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i = 0; i < propcnt; i++) {
82013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (props[i] == PTP_OPC_RepresentativeSampleData) {
82023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      supported = 1;
82033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
82043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
82053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
82063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!supported) {
82073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(props);
82083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Send_Representative_Sample(): object type doesn't support RepresentativeSampleData.");
82093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
82103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
82113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(props);
82123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
82133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Go ahead and send the data
82143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  propval.a.count = sampledata->size;
82153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  propval.a.v = malloc(sizeof(PTPPropertyValue) * sampledata->size);
82163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i = 0; i < sampledata->size; i++) {
82173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    propval.a.v[i].u8 = sampledata->data[i];
82183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
82193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
82203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_setobjectpropvalue(params,id,PTP_OPC_RepresentativeSampleData,
82213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				   &propval,PTP_DTC_AUINT8);
82223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
82233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Send_Representative_Sample(): could not send sample data.");
82243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(propval.a.v);
82253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
82263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
82273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(propval.a.v);
82283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
82293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  /* Set the height and width if the sample is an image, otherwise just
82303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev   * set the duration and size */
82313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  switch(sampledata->filetype) {
82323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case LIBMTP_FILETYPE_JPEG:
82333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case LIBMTP_FILETYPE_JFIF:
82343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case LIBMTP_FILETYPE_TIFF:
82353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case LIBMTP_FILETYPE_BMP:
82363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case LIBMTP_FILETYPE_GIF:
82373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case LIBMTP_FILETYPE_PICT:
82383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  case LIBMTP_FILETYPE_PNG:
82393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (!FLAG_BROKEN_SET_SAMPLE_DIMENSIONS(ptp_usb)) {
82403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      // For images, set the height and width
82413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      set_object_u32(device, id, PTP_OPC_RepresentativeSampleHeight, sampledata->height);
82423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      set_object_u32(device, id, PTP_OPC_RepresentativeSampleWidth, sampledata->width);
82433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
82443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
82453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  default:
82463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    // For anything not an image, set the duration and size
82473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    set_object_u32(device, id, PTP_OPC_RepresentativeSampleDuration, sampledata->duration);
82483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    set_object_u32(device, id, PTP_OPC_RepresentativeSampleSize, sampledata->size);
82493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    break;
82503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
82513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
82523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
82533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
82543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
82553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
82563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This routine gets representative sample data for an object.
82573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This uses the RepresentativeSampleData property of the album,
82583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * if the device supports it.
82593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device which the object is on.
82603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param id unique id of the object to get data for.
82613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param pointer to LIBMTP_filesampledata_t struct to receive data
82623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
82633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Send_Representative_Sample()
82643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Get_Representative_Sample_Format()
82653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Create_New_Album()
82663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
82673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Get_Representative_Sample(LIBMTP_mtpdevice_t *device,
82683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                          uint32_t const id,
82693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev                          LIBMTP_filesampledata_t *sampledata)
82703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
82713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
82723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *) device->params;
82733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPPropertyValue propval;
82743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPObject *ob;
82753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t i;
82763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t *props = NULL;
82773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint32_t propcnt = 0;
82783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  int supported = 0;
82793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
82803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // get the file format for the object we're going to send representative data for
82813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_object_want (params, id, PTPOBJECT_OBJECTINFO_LOADED, &ob);
82823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
82833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_Representative_Sample(): could not get object info.");
82843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
82853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
82863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
82873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // check that we can store representative sample data for this object format
82883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectpropssupported(params, ob->oi.ObjectFormat, &propcnt, &props);
82893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
82903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Representative_Sample(): could not get object properties.");
82913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
82923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
82933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
82943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i = 0; i < propcnt; i++) {
82953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    if (props[i] == PTP_OPC_RepresentativeSampleData) {
82963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      supported = 1;
82973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev      break;
82983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    }
82993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
83003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (!supported) {
83013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    free(props);
83023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_Representative_Sample(): object type doesn't support RepresentativeSampleData.");
83033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
83043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
83053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(props);
83063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
83073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Get the data
83083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_mtp_getobjectpropvalue(params,id,PTP_OPC_RepresentativeSampleData,
83093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev				   &propval,PTP_DTC_AUINT8);
83103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
83113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Representative_Sample(): could not get sample data.");
83123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    return -1;
83133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
83143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
83153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Store it
83163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  sampledata->size = propval.a.count;
83173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  sampledata->data = malloc(sizeof(PTPPropertyValue) * propval.a.count);
83183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  for (i = 0; i < propval.a.count; i++) {
83193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    sampledata->data[i] = propval.a.v[i].u8;
83203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
83213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  free(propval.a.v);
83223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
83233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  // Get the other properties
83243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  sampledata->width = get_u32_from_object(device, id, PTP_OPC_RepresentativeSampleWidth, 0);
83253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  sampledata->height = get_u32_from_object(device, id, PTP_OPC_RepresentativeSampleHeight, 0);
83263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  sampledata->duration = get_u32_from_object(device, id, PTP_OPC_RepresentativeSampleDuration, 0);
83273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  sampledata->filetype = map_ptp_type_to_libmtp_type(
83283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev        get_u16_from_object(device, id, PTP_OPC_RepresentativeSampleFormat, LIBMTP_FILETYPE_UNKNOWN));
83293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
83303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return 0;
83313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
83323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
83333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
83343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This routine updates an album based on the metadata
83353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * supplied. If the <code>tracks</code> field of the metadata
83363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * contains a track listing, these tracks will be added to the
83373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * album in place of those already present, i.e. the
83383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * previous track listing will be deleted.
83393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device a pointer to the device to create the new album on.
83403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param metadata the metadata for the album to be updated.
83413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *                 notice that the field <code>album_id</code>
83423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev *                 must contain the apropriate album ID.
83433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @return 0 on success, any other value means failure.
83443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Create_New_Album()
83453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @see LIBMTP_Delete_Object()
83463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
83473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint LIBMTP_Update_Album(LIBMTP_mtpdevice_t *device,
83483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			   LIBMTP_album_t const * const metadata)
83493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
83503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return update_abstract_list(device,
83513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      metadata->name,
83523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      metadata->artist,
83533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      metadata->composer,
83543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      metadata->genre,
83553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      metadata->album_id,
83563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      PTP_OFC_MTP_AbstractAudioAlbum,
83573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      metadata->tracks,
83583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev			      metadata->no_tracks);
83593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
83603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
83613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
83623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Dummy function needed to interface to upstream
83633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * ptp.c/ptp.h files.
83643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
83653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevvoid ptp_nikon_getptpipguid (unsigned char* guid) {
83663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  return;
83673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
83683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
83693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
83703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Add an object to cache.
83713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device the device which may have a cache to which the object should be added.
83723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id the object to add to the cache.
83733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
83743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void add_object_to_cache(LIBMTP_mtpdevice_t *device, uint32_t object_id)
83753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
83763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *)device->params;
83773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  uint16_t ret;
83783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
83793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ret = ptp_add_object_to_cache(params, object_id);
83803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  if (ret != PTP_RC_OK) {
83813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev    add_ptp_error_to_errorstack(device, ret, "add_object_to_cache(): couldn't add object to cache");
83823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  }
83833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
83843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
83853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
83863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/**
83873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Update cache after object has been modified
83883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param device the device which may have a cache to which the object should be updated.
83893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * @param object_id the object to update.
83903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */
83913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void update_metadata_cache(LIBMTP_mtpdevice_t *device, uint32_t object_id)
83923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{
83933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  PTPParams *params = (PTPParams *)device->params;
83943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev
83953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  ptp_remove_object_from_cache(params, object_id);
83963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev  add_object_to_cache(device, object_id);
83973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}
8398