352
408
return LIBMTP_FILETYPE_UNKNOWN;
412
* Create a new property mapping entry
413
* @return a newly allocated propertymapping entry.
415
static propertymap_t *new_propertymap_entry()
417
propertymap_t *propertymap;
419
propertymap = (propertymap_t *)malloc(sizeof(propertymap_t));
421
if( propertymap != NULL ) {
422
propertymap->description = NULL;
423
propertymap->id = LIBMTP_PROPERTY_UNKNOWN;
424
propertymap->ptp_id = 0;
425
propertymap->next = NULL;
432
* Register an MTP or PTP property for data retrieval
434
* @param description Text description of property
435
* @param id libmtp internal property id
436
* @param ptp_id PTP property id
437
* @return 0 for success any other value means error.
439
static int register_property(char const * const description, LIBMTP_property_t const id,
440
uint16_t const ptp_id)
442
propertymap_t *new = NULL, *current;
444
// Has this LIBMTP propety been registered before ?
445
current = propertymap;
446
while (current != NULL) {
447
if(current->id == id) {
450
current = current->next;
454
if(current == NULL) {
455
new = new_propertymap_entry();
461
if(description != NULL) {
462
new->description = strdup(description);
464
new->ptp_id = ptp_id;
466
// Add the entry to the list
467
if(propertymap == NULL) {
470
current = propertymap;
471
while (current->next != NULL ) current=current->next;
474
// Update the existing entry
476
if (current->description != NULL) {
477
free(current->description);
479
current->description = NULL;
480
if(description != NULL) {
481
current->description = strdup(description);
483
current->ptp_id = ptp_id;
489
static void init_propertymap()
491
register_property("Storage ID", LIBMTP_PROPERTY_StorageID, PTP_OPC_StorageID);
492
register_property("Object Format", LIBMTP_PROPERTY_ObjectFormat, PTP_OPC_ObjectFormat);
493
register_property("Protection Status", LIBMTP_PROPERTY_ProtectionStatus, PTP_OPC_ProtectionStatus);
494
register_property("Object Size", LIBMTP_PROPERTY_ObjectSize, PTP_OPC_ObjectSize);
495
register_property("Association Type", LIBMTP_PROPERTY_AssociationType, PTP_OPC_AssociationType);
496
register_property("Association Desc", LIBMTP_PROPERTY_AssociationDesc, PTP_OPC_AssociationDesc);
497
register_property("Object File Name", LIBMTP_PROPERTY_ObjectFileName, PTP_OPC_ObjectFileName);
498
register_property("Date Created", LIBMTP_PROPERTY_DateCreated, PTP_OPC_DateCreated);
499
register_property("Date Modified", LIBMTP_PROPERTY_DateModified, PTP_OPC_DateModified);
500
register_property("Keywords", LIBMTP_PROPERTY_Keywords, PTP_OPC_Keywords);
501
register_property("Parent Object", LIBMTP_PROPERTY_ParentObject, PTP_OPC_ParentObject);
502
register_property("Allowed Folder Contents", LIBMTP_PROPERTY_AllowedFolderContents, PTP_OPC_AllowedFolderContents);
503
register_property("Hidden", LIBMTP_PROPERTY_Hidden, PTP_OPC_Hidden);
504
register_property("System Object", LIBMTP_PROPERTY_SystemObject, PTP_OPC_SystemObject);
505
register_property("Persistant Unique Object Identifier", LIBMTP_PROPERTY_PersistantUniqueObjectIdentifier, PTP_OPC_PersistantUniqueObjectIdentifier);
506
register_property("Sync ID", LIBMTP_PROPERTY_SyncID, PTP_OPC_SyncID);
507
register_property("Property Bag", LIBMTP_PROPERTY_PropertyBag, PTP_OPC_PropertyBag);
508
register_property("Name", LIBMTP_PROPERTY_Name, PTP_OPC_Name);
509
register_property("Created By", LIBMTP_PROPERTY_CreatedBy, PTP_OPC_CreatedBy);
510
register_property("Artist", LIBMTP_PROPERTY_Artist, PTP_OPC_Artist);
511
register_property("Date Authored", LIBMTP_PROPERTY_DateAuthored, PTP_OPC_DateAuthored);
512
register_property("Description", LIBMTP_PROPERTY_Description, PTP_OPC_Description);
513
register_property("URL Reference", LIBMTP_PROPERTY_URLReference, PTP_OPC_URLReference);
514
register_property("Language Locale", LIBMTP_PROPERTY_LanguageLocale, PTP_OPC_LanguageLocale);
515
register_property("Copyright Information", LIBMTP_PROPERTY_CopyrightInformation, PTP_OPC_CopyrightInformation);
516
register_property("Source", LIBMTP_PROPERTY_Source, PTP_OPC_Source);
517
register_property("Origin Location", LIBMTP_PROPERTY_OriginLocation, PTP_OPC_OriginLocation);
518
register_property("Date Added", LIBMTP_PROPERTY_DateAdded, PTP_OPC_DateAdded);
519
register_property("Non Consumable", LIBMTP_PROPERTY_NonConsumable, PTP_OPC_NonConsumable);
520
register_property("Corrupt Or Unplayable", LIBMTP_PROPERTY_CorruptOrUnplayable, PTP_OPC_CorruptOrUnplayable);
521
register_property("Producer Serial Number", LIBMTP_PROPERTY_ProducerSerialNumber, PTP_OPC_ProducerSerialNumber);
522
register_property("Representative Sample Format", LIBMTP_PROPERTY_RepresentativeSampleFormat, PTP_OPC_RepresentativeSampleFormat);
523
register_property("Representative Sample Sise", LIBMTP_PROPERTY_RepresentativeSampleSize, PTP_OPC_RepresentativeSampleSize);
524
register_property("Representative Sample Height", LIBMTP_PROPERTY_RepresentativeSampleHeight, PTP_OPC_RepresentativeSampleHeight);
525
register_property("Representative Sample Width", LIBMTP_PROPERTY_RepresentativeSampleWidth, PTP_OPC_RepresentativeSampleWidth);
526
register_property("Representative Sample Duration", LIBMTP_PROPERTY_RepresentativeSampleDuration, PTP_OPC_RepresentativeSampleDuration);
527
register_property("Representative Sample Data", LIBMTP_PROPERTY_RepresentativeSampleData, PTP_OPC_RepresentativeSampleData);
528
register_property("Width", LIBMTP_PROPERTY_Width, PTP_OPC_Width);
529
register_property("Height", LIBMTP_PROPERTY_Height, PTP_OPC_Height);
530
register_property("Duration", LIBMTP_PROPERTY_Duration, PTP_OPC_Duration);
531
register_property("Rating", LIBMTP_PROPERTY_Rating, PTP_OPC_Rating);
532
register_property("Track", LIBMTP_PROPERTY_Track, PTP_OPC_Track);
533
register_property("Genre", LIBMTP_PROPERTY_Genre, PTP_OPC_Genre);
534
register_property("Credits", LIBMTP_PROPERTY_Credits, PTP_OPC_Credits);
535
register_property("Lyrics", LIBMTP_PROPERTY_Lyrics, PTP_OPC_Lyrics);
536
register_property("Subscription Content ID", LIBMTP_PROPERTY_SubscriptionContentID, PTP_OPC_SubscriptionContentID);
537
register_property("Produced By", LIBMTP_PROPERTY_ProducedBy, PTP_OPC_ProducedBy);
538
register_property("Use Count", LIBMTP_PROPERTY_UseCount, PTP_OPC_UseCount);
539
register_property("Skip Count", LIBMTP_PROPERTY_SkipCount, PTP_OPC_SkipCount);
540
register_property("Last Accessed", LIBMTP_PROPERTY_LastAccessed, PTP_OPC_LastAccessed);
541
register_property("Parental Rating", LIBMTP_PROPERTY_ParentalRating, PTP_OPC_ParentalRating);
542
register_property("Meta Genre", LIBMTP_PROPERTY_MetaGenre, PTP_OPC_MetaGenre);
543
register_property("Composer", LIBMTP_PROPERTY_Composer, PTP_OPC_Composer);
544
register_property("Effective Rating", LIBMTP_PROPERTY_EffectiveRating, PTP_OPC_EffectiveRating);
545
register_property("Subtitle", LIBMTP_PROPERTY_Subtitle, PTP_OPC_Subtitle);
546
register_property("Original Release Date", LIBMTP_PROPERTY_OriginalReleaseDate, PTP_OPC_OriginalReleaseDate);
547
register_property("Album Name", LIBMTP_PROPERTY_AlbumName, PTP_OPC_AlbumName);
548
register_property("Album Artist", LIBMTP_PROPERTY_AlbumArtist, PTP_OPC_AlbumArtist);
549
register_property("Mood", LIBMTP_PROPERTY_Mood, PTP_OPC_Mood);
550
register_property("DRM Status", LIBMTP_PROPERTY_DRMStatus, PTP_OPC_DRMStatus);
551
register_property("Sub Description", LIBMTP_PROPERTY_SubDescription, PTP_OPC_SubDescription);
552
register_property("Is Cropped", LIBMTP_PROPERTY_IsCropped, PTP_OPC_IsCropped);
553
register_property("Is Color Corrected", LIBMTP_PROPERTY_IsColorCorrected, PTP_OPC_IsColorCorrected);
554
register_property("Image Bit Depth", LIBMTP_PROPERTY_ImageBitDepth, PTP_OPC_ImageBitDepth);
555
register_property("f Number", LIBMTP_PROPERTY_Fnumber, PTP_OPC_Fnumber);
556
register_property("Exposure Time", LIBMTP_PROPERTY_ExposureTime, PTP_OPC_ExposureTime);
557
register_property("Exposure Index", LIBMTP_PROPERTY_ExposureIndex, PTP_OPC_ExposureIndex);
558
register_property("Display Name", LIBMTP_PROPERTY_DisplayName, PTP_OPC_DisplayName);
559
register_property("Body Text", LIBMTP_PROPERTY_BodyText, PTP_OPC_BodyText);
560
register_property("Subject", LIBMTP_PROPERTY_Subject, PTP_OPC_Subject);
561
register_property("Priority", LIBMTP_PROPERTY_Priority, PTP_OPC_Priority);
562
register_property("Given Name", LIBMTP_PROPERTY_GivenName, PTP_OPC_GivenName);
563
register_property("Middle Names", LIBMTP_PROPERTY_MiddleNames, PTP_OPC_MiddleNames);
564
register_property("Family Name", LIBMTP_PROPERTY_FamilyName, PTP_OPC_FamilyName);
565
register_property("Prefix", LIBMTP_PROPERTY_Prefix, PTP_OPC_Prefix);
566
register_property("Suffix", LIBMTP_PROPERTY_Suffix, PTP_OPC_Suffix);
567
register_property("Phonetic Given Name", LIBMTP_PROPERTY_PhoneticGivenName, PTP_OPC_PhoneticGivenName);
568
register_property("Phonetic Family Name", LIBMTP_PROPERTY_PhoneticFamilyName, PTP_OPC_PhoneticFamilyName);
569
register_property("Email: Primary", LIBMTP_PROPERTY_EmailPrimary, PTP_OPC_EmailPrimary);
570
register_property("Email: Personal 1", LIBMTP_PROPERTY_EmailPersonal1, PTP_OPC_EmailPersonal1);
571
register_property("Email: Personal 2", LIBMTP_PROPERTY_EmailPersonal2, PTP_OPC_EmailPersonal2);
572
register_property("Email: Business 1", LIBMTP_PROPERTY_EmailBusiness1, PTP_OPC_EmailBusiness1);
573
register_property("Email: Business 2", LIBMTP_PROPERTY_EmailBusiness2, PTP_OPC_EmailBusiness2);
574
register_property("Email: Others", LIBMTP_PROPERTY_EmailOthers, PTP_OPC_EmailOthers);
575
register_property("Phone Number: Primary", LIBMTP_PROPERTY_PhoneNumberPrimary, PTP_OPC_PhoneNumberPrimary);
576
register_property("Phone Number: Personal", LIBMTP_PROPERTY_PhoneNumberPersonal, PTP_OPC_PhoneNumberPersonal);
577
register_property("Phone Number: Personal 2", LIBMTP_PROPERTY_PhoneNumberPersonal2, PTP_OPC_PhoneNumberPersonal2);
578
register_property("Phone Number: Business", LIBMTP_PROPERTY_PhoneNumberBusiness, PTP_OPC_PhoneNumberBusiness);
579
register_property("Phone Number: Business 2", LIBMTP_PROPERTY_PhoneNumberBusiness2, PTP_OPC_PhoneNumberBusiness2);
580
register_property("Phone Number: Mobile", LIBMTP_PROPERTY_PhoneNumberMobile, PTP_OPC_PhoneNumberMobile);
581
register_property("Phone Number: Mobile 2", LIBMTP_PROPERTY_PhoneNumberMobile2, PTP_OPC_PhoneNumberMobile2);
582
register_property("Fax Number: Primary", LIBMTP_PROPERTY_FaxNumberPrimary, PTP_OPC_FaxNumberPrimary);
583
register_property("Fax Number: Personal", LIBMTP_PROPERTY_FaxNumberPersonal, PTP_OPC_FaxNumberPersonal);
584
register_property("Fax Number: Business", LIBMTP_PROPERTY_FaxNumberBusiness, PTP_OPC_FaxNumberBusiness);
585
register_property("Pager Number", LIBMTP_PROPERTY_PagerNumber, PTP_OPC_PagerNumber);
586
register_property("Phone Number: Others", LIBMTP_PROPERTY_PhoneNumberOthers, PTP_OPC_PhoneNumberOthers);
587
register_property("Primary Web Address", LIBMTP_PROPERTY_PrimaryWebAddress, PTP_OPC_PrimaryWebAddress);
588
register_property("Personal Web Address", LIBMTP_PROPERTY_PersonalWebAddress, PTP_OPC_PersonalWebAddress);
589
register_property("Business Web Address", LIBMTP_PROPERTY_BusinessWebAddress, PTP_OPC_BusinessWebAddress);
590
register_property("Instant Messenger Address 1", LIBMTP_PROPERTY_InstantMessengerAddress, PTP_OPC_InstantMessengerAddress);
591
register_property("Instant Messenger Address 2", LIBMTP_PROPERTY_InstantMessengerAddress2, PTP_OPC_InstantMessengerAddress2);
592
register_property("Instant Messenger Address 3", LIBMTP_PROPERTY_InstantMessengerAddress3, PTP_OPC_InstantMessengerAddress3);
593
register_property("Postal Address: Personal: Full", LIBMTP_PROPERTY_PostalAddressPersonalFull, PTP_OPC_PostalAddressPersonalFull);
594
register_property("Postal Address: Personal: Line 1", LIBMTP_PROPERTY_PostalAddressPersonalFullLine1, PTP_OPC_PostalAddressPersonalFullLine1);
595
register_property("Postal Address: Personal: Line 2", LIBMTP_PROPERTY_PostalAddressPersonalFullLine2, PTP_OPC_PostalAddressPersonalFullLine2);
596
register_property("Postal Address: Personal: City", LIBMTP_PROPERTY_PostalAddressPersonalFullCity, PTP_OPC_PostalAddressPersonalFullCity);
597
register_property("Postal Address: Personal: Region", LIBMTP_PROPERTY_PostalAddressPersonalFullRegion, PTP_OPC_PostalAddressPersonalFullRegion);
598
register_property("Postal Address: Personal: Postal Code", LIBMTP_PROPERTY_PostalAddressPersonalFullPostalCode, PTP_OPC_PostalAddressPersonalFullPostalCode);
599
register_property("Postal Address: Personal: Country", LIBMTP_PROPERTY_PostalAddressPersonalFullCountry, PTP_OPC_PostalAddressPersonalFullCountry);
600
register_property("Postal Address: Business: Full", LIBMTP_PROPERTY_PostalAddressBusinessFull, PTP_OPC_PostalAddressBusinessFull);
601
register_property("Postal Address: Business: Line 1", LIBMTP_PROPERTY_PostalAddressBusinessLine1, PTP_OPC_PostalAddressBusinessLine1);
602
register_property("Postal Address: Business: Line 2", LIBMTP_PROPERTY_PostalAddressBusinessLine2, PTP_OPC_PostalAddressBusinessLine2);
603
register_property("Postal Address: Business: City", LIBMTP_PROPERTY_PostalAddressBusinessCity, PTP_OPC_PostalAddressBusinessCity);
604
register_property("Postal Address: Business: Region", LIBMTP_PROPERTY_PostalAddressBusinessRegion, PTP_OPC_PostalAddressBusinessRegion);
605
register_property("Postal Address: Business: Postal Code", LIBMTP_PROPERTY_PostalAddressBusinessPostalCode, PTP_OPC_PostalAddressBusinessPostalCode);
606
register_property("Postal Address: Business: Country", LIBMTP_PROPERTY_PostalAddressBusinessCountry, PTP_OPC_PostalAddressBusinessCountry);
607
register_property("Postal Address: Other: Full", LIBMTP_PROPERTY_PostalAddressOtherFull, PTP_OPC_PostalAddressOtherFull);
608
register_property("Postal Address: Other: Line 1", LIBMTP_PROPERTY_PostalAddressOtherLine1, PTP_OPC_PostalAddressOtherLine1);
609
register_property("Postal Address: Other: Line 2", LIBMTP_PROPERTY_PostalAddressOtherLine2, PTP_OPC_PostalAddressOtherLine2);
610
register_property("Postal Address: Other: City", LIBMTP_PROPERTY_PostalAddressOtherCity, PTP_OPC_PostalAddressOtherCity);
611
register_property("Postal Address: Other: Region", LIBMTP_PROPERTY_PostalAddressOtherRegion, PTP_OPC_PostalAddressOtherRegion);
612
register_property("Postal Address: Other: Postal Code", LIBMTP_PROPERTY_PostalAddressOtherPostalCode, PTP_OPC_PostalAddressOtherPostalCode);
613
register_property("Postal Address: Other: Counrtry", LIBMTP_PROPERTY_PostalAddressOtherCountry, PTP_OPC_PostalAddressOtherCountry);
614
register_property("Organization Name", LIBMTP_PROPERTY_OrganizationName, PTP_OPC_OrganizationName);
615
register_property("Phonetic Organization Name", LIBMTP_PROPERTY_PhoneticOrganizationName, PTP_OPC_PhoneticOrganizationName);
616
register_property("Role", LIBMTP_PROPERTY_Role, PTP_OPC_Role);
617
register_property("Birthdate", LIBMTP_PROPERTY_Birthdate, PTP_OPC_Birthdate);
618
register_property("Message To", LIBMTP_PROPERTY_MessageTo, PTP_OPC_MessageTo);
619
register_property("Message CC", LIBMTP_PROPERTY_MessageCC, PTP_OPC_MessageCC);
620
register_property("Message BCC", LIBMTP_PROPERTY_MessageBCC, PTP_OPC_MessageBCC);
621
register_property("Message Read", LIBMTP_PROPERTY_MessageRead, PTP_OPC_MessageRead);
622
register_property("Message Received Time", LIBMTP_PROPERTY_MessageReceivedTime, PTP_OPC_MessageReceivedTime);
623
register_property("Message Sender", LIBMTP_PROPERTY_MessageSender, PTP_OPC_MessageSender);
624
register_property("Activity Begin Time", LIBMTP_PROPERTY_ActivityBeginTime, PTP_OPC_ActivityBeginTime);
625
register_property("Activity End Time", LIBMTP_PROPERTY_ActivityEndTime, PTP_OPC_ActivityEndTime);
626
register_property("Activity Location", LIBMTP_PROPERTY_ActivityLocation, PTP_OPC_ActivityLocation);
627
register_property("Activity Required Attendees", LIBMTP_PROPERTY_ActivityRequiredAttendees, PTP_OPC_ActivityRequiredAttendees);
628
register_property("Optional Attendees", LIBMTP_PROPERTY_ActivityOptionalAttendees, PTP_OPC_ActivityOptionalAttendees);
629
register_property("Activity Resources", LIBMTP_PROPERTY_ActivityResources, PTP_OPC_ActivityResources);
630
register_property("Activity Accepted", LIBMTP_PROPERTY_ActivityAccepted, PTP_OPC_ActivityAccepted);
631
register_property("Owner", LIBMTP_PROPERTY_Owner, PTP_OPC_Owner);
632
register_property("Editor", LIBMTP_PROPERTY_Editor, PTP_OPC_Editor);
633
register_property("Webmaster", LIBMTP_PROPERTY_Webmaster, PTP_OPC_Webmaster);
634
register_property("URL Source", LIBMTP_PROPERTY_URLSource, PTP_OPC_URLSource);
635
register_property("URL Destination", LIBMTP_PROPERTY_URLDestination, PTP_OPC_URLDestination);
636
register_property("Time Bookmark", LIBMTP_PROPERTY_TimeBookmark, PTP_OPC_TimeBookmark);
637
register_property("Object Bookmark", LIBMTP_PROPERTY_ObjectBookmark, PTP_OPC_ObjectBookmark);
638
register_property("Byte Bookmark", LIBMTP_PROPERTY_ByteBookmark, PTP_OPC_ByteBookmark);
639
register_property("Last Build Date", LIBMTP_PROPERTY_LastBuildDate, PTP_OPC_LastBuildDate);
640
register_property("Time To Live", LIBMTP_PROPERTY_TimetoLive, PTP_OPC_TimetoLive);
641
register_property("Media GUID", LIBMTP_PROPERTY_MediaGUID, PTP_OPC_MediaGUID);
642
register_property("Total Bit Rate", LIBMTP_PROPERTY_TotalBitRate, PTP_OPC_TotalBitRate);
643
register_property("Bit Rate Type", LIBMTP_PROPERTY_BitRateType, PTP_OPC_BitRateType);
644
register_property("Sample Rate", LIBMTP_PROPERTY_SampleRate, PTP_OPC_SampleRate);
645
register_property("Number Of Channels", LIBMTP_PROPERTY_NumberOfChannels, PTP_OPC_NumberOfChannels);
646
register_property("Audio Bit Depth", LIBMTP_PROPERTY_AudioBitDepth, PTP_OPC_AudioBitDepth);
647
register_property("Scan Depth", LIBMTP_PROPERTY_ScanDepth, PTP_OPC_ScanDepth);
648
register_property("Audio WAVE Codec", LIBMTP_PROPERTY_AudioWAVECodec, PTP_OPC_AudioWAVECodec);
649
register_property("Audio Bit Rate", LIBMTP_PROPERTY_AudioBitRate, PTP_OPC_AudioBitRate);
650
register_property("Video Four CC Codec", LIBMTP_PROPERTY_VideoFourCCCodec, PTP_OPC_VideoFourCCCodec);
651
register_property("Video Bit Rate", LIBMTP_PROPERTY_VideoBitRate, PTP_OPC_VideoBitRate);
652
register_property("Frames Per Thousand Seconds", LIBMTP_PROPERTY_FramesPerThousandSeconds, PTP_OPC_FramesPerThousandSeconds);
653
register_property("Key Frame Distance", LIBMTP_PROPERTY_KeyFrameDistance, PTP_OPC_KeyFrameDistance);
654
register_property("Buffer Size", LIBMTP_PROPERTY_BufferSize, PTP_OPC_BufferSize);
655
register_property("Encoding Quality", LIBMTP_PROPERTY_EncodingQuality, PTP_OPC_EncodingQuality);
656
register_property("Encoding Profile", LIBMTP_PROPERTY_EncodingProfile, PTP_OPC_EncodingProfile);
657
register_property("Buy flag", LIBMTP_PROPERTY_BuyFlag, PTP_OPC_BuyFlag);
658
register_property("Unknown property", LIBMTP_PROPERTY_UNKNOWN, 0);
662
* Returns the PTP property that maps to a certain libmtp internal property type.
663
* @param inproperty the MTP library interface property
664
* @return the PTP (libgphoto2) property type
666
static uint16_t map_libmtp_property_to_ptp_property(LIBMTP_property_t inproperty)
668
propertymap_t *current;
670
current = propertymap;
672
while (current != NULL) {
673
if(current->id == inproperty) {
674
return current->ptp_id;
676
current = current->next;
683
* Returns the MTP internal interface property that maps to a certain ptp
684
* interface property.
685
* @param inproperty the PTP (libgphoto2) interface property
686
* @return the MTP library interface property
688
static LIBMTP_property_t map_ptp_property_to_libmtp_property(uint16_t inproperty)
690
propertymap_t *current;
692
current = propertymap;
694
while (current != NULL) {
695
if(current->ptp_id == inproperty) {
698
current = current->next;
700
// printf("map_ptp_type_to_libmtp_type: unknown filetype.\n");
701
return LIBMTP_PROPERTY_UNKNOWN;
357
706
* Initialize the library. You are only supposed to call this
875
* Gets the allowed values (range or enum) for a property
876
* @param device a pointer to an MTP device
877
* @param property the property to query
878
* @param filetype the filetype of the object you want to set values for
879
* @param allowed_vals pointer to a LIBMTP_allowed_values_t struct to
880
* receive the allowed values. Call LIBMTP_destroy_allowed_values_t
881
* on this on successful completion.
882
* @return 0 on success, any other value means failure
884
int LIBMTP_Get_Allowed_Property_Values(LIBMTP_mtpdevice_t *device, LIBMTP_property_t const property,
885
LIBMTP_filetype_t const filetype, LIBMTP_allowed_values_t *allowed_vals)
887
PTPObjectPropDesc opd;
890
ret = ptp_mtp_getobjectpropdesc(device->params, map_libmtp_property_to_ptp_property(property), map_libmtp_type_to_ptp_type(filetype), &opd);
891
if (ret != PTP_RC_OK) {
892
add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Allowed_Property_Values(): could not get property description.");
896
if (opd.FormFlag == PTP_OPFF_Enumeration) {
899
allowed_vals->is_range = 0;
900
allowed_vals->num_entries = opd.FORM.Enum.NumberOfValues;
902
switch (opd.DataType)
905
allowed_vals->i8vals = malloc(sizeof(int8_t) * opd.FORM.Enum.NumberOfValues);
906
allowed_vals->datatype = LIBMTP_DATATYPE_INT8;
909
allowed_vals->u8vals = malloc(sizeof(uint8_t) * opd.FORM.Enum.NumberOfValues);
910
allowed_vals->datatype = LIBMTP_DATATYPE_UINT8;
913
allowed_vals->i16vals = malloc(sizeof(int16_t) * opd.FORM.Enum.NumberOfValues);
914
allowed_vals->datatype = LIBMTP_DATATYPE_INT16;
917
allowed_vals->u16vals = malloc(sizeof(uint16_t) * opd.FORM.Enum.NumberOfValues);
918
allowed_vals->datatype = LIBMTP_DATATYPE_UINT16;
921
allowed_vals->i32vals = malloc(sizeof(int32_t) * opd.FORM.Enum.NumberOfValues);
922
allowed_vals->datatype = LIBMTP_DATATYPE_INT32;
925
allowed_vals->u32vals = malloc(sizeof(uint32_t) * opd.FORM.Enum.NumberOfValues);
926
allowed_vals->datatype = LIBMTP_DATATYPE_UINT32;
929
allowed_vals->i64vals = malloc(sizeof(int64_t) * opd.FORM.Enum.NumberOfValues);
930
allowed_vals->datatype = LIBMTP_DATATYPE_INT64;
933
allowed_vals->u64vals = malloc(sizeof(uint64_t) * opd.FORM.Enum.NumberOfValues);
934
allowed_vals->datatype = LIBMTP_DATATYPE_UINT64;
938
for (i = 0; i < opd.FORM.Enum.NumberOfValues; i++) {
939
switch (opd.DataType)
942
allowed_vals->i8vals[i] = opd.FORM.Enum.SupportedValue[i].i8;
945
allowed_vals->u8vals[i] = opd.FORM.Enum.SupportedValue[i].u8;
948
allowed_vals->i16vals[i] = opd.FORM.Enum.SupportedValue[i].i16;
951
allowed_vals->u16vals[i] = opd.FORM.Enum.SupportedValue[i].u16;
954
allowed_vals->i32vals[i] = opd.FORM.Enum.SupportedValue[i].i32;
957
allowed_vals->u32vals[i] = opd.FORM.Enum.SupportedValue[i].u32;
960
allowed_vals->i64vals[i] = opd.FORM.Enum.SupportedValue[i].i64;
963
allowed_vals->u64vals[i] = opd.FORM.Enum.SupportedValue[i].u64;
967
ptp_free_objectpropdesc(&opd);
969
} else if (opd.FormFlag == PTP_OPFF_Range) {
970
allowed_vals->is_range = 1;
972
switch (opd.DataType)
975
allowed_vals->i8min = opd.FORM.Range.MinimumValue.i8;
976
allowed_vals->i8max = opd.FORM.Range.MaximumValue.i8;
977
allowed_vals->i8step = opd.FORM.Range.StepSize.i8;
978
allowed_vals->datatype = LIBMTP_DATATYPE_INT8;
981
allowed_vals->u8min = opd.FORM.Range.MinimumValue.u8;
982
allowed_vals->u8max = opd.FORM.Range.MaximumValue.u8;
983
allowed_vals->u8step = opd.FORM.Range.StepSize.u8;
984
allowed_vals->datatype = LIBMTP_DATATYPE_UINT8;
987
allowed_vals->i16min = opd.FORM.Range.MinimumValue.i16;
988
allowed_vals->i16max = opd.FORM.Range.MaximumValue.i16;
989
allowed_vals->i16step = opd.FORM.Range.StepSize.i16;
990
allowed_vals->datatype = LIBMTP_DATATYPE_INT16;
993
allowed_vals->u16min = opd.FORM.Range.MinimumValue.u16;
994
allowed_vals->u16max = opd.FORM.Range.MaximumValue.u16;
995
allowed_vals->u16step = opd.FORM.Range.StepSize.u16;
996
allowed_vals->datatype = LIBMTP_DATATYPE_UINT16;
999
allowed_vals->i32min = opd.FORM.Range.MinimumValue.i32;
1000
allowed_vals->i32max = opd.FORM.Range.MaximumValue.i32;
1001
allowed_vals->i32step = opd.FORM.Range.StepSize.i32;
1002
allowed_vals->datatype = LIBMTP_DATATYPE_INT32;
1004
case PTP_DTC_UINT32:
1005
allowed_vals->u32min = opd.FORM.Range.MinimumValue.u32;
1006
allowed_vals->u32max = opd.FORM.Range.MaximumValue.u32;
1007
allowed_vals->u32step = opd.FORM.Range.StepSize.u32;
1008
allowed_vals->datatype = LIBMTP_DATATYPE_UINT32;
1011
allowed_vals->i64min = opd.FORM.Range.MinimumValue.i64;
1012
allowed_vals->i64max = opd.FORM.Range.MaximumValue.i64;
1013
allowed_vals->i64step = opd.FORM.Range.StepSize.i64;
1014
allowed_vals->datatype = LIBMTP_DATATYPE_INT64;
1016
case PTP_DTC_UINT64:
1017
allowed_vals->u64min = opd.FORM.Range.MinimumValue.u64;
1018
allowed_vals->u64max = opd.FORM.Range.MaximumValue.u64;
1019
allowed_vals->u64step = opd.FORM.Range.StepSize.u64;
1020
allowed_vals->datatype = LIBMTP_DATATYPE_UINT64;
1029
* Destroys a LIBMTP_allowed_values_t struct
1030
* @param allowed_vals the struct to destroy
1032
void LIBMTP_destroy_allowed_values_t(LIBMTP_allowed_values_t *allowed_vals)
1034
if (!allowed_vals->is_range)
1036
switch (allowed_vals->datatype)
1038
case LIBMTP_DATATYPE_INT8:
1039
if (allowed_vals->i8vals)
1040
free(allowed_vals->i8vals);
1042
case LIBMTP_DATATYPE_UINT8:
1043
if (allowed_vals->u8vals)
1044
free(allowed_vals->u8vals);
1046
case LIBMTP_DATATYPE_INT16:
1047
if (allowed_vals->i16vals)
1048
free(allowed_vals->i16vals);
1050
case LIBMTP_DATATYPE_UINT16:
1051
if (allowed_vals->u16vals)
1052
free(allowed_vals->u16vals);
1054
case LIBMTP_DATATYPE_INT32:
1055
if (allowed_vals->i32vals)
1056
free(allowed_vals->i32vals);
1058
case LIBMTP_DATATYPE_UINT32:
1059
if (allowed_vals->u32vals)
1060
free(allowed_vals->u32vals);
1062
case LIBMTP_DATATYPE_INT64:
1063
if (allowed_vals->i64vals)
1064
free(allowed_vals->i64vals);
1066
case LIBMTP_DATATYPE_UINT64:
1067
if (allowed_vals->u64vals)
1068
free(allowed_vals->u64vals);
1075
* Determine if a property is supported for a given file type
1076
* @param device a pointer to an MTP device
1077
* @param property the property to query
1078
* @param filetype the filetype of the object you want to set values for
1079
* @return 0 if not supported, positive if supported, negative on error
1081
int LIBMTP_Is_Property_Supported(LIBMTP_mtpdevice_t *device, LIBMTP_property_t const property,
1082
LIBMTP_filetype_t const filetype)
1084
uint16_t *props = NULL;
1085
uint32_t propcnt = 0;
1089
uint16_t ptp_prop = map_libmtp_property_to_ptp_property(property);
1091
ret = ptp_mtp_getobjectpropssupported(device->params, map_libmtp_type_to_ptp_type(filetype), &propcnt, &props);
1092
if (ret != PTP_RC_OK) {
1093
add_ptp_error_to_errorstack(device, ret, "LIBMTP_Is_Property_Supported(): could not get properties supported.");
1097
for (i = 0; i < propcnt; i++) {
1098
if (props[i] == ptp_prop) {
1110
* Retrieves a string from an object
1112
* @param device a pointer to an MTP device.
1113
* @param object_id Object reference
1114
* @param attribute_id MTP attribute ID
1115
* @return valid string or NULL on failure. The returned string
1116
* must bee <code>free()</code>:ed by the caller after
1119
char *LIBMTP_Get_String_From_Object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1120
LIBMTP_property_t const attribute_id)
1122
return get_string_from_object(device, object_id, attribute_id);
1126
* Retrieves an unsigned 64-bit integer from an object attribute
1128
* @param device a pointer to an MTP device.
1129
* @param object_id Object reference
1130
* @param attribute_id MTP attribute ID
1131
* @param value_default Default value to return on failure
1134
uint64_t LIBMTP_Get_u64_From_Object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
1135
LIBMTP_property_t const attribute_id, uint64_t const value_default)
1137
return get_u64_from_object(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value_default);
1141
* Retrieves an unsigned 32-bit integer from an object attribute
1143
* @param device a pointer to an MTP device.
1144
* @param object_id Object reference
1145
* @param attribute_id MTP attribute ID
1146
* @param value_default Default value to return on failure
1149
uint32_t LIBMTP_Get_u32_From_Object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
1150
LIBMTP_property_t const attribute_id, uint32_t const value_default)
1152
return get_u32_from_object(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value_default);
1156
* Retrieves an unsigned 16-bit integer from an object attribute
1158
* @param device a pointer to an MTP device.
1159
* @param object_id Object reference
1160
* @param attribute_id MTP attribute ID
1161
* @param value_default Default value to return on failure
1164
uint16_t LIBMTP_Get_u16_From_Object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1165
LIBMTP_property_t const attribute_id, uint16_t const value_default)
1167
return get_u16_from_object(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value_default);
1171
* Retrieves an unsigned 8-bit integer from an object attribute
1173
* @param device a pointer to an MTP device.
1174
* @param object_id Object reference
1175
* @param attribute_id MTP attribute ID
1176
* @param value_default Default value to return on failure
1179
uint8_t LIBMTP_Get_u8_From_Object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1180
LIBMTP_property_t const attribute_id, uint8_t const value_default)
1182
return get_u8_from_object(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value_default);
1186
* Sets an object attribute from a string
1188
* @param device a pointer to an MTP device.
1189
* @param object_id Object reference
1190
* @param attribute_id MTP attribute ID
1191
* @param string string value to set
1192
* @return 0 on success, any other value means failure
1194
int LIBMTP_Set_Object_String(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1195
LIBMTP_property_t const attribute_id, char const * const string)
1197
return set_object_string(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), string);
1202
* Sets an object attribute from an unsigned 32-bit integer
1204
* @param device a pointer to an MTP device.
1205
* @param object_id Object reference
1206
* @param attribute_id MTP attribute ID
1207
* @param value 32-bit unsigned integer to set
1208
* @return 0 on success, any other value means failure
1210
int LIBMTP_Set_Object_u32(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1211
LIBMTP_property_t const attribute_id, uint32_t const value)
1213
return set_object_u32(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value);
1217
* Sets an object attribute from an unsigned 16-bit integer
1219
* @param device a pointer to an MTP device.
1220
* @param object_id Object reference
1221
* @param attribute_id MTP attribute ID
1222
* @param value 16-bit unsigned integer to set
1223
* @return 0 on success, any other value means failure
1225
int LIBMTP_Set_Object_u16(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1226
LIBMTP_property_t const attribute_id, uint16_t const value)
1228
return set_object_u16(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value);
1232
* Sets an object attribute from an unsigned 8-bit integer
1234
* @param device a pointer to an MTP device.
1235
* @param object_id Object reference
1236
* @param attribute_id MTP attribute ID
1237
* @param value 8-bit unsigned integer to set
1238
* @return 0 on success, any other value means failure
1240
int LIBMTP_Set_Object_u8(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
1241
LIBMTP_property_t const attribute_id, uint8_t const value)
1243
return set_object_u8(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value);
502
1247
* Retrieves a string from an object
504
1249
* @param device a pointer to an MTP device.
1642
2349
* keywords, then attempt to locate some default folders
1643
2350
* in the root directory of the primary storage.
1645
for(i = 0; i < params->handles.n; i++) {
1648
oi = ¶ms->objectinfo[i];
1649
if (oi->Filename == NULL) {
1650
oi->Filename = strdup("<null>");
1652
if (oi->Keywords == NULL) {
1653
oi->Keywords = strdup("<null>");
2352
for(i = 0; i < params->nrofobjects; i++) {
2353
PTPObject *ob, *xob;
2355
ob = ¶ms->objects[i];
2356
ret = ptp_object_want(params,params->objects[i].oid,PTPOBJECT_OBJECTINFO_LOADED, &xob);
2357
if (ret != PTP_RC_OK) {
2358
fprintf(stderr,"broken! %x not found\n", params->objects[i].oid);
2360
if (ob->oi.Filename == NULL)
2361
ob->oi.Filename = strdup("<null>");
2362
if (ob->oi.Keywords == NULL)
2363
ob->oi.Keywords = strdup("<null>");
1656
2365
/* Ignore handles that point to non-folders */
1657
if(oi->ObjectFormat != PTP_OFC_Association)
2366
if(ob->oi.ObjectFormat != PTP_OFC_Association)
1659
2368
/* Only look in the root folder */
1660
if (oi->ParentObject != 0x00000000U)
2369
if (ob->oi.ParentObject != 0x00000000U)
1662
2371
/* Only look in the primary storage */
1663
if (device->storage != NULL && oi->StorageID != device->storage->id)
2372
if (device->storage != NULL && ob->oi.StorageID != device->storage->id)
1667
2376
/* Is this the Music Folder */
1668
if (!strcasecmp(oi->Filename, "My Music") ||
1669
!strcasecmp(oi->Filename, "Music")) {
1670
device->default_music_folder =
1671
params->handles.Handler[i];
1673
else if (!strcasecmp(oi->Filename, "My Playlists") ||
1674
!strcasecmp(oi->Filename, "Playlists")) {
1675
device->default_playlist_folder =
1676
params->handles.Handler[i];
1678
else if (!strcasecmp(oi->Filename, "My Pictures") ||
1679
!strcasecmp(oi->Filename, "Pictures")) {
1680
device->default_picture_folder =
1681
params->handles.Handler[i];
1683
else if (!strcasecmp(oi->Filename, "My Video") ||
1684
!strcasecmp(oi->Filename, "Video")) {
1685
device->default_video_folder =
1686
params->handles.Handler[i];
1688
else if (!strcasecmp(oi->Filename, "My Organizer")) {
1689
device->default_organizer_folder =
1690
params->handles.Handler[i];
1692
else if (!strcasecmp(oi->Filename, "ZENcast") ||
1693
!strcasecmp(oi->Filename, "Datacasts")) {
1694
device->default_zencast_folder =
1695
params->handles.Handler[i];
1697
else if (!strcasecmp(oi->Filename, "My Albums") ||
1698
!strcasecmp(oi->Filename, "Albums")) {
1699
device->default_album_folder =
1700
params->handles.Handler[i];
1702
else if (!strcasecmp(oi->Filename, "Text") ||
1703
!strcasecmp(oi->Filename, "Texts")) {
1704
device->default_text_folder =
1705
params->handles.Handler[i];
2377
if (!strcasecmp(ob->oi.Filename, "My Music") ||
2378
!strcasecmp(ob->oi.Filename, "Music")) {
2379
device->default_music_folder = ob->oid;
2381
else if (!strcasecmp(ob->oi.Filename, "My Playlists") ||
2382
!strcasecmp(ob->oi.Filename, "Playlists")) {
2383
device->default_playlist_folder = ob->oid;
2385
else if (!strcasecmp(ob->oi.Filename, "My Pictures") ||
2386
!strcasecmp(ob->oi.Filename, "Pictures")) {
2387
device->default_picture_folder = ob->oid;
2389
else if (!strcasecmp(ob->oi.Filename, "My Video") ||
2390
!strcasecmp(ob->oi.Filename, "Video")) {
2391
device->default_video_folder = ob->oid;
2393
else if (!strcasecmp(ob->oi.Filename, "My Organizer")) {
2394
device->default_organizer_folder = ob->oid;
2396
else if (!strcasecmp(ob->oi.Filename, "ZENcast") ||
2397
!strcasecmp(ob->oi.Filename, "Datacasts")) {
2398
device->default_zencast_folder = ob->oid;
2400
else if (!strcasecmp(ob->oi.Filename, "My Albums") ||
2401
!strcasecmp(ob->oi.Filename, "Albums")) {
2402
device->default_album_folder = ob->oid;
2404
else if (!strcasecmp(ob->oi.Filename, "Text") ||
2405
!strcasecmp(ob->oi.Filename, "Texts")) {
2406
device->default_text_folder = ob->oid;
3162
3825
uint32_t i = 0;
3163
3826
PTPParams *params = (PTPParams *) device->params;
3164
PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
3829
LIBMTP_file_t *file;
3167
3831
// Get all the handles if we haven't already done that
3168
if (params->handles.Handler == NULL) {
3832
if (params->nrofobjects == 0) {
3169
3833
flush_handles(device);
3172
for (i = 0; i < params->handles.n; i++) {
3173
LIBMTP_file_t *file;
3176
// Is this the file we're looking for?
3177
if (params->handles.Handler[i] != fileid) {
3181
oi = ¶ms->objectinfo[i];
3183
// Allocate a new file type
3184
file = LIBMTP_new_file_t();
3186
file->parent_id = oi->ParentObject;
3187
file->storage_id = oi->StorageID;
3190
file->filetype = map_ptp_type_to_libmtp_type(oi->ObjectFormat);
3192
// Original file-specific properties
3194
// We only have 32-bit file size here; later we use the PTP_OPC_ObjectSize property
3195
file->filesize = oi->ObjectCompressedSize;
3196
if (oi->Filename != NULL) {
3197
file->filename = strdup(oi->Filename);
3200
// This is some sort of unique ID so we can keep track of the file.
3201
file->item_id = params->handles.Handler[i];
3204
* If we have a cached, large set of metadata, then use it!
3206
if (params->props) {
3207
MTPProperties *prop = params->props;
3209
for (i=0;(i<params->nrofprops) && (prop->ObjectHandle != file->item_id);i++,prop++)
3211
for (;(i<params->nrofprops) && (prop->ObjectHandle == file->item_id);i++,prop++) {
3212
// Pick ObjectSize here...
3213
if (prop->property == PTP_OPC_ObjectSize) {
3214
// This may already be set, but this 64bit precision value
3215
// is better than the PTP 32bit value, so let it override.
3216
if (device->object_bitsize == 64) {
3217
file->filesize = prop->propval.u64;
3219
file->filesize = prop->propval.u32;
3224
} else if (ptp_operation_issupported(params,PTP_OC_MTP_GetObjPropList)
3225
&& !FLAG_BROKEN_MTPGETOBJPROPLIST(ptp_usb)) {
3226
MTPProperties *props = NULL;
3227
MTPProperties *prop;
3231
* This should retrieve all properties for an object, but on devices
3232
* which are inherently broken it will not, so these need the
3233
* special flag DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST.
3235
ret = ptp_mtp_getobjectproplist(params, file->item_id, &props, &nrofprops);
3236
if (ret != PTP_RC_OK) {
3237
add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Filelisting_With_Callback(): "
3238
"call to ptp_mtp_getobjectproplist() failed.");
3239
// Silently fall through.
3241
if (props == NULL && nrofprops != 0) {
3242
add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
3243
"LIBMTP_Get_Filelisting_With_Callback(): "
3244
"call to ptp_mtp_getobjectproplist() returned "
3245
"inconsistent results.");
3249
for (i=0;i<nrofprops;i++) {
3250
if ((prop->ObjectHandle == file->item_id) && (prop->property == PTP_OPC_ObjectSize)) {
3251
// This may already be set, but this 64bit precision value
3252
// is better than the PTP 32bit value, so let it override.
3253
if (device->object_bitsize == 64) {
3254
file->filesize = prop->propval.u64;
3256
file->filesize = prop->propval.u32;
3262
ptp_destroy_object_prop_list(props, nrofprops);
3836
ret = ptp_object_want (params, fileid, PTPOBJECT_OBJECTINFO_LOADED|PTPOBJECT_MTPPROPLIST_LOADED, &ob);
3837
if (ret != PTP_RC_OK)
3840
// Allocate a new file type
3841
file = LIBMTP_new_file_t();
3843
file->parent_id = ob->oi.ParentObject;
3844
file->storage_id = ob->oi.StorageID;
3847
file->filetype = map_ptp_type_to_libmtp_type(ob->oi.ObjectFormat);
3849
// Original file-specific properties
3851
// We only have 32-bit file size here; later we use the PTP_OPC_ObjectSize property
3852
file->filesize = ob->oi.ObjectCompressedSize;
3853
if (ob->oi.Filename != NULL) {
3854
file->filename = strdup(ob->oi.Filename);
3857
// This is some sort of unique ID so we can keep track of the file.
3858
file->item_id = fileid;
3861
* If we have a cached, large set of metadata, then use it!
3864
MTPProperties *prop = ob->mtpprops;
3866
for (i=0;i<ob->nrofmtpprops;i++,prop++) {
3867
// Pick ObjectSize here...
3868
if (prop->property == PTP_OPC_ObjectSize) {
3869
// This may already be set, but this 64bit precision value
3870
// is better than the PTP 32bit value, so let it override.
3871
if (device->object_bitsize == 64) {
3872
file->filesize = prop->propval.u64;
3874
file->filesize = prop->propval.u32;
3880
uint16_t *props = NULL;
3881
uint32_t propcnt = 0;
3883
// First see which properties can be retrieved for this object format
3884
ret = ptp_mtp_getobjectpropssupported(params, map_libmtp_type_to_ptp_type(file->filetype), &propcnt, &props);
3885
if (ret != PTP_RC_OK) {
3886
add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Filemetadata(): call to ptp_mtp_getobjectpropssupported() failed.");
3887
// Silently fall through.
3264
uint16_t *props = NULL;
3265
uint32_t propcnt = 0;
3267
// First see which properties can be retrieved for this object format
3268
ret = ptp_mtp_getobjectpropssupported(params, map_libmtp_type_to_ptp_type(file->filetype), &propcnt, &props);
3269
if (ret != PTP_RC_OK) {
3270
add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Filemetadata(): call to ptp_mtp_getobjectpropssupported() failed.");
3271
// Silently fall through.
3273
for (i=0;i<propcnt;i++) {
3275
case PTP_OPC_ObjectSize:
3276
if (device->object_bitsize == 64) {
3277
file->filesize = get_u64_from_object(device, file->item_id, PTP_OPC_ObjectSize, 0);
3279
file->filesize = get_u32_from_object(device, file->item_id, PTP_OPC_ObjectSize, 0);
3889
for (i=0;i<propcnt;i++) {
3891
case PTP_OPC_ObjectSize:
3892
if (device->object_bitsize == 64) {
3893
file->filesize = get_u64_from_object(device, file->item_id, PTP_OPC_ObjectSize, 0);
3895
file->filesize = get_u32_from_object(device, file->item_id, PTP_OPC_ObjectSize, 0);
3749
4336
LIBMTP_track_t *LIBMTP_Get_Trackmetadata(LIBMTP_mtpdevice_t *device, uint32_t const trackid)
3752
4338
PTPParams *params = (PTPParams *) device->params;
3753
4339
PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
4341
LIBMTP_track_t *track;
4342
LIBMTP_filetype_t mtptype;
3755
4345
// Get all the handles if we haven't already done that
3756
if (params->handles.Handler == NULL) {
4346
if (params->nrofobjects == 0)
3757
4347
flush_handles(device);
3760
for (i = 0; i < params->handles.n; i++) {
3762
LIBMTP_track_t *track;
3763
LIBMTP_filetype_t mtptype;
3765
// Skip if this is not the track we want.
3766
if (params->handles.Handler[i] != trackid) {
3770
oi = ¶ms->objectinfo[i];
3771
mtptype = map_ptp_type_to_libmtp_type(oi->ObjectFormat);
3773
// Ignore stuff we don't know how to handle...
3774
if (!LIBMTP_FILETYPE_IS_TRACK(mtptype) &&
3775
// This row lets through undefined files for examination since they may be forgotten OGG files.
3776
(oi->ObjectFormat != PTP_OFC_Undefined ||
3777
(!FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) &&
3778
!FLAG_OGG_IS_UNKNOWN(ptp_usb)))
3780
//printf("Not a music track (name: %s format: %d), skipping...\n", oi->Filename, oi->ObjectFormat);
4349
ret = ptp_object_want (params, trackid, PTPOBJECT_OBJECTINFO_LOADED, &ob);
4350
if (ret != PTP_RC_OK)
4353
mtptype = map_ptp_type_to_libmtp_type(ob->oi.ObjectFormat);
4355
// Ignore stuff we don't know how to handle...
4356
if (!LIBMTP_FILETYPE_IS_TRACK(mtptype) &&
4358
* This row lets through undefined files for examination
4359
* since they may be forgotten OGG or FLAC files.
4361
(ob->oi.ObjectFormat != PTP_OFC_Undefined ||
4362
(!FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) &&
4363
!FLAG_OGG_IS_UNKNOWN(ptp_usb) &&
4364
!FLAG_FLAC_IS_UNKNOWN(ptp_usb)))
4366
//printf("Not a music track (name: %s format: %d), skipping...\n", oi->Filename, oi->ObjectFormat);
4370
// Allocate a new track type
4371
track = LIBMTP_new_track_t();
4373
// This is some sort of unique ID so we can keep track of the track.
4374
track->item_id = ob->oid;
4375
track->parent_id = ob->oi.ParentObject;
4376
track->storage_id = ob->oi.StorageID;
4377
track->modificationdate = ob->oi.ModificationDate;
4379
track->filetype = mtptype;
4381
// Original file-specific properties
4382
track->filesize = ob->oi.ObjectCompressedSize;
4383
if (ob->oi.Filename != NULL) {
4384
track->filename = strdup(ob->oi.Filename);
4388
* A special quirk for devices that doesn't quite
4389
* remember that some files marked as "unknown" type are
4390
* actually OGG or FLAC files. We look at the filename extension
4391
* and see if it happens that this was atleast named "ogg"
4392
* and fall back on this heuristic approach in that case,
4393
* for these bugged devices only.
4395
if (track->filetype == LIBMTP_FILETYPE_UNKNOWN &&
4396
track->filename != NULL) {
4397
if ((FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) ||
4398
FLAG_OGG_IS_UNKNOWN(ptp_usb)) &&
4399
has_ogg_extension(track->filename))
4400
track->filetype = LIBMTP_FILETYPE_OGG;
4401
else if (FLAG_FLAC_IS_UNKNOWN(ptp_usb) &&
4402
has_flac_extension(track->filename))
4403
track->filetype = LIBMTP_FILETYPE_FLAC;
4405
// This was not an OGG/FLAC file so discard it
4406
LIBMTP_destroy_track_t(track);
3784
// Allocate a new track type
3785
track = LIBMTP_new_track_t();
3787
// This is some sort of unique ID so we can keep track of the track.
3788
track->item_id = params->handles.Handler[i];
3789
track->parent_id = oi->ParentObject;
3790
track->storage_id = oi->StorageID;
3792
track->filetype = mtptype;
3794
// Original file-specific properties
3795
track->filesize = oi->ObjectCompressedSize;
3796
if (oi->Filename != NULL) {
3797
track->filename = strdup(oi->Filename);
3801
* A special quirk for iriver devices that doesn't quite
3802
* remember that some files marked as "unknown" type are
3803
* actually OGG files. We look at the filename extension
3804
* and see if it happens that this was atleast named "ogg"
3805
* and fall back on this heuristic approach in that case,
3806
* for these bugged devices only.
3808
if (track->filetype == LIBMTP_FILETYPE_UNKNOWN &&
3809
(FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) ||
3810
FLAG_OGG_IS_UNKNOWN(ptp_usb))) {
3811
if (has_ogg_extension(track->filename)) {
3813
track->filetype = LIBMTP_FILETYPE_OGG;
3815
// This was not an OGG file so discard it
3816
LIBMTP_destroy_track_t(track);
3821
get_track_metadata(device, oi->ObjectFormat, track);
4410
get_track_metadata(device, ob->oi.ObjectFormat, track);
4415
* This is a manual conversion from MTPDataGetFunc to PTPDataGetFunc
4416
* to isolate the internal type.
4418
static uint16_t get_func_wrapper(PTPParams* params, void* priv, unsigned long wantlen, unsigned char *data, unsigned long *gotlen)
4420
MTPDataHandler *handler = (MTPDataHandler *)priv;
4422
uint32_t local_gotlen = 0;
4423
ret = handler->getfunc(params, handler->priv, wantlen, data, &local_gotlen);
4424
*gotlen = local_gotlen;
4427
case LIBMTP_HANDLER_RETURN_OK:
4429
case LIBMTP_HANDLER_RETURN_ERROR:
4430
return PTP_ERROR_IO;
4431
case LIBMTP_HANDLER_RETURN_CANCEL:
4432
return PTP_ERROR_CANCEL;
4434
return PTP_ERROR_IO;
4439
* This is a manual conversion from MTPDataPutFunc to PTPDataPutFunc
4440
* to isolate the internal type.
4442
static uint16_t put_func_wrapper(PTPParams* params, void* priv, unsigned long sendlen, unsigned char *data, unsigned long *putlen)
4444
MTPDataHandler *handler = (MTPDataHandler *)priv;
4446
uint32_t local_putlen = 0;
4447
ret = handler->putfunc(params, handler->priv, sendlen, data, &local_putlen);
4448
*putlen = local_putlen;
4451
case LIBMTP_HANDLER_RETURN_OK:
4453
case LIBMTP_HANDLER_RETURN_ERROR:
4454
return PTP_ERROR_IO;
4455
case LIBMTP_HANDLER_RETURN_CANCEL:
4456
return PTP_ERROR_CANCEL;
4458
return PTP_ERROR_IO;
3831
4463
* This gets a file off the device to a local file identified
4911
* This function sends a track from a handler function to an
4912
* MTP device. A filename and a set of metadata must be
4914
* @param device a pointer to the device to send the track to.
4915
* @param get_func the function to call when we have data.
4916
* @param priv the user-defined pointer that is passed to
4917
* <code>get_func</code>.
4918
* @param metadata a track metadata set to be written along with the file.
4919
* After this call the field <code>metadata->item_id</code>
4920
* will contain the new track ID. Other fields such
4921
* as the <code>metadata->filename</code>, <code>metadata->parent_id</code>
4922
* or <code>metadata->storage_id</code> may also change during this
4923
* operation due to device restrictions, so do not rely on the
4924
* contents of this struct to be preserved in any way.
4926
* <li><code>metadata->parent_id</code> should be set to the parent
4927
* (e.g. folder) to store this track in. Since some
4928
* devices are a bit picky about where files
4929
* are placed, a default folder will be chosen if libmtp
4930
* has detected one for the current filetype and this
4931
* parameter is set to 0. If this is 0 and no default folder
4932
* can be found, the file will be stored in the root folder.
4933
* <li><code>metadata->storage_id</code> should be set to the
4934
* desired storage (e.g. memory card or whatever your device
4935
* presents) to store this track in. Setting this to 0 will store
4936
* the track on the primary storage.
4938
* @param callback a progress indicator function or NULL to ignore.
4939
* @param data a user-defined pointer that is passed along to
4940
* the <code>progress</code> function in order to
4941
* pass along some user defined data to the progress
4942
* updates. If not used, set this to NULL.
4943
* @return 0 if the transfer was successful, any other value means
4945
* @see LIBMTP_Send_Track_From_File()
4946
* @see LIBMTP_Delete_Object()
4948
int LIBMTP_Send_Track_From_Handler(LIBMTP_mtpdevice_t *device,
4949
MTPDataGetFunc get_func, void * priv, LIBMTP_track_t * const metadata,
4950
LIBMTP_progressfunc_t const callback,
4951
void const * const data)
4954
LIBMTP_file_t filedata;
4956
// Sanity check, is this really a track?
4957
if (!LIBMTP_FILETYPE_IS_TRACK(metadata->filetype)) {
4958
add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
4959
"LIBMTP_Send_Track_From_Handler(): "
4960
"I don't think this is actually a track, strange filetype...");
4963
// Wrap around the file transfer function
4964
filedata.item_id = metadata->item_id;
4965
filedata.parent_id = metadata->parent_id;
4966
filedata.storage_id = metadata->storage_id;
4967
filedata.filename = metadata->filename;
4968
filedata.filesize = metadata->filesize;
4969
filedata.filetype = metadata->filetype;
4970
filedata.next = NULL;
4972
subcall_ret = LIBMTP_Send_File_From_Handler(device,
4979
if (subcall_ret != 0) {
4980
add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
4981
"LIBMTP_Send_Track_From_Handler(): "
4982
"subcall to LIBMTP_Send_File_From_Handler failed.");
4983
// We used to delete the file here, but don't... It might be OK after all.
4984
// (void) LIBMTP_Delete_Object(device, metadata->item_id);
4988
// Pick up new item (and parent, storage) ID
4989
metadata->item_id = filedata.item_id;
4990
metadata->parent_id = filedata.parent_id;
4991
metadata->storage_id = filedata.storage_id;
4993
// Set track metadata for the new fine track
4994
subcall_ret = LIBMTP_Update_Track_Metadata(device, metadata);
4995
if (subcall_ret != 0) {
4996
// Subcall will add error to errorstack
4997
// We used to delete the file here, but don't... It might be OK after all.
4998
// (void) LIBMTP_Delete_Object(device, metadata->item_id);
5002
// note we don't need to update the cache here because LIBMTP_Send_File_From_File_Descriptor
5003
// has added the object handle and LIBMTP_Update_Track_Metadata has added the metadata.
4192
5009
* This function sends a local file to an MTP device.
4193
5010
* A filename and a set of metadata must be
4194
5011
* given as input.
4308
5121
void const * const data)
5124
PTPParams *params = (PTPParams *) device->params;
5125
PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
5126
LIBMTP_file_t *newfilemeta;
5128
if (send_file_object_info(device, filedata))
5130
// no need to output an error since send_file_object_info will already have done so
5135
ptp_usb->callback_active = 1;
5136
// The callback will deactivate itself after this amount of data has been sent
5137
// One BULK header for the request, one for the data phase. No parameters to the request.
5138
ptp_usb->current_transfer_total = filedata->filesize+PTP_USB_BULK_HDR_LEN*2;
5139
ptp_usb->current_transfer_complete = 0;
5140
ptp_usb->current_transfer_callback = callback;
5141
ptp_usb->current_transfer_callback_data = data;
5143
ret = ptp_sendobject_fromfd(params, fd, filedata->filesize);
5145
ptp_usb->callback_active = 0;
5146
ptp_usb->current_transfer_callback = NULL;
5147
ptp_usb->current_transfer_callback_data = NULL;
5149
if (ret == PTP_ERROR_CANCEL) {
5150
add_error_to_errorstack(device, LIBMTP_ERROR_CANCELLED, "LIBMTP_Send_File_From_File_Descriptor(): Cancelled transfer.");
5153
if (ret != PTP_RC_OK) {
5154
add_ptp_error_to_errorstack(device, ret, "LIBMTP_Send_File_From_File_Descriptor(): "
5155
"Could not send object.");
5159
add_object_to_cache(device, filedata->item_id);
5162
* Get the device-assined parent_id from the cache.
5163
* The operation that adds it to the cache will
5164
* look it up from the device, so we get the new
5165
* parent_id from the cache.
5167
newfilemeta = LIBMTP_Get_Filemetadata(device, filedata->item_id);
5168
if (newfilemeta != NULL) {
5169
filedata->parent_id = newfilemeta->parent_id;
5170
filedata->storage_id = newfilemeta->storage_id;
5171
LIBMTP_destroy_file_t(newfilemeta);
5173
add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
5174
"LIBMTP_Send_File_From_File_Descriptor(): "
5175
"Could not retrieve updated metadata.");
5183
* This function sends a generic file from a handler function to an
5184
* MTP device. A filename and a set of metadata must be
5187
* This can potentially be used for sending in a stream of unknown
5188
* length. Send music files with
5189
* <code>LIBMTP_Send_Track_From_Handler()</code>
5191
* @param device a pointer to the device to send the file to.
5192
* @param get_func the function to call to get data to write
5193
* @param priv a user-defined pointer that is passed along to
5194
* <code>get_func</code>. If not used, this is set to NULL.
5195
* @param filedata a file metadata set to be written along with the file.
5196
* After this call the field <code>filedata->item_id</code>
5197
* will contain the new file ID. Other fields such
5198
* as the <code>filedata->filename</code>, <code>filedata->parent_id</code>
5199
* or <code>filedata->storage_id</code> may also change during this
5200
* operation due to device restrictions, so do not rely on the
5201
* contents of this struct to be preserved in any way.
5203
* <li><code>filedata->parent_id</code> should be set to the parent
5204
* (e.g. folder) to store this file in. If this is 0,
5205
* the file will be stored in the root folder.
5206
* <li><code>filedata->storage_id</code> should be set to the
5207
* desired storage (e.g. memory card or whatever your device
5208
* presents) to store this file in. Setting this to 0 will store
5209
* the file on the primary storage.
5211
* @param callback a progress indicator function or NULL to ignore.
5212
* @param data a user-defined pointer that is passed along to
5213
* the <code>progress</code> function in order to
5214
* pass along some user defined data to the progress
5215
* updates. If not used, set this to NULL.
5216
* @return 0 if the transfer was successful, any other value means
5218
* @see LIBMTP_Send_File_From_File()
5219
* @see LIBMTP_Send_Track_From_File_Descriptor()
5220
* @see LIBMTP_Delete_Object()
5222
int LIBMTP_Send_File_From_Handler(LIBMTP_mtpdevice_t *device,
5223
MTPDataGetFunc get_func, void * priv, LIBMTP_file_t * const filedata,
5224
LIBMTP_progressfunc_t const callback, void const * const data)
5227
PTPParams *params = (PTPParams *) device->params;
5228
PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
5229
LIBMTP_file_t *newfilemeta;
5231
if (send_file_object_info(device, filedata))
5233
// no need to output an error since send_file_object_info will already have done so
5238
ptp_usb->callback_active = 1;
5239
// The callback will deactivate itself after this amount of data has been sent
5240
// One BULK header for the request, one for the data phase. No parameters to the request.
5241
ptp_usb->current_transfer_total = filedata->filesize+PTP_USB_BULK_HDR_LEN*2;
5242
ptp_usb->current_transfer_complete = 0;
5243
ptp_usb->current_transfer_callback = callback;
5244
ptp_usb->current_transfer_callback_data = data;
5246
MTPDataHandler mtp_handler;
5247
mtp_handler.getfunc = get_func;
5248
mtp_handler.putfunc = NULL;
5249
mtp_handler.priv = priv;
5251
PTPDataHandler handler;
5252
handler.getfunc = get_func_wrapper;
5253
handler.putfunc = NULL;
5254
handler.priv = &mtp_handler;
5256
ret = ptp_sendobject_from_handler(params, &handler, filedata->filesize);
5258
ptp_usb->callback_active = 0;
5259
ptp_usb->current_transfer_callback = NULL;
5260
ptp_usb->current_transfer_callback_data = NULL;
5262
if (ret == PTP_ERROR_CANCEL) {
5263
add_error_to_errorstack(device, LIBMTP_ERROR_CANCELLED, "LIBMTP_Send_File_From_Handler(): Cancelled transfer.");
5266
if (ret != PTP_RC_OK) {
5267
add_ptp_error_to_errorstack(device, ret, "LIBMTP_Send_File_From_Handler(): "
5268
"Could not send object.");
5272
add_object_to_cache(device, filedata->item_id);
5275
* Get the device-assined parent_id from the cache.
5276
* The operation that adds it to the cache will
5277
* look it up from the device, so we get the new
5278
* parent_id from the cache.
5280
newfilemeta = LIBMTP_Get_Filemetadata(device, filedata->item_id);
5281
if (newfilemeta != NULL) {
5282
filedata->parent_id = newfilemeta->parent_id;
5283
filedata->storage_id = newfilemeta->storage_id;
5284
LIBMTP_destroy_file_t(newfilemeta);
5286
add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
5287
"LIBMTP_Send_File_From_Handler(): "
5288
"Could not retrieve updated metadata.");
5296
* This function sends the file object info, ready for sendobject
5297
* @param device a pointer to the device to send the file to.
5298
* @param filedata a file metadata set to be written along with the file.
5299
* @return 0 if the transfer was successful, any other value means
5302
static int send_file_object_info(LIBMTP_mtpdevice_t *device, LIBMTP_file_t *filedata)
5304
PTPParams *params = (PTPParams *) device->params;
5305
PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
4311
5306
uint32_t store;
5307
int use_primary_storage = 1;
5308
uint16_t of = map_libmtp_type_to_ptp_type(filedata->filetype);
5309
LIBMTP_devicestorage_t *storage;
4312
5310
uint32_t localph = filedata->parent_id;
4313
LIBMTP_devicestorage_t *storage;
4314
PTPParams *params = (PTPParams *) device->params;
4315
PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
4317
uint16_t of = map_libmtp_type_to_ptp_type(filedata->filetype);
4318
LIBMTP_file_t *newfilemeta;
4319
int use_primary_storage = 1;
4321
5314
// Sanity check: no zerolength files.
4322
5315
if (filedata->filesize == 0) {
4323
add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Send_File_From_File_Descriptor(): "
5316
add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "send_file_object_info(): "
4324
5317
"File of zero size.");