|
|
|
@@ -10,8 +10,15 @@ static NSDictionary *make_error_dict(NSString *message) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static BOOL semaphore_wait_with_timeout(dispatch_semaphore_t sem, int64_t seconds) {
|
|
|
|
|
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC);
|
|
|
|
|
return dispatch_semaphore_wait(sem, timeout) == 0;
|
|
|
|
|
int64_t deadline = (int64_t)[NSDate timeIntervalSinceReferenceDate] + seconds;
|
|
|
|
|
while (1) {
|
|
|
|
|
if (photos_cancelled) return NO;
|
|
|
|
|
int64_t remaining = deadline - (int64_t)[NSDate timeIntervalSinceReferenceDate];
|
|
|
|
|
if (remaining <= 0) return NO;
|
|
|
|
|
int64_t waitSecs = remaining < 1 ? remaining : 1;
|
|
|
|
|
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, waitSecs * NSEC_PER_SEC);
|
|
|
|
|
if (dispatch_semaphore_wait(sem, timeout) == 0) return YES;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NSDictionary *collection_to_dict(PHCollection *collection) {
|
|
|
|
@@ -267,6 +274,10 @@ char *photos_export_preview_json(const char *asset_id, const char *output_dir, i
|
|
|
|
|
NSString *nsOutputDir = [NSString stringWithUTF8String:output_dir];
|
|
|
|
|
if (!nsAssetId || !nsOutputDir) return json_from_object(make_error_dict(@"invalid UTF-8 in arguments"));
|
|
|
|
|
|
|
|
|
|
if (!ensure_directory(nsOutputDir)) {
|
|
|
|
|
return json_from_object(make_error_dict(@"failed to create output directory"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PHFetchResult<PHAsset *> *fetch = [PHAsset fetchAssetsWithLocalIdentifiers:@[nsAssetId] options:nil];
|
|
|
|
|
if (fetch.count == 0) return json_from_object(make_error_dict(@"asset not found"));
|
|
|
|
|
|
|
|
|
@@ -315,7 +326,8 @@ char *photos_export_preview_json(const char *asset_id, const char *output_dir, i
|
|
|
|
|
|
|
|
|
|
NSError *writeErr = nil;
|
|
|
|
|
if (![imageData writeToFile:filepath options:NSDataWritingAtomic error:&writeErr]) {
|
|
|
|
|
return json_from_object(@{@"error": @"write failed", @"cloud": asset_cloud_status_string(asset)});
|
|
|
|
|
NSString *msg = writeErr ? writeErr.localizedDescription : @"unknown write error";
|
|
|
|
|
return json_from_object(@{@"error": [NSString stringWithFormat:@"write failed: %@", msg], @"cloud": asset_cloud_status_string(asset)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NSNumber *fileSize = nil;
|
|
|
|
@@ -338,6 +350,10 @@ char *photos_export_original_json(const char *asset_id, const char *output_dir,
|
|
|
|
|
NSString *nsOutputDir = [NSString stringWithUTF8String:output_dir];
|
|
|
|
|
if (!nsAssetId || !nsOutputDir) return json_from_object(make_error_dict(@"invalid UTF-8 in arguments"));
|
|
|
|
|
|
|
|
|
|
if (!ensure_directory(nsOutputDir)) {
|
|
|
|
|
return json_from_object(make_error_dict(@"failed to create output directory"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PHFetchResult<PHAsset *> *fetch = [PHAsset fetchAssetsWithLocalIdentifiers:@[nsAssetId] options:nil];
|
|
|
|
|
if (fetch.count == 0) return json_from_object(make_error_dict(@"asset not found"));
|
|
|
|
|
|
|
|
|
@@ -375,7 +391,7 @@ char *photos_export_original_json(const char *asset_id, const char *output_dir,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (writeErr) {
|
|
|
|
|
return json_from_object(@{@"error": @"write failed", @"cloud": asset_cloud_status_string(asset)});
|
|
|
|
|
return json_from_object(@{@"error": [NSString stringWithFormat:@"write failed: %@", writeErr.localizedDescription], @"cloud": asset_cloud_status_string(asset)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NSString *writtenFilename = [filepath lastPathComponent];
|
|
|
|
|