mtp

Merge lp:~cyphermox/mtp/rename into lp:mtp

Proposed by Mathieu Trudel-Lapierre
Status: Merged
Approved by: Ricardo Salveti
Approved revision: 41
Merged at revision: 37
Proposed branch: lp:~cyphermox/mtp/rename
Merge into: lp:mtp
Diff against target: 495 lines (+209/-39)
6 files modified
debian/changelog (+6/-0)
include/MtpDatabase.h (+3/-0)
include/MtpServer.h (+8/-1)
server/UbuntuMtpDatabase.h (+125/-31)
src/MtpServer.cpp (+58/-7)
tests/MockMtpDatabase.h (+9/-0)
To merge this branch: bzr merge lp:~cyphermox/mtp/rename
Reviewer Review Type Date Requested Status
Ricardo Salveti (community) Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+197113@code.launchpad.net

Commit message

Miscellaneous standard file operation fixes:

- fix renaming files
- correctly list file size after an edit
- return proper file size in ObjectInfo
- implement MTP_OPERATION_MOVE
- allow sending out events for ObjectInfo and ObjectProperty changes

Description of the change

Miscellaneous standard file operation fixes:

- fix renaming files
- correctly list file size after an edit
- return proper file size in ObjectInfo
- implement MTP_OPERATION_MOVE
- allow sending out events for ObjectInfo and ObjectProperty changes

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:~cyphermox/mtp/rename updated
40. By Mathieu Trudel-Lapierre

Guess object format for media players support

41. By Mathieu Trudel-Lapierre

Add playback formats supported, fix folder send.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

Looks good, tested with mako, copying over videos and mp3s, doing rename and removes, everything working as expected.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2013-10-23 05:07:47 +0000
3+++ debian/changelog 2013-12-03 21:19:01 +0000
4@@ -1,3 +1,9 @@
5+mtp (0.0.2+14.04.20131127-0ubuntu1) UNRELEASED; urgency=low
6+
7+ * New release.
8+
9+ -- Mathieu Trudel-Lapierre <mathieu-tl@ubuntu.com> Wed, 27 Nov 2013 13:35:01 -0500
10+
11 mtp (0.0.1+13.10.20130926.3-0ubuntu2) trusty; urgency=low
12
13 * No change rebuild for Boost 1.54 transition.
14
15=== modified file 'include/MtpDatabase.h'
16--- include/MtpDatabase.h 2013-06-13 10:22:21 +0000
17+++ include/MtpDatabase.h 2013-12-03 21:19:01 +0000
18@@ -93,6 +93,9 @@
19
20 virtual MtpResponseCode deleteFile(MtpObjectHandle handle) = 0;
21
22+ virtual MtpResponseCode moveFile(MtpObjectHandle handle,
23+ MtpObjectHandle new_parent) = 0;
24+
25 virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle) = 0;
26
27 virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle,
28
29=== modified file 'include/MtpServer.h'
30--- include/MtpServer.h 2013-06-13 10:22:21 +0000
31+++ include/MtpServer.h 2013-12-03 21:19:01 +0000
32@@ -104,11 +104,17 @@
33
34 void sendObjectAdded(MtpObjectHandle handle);
35 void sendObjectRemoved(MtpObjectHandle handle);
36+ void sendObjectInfoChanged(MtpObjectHandle handle);
37+ void sendObjectPropChanged(MtpObjectHandle handle,
38+ MtpObjectProperty prop);
39
40 private:
41 void sendStoreAdded(MtpStorageID id);
42 void sendStoreRemoved(MtpStorageID id);
43- void sendEvent(MtpEventCode code, uint32_t param1);
44+ void sendEvent(MtpEventCode code,
45+ uint32_t param1,
46+ uint32_t param2,
47+ uint32_t param3);
48
49 void addEditObject(MtpObjectHandle handle, MtpString& path,
50 uint64_t size, MtpObjectFormat format, int fd);
51@@ -141,6 +147,7 @@
52 MtpResponseCode doSendObjectInfo();
53 MtpResponseCode doSendObject();
54 MtpResponseCode doDeleteObject();
55+ MtpResponseCode doMoveObject();
56 MtpResponseCode doGetObjectPropDesc();
57 MtpResponseCode doGetDevicePropDesc();
58 MtpResponseCode doSendPartialObject();
59
60=== modified file 'server/UbuntuMtpDatabase.h'
61--- server/UbuntuMtpDatabase.h 2013-09-13 17:11:57 +0000
62+++ server/UbuntuMtpDatabase.h 2013-12-03 21:19:01 +0000
63@@ -21,6 +21,7 @@
64 #include <mtp.h>
65 #include <MtpDatabase.h>
66 #include <MtpDataPacket.h>
67+#include <MtpStringBuffer.h>
68 #include <MtpObjectInfo.h>
69 #include <MtpProperty.h>
70
71@@ -31,7 +32,10 @@
72 #include <vector>
73 #include <string>
74 #include <tuple>
75+#include <exception>
76
77+#include <boost/algorithm/string.hpp>
78+#include <boost/assign/list_of.hpp>
79 #include <boost/foreach.hpp>
80 #include <boost/filesystem.hpp>
81 #include <boost/range/adaptors.hpp>
82@@ -46,7 +50,6 @@
83 struct DbEntry
84 {
85 MtpStorageID storage_id;
86- std::string object_name;
87 MtpObjectFormat object_format;
88 MtpObjectHandle parent;
89 size_t object_size;
90@@ -56,7 +59,31 @@
91
92 uint32_t counter;
93 std::map<MtpObjectHandle, DbEntry> db;
94-
95+ std::map<std::string, MtpObjectFormat> formats = boost::assign::map_list_of
96+ (".ogg", MTP_FORMAT_OGG)
97+ (".mp3", MTP_FORMAT_MP3)
98+ (".wav", MTP_FORMAT_WAV)
99+ (".wma", MTP_FORMAT_WMA)
100+ (".aac", MTP_FORMAT_AAC)
101+ (".flac", MTP_FORMAT_FLAC);
102+
103+ MtpObjectFormat guess_object_format(std::string extension)
104+ {
105+ std::map<std::string, MtpObjectFormat>::iterator it;
106+
107+ std::cout << __PRETTY_FUNCTION__ << " extension: " << extension << std::endl;
108+ it = formats.find(extension);
109+ if (it == formats.end()) {
110+ boost::to_upper(extension);
111+ it = formats.find(extension);
112+ if (it == formats.end()) {
113+ return MTP_FORMAT_UNDEFINED;
114+ }
115+ }
116+
117+ return it->second;
118+ }
119+
120 void parse_directory(path p, MtpObjectHandle parent)
121 {
122 DbEntry entry;
123@@ -74,14 +101,15 @@
124
125 entry.storage_id = MTP_STORAGE_FIXED_RAM;
126 entry.parent = parent;
127- entry.object_name = it->filename().string();
128- entry.display_name = it->filename().string();
129+ entry.display_name = std::string(it->filename().string());
130 entry.path = it->string();
131
132 if (is_regular_file (*it)) {
133- entry.object_format = MTP_FORMAT_DEFINED;
134+ entry.object_format = guess_object_format(it->extension().string());
135 entry.object_size = file_size(*it);
136
137+ std::cout << " format: " << std::hex << entry.object_format << std::endl;
138+
139 db.insert( std::pair<MtpObjectHandle, DbEntry>(handle, entry) );
140 } else if (is_directory (*it)) {
141 entry.object_format = MTP_FORMAT_ASSOCIATION;
142@@ -107,8 +135,7 @@
143
144 entry.storage_id = MTP_STORAGE_FIXED_RAM;
145 entry.parent = MTP_PARENT_ROOT;
146- entry.object_name = p.filename().string();
147- entry.display_name = p.filename().string();
148+ entry.display_name = std::string(p.filename().string());
149 entry.path = p.string();
150 entry.object_format = MTP_FORMAT_ASSOCIATION;
151 entry.object_size = 0;
152@@ -163,7 +190,6 @@
153
154 entry.storage_id = storage;
155 entry.parent = parent;
156- entry.object_name = std::string(basename(path.c_str()));
157 entry.display_name = std::string(basename(path.c_str()));
158 entry.path = path;
159 entry.object_format = format;
160@@ -188,8 +214,15 @@
161 std::cout << __PRETTY_FUNCTION__ << ": " << path << std::endl;
162
163 if (!succeeded) {
164- db.erase(handle);
165- }
166+ db.erase(handle);
167+ } else {
168+ boost::filesystem::path p (path);
169+
170+ if (format != MTP_FORMAT_ASSOCIATION) {
171+ /* Resync file size, just in case this is actually an Edit. */
172+ db.at(handle).object_size = file_size(p);
173+ }
174+ }
175 }
176
177 virtual MtpObjectHandleList* getObjectList(
178@@ -238,7 +271,28 @@
179 virtual MtpObjectFormatList* getSupportedPlaybackFormats()
180 {
181 std::cout << __PRETTY_FUNCTION__ << std::endl;
182- static const MtpObjectFormatList list = {MTP_FORMAT_PNG};
183+ static const MtpObjectFormatList list = {
184+ /* Generic files */
185+ MTP_FORMAT_UNDEFINED,
186+
187+ /* Supported audio formats */
188+ MTP_FORMAT_OGG,
189+ MTP_FORMAT_MP3,
190+ MTP_FORMAT_WAV,
191+ MTP_FORMAT_WMA,
192+ MTP_FORMAT_AAC,
193+ MTP_FORMAT_FLAC,
194+
195+ /* Supported video formats */
196+ // none listed yet, video apparently broken.
197+
198+ /* Audio album, and album art */
199+ MTP_FORMAT_ABSTRACT_AUDIO_ALBUM,
200+
201+ /* Playlists for audio and video */
202+ MTP_FORMAT_ABSTRACT_AV_PLAYLIST,
203+ };
204+
205 return new MtpObjectFormatList{list};
206 }
207
208@@ -266,6 +320,7 @@
209 MTP_PROPERTY_WIDTH,
210 MTP_PROPERTY_HEIGHT,
211 MTP_PROPERTY_IMAGE_BIT_DEPTH,
212+ MTP_PROPERTY_OBJECT_FILE_NAME,
213 MTP_PROPERTY_DISPLAY_NAME
214 };
215
216@@ -292,6 +347,7 @@
217 case MTP_PROPERTY_OBJECT_FORMAT: packet.putUInt32(db.at(handle).object_format); break;
218 case MTP_PROPERTY_OBJECT_SIZE: packet.putUInt32(db.at(handle).object_size); break;
219 case MTP_PROPERTY_DISPLAY_NAME: packet.putString(db.at(handle).display_name.c_str()); break;
220+ case MTP_PROPERTY_OBJECT_FILE_NAME: packet.putString(db.at(handle).display_name.c_str()); break;
221 default: return MTP_RESPONSE_GENERAL_ERROR; break;
222 }
223
224@@ -303,8 +359,47 @@
225 MtpObjectProperty property,
226 MtpDataPacket& packet)
227 {
228+ DbEntry entry;
229+ MtpStringBuffer buffer;
230+ std::string oldname;
231+ std::string newname;
232+ path oldpath;
233+ path newpath;
234+
235 std::cout << __PRETTY_FUNCTION__ << std::endl;
236- return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
237+
238+ switch(property)
239+ {
240+ case MTP_PROPERTY_OBJECT_FILE_NAME:
241+ try {
242+ entry = db.at(handle);
243+
244+ packet.getString(buffer);
245+ newname = strdup(buffer);
246+
247+ oldpath /= entry.path;
248+ newpath /= oldpath.branch_path() / "/" / newname;
249+
250+ boost::filesystem::rename(oldpath, newpath);
251+
252+ db.at(handle).display_name = newname;
253+ db.at(handle).path = newpath.string();
254+ } catch (filesystem_error& fe) {
255+ std::cout << "ERROR: " << fe.what() << std::endl;
256+ return MTP_RESPONSE_DEVICE_BUSY;
257+ } catch (std::exception& e) {
258+ std::cout << "ERROR: " << e.what() << std::endl;
259+ return MTP_RESPONSE_GENERAL_ERROR;
260+ } catch (...) {
261+ std::cout << "ERROR: autre exception" << std::endl;
262+ return MTP_RESPONSE_GENERAL_ERROR;
263+ }
264+
265+ break;
266+ default: return MTP_RESPONSE_OPERATION_NOT_SUPPORTED; break;
267+ }
268+
269+ return MTP_RESPONSE_OK;
270 }
271
272 virtual MtpResponseCode getDevicePropertyValue(
273@@ -347,23 +442,20 @@
274 MtpObjectInfo& info)
275 {
276 std::cout << __PRETTY_FUNCTION__ << std::endl;
277+
278 info.mHandle = handle;
279 info.mStorageID = db.at(handle).storage_id;
280 info.mFormat = db.at(handle).object_format;
281 info.mProtectionStatus = 0x0;
282- info.mCompressedSize = 0;
283- info.mThumbFormat = db.at(handle).object_format;
284- info.mThumbCompressedSize = 20*20*4;
285- info.mThumbPixWidth = 20;
286- info.mThumbPixHeight =20;
287- info.mImagePixWidth = 20;
288- info.mImagePixHeight = 20;
289- info.mImagePixDepth = 4;
290+ info.mCompressedSize = db.at(handle).object_size;
291+ info.mImagePixWidth = 0;
292+ info.mImagePixHeight = 0;
293+ info.mImagePixDepth = 0;
294 info.mParent = db.at(handle).parent;
295 info.mAssociationType = 0;
296 info.mAssociationDesc = 0;
297 info.mSequenceNumber = 0;
298- info.mName = ::strdup(db.at(handle).object_name.c_str());
299+ info.mName = ::strdup(db.at(handle).display_name.c_str());
300 info.mDateCreated = 0;
301 info.mDateModified = 0;
302 info.mKeywords = ::strdup("ubuntu,touch");
303@@ -422,16 +514,17 @@
304 return MTP_RESPONSE_GENERAL_ERROR;
305 }
306
307+ virtual MtpResponseCode moveFile(MtpObjectHandle handle, MtpObjectHandle new_parent)
308+ {
309+ std::cout << __PRETTY_FUNCTION__ << std::endl;
310+
311+ // change parent
312+ db.at(handle).parent = new_parent;
313+
314+ return MTP_RESPONSE_OK;
315+ }
316+
317 /*
318- virtual MtpResponseCode moveFile(MtpObjectHandle handle, MtpObjectHandle new_parent)
319- {
320- std::cout << __PRETTY_FUNCTION__ << std::endl;
321-
322- // change parent
323-
324- return MTP_RESPONSE_OK
325- }
326-
327 virtual MtpResponseCode copyFile(MtpObjectHandle handle, MtpObjectHandle new_parent)
328 {
329 std::cout << __PRETTY_FUNCTION__ << std::endl;
330@@ -471,7 +564,8 @@
331 case MTP_PROPERTY_WIDTH: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
332 case MTP_PROPERTY_HEIGHT: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
333 case MTP_PROPERTY_IMAGE_BIT_DEPTH: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
334- case MTP_PROPERTY_DISPLAY_NAME: result = new MtpProperty(property, MTP_TYPE_STR); break;
335+ case MTP_PROPERTY_DISPLAY_NAME: result = new MtpProperty(property, MTP_TYPE_STR, true); break;
336+ case MTP_PROPERTY_OBJECT_FILE_NAME: result = new MtpProperty(property, MTP_TYPE_STR, true); break;
337 default: break;
338 }
339
340
341=== modified file 'src/MtpServer.cpp'
342--- src/MtpServer.cpp 2013-09-13 16:37:39 +0000
343+++ src/MtpServer.cpp 2013-12-03 21:19:01 +0000
344@@ -68,7 +68,7 @@
345 MTP_OPERATION_SET_DEVICE_PROP_VALUE,
346 MTP_OPERATION_RESET_DEVICE_PROP_VALUE,
347 // MTP_OPERATION_TERMINATE_OPEN_CAPTURE,
348-// MTP_OPERATION_MOVE_OBJECT,
349+ MTP_OPERATION_MOVE_OBJECT,
350 // MTP_OPERATION_COPY_OBJECT,
351 MTP_OPERATION_GET_PARTIAL_OBJECT,
352 // MTP_OPERATION_INITIATE_OPEN_CAPTURE,
353@@ -96,6 +96,8 @@
354 MTP_EVENT_OBJECT_REMOVED,
355 MTP_EVENT_STORE_ADDED,
356 MTP_EVENT_STORE_REMOVED,
357+ MTP_EVENT_OBJECT_INFO_CHANGED,
358+ MTP_EVENT_OBJECT_PROP_CHANGED,
359 };
360
361 MtpServer::MtpServer(int fd, MtpDatabase* database, bool ptp,
362@@ -246,29 +248,45 @@
363
364 void MtpServer::sendObjectAdded(MtpObjectHandle handle) {
365 ALOGV("sendObjectAdded %d\n", handle);
366- sendEvent(MTP_EVENT_OBJECT_ADDED, handle);
367+ sendEvent(MTP_EVENT_OBJECT_ADDED, handle, 0, 0);
368 }
369
370 void MtpServer::sendObjectRemoved(MtpObjectHandle handle) {
371 ALOGV("sendObjectRemoved %d\n", handle);
372- sendEvent(MTP_EVENT_OBJECT_REMOVED, handle);
373+ sendEvent(MTP_EVENT_OBJECT_REMOVED, handle, 0, 0);
374+}
375+
376+void MtpServer::sendObjectInfoChanged(MtpObjectHandle handle) {
377+ ALOGV("sendObjectInfoChanged %d\n", handle);
378+ sendEvent(MTP_EVENT_OBJECT_INFO_CHANGED, handle, 0, 0);
379+}
380+
381+void MtpServer::sendObjectPropChanged(MtpObjectHandle handle,
382+ MtpObjectProperty prop) {
383+ ALOGV("sendObjectPropChanged %d %d\n", handle, prop);
384+ sendEvent(MTP_EVENT_OBJECT_PROP_CHANGED, handle, prop, 0);
385 }
386
387 void MtpServer::sendStoreAdded(MtpStorageID id) {
388 ALOGV("sendStoreAdded %08X\n", id);
389- sendEvent(MTP_EVENT_STORE_ADDED, id);
390+ sendEvent(MTP_EVENT_STORE_ADDED, id, 0, 0);
391 }
392
393 void MtpServer::sendStoreRemoved(MtpStorageID id) {
394 ALOGV("sendStoreRemoved %08X\n", id);
395- sendEvent(MTP_EVENT_STORE_REMOVED, id);
396+ sendEvent(MTP_EVENT_STORE_REMOVED, id, 0, 0);
397 }
398
399-void MtpServer::sendEvent(MtpEventCode code, uint32_t param1) {
400+void MtpServer::sendEvent(MtpEventCode code,
401+ uint32_t param1,
402+ uint32_t param2,
403+ uint32_t param3) {
404 if (mSessionOpen) {
405 mEvent.setEventCode(code);
406 mEvent.setTransactionID(mRequest.getTransactionID());
407 mEvent.setParameter(1, param1);
408+ mEvent.setParameter(2, param2);
409+ mEvent.setParameter(3, param3);
410 int ret = mEvent.write(mFD);
411 ALOGV("mEvent.write returned %d\n", ret);
412 }
413@@ -392,6 +410,9 @@
414 case MTP_OPERATION_DELETE_OBJECT:
415 response = doDeleteObject();
416 break;
417+ case MTP_OPERATION_MOVE_OBJECT:
418+ response = doMoveObject();
419+ break;
420 case MTP_OPERATION_GET_OBJECT_PROP_DESC:
421 response = doGetObjectPropDesc();
422 break;
423@@ -625,6 +646,8 @@
424 }
425
426 MtpResponseCode MtpServer::doSetObjectPropValue() {
427+ MtpResponseCode response;
428+
429 if (!hasStorage())
430 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
431 MtpObjectHandle handle = mRequest.getParameter(1);
432@@ -632,7 +655,11 @@
433 ALOGV("SetObjectPropValue %d %s\n", handle,
434 MtpDebug::getObjectPropCodeName(property));
435
436- return mDatabase->setObjectPropertyValue(handle, property, mData);
437+ response = mDatabase->setObjectPropertyValue(handle, property, mData);
438+
439+ //sendObjectPropChanged(handle, property);
440+
441+ return response;
442 }
443
444 MtpResponseCode MtpServer::doGetDevicePropValue() {
445@@ -1065,6 +1092,30 @@
446 return result;
447 }
448
449+MtpResponseCode MtpServer::doMoveObject() {
450+ if (!hasStorage())
451+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
452+ MtpObjectHandle handle = mRequest.getParameter(1);
453+ MtpObjectFormat format = mRequest.getParameter(2);
454+ MtpObjectHandle newparent = mRequest.getParameter(3);
455+
456+ MtpString filePath;
457+ MtpString newPath;
458+ int64_t fileLength;
459+ int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format);
460+ result = mDatabase->getObjectFilePath(handle, newPath, fileLength, format);
461+ if (result == MTP_RESPONSE_OK) {
462+ ALOGV("moving %s to %s", filePath.c_str(), newPath.c_str());
463+ result = mDatabase->moveFile(handle, newparent);
464+ // Don't move the actual files unless the database deletion is allowed
465+ if (result == MTP_RESPONSE_OK) {
466+ rename(filePath.c_str(), newPath.c_str());
467+ }
468+ }
469+
470+ return result;
471+}
472+
473 MtpResponseCode MtpServer::doGetObjectPropDesc() {
474 MtpObjectProperty propCode = mRequest.getParameter(1);
475 MtpObjectFormat format = mRequest.getParameter(2);
476
477=== modified file 'tests/MockMtpDatabase.h'
478--- tests/MockMtpDatabase.h 2013-09-13 14:21:51 +0000
479+++ tests/MockMtpDatabase.h 2013-12-03 21:19:01 +0000
480@@ -303,6 +303,15 @@
481 return MTP_RESPONSE_GENERAL_ERROR;
482 }
483
484+ virtual MtpResponseCode moveFile(MtpObjectHandle handle, MtpObjectHandle new_parent)
485+ {
486+ std::cout << __PRETTY_FUNCTION__ << std::endl;
487+
488+ db.at(handle).parent = new_parent;
489+
490+ return MTP_RESPONSE_OK;
491+ }
492+
493 virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle)
494 {
495 std::cout << __PRETTY_FUNCTION__ << std::endl;

Subscribers

People subscribed via source and target branches