blob: b5096fe7645daebefdf42cd655443ff314944b75 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2014 TeamWin - bigbiff and Dees_Troy mtp database conversion to C++
*/
#include <utils/Log.h>
#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
#include <map>
#include <libgen.h>
#include <cutils/properties.h>
#include "MtpDatabase.h"
#include "MtpStorage.h"
#include "MtpDataPacket.h"
#include "MtpObjectInfo.h"
#include "MtpProperty.h"
#include "MtpDebug.h"
#include "MtpStringBuffer.h"
#include "MtpUtils.h"
#include "mtp.h"
#include "mtp_MtpDatabase.hpp"
#include "btree.hpp"
MyMtpDatabase::MyMtpDatabase()
{
storagenum = 0;
count = -1;
}
MyMtpDatabase::~MyMtpDatabase() {
std::map<int, MtpStorage*>::iterator i;
for (i = storagemap.begin(); i != storagemap.end(); i++) {
delete i->second;
}
}
int MyMtpDatabase::DEVICE_PROPERTIES[3] = {
MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
MTP_DEVICE_PROPERTY_IMAGE_SIZE
};
int MyMtpDatabase::FILE_PROPERTIES[10] = {
// NOTE must match beginning of AUDIO_PROPERTIES, VIDEO_PROPERTIES
// and IMAGE_PROPERTIES below
MTP_PROPERTY_STORAGE_ID,
MTP_PROPERTY_OBJECT_FORMAT,
MTP_PROPERTY_PROTECTION_STATUS,
MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME,
MTP_PROPERTY_DATE_MODIFIED,
MTP_PROPERTY_PARENT_OBJECT,
MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME,
MTP_PROPERTY_DATE_ADDED
};
int MyMtpDatabase::AUDIO_PROPERTIES[19] = {
// NOTE must match FILE_PROPERTIES above
MTP_PROPERTY_STORAGE_ID,
MTP_PROPERTY_OBJECT_FORMAT,
MTP_PROPERTY_PROTECTION_STATUS,
MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME,
MTP_PROPERTY_DATE_MODIFIED,
MTP_PROPERTY_PARENT_OBJECT,
MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME,
MTP_PROPERTY_DISPLAY_NAME,
MTP_PROPERTY_DATE_ADDED,
// audio specific properties
MTP_PROPERTY_ARTIST,
MTP_PROPERTY_ALBUM_NAME,
MTP_PROPERTY_ALBUM_ARTIST,
MTP_PROPERTY_TRACK,
MTP_PROPERTY_ORIGINAL_RELEASE_DATE,
MTP_PROPERTY_DURATION,
MTP_PROPERTY_GENRE,
MTP_PROPERTY_COMPOSER
};
int MyMtpDatabase::VIDEO_PROPERTIES[15] = {
// NOTE must match FILE_PROPERTIES above
MTP_PROPERTY_STORAGE_ID,
MTP_PROPERTY_OBJECT_FORMAT,
MTP_PROPERTY_PROTECTION_STATUS,
MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME,
MTP_PROPERTY_DATE_MODIFIED,
MTP_PROPERTY_PARENT_OBJECT,
MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME,
MTP_PROPERTY_DISPLAY_NAME,
MTP_PROPERTY_DATE_ADDED,
// video specific properties
MTP_PROPERTY_ARTIST,
MTP_PROPERTY_ALBUM_NAME,
MTP_PROPERTY_DURATION,
MTP_PROPERTY_DESCRIPTION
};
int MyMtpDatabase::IMAGE_PROPERTIES[12] = {
// NOTE must match FILE_PROPERTIES above
MTP_PROPERTY_STORAGE_ID,
MTP_PROPERTY_OBJECT_FORMAT,
MTP_PROPERTY_PROTECTION_STATUS,
MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME,
MTP_PROPERTY_DATE_MODIFIED,
MTP_PROPERTY_PARENT_OBJECT,
MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME,
MTP_PROPERTY_DISPLAY_NAME,
MTP_PROPERTY_DATE_ADDED,
// image specific properties
MTP_PROPERTY_DESCRIPTION
};
int MyMtpDatabase::ALL_PROPERTIES[25] = {
// NOTE must match FILE_PROPERTIES above
MTP_PROPERTY_STORAGE_ID,
MTP_PROPERTY_OBJECT_FORMAT,
MTP_PROPERTY_PROTECTION_STATUS,
MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME,
MTP_PROPERTY_DATE_MODIFIED,
MTP_PROPERTY_PARENT_OBJECT,
MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME,
MTP_PROPERTY_DISPLAY_NAME,
MTP_PROPERTY_DATE_ADDED,
// image specific properties
MTP_PROPERTY_DESCRIPTION,
// audio specific properties
MTP_PROPERTY_ARTIST,
MTP_PROPERTY_ALBUM_NAME,
MTP_PROPERTY_ALBUM_ARTIST,
MTP_PROPERTY_TRACK,
MTP_PROPERTY_ORIGINAL_RELEASE_DATE,
MTP_PROPERTY_DURATION,
MTP_PROPERTY_GENRE,
MTP_PROPERTY_COMPOSER,
// video specific properties
MTP_PROPERTY_ARTIST,
MTP_PROPERTY_ALBUM_NAME,
MTP_PROPERTY_DURATION,
MTP_PROPERTY_DESCRIPTION,
// image specific properties
MTP_PROPERTY_DESCRIPTION
};
int MyMtpDatabase::SUPPORTED_PLAYBACK_FORMATS[26] = {
SUPPORTED_PLAYBACK_FORMAT_UNDEFINED,
SUPPORTED_PLAYBACK_FORMAT_ASSOCIATION,
SUPPORTED_PLAYBACK_FORMAT_TEXT,
SUPPORTED_PLAYBACK_FORMAT_HTML,
SUPPORTED_PLAYBACK_FORMAT_WAV,
SUPPORTED_PLAYBACK_FORMAT_MP3,
SUPPORTED_PLAYBACK_FORMAT_MPEG,
SUPPORTED_PLAYBACK_FORMAT_EXIF_JPEG,
SUPPORTED_PLAYBACK_FORMAT_TIFF_EP,
SUPPORTED_PLAYBACK_FORMAT_BMP,
SUPPORTED_PLAYBACK_FORMAT_GIF,
SUPPORTED_PLAYBACK_FORMAT_JFIF,
SUPPORTED_PLAYBACK_FORMAT_PNG,
SUPPORTED_PLAYBACK_FORMAT_TIFF,
SUPPORTED_PLAYBACK_FORMAT_WMA,
SUPPORTED_PLAYBACK_FORMAT_OGG,
SUPPORTED_PLAYBACK_FORMAT_AAC,
SUPPORTED_PLAYBACK_FORMAT_MP4_CONTAINER,
SUPPORTED_PLAYBACK_FORMAT_MP2,
SUPPORTED_PLAYBACK_FORMAT_3GP_CONTAINER,
SUPPORTED_PLAYBACK_FORMAT_ABSTRACT_AV_PLAYLIST,
SUPPORTED_PLAYBACK_FORMAT_WPL_PLAYLIST,
SUPPORTED_PLAYBACK_FORMAT_M3U_PLAYLIST,
SUPPORTED_PLAYBACK_FORMAT_PLS_PLAYLIST,
SUPPORTED_PLAYBACK_FORMAT_XML_DOCUMENT,
SUPPORTED_PLAYBACK_FORMAT_FLAC
};
MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
MtpObjectFormat format,
MtpObjectHandle parent,
MtpStorageID storage,
uint64_t size,
time_t modified) {
MTPD("MyMtpDatabase::beginSendObject() which passes to MtpStorage.cpp\n");
return storagemap[storage]->beginSendObject(path, format, parent, storage, size, modified);
}
void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
MtpObjectFormat format, bool succeeded) {
MTPD("endSendObject() %s\n", path);
if (!succeeded) {
MTPE("endSendObject() failed, unlinking %s\n", path);
unlink(path);
}
}
void MyMtpDatabase::createDB(MtpStorage* storage, MtpStorageID storageID) {
storagemap[storageID] = storage;
storage->createDB();
}
MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
MtpObjectFormat format,
MtpObjectHandle parent) {
MTPD("storageID: %d\n", storageID);
MtpObjectHandleList* list = new MtpObjectHandleList();
list = storagemap[storageID]->getObjectList(storageID, parent);
MTPD("list: %d\n", list->size());
return list;
}
int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
MtpObjectFormat format,
MtpObjectHandle parent) {
MTPE("MyMtpDatabase::getNumObjects not implemented, returning 0\n");
int result = 0;
//get number of objects on filesystem storage
return result;
}
MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
// This function tells the host PC which file formats the device supports
int* formats;
MtpObjectFormatList* list = new MtpObjectFormatList();
formats = SUPPORTED_PLAYBACK_FORMATS;
int length = sizeof(formats)/ sizeof(int);
MTPD("MyMtpDatabase::getSupportedPlaybackFormats length: %i\n", length);
for (int i = 0; i < length; i++) {
MTPD("supported playback format: %d\n", formats[i]);
list->push(formats[i]);
}
return list;
}
MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
// Android OS implementation of this function returns NULL
// so we are not implementing this function either.
MTPD("MyMtpDatabase::getSupportedCaptureFormats returning NULL (This is what Android does as well).\n");
return NULL;
}
MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
int* properties;
MtpObjectPropertyList* list = new MtpObjectPropertyList();
int length = 0;
switch (format) {
case MTP_FORMAT_MP3:
case MTP_FORMAT_WAV:
case MTP_FORMAT_WMA:
case MTP_FORMAT_OGG:
case MTP_FORMAT_AAC:
properties = AUDIO_PROPERTIES;
length = sizeof(AUDIO_PROPERTIES) / sizeof(AUDIO_PROPERTIES[0]);
case MTP_FORMAT_MPEG:
case MTP_FORMAT_3GP_CONTAINER:
case MTP_FORMAT_WMV:
properties = VIDEO_PROPERTIES;
length = sizeof(VIDEO_PROPERTIES) / sizeof(VIDEO_PROPERTIES[0]);
case MTP_FORMAT_EXIF_JPEG:
case MTP_FORMAT_GIF:
case MTP_FORMAT_PNG:
case MTP_FORMAT_BMP:
properties = IMAGE_PROPERTIES;
length = sizeof(IMAGE_PROPERTIES) / sizeof(IMAGE_PROPERTIES[0]);
case 0:
properties = ALL_PROPERTIES;
length = sizeof(ALL_PROPERTIES) / sizeof(ALL_PROPERTIES[0]);
default:
properties = FILE_PROPERTIES;
length = sizeof(FILE_PROPERTIES) / sizeof(FILE_PROPERTIES[0]);
}
MTPD("MyMtpDatabase::getSupportedObjectProperties length is: %i, format: %x, sizeof: %i", length, format);
for (int i = 0; i < length; i++) {
MTPD("supported object property: %x\n", properties[i]);
list->push(properties[i]);
}
return list;
}
MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
MtpDevicePropertyList* list = new MtpDevicePropertyList();
int length = sizeof(DEVICE_PROPERTIES) / sizeof(DEVICE_PROPERTIES[0]);
MTPD("MyMtpDatabase::getSupportedDeviceProperties length was: %i\n");
for (int i = 0; i < length; i++)
list->push(DEVICE_PROPERTIES[i]);
return list;
}
MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
MtpObjectProperty property,
MtpDataPacket& packet) {
MTPD("MyMtpDatabase::getObjectPropertyValue mtpid: %i, property: %x\n", handle, property);
int type;
MtpResponseCode result = MTP_RESPONSE_INVALID_OBJECT_HANDLE;
uint64_t longValue;
if (!getObjectPropertyInfo(property, type)) {
MTPE("MyMtpDatabase::setObjectPropertyValue returning MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED\n");
return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
}
std::map<int, MtpStorage*>::iterator storit;
for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
if (storit->second->getObjectPropertyValue(handle, property, longValue) == 0) {
result = MTP_RESPONSE_OK;
break;
}
}
if (result != MTP_RESPONSE_OK) {
MTPE("MyMtpDatabase::setObjectPropertyValue unable to locate handle: %i\n", handle);
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
}
// special case date properties, which are strings to MTP
// but stored internally as a uint64
if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
char date[20];
formatDateTime(longValue, date, sizeof(date));
packet.putString(date);
goto out;
}
// release date is stored internally as just the year
if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
char date[20];
snprintf(date, sizeof(date), "%04lld0101T000000", longValue);
packet.putString(date);
goto out;
}
switch (type) {
case MTP_TYPE_INT8:
packet.putInt8(longValue);
break;
case MTP_TYPE_UINT8:
packet.putUInt8(longValue);
break;
case MTP_TYPE_INT16:
packet.putInt16(longValue);
break;
case MTP_TYPE_UINT16:
packet.putUInt16(longValue);
break;
case MTP_TYPE_INT32:
packet.putInt32(longValue);
break;
case MTP_TYPE_UINT32:
packet.putUInt32(longValue);
break;
case MTP_TYPE_INT64:
packet.putInt64(longValue);
break;
case MTP_TYPE_UINT64:
packet.putUInt64(longValue);
break;
case MTP_TYPE_INT128:
packet.putInt128(longValue);
break;
case MTP_TYPE_UINT128:
packet.putInt128(longValue);
break;
case MTP_TYPE_STR:
{
/*std::string stringValue = (string)stringValuesArray[0];
if (stringValue) {
const char* str = stringValue.c_str();
if (str == NULL) {
return MTP_RESPONSE_GENERAL_ERROR;
}
packet.putString(str);
} else {
packet.putEmptyString();
}*/
MTPE("STRING unsupported type in getObjectPropertyValue\n");
result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
break;
}
default:
MTPE("unsupported type in getObjectPropertyValue\n");
result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
}
out:
return result;
}
MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
MtpObjectProperty property,
MtpDataPacket& packet) {
int type;
MTPD("MyMtpDatabase::setObjectPropertyValue start\n");
if (!getObjectPropertyInfo(property, type)) {
MTPE("MyMtpDatabase::setObjectPropertyValue returning MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED\n");
return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
}
MTPD("MyMtpDatabase::setObjectPropertyValue continuing\n");
long longValue = 0;
std::string stringValue;
switch (type) {
case MTP_TYPE_INT8:
MTPD("int8\n");
longValue = packet.getInt8();
break;
case MTP_TYPE_UINT8:
MTPD("uint8\n");
longValue = packet.getUInt8();
break;
case MTP_TYPE_INT16:
MTPD("int16\n");
longValue = packet.getInt16();
break;
case MTP_TYPE_UINT16:
MTPD("uint16\n");
longValue = packet.getUInt16();
break;
case MTP_TYPE_INT32:
MTPD("int32\n");
longValue = packet.getInt32();
break;
case MTP_TYPE_UINT32:
MTPD("uint32\n");
longValue = packet.getUInt32();
break;
case MTP_TYPE_INT64:
MTPD("int64\n");
longValue = packet.getInt64();
break;
case MTP_TYPE_UINT64:
MTPD("uint64\n");
longValue = packet.getUInt64();
break;
case MTP_TYPE_STR:
{
MTPD("string\n");
MtpStringBuffer buffer;
packet.getString(buffer);
stringValue = (const char *)buffer;
break;
}
default:
MTPE("MyMtpDatabase::setObjectPropertyValue unsupported type %i in getObjectPropertyValue\n", type);
return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
}
int result = MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
switch (property) {
case MTP_PROPERTY_OBJECT_FILE_NAME:
{
MTPD("MyMtpDatabase::setObjectPropertyValue renaming file, handle: %d, new name: '%s'\n", handle, stringValue.c_str());
std::map<int, MtpStorage*>::iterator storit;
for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
if (storit->second->renameObject(handle, stringValue) == 0) {
MTPD("MTP_RESPONSE_OK\n");
result = MTP_RESPONSE_OK;
break;
}
}
}
break;
default:
MTPE("MyMtpDatabase::setObjectPropertyValue property %x not supported.\n", property);
result = MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
}
MTPD("MyMtpDatabase::setObjectPropertyValue returning %d\n", result);
return result;
}
MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
MtpDataPacket& packet) {
int type, result = 0;
char prop_value[PROPERTY_VALUE_MAX];
MTPD("property %s\n",
MtpDebug::getDevicePropCodeName(property));
if (!getDevicePropertyInfo(property, type)) {
MTPE("MyMtpDatabase::getDevicePropertyValue MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED\n");
return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
}
MTPD("property %s\n",
MtpDebug::getDevicePropCodeName(property));
MTPD("property %x\n", property);
MTPD("MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME %x\n", MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME);
switch (property) {
case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
result = MTP_RESPONSE_OK;
break;
default:
{
MTPE("MyMtpDatabase::getDevicePropertyValue property %x not supported\n", property);
result = MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
break;
}
}
if (result != MTP_RESPONSE_OK) {
MTPD("MTP_REPONSE_OK NOT OK\n");
return result;
}
long longValue = 0;
property_get("ro.build.product", prop_value, "unknown manufacturer");
switch (type) {
case MTP_TYPE_INT8: {
MTPD("MTP_TYPE_INT8\n");
packet.putInt8(longValue);
break;
}
case MTP_TYPE_UINT8:
{
MTPD("MTP_TYPE_UINT8\n");
packet.putUInt8(longValue);
break;
}
case MTP_TYPE_INT16:
{
MTPD("MTP_TYPE_INT16\n");
packet.putInt16(longValue);
break;
}
case MTP_TYPE_UINT16:
{
MTPD("MTP_TYPE_UINT16\n");
packet.putUInt16(longValue);
break;
}
case MTP_TYPE_INT32:
{
MTPD("MTP_TYPE_INT32\n");
packet.putInt32(longValue);
break;
}
case MTP_TYPE_UINT32:
{
MTPD("MTP_TYPE_UINT32\n");
packet.putUInt32(longValue);
break;
}
case MTP_TYPE_INT64:
{
MTPD("MTP_TYPE_INT64\n");
packet.putInt64(longValue);
break;
}
case MTP_TYPE_UINT64:
{
MTPD("MTP_TYPE_UINT64\n");
packet.putUInt64(longValue);
break;
}
case MTP_TYPE_INT128:
{
MTPD("MTP_TYPE_INT128\n");
packet.putInt128(longValue);
break;
}
case MTP_TYPE_UINT128:
{
MTPD("MTP_TYPE_UINT128\n");
packet.putInt128(longValue);
break;
}
case MTP_TYPE_STR:
{
MTPD("MTP_TYPE_STR\n");
char* str = prop_value;
packet.putString(str);
break;
}
default:
MTPE("MyMtpDatabase::getDevicePropertyValue unsupported type %i in getDevicePropertyValue\n", type);
return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
}
return MTP_RESPONSE_OK;
}
MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property, MtpDataPacket& packet) {
int type;
MTPE("MyMtpDatabase::setDevicePropertyValue not implemented, returning 0\n");
return 0;
}
MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
MTPE("MyMtpDatabase::resetDeviceProperty not implemented, returning -1\n");
return -1;
}
MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle, uint32_t format, uint32_t property, int groupCode, int depth, MtpDataPacket& packet) {
MTPD("getObjectPropertyList()\n");
MTPD("property: %x\n", property);
std::map<int, MtpStorage*>::iterator storit;
for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
MTPD("MyMtpDatabase::getObjectPropertyList calling getObjectPropertyList\n");
if (storit->second->getObjectPropertyList(handle, format, property, groupCode, depth, packet) == 0) {
MTPD("MTP_RESPONSE_OK\n");
return MTP_RESPONSE_OK;
}
}
MTPE("MyMtpDatabase::getObjectPropertyList MTP_RESPOSNE_INVALID_OBJECT_HANDLE %i\n", handle);
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
}
MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle, MtpObjectInfo& info) {
std::map<int, MtpStorage*>::iterator storit;
for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
if (storit->second->getObjectInfo(handle, info) == 0) {
MTPD("MTP_RESPONSE_OK\n");
return MTP_RESPONSE_OK;
}
}
MTPE("MyMtpDatabase::getObjectInfo MTP_RESPONSE_INVALID_OBJECT_HANDLE %i\n", handle);
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
}
void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
MtpString path;
int64_t length;
MtpObjectFormat format;
void* result = NULL;
outThumbSize = 0;
MTPE("MyMtpDatabase::getThumbnail not implemented, returning 0\n");
return 0;
}
MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle, MtpString& outFilePath, int64_t& outFileLength, MtpObjectFormat& outFormat) {
std::map<int, MtpStorage*>::iterator storit;
for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
MTPD("MyMtpDatabase::getObjectFilePath calling getObjectFilePath\n");
if (storit->second->getObjectFilePath(handle, outFilePath, outFileLength, outFormat) == 0) {
MTPD("MTP_RESPONSE_OK\n");
return MTP_RESPONSE_OK;
}
}
MTPE("MyMtpDatabase::getObjectFilePath MTP_RESPOSNE_INVALID_OBJECT_HANDLE %i\n", handle);
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
}
MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
MTPD("deleteFile\n");
std::map<int, MtpStorage*>::iterator storit;
for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
if (storit->second->deleteFile(handle) == 0) {
MTPD("MTP_RESPONSE_OK\n");
return MTP_RESPONSE_OK;
}
}
MTPE("MyMtpDatabase::deleteFile MTP_RESPONSE_INVALID_OBJECT_HANDLE %i\n", handle);
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
}
struct PropertyTableEntry {
MtpObjectProperty property;
int type;
};
static const PropertyTableEntry kObjectPropertyTable[] = {
{ MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
{ MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
{ MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
{ MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
{ MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
{ MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
{ MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
{ MTP_PROPERTY_NAME, MTP_TYPE_STR },
{ MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
{ MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
{ MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
{ MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
{ MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
{ MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
{ MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
{ MTP_PROPERTY_GENRE, MTP_TYPE_STR },
{ MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
{ MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
{ MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
};
static const PropertyTableEntry kDevicePropertyTable[] = {
{ MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
{ MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
{ MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
};
bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
const PropertyTableEntry* entry = kObjectPropertyTable;
MTPD("MyMtpDatabase::getObjectPropertyInfo size is: %i\n", count);
for (int i = 0; i < count; i++, entry++) {
if (entry->property == property) {
type = entry->type;
return true;
}
}
return false;
}
bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
const PropertyTableEntry* entry = kDevicePropertyTable;
MTPD("MyMtpDatabase::getDevicePropertyInfo count is: %i\n", count);
for (int i = 0; i < count; i++, entry++) {
if (entry->property == property) {
type = entry->type;
MTPD("type: %x\n", type);
return true;
}
}
return false;
}
MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
// call function and place files with associated handles into int array
MTPD("MyMtpDatabase::getObjectReferences returning null, this seems to be what Android always does.\n");
MTPD("handle: %d\n", handle);
// Windows + Android seems to always return a NULL in this function, c == null path
// The way that this is handled in Android then is to do this:
return NULL;
}
MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
MtpObjectHandleList* references) {
int count = references->size();
MTPE("MyMtpDatabase::setObjectReferences not implemented, returning 0\n");
return 0;
}
MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
MtpObjectFormat format) {
MTPD("MyMtpDatabase::getObjectPropertyDesc start\n");
MtpProperty* result = NULL;
switch (property) {
case MTP_PROPERTY_OBJECT_FORMAT:
// use format as default value
MTPD("MyMtpDatabase::getObjectPropertyDesc format\n");
result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
break;
case MTP_PROPERTY_PROTECTION_STATUS:
case MTP_PROPERTY_TRACK:
MTPD("MyMtpDatabase::getObjectPropertyDesc track\n");
result = new MtpProperty(property, MTP_TYPE_UINT16);
break;
case MTP_PROPERTY_STORAGE_ID:
case MTP_PROPERTY_PARENT_OBJECT:
case MTP_PROPERTY_DURATION:
MTPD("MyMtpDatabase::getObjectPropertyDesc duration\n");
result = new MtpProperty(property, MTP_TYPE_UINT32);
break;
case MTP_PROPERTY_OBJECT_SIZE:
MTPD("MyMtpDatabase::getObjectPropertyDesc size\n");
result = new MtpProperty(property, MTP_TYPE_UINT64);
break;
case MTP_PROPERTY_PERSISTENT_UID:
MTPD("MyMtpDatabase::getObjectPropertyDesc persistent uid\n");
result = new MtpProperty(property, MTP_TYPE_UINT128);
break;
case MTP_PROPERTY_NAME:
case MTP_PROPERTY_DISPLAY_NAME:
case MTP_PROPERTY_ARTIST:
case MTP_PROPERTY_ALBUM_NAME:
case MTP_PROPERTY_ALBUM_ARTIST:
case MTP_PROPERTY_GENRE:
case MTP_PROPERTY_COMPOSER:
case MTP_PROPERTY_DESCRIPTION:
MTPD("MyMtpDatabase::getObjectPropertyDesc description\n");
result = new MtpProperty(property, MTP_TYPE_STR);
break;
case MTP_PROPERTY_DATE_MODIFIED:
case MTP_PROPERTY_DATE_ADDED:
case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
MTPD("MyMtpDatabase::getObjectPropertyDesc date\n");
result = new MtpProperty(property, MTP_TYPE_STR);
result->setFormDateTime();
break;
case MTP_PROPERTY_OBJECT_FILE_NAME:
MTPD("MyMtpDatabase::getObjectPropertyDesc file name\n");
// We allow renaming files and folders
result = new MtpProperty(property, MTP_TYPE_STR, true);
break;
}
return result;
}
MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
MtpProperty* result = NULL;
int ret;
bool writable = true;
switch (property) {
case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
ret = MTP_RESPONSE_OK;
// fall through
case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
result = new MtpProperty(property, MTP_TYPE_STR, writable);
ret = MTP_RESPONSE_OK;
// get current value
if (ret == MTP_RESPONSE_OK) {
result->setCurrentValue('\0');
result->setDefaultValue('\0');
} else {
MTPE("unable to read device property, response: %04X", ret);
}
break;
default:
ret = MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
break;
}
return result;
}
void MyMtpDatabase::sessionStarted() {
MTPD("MyMtpDatabase::sessionStarted not implemented or does nothing, returning\n");
return;
}
void MyMtpDatabase::sessionEnded() {
MTPD("MyMtpDatabase::sessionEnded not implemented or does nothing, returning\n");
return;
}
// ----------------------------------------------------------------------------
static void
android_mtp_MtpDatabase_setup()
{
MyMtpDatabase* database = new MyMtpDatabase();
}
static void
android_mtp_MtpDatabase_finalize()
{
return;
}
static std::string
android_mtp_MtpPropertyGroup_format_date_time(long seconds)
{
char date[20];
formatDateTime(seconds, date, sizeof(date));
return date;
}
void MyMtpDatabase::lockMutex(void) {
std::map<int, MtpStorage*>::iterator storit;
for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
storit->second->lockMutex(0);
}
}
void MyMtpDatabase::unlockMutex(void) {
std::map<int, MtpStorage*>::iterator storit;
for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
storit->second->unlockMutex(0);
}
}