blob: 775a07082112bb419974e5406fb340df422a31c6 [file] [log] [blame]
Mike Lockwood16864ba2010-05-11 17:16:59 -04001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "MtpDatabase.h"
18#include "MtpDataPacket.h"
Mike Lockwood335dd2b2010-05-19 10:33:39 -040019#include "MtpUtils.h"
Mike Lockwood16864ba2010-05-11 17:16:59 -040020#include "SqliteDatabase.h"
21#include "SqliteStatement.h"
22
23#include <stdio.h>
Mike Lockwoodfceef462010-05-14 15:35:17 -040024#include <stdlib.h>
Mike Lockwood16864ba2010-05-11 17:16:59 -040025#include <sqlite3.h>
26
Mike Lockwood7850ef92010-05-14 10:10:36 -040027namespace android {
28
Mike Lockwoodfceef462010-05-14 15:35:17 -040029#define FILE_ID_COLUMN 1
30#define FILE_PATH_COLUMN 2
31#define FILE_FORMAT_COLUMN 3
32#define FILE_PARENT_COLUMN 4
33#define FILE_STORAGE_COLUMN 5
34#define FILE_SIZE_COLUMN 6
35#define FILE_MODIFIED_COLUMN 7
Mike Lockwood16864ba2010-05-11 17:16:59 -040036
Mike Lockwoodfceef462010-05-14 15:35:17 -040037#define AUDIO_ID_COLUMN 1
38#define AUDIO_TITLE_COLUMN 2
39#define AUDIO_ARTIST_COLUMN 3
40#define AUDIO_ALBUM_COLUMN 4
41#define AUDIO_ALBUM_ARTIST_COLUMN 5
42#define AUDIO_GENRE_COLUMN 6
43#define AUDIO_COMPOSER_COLUMN 7
44#define AUDIO_TRACK_NUMBER_COLUMN 8
45#define AUDIO_YEAR_COLUMN 9
46#define AUDIO_DURATION_COLUMN 10
47#define AUDIO_USE_COUNT_COLUMN 11
48#define AUDIO_SAMPLE_RATE_COLUMN 12
49#define AUDIO_NUM_CHANNELS_COLUMN 13
50#define AUDIO_AUDIO_WAVE_CODEC_COLUMN 14
51#define AUDIO_AUDIO_BIT_RATE_COLUMN 15
52
53#define FILE_TABLE_CREATE "CREATE TABLE IF NOT EXISTS files (" \
Mike Lockwood16864ba2010-05-11 17:16:59 -040054 "_id INTEGER PRIMARY KEY," \
55 "path TEXT," \
56 "format INTEGER," \
57 "parent INTEGER," \
58 "storage INTEGER," \
59 "size INTEGER," \
Mike Lockwoodfceef462010-05-14 15:35:17 -040060 "date_modified INTEGER" \
61 ");"
62
63#define AUDIO_TABLE_CREATE "CREATE TABLE IF NOT EXISTS audio (" \
64 "id INTEGER PRIMARY KEY," \
65 "title TEXT," \
66 "artist TEXT," \
67 "album TEXT," \
68 "album_artist TEXT," \
69 "genre TEXT," \
70 "composer TEXT," \
71 "track_number INTEGER," \
72 "year INTEGER," \
73 "duration INTEGER," \
74 "use_count INTEGER," \
75 "sample_rate INTEGER," \
76 "num_channels INTEGER," \
77 "audio_wave_codec TEXT," \
78 "audio_bit_rate INTEGER" \
Mike Lockwood16864ba2010-05-11 17:16:59 -040079 ");"
80
81#define PATH_INDEX_CREATE "CREATE INDEX IF NOT EXISTS path_index on files(path);"
82
Mike Lockwoodfceef462010-05-14 15:35:17 -040083#define FILE_ID_QUERY "SELECT _id,format FROM files WHERE path = ?;"
Mike Lockwood16864ba2010-05-11 17:16:59 -040084#define FILE_PATH_QUERY "SELECT path,size FROM files WHERE _id = ?"
85
Mike Lockwoodfceef462010-05-14 15:35:17 -040086#define GET_OBJECT_INFO_QUERY "SELECT storage,format,parent,path,size,date_modified FROM files WHERE _id = ?;"
87#define FILE_INSERT "INSERT INTO files VALUES(?,?,?,?,?,?,?);"
88#define FILE_DELETE "DELETE FROM files WHERE _id = ?;"
89
90#define AUDIO_INSERT "INSERT INTO audio VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);"
91#define AUDIO_DELETE "DELETE FROM audio WHERE id = ?;"
Mike Lockwood16864ba2010-05-11 17:16:59 -040092
Mike Lockwood16864ba2010-05-11 17:16:59 -040093struct PropertyTableEntry {
94 MtpObjectProperty property;
95 int type;
96 const char* columnName;
97};
98
99static const PropertyTableEntry kPropertyTable[] = {
100 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32, "parent" },
101 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, "storage" },
102 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT32, "format" },
103 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR, "path" },
104 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64, "size" },
Mike Lockwood16864ba2010-05-11 17:16:59 -0400105 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR, "date_modified" },
106};
107
108static bool getPropertyInfo(MtpObjectProperty property, int& type, const char*& columnName) {
109 int count = sizeof(kPropertyTable) / sizeof(kPropertyTable[0]);
110 const PropertyTableEntry* entry = kPropertyTable;
111 for (int i = 0; i < count; i++, entry++) {
112 if (entry->property == property) {
113 type = entry->type;
114 columnName = entry->columnName;
115 return true;
116 }
117 }
118 return false;
119}
120
121
Mike Lockwoodfceef462010-05-14 15:35:17 -0400122
Mike Lockwood16864ba2010-05-11 17:16:59 -0400123MtpDatabase::MtpDatabase()
124 : mFileIdQuery(NULL),
125 mObjectInfoQuery(NULL),
126 mFileInserter(NULL),
Mike Lockwoodfceef462010-05-14 15:35:17 -0400127 mFileDeleter(NULL),
128 mAudioInserter(NULL),
129 mAudioDeleter(NULL)
Mike Lockwood16864ba2010-05-11 17:16:59 -0400130{
131}
132
133MtpDatabase::~MtpDatabase() {
134}
135
136bool MtpDatabase::open(const char* path, bool create) {
137 if (!SqliteDatabase::open(path, create))
138 return false;
139
Mike Lockwoodfceef462010-05-14 15:35:17 -0400140 // create tables and indices if necessary
141 if (!exec(FILE_TABLE_CREATE)) {
142 fprintf(stderr, "could not create file table\n");
Mike Lockwood16864ba2010-05-11 17:16:59 -0400143 return false;
144 }
145 if (!exec(PATH_INDEX_CREATE)) {
Mike Lockwoodfceef462010-05-14 15:35:17 -0400146 fprintf(stderr, "could not path index on file table\n");
Mike Lockwood16864ba2010-05-11 17:16:59 -0400147 return false;
148 }
Mike Lockwoodfceef462010-05-14 15:35:17 -0400149 if (!exec(AUDIO_TABLE_CREATE)) {
150 fprintf(stderr, "could not create file table\n");
151 return false;
152 }
153
154 if (!mFileIdQuery) {
155 mFileIdQuery = new SqliteStatement(this);
156 if (!mFileIdQuery->prepare(FILE_ID_QUERY)) {
157 fprintf(stderr, "could not compile FILE_ID_QUERY\n");
158 exit(-1);
159 }
160 }
161 if (!mFilePathQuery) {
162 mFilePathQuery = new SqliteStatement(this);
163 if (!mFilePathQuery->prepare(FILE_PATH_QUERY)) {
164 fprintf(stderr, "could not compile FILE_PATH_QUERY\n");
165 exit(-1);
166 }
167 }
168 if (!mObjectInfoQuery) {
169 mObjectInfoQuery = new SqliteStatement(this);
170 if (!mObjectInfoQuery->prepare(GET_OBJECT_INFO_QUERY)) {
171 fprintf(stderr, "could not compile GET_OBJECT_INFO_QUERY\n");
172 exit(-1);
173 }
174 }
175 if (!mFileInserter) {
176 mFileInserter = new SqliteStatement(this);
177 if (!mFileInserter->prepare(FILE_INSERT)) {
178 fprintf(stderr, "could not compile FILE_INSERT\n");
179 exit(-1);
180 }
181 }
182 if (!mFileDeleter) {
183 mFileDeleter = new SqliteStatement(this);
184 if (!mFileDeleter->prepare(FILE_DELETE)) {
185 fprintf(stderr, "could not compile FILE_DELETE\n");
186 exit(-1);
187 }
188 }
189 if (!mAudioInserter) {
190 mAudioInserter = new SqliteStatement(this);
191 if (!mAudioInserter->prepare(AUDIO_INSERT)) {
192 fprintf(stderr, "could not compile AUDIO_INSERT\n");
193 exit(-1);
194 }
195 }
196 if (!mAudioDeleter) {
197 mAudioDeleter = new SqliteStatement(this);
198 if (!mAudioDeleter->prepare(AUDIO_DELETE)) {
199 fprintf(stderr, "could not compile AUDIO_DELETE\n");
200 exit(-1);
201 }
202 }
203
Mike Lockwood16864ba2010-05-11 17:16:59 -0400204 return true;
205}
206
Mike Lockwoodfceef462010-05-14 15:35:17 -0400207uint32_t MtpDatabase::getTableForFile(MtpObjectFormat format) {
208 switch (format) {
209 case MTP_FORMAT_AIFF:
210 case MTP_FORMAT_WAV:
211 case MTP_FORMAT_MP3:
212 case MTP_FORMAT_FLAC:
213 case MTP_FORMAT_UNDEFINED_AUDIO:
214 case MTP_FORMAT_WMA:
215 case MTP_FORMAT_OGG:
216 case MTP_FORMAT_AAC:
217 case MTP_FORMAT_AUDIBLE:
218 return kObjectHandleTableAudio;
219 case MTP_FORMAT_AVI:
220 case MTP_FORMAT_MPEG:
221 case MTP_FORMAT_ASF:
222 case MTP_FORMAT_UNDEFINED_VIDEO:
223 case MTP_FORMAT_WMV:
224 case MTP_FORMAT_MP4_CONTAINER:
225 case MTP_FORMAT_MP2:
226 case MTP_FORMAT_3GP_CONTAINER:
227 return kObjectHandleTableVideo;
228 case MTP_FORMAT_DEFINED:
229 case MTP_FORMAT_EXIF_JPEG:
230 case MTP_FORMAT_TIFF_EP:
231 case MTP_FORMAT_FLASHPIX:
232 case MTP_FORMAT_BMP:
233 case MTP_FORMAT_CIFF:
234 case MTP_FORMAT_GIF:
235 case MTP_FORMAT_JFIF:
236 case MTP_FORMAT_CD:
237 case MTP_FORMAT_PICT:
238 case MTP_FORMAT_PNG:
239 case MTP_FORMAT_TIFF:
240 case MTP_FORMAT_TIFF_IT:
241 case MTP_FORMAT_JP2:
242 case MTP_FORMAT_JPX:
243 case MTP_FORMAT_WINDOWS_IMAGE_FORMAT:
244 return kObjectHandleTableImage;
245 case MTP_FORMAT_ABSTRACT_AUDIO_PLAYLIST:
246 case MTP_FORMAT_ABSTRACT_AV_PLAYLIST:
247 case MTP_FORMAT_ABSTRACT_VIDEO_PLAYLIST:
248 case MTP_FORMAT_WPL_PLAYLIST:
249 case MTP_FORMAT_M3U_PLAYLIST:
250 case MTP_FORMAT_MPL_PLAYLIST:
251 case MTP_FORMAT_ASX_PLAYLIST:
252 case MTP_FORMAT_PLS_PLAYLIST:
253 return kObjectHandleTablePlaylist;
254 default:
255 return kObjectHandleTableFile;
256 }
257}
258
259MtpObjectHandle MtpDatabase::getObjectHandle(const char* path) {
260 mFileIdQuery->reset();
261 mFileIdQuery->bind(1, path);
262 if (mFileIdQuery->step()) {
263 int row = mFileIdQuery->getColumnInt(0);
264 if (row > 0) {
265 MtpObjectFormat format = mFileIdQuery->getColumnInt(1);
266 row |= getTableForFile(format);
267 return row;
268 }
269 }
270
271 return 0;
272}
273
Mike Lockwood16864ba2010-05-11 17:16:59 -0400274MtpObjectHandle MtpDatabase::addFile(const char* path,
275 MtpObjectFormat format,
276 MtpObjectHandle parent,
277 MtpStorageID storage,
278 uint64_t size,
Mike Lockwood16864ba2010-05-11 17:16:59 -0400279 time_t modified) {
Mike Lockwoodfceef462010-05-14 15:35:17 -0400280 mFileInserter->bind(FILE_PATH_COLUMN, path);
281 mFileInserter->bind(FILE_FORMAT_COLUMN, format);
282 mFileInserter->bind(FILE_PARENT_COLUMN, parent);
283 mFileInserter->bind(FILE_STORAGE_COLUMN, storage);
284 mFileInserter->bind(FILE_SIZE_COLUMN, size);
285 mFileInserter->bind(FILE_MODIFIED_COLUMN, modified);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400286 mFileInserter->step();
287 mFileInserter->reset();
Mike Lockwoodfceef462010-05-14 15:35:17 -0400288 int result = lastInsertedRow();
289 return (result <= 0 ? kInvalidObjectHandle : result);
290}
291
292MtpObjectHandle MtpDatabase::addAudioFile(MtpObjectHandle handle) {
293 mAudioInserter->bind(AUDIO_ID_COLUMN, handle);
294 mAudioInserter->step();
295 mAudioInserter->reset();
296 int result = lastInsertedRow();
297 handle |= kObjectHandleTableAudio;
298 return (result > 0 ? handle : kInvalidObjectHandle);
299}
300
301MtpObjectHandle MtpDatabase::addAudioFile(MtpObjectHandle handle,
302 const char* title,
303 const char* artist,
304 const char* album,
305 const char* albumArtist,
306 const char* genre,
307 const char* composer,
308 const char* mimeType,
309 int track,
310 int year,
311 int duration) {
312 mAudioInserter->bind(AUDIO_ID_COLUMN, handle);
313 if (title) mAudioInserter->bind(AUDIO_TITLE_COLUMN, title);
314 if (artist) mAudioInserter->bind(AUDIO_ARTIST_COLUMN, artist);
315 if (album) mAudioInserter->bind(AUDIO_ALBUM_COLUMN, album);
316 if (albumArtist) mAudioInserter->bind(AUDIO_ALBUM_ARTIST_COLUMN, albumArtist);
317 if (genre) mAudioInserter->bind(AUDIO_GENRE_COLUMN, genre);
318 if (composer) mAudioInserter->bind(AUDIO_COMPOSER_COLUMN, composer);
319 if (track) mAudioInserter->bind(AUDIO_TRACK_NUMBER_COLUMN, track);
320 if (year) mAudioInserter->bind(AUDIO_YEAR_COLUMN, year);
321 if (duration) mAudioInserter->bind(AUDIO_DURATION_COLUMN, duration);
322 mAudioInserter->step();
323 mAudioInserter->reset();
324 int result = lastInsertedRow();
325 if (result <= 0)
326 return kInvalidObjectHandle;
327 result |= kObjectHandleTableAudio;
328 return result;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400329}
330
331MtpObjectHandleList* MtpDatabase::getObjectList(MtpStorageID storageID,
332 MtpObjectFormat format,
333 MtpObjectHandle parent) {
334 bool whereStorage = (storageID != 0xFFFFFFFF);
335 bool whereFormat = (format != 0);
336 bool whereParent = (parent != 0);
337 char intBuffer[20];
338
Mike Lockwoodfceef462010-05-14 15:35:17 -0400339 MtpString query("SELECT _id,format FROM files");
Mike Lockwood16864ba2010-05-11 17:16:59 -0400340 if (whereStorage || whereFormat || whereParent)
341 query += " WHERE";
342 if (whereStorage) {
343 snprintf(intBuffer, sizeof(intBuffer), "%d", storageID);
344 query += " storage = ";
345 query += intBuffer;
346 }
347 if (whereFormat) {
348 snprintf(intBuffer, sizeof(intBuffer), "%d", format);
349 if (whereStorage)
350 query += " AND";
351 query += " format = ";
352 query += intBuffer;
353 }
354 if (whereParent) {
Mike Lockwoodfceef462010-05-14 15:35:17 -0400355 if (parent != MTP_PARENT_ROOT)
356 parent &= kObjectHandleIndexMask;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400357 snprintf(intBuffer, sizeof(intBuffer), "%d", parent);
358 if (whereStorage || whereFormat)
359 query += " AND";
360 query += " parent = ";
361 query += intBuffer;
362 }
363 query += ";";
364
365 SqliteStatement stmt(this);
366 printf("%s\n", (const char *)query);
367 stmt.prepare(query);
368
369 MtpObjectHandleList* list = new MtpObjectHandleList();
370 while (!stmt.isDone()) {
371 if (stmt.step()) {
372 int index = stmt.getColumnInt(0);
373 printf("stmt.getColumnInt returned %d\n", index);
Mike Lockwoodfceef462010-05-14 15:35:17 -0400374 if (index > 0) {
375 MtpObjectFormat format = stmt.getColumnInt(1);
376 index |= getTableForFile(format);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400377 list->push(index);
Mike Lockwoodfceef462010-05-14 15:35:17 -0400378 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400379 }
380 }
381 printf("list size: %d\n", list->size());
382 return list;
383}
384
Mike Lockwoodfceef462010-05-14 15:35:17 -0400385
Mike Lockwood16864ba2010-05-11 17:16:59 -0400386MtpResponseCode MtpDatabase::getObjectProperty(MtpObjectHandle handle,
387 MtpObjectProperty property,
388 MtpDataPacket& packet) {
389 int type;
390 const char* columnName;
391 char intBuffer[20];
392
Mike Lockwoodfceef462010-05-14 15:35:17 -0400393 if (handle != MTP_PARENT_ROOT)
394 handle &= kObjectHandleIndexMask;
395
Mike Lockwood16864ba2010-05-11 17:16:59 -0400396 if (!getPropertyInfo(property, type, columnName))
397 return MTP_RESPONSE_INVALID_OBJECT_PROP_CODE;
398 snprintf(intBuffer, sizeof(intBuffer), "%d", handle);
399
400 MtpString query("SELECT ");
401 query += columnName;
402 query += " FROM files WHERE _id = ";
403 query += intBuffer;
404 query += ";";
405
406 SqliteStatement stmt(this);
407 printf("%s\n", (const char *)query);
408 stmt.prepare(query);
409
410 if (!stmt.step())
411 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
412
413 switch (type) {
414 case MTP_TYPE_INT8:
415 packet.putInt8(stmt.getColumnInt(0));
416 break;
417 case MTP_TYPE_UINT8:
418 packet.putUInt8(stmt.getColumnInt(0));
419 break;
420 case MTP_TYPE_INT16:
421 packet.putInt16(stmt.getColumnInt(0));
422 break;
423 case MTP_TYPE_UINT16:
424 packet.putUInt16(stmt.getColumnInt(0));
425 break;
426 case MTP_TYPE_INT32:
427 packet.putInt32(stmt.getColumnInt(0));
428 break;
429 case MTP_TYPE_UINT32:
430 packet.putUInt32(stmt.getColumnInt(0));
431 break;
432 case MTP_TYPE_INT64:
433 packet.putInt64(stmt.getColumnInt64(0));
434 break;
435 case MTP_TYPE_UINT64:
436 packet.putUInt64(stmt.getColumnInt64(0));
437 break;
438 case MTP_TYPE_STR:
439 packet.putString(stmt.getColumnString(0));
440 break;
441 default:
442 fprintf(stderr, "unsupported object type\n");
443 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
444 }
445 return MTP_RESPONSE_OK;
446}
447
448MtpResponseCode MtpDatabase::getObjectInfo(MtpObjectHandle handle,
449 MtpDataPacket& packet) {
450 char date[20];
451
Mike Lockwoodfceef462010-05-14 15:35:17 -0400452 if (handle != MTP_PARENT_ROOT)
453 handle &= kObjectHandleIndexMask;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400454
Mike Lockwoodfceef462010-05-14 15:35:17 -0400455 mObjectInfoQuery->reset();
Mike Lockwood16864ba2010-05-11 17:16:59 -0400456 mObjectInfoQuery->bind(1, handle);
457 if (!mObjectInfoQuery->step())
458 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
459
460 MtpStorageID storageID = mObjectInfoQuery->getColumnInt(0);
461 MtpObjectFormat format = mObjectInfoQuery->getColumnInt(1);
462 MtpObjectHandle parent = mObjectInfoQuery->getColumnInt(2);
463 // extract name from path. do we want a separate database entry for this?
464 const char* name = mObjectInfoQuery->getColumnString(3);
465 const char* lastSlash = strrchr(name, '/');
466 if (lastSlash)
467 name = lastSlash + 1;
468 int64_t size = mObjectInfoQuery->getColumnInt64(4);
Mike Lockwoodfceef462010-05-14 15:35:17 -0400469 time_t modified = mObjectInfoQuery->getColumnInt(5);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400470 int associationType = (format == MTP_FORMAT_ASSOCIATION ?
471 MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
472 MTP_ASSOCIATION_TYPE_UNDEFINED);
473
474 printf("storageID: %d, format: %d, parent: %d\n", storageID, format, parent);
475
476 packet.putUInt32(storageID);
477 packet.putUInt16(format);
478 packet.putUInt16(0); // protection status
479 packet.putUInt32((size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size));
480 packet.putUInt16(0); // thumb format
481 packet.putUInt32(0); // thumb compressed size
482 packet.putUInt32(0); // thumb pix width
483 packet.putUInt32(0); // thumb pix height
484 packet.putUInt32(0); // image pix width
485 packet.putUInt32(0); // image pix height
486 packet.putUInt32(0); // image bit depth
487 packet.putUInt32(parent);
488 packet.putUInt16(associationType);
489 packet.putUInt32(0); // association desc
490 packet.putUInt32(0); // sequence number
491 packet.putString(name); // file name
Mike Lockwoodfceef462010-05-14 15:35:17 -0400492 packet.putEmptyString();
Mike Lockwood16864ba2010-05-11 17:16:59 -0400493 formatDateTime(modified, date, sizeof(date));
494 packet.putString(date); // date modified
495 packet.putEmptyString(); // keywords
496
497 return MTP_RESPONSE_OK;
498}
499
500bool MtpDatabase::getObjectFilePath(MtpObjectHandle handle,
501 MtpString& filePath,
502 int64_t& fileLength) {
Mike Lockwoodfceef462010-05-14 15:35:17 -0400503 if (handle != MTP_PARENT_ROOT)
504 handle &= kObjectHandleIndexMask;
505 mFilePathQuery->reset();
Mike Lockwood16864ba2010-05-11 17:16:59 -0400506 mFilePathQuery->bind(1, handle);
507 if (!mFilePathQuery->step())
508 return false;
509
510 const char* path = mFilePathQuery->getColumnString(0);
511 if (!path)
512 return false;
513 filePath = path;
514 fileLength = mFilePathQuery->getColumnInt64(1);
515 return true;
516}
517
518bool MtpDatabase::deleteFile(MtpObjectHandle handle) {
Mike Lockwoodfceef462010-05-14 15:35:17 -0400519 uint32_t table = handle & kObjectHandleTableMask;
520 handle &= kObjectHandleIndexMask;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400521 mFileDeleter->bind(1, handle);
522 mFileDeleter->step();
523 mFileDeleter->reset();
Mike Lockwoodfceef462010-05-14 15:35:17 -0400524 if (table == kObjectHandleTableAudio) {
525 mAudioDeleter->bind(1, handle);
526 mAudioDeleter->step();
527 mAudioDeleter->reset();
528 }
529
Mike Lockwood16864ba2010-05-11 17:16:59 -0400530 return true;
531}
532
Mike Lockwoodfceef462010-05-14 15:35:17 -0400533MtpObjectHandle* MtpDatabase::getFileList(int& outCount) {
534 MtpObjectHandle* result = NULL;
535 int count = 0;
536 SqliteStatement stmt(this);
537 stmt.prepare("SELECT count(*) FROM files;");
538
539 MtpObjectHandleList* list = new MtpObjectHandleList();
540 if (stmt.step())
541 count = stmt.getColumnInt(0);
542
543 if (count > 0) {
544 result = new MtpObjectHandle[count];
545 memset(result, 0, count * sizeof(*result));
546 SqliteStatement stmt2(this);
547 stmt2.prepare("SELECT _id,format FROM files;");
548
549 for (int i = 0; i < count; i++) {
550 if (!stmt2.step()) {
551 printf("getFileList ended early\n");
552 count = i;
553 break;
554 }
555 MtpObjectHandle handle = stmt2.getColumnInt(0);
556 MtpObjectFormat format = stmt2.getColumnInt(1);
557 handle |= getTableForFile(format);
558 result[i] = handle;
559 }
560 }
561 outCount = count;
562 return result;
563}
564
Mike Lockwood16864ba2010-05-11 17:16:59 -0400565/*
566 for getObjectPropDesc
567
568 packet.putUInt16(property);
569 packet.putUInt16(dataType);
570 packet.putUInt8(getSet);
571 // default value DTS
572 packet.putUInt32(groupCode);
573 packet.putUInt8(formFlag);
574 // form, variable
575*/
Mike Lockwood7850ef92010-05-14 10:10:36 -0400576
577} // namespace android