Commit 6e2dfccf authored by Tobias's avatar Tobias

rename MLFile property url to path

only save relative paths on iOS, save full paths on OS X
migrate full urls strings to relative path strings
add url property to MLFile which always returns full absolut NSURL
parent 389ecf23
/*****************************************************************************
* MLFileEntityMappingPolicy_2_5_to_2_5_2.h
* MobileMediaLibraryKit
*****************************************************************************
* Copyright (c) 2015 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Tobias Conradi <videolan # tobias-conradi.de>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import <CoreData/CoreData.h>
@interface MLFileEntityMappingPolicy_2_5_to_2_5_2 : NSEntityMigrationPolicy
@end
......@@ -8,6 +8,7 @@
*
* Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
* Felix Paul Kühne <fkuehne # videolan.org>
* Tobias Conradi <videolan # tobias-conradi.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
......@@ -37,7 +38,7 @@ extern NSString *kMLFileTypeAudio;
@interface MLFile : NSManagedObject
+ (NSArray *)allFiles;
+ (NSArray *)fileForURL:(NSString *)url;
+ (NSArray *)fileForURL:(NSURL *)url;
+ (instancetype)fileForURIRepresentation:(NSURL *)uriRepresentation;
......@@ -56,7 +57,9 @@ extern NSString *kMLFileTypeAudio;
@property (nonatomic, strong) NSNumber *lastAudioTrack;
@property (nonatomic, strong) NSNumber *playCount;
@property (nonatomic, strong) NSString *artworkURL;
@property (nonatomic, strong) NSString *url;
// on iOS the path relative to documents folder on OS X full path
// if you want to set path maybe set url instead which does the right thing depending on the OS
@property (nonatomic, strong) NSString *path;
@property (nonatomic, strong) NSString *type;
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *shortSummary;
......@@ -83,6 +86,11 @@ extern NSString *kMLFileTypeAudio;
@property (nonatomic, assign) BOOL isBeingParsed;
@property (nonatomic, assign) BOOL thumbnailTimeouted;
// always full URL, derived from path
// on Mac directly path as URL
// on iOS combined path appended MLMediaLibrary documentsFolder
@property (nonatomic, strong) NSURL *url;
/**
* the data in this object are about to be put on screen
*
......
......@@ -7,6 +7,8 @@
* $Id$
*
* Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
* Felix Paul Kühne <fkuehne # videolan.org>
* Tobias Conradi <videolan # tobias-conradi.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
......@@ -53,6 +55,9 @@
- (NSString *)thumbnailFolderPath;
- (NSString *)documentFolderPath;
- (NSString *)pathRelativeToDocumentsFolderFromAbsolutPath:(NSString *)absolutPath;
- (NSString *)absolutPathFromPathRelativeToDocumentsFolder:(NSString *)relativePath;
- (NSManagedObject *)objectForURIRepresentation:(NSURL *)uriRepresenation;
- (void)applicationWillStart;
......
......@@ -49,6 +49,7 @@
A792468E170F09A30036AAF2 /* MLThumbnailerQueue.h in Copy Files */ = {isa = PBXBuildFile; fileRef = 7D0EF521170885130003ED47 /* MLThumbnailerQueue.h */; };
DDB959371AFB9B2B00BB8CFF /* MLMediaLibrary+Migration.m in Sources */ = {isa = PBXBuildFile; fileRef = DDB959361AFB9B2B00BB8CFF /* MLMediaLibrary+Migration.m */; };
DDB959391AFBAD8700BB8CFF /* MappingModel_2_5_to_2_5_2.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = DDB959381AFBAD8700BB8CFF /* MappingModel_2_5_to_2_5_2.xcmappingmodel */; };
DDC57DFB1AFD0B5000DBAEF7 /* MLFileEntityMappingPolicy_2_5_to_2_5_2.m in Sources */ = {isa = PBXBuildFile; fileRef = DDC57DFA1AFD0B5000DBAEF7 /* MLFileEntityMappingPolicy_2_5_to_2_5_2.m */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
......@@ -144,6 +145,8 @@
DDB959351AFB9B2B00BB8CFF /* MLMediaLibrary+Migration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MLMediaLibrary+Migration.h"; sourceTree = "<group>"; };
DDB959361AFB9B2B00BB8CFF /* MLMediaLibrary+Migration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MLMediaLibrary+Migration.m"; sourceTree = "<group>"; };
DDB959381AFBAD8700BB8CFF /* MappingModel_2_5_to_2_5_2.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = MappingModel_2_5_to_2_5_2.xcmappingmodel; sourceTree = "<group>"; };
DDC57DF91AFD0B5000DBAEF7 /* MLFileEntityMappingPolicy_2_5_to_2_5_2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLFileEntityMappingPolicy_2_5_to_2_5_2.h; sourceTree = "<group>"; };
DDC57DFA1AFD0B5000DBAEF7 /* MLFileEntityMappingPolicy_2_5_to_2_5_2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLFileEntityMappingPolicy_2_5_to_2_5_2.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
......@@ -210,6 +213,7 @@
7D0EF507170885130003ED47 /* Internal */ = {
isa = PBXGroup;
children = (
DDC57DF91AFD0B5000DBAEF7 /* MLFileEntityMappingPolicy_2_5_to_2_5_2.h */,
7D0EF508170885130003ED47 /* MLMovieInfoGrabber.h */,
7D0EF509170885130003ED47 /* MLTitleDecrapifier.h */,
7D0EF50A170885130003ED47 /* MLTVShowEpisodesInfoGrabber.h */,
......@@ -254,6 +258,7 @@
7D0EF520170885130003ED47 /* MLShowEpisode.m */,
7D9E238717AEEA71008485E5 /* MLAlbum.m */,
7D9E238517AEEA13008485E5 /* MLAlbumTrack.m */,
DDC57DFA1AFD0B5000DBAEF7 /* MLFileEntityMappingPolicy_2_5_to_2_5_2.m */,
7D0EF522170885130003ED47 /* MLThumbnailerQueue.m */,
7D0EF523170885130003ED47 /* MLTitleDecrapifier.m */,
7D0EF524170885130003ED47 /* MLTVShowEpisodesInfoGrabber.m */,
......@@ -374,6 +379,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DDC57DFB1AFD0B5000DBAEF7 /* MLFileEntityMappingPolicy_2_5_to_2_5_2.m in Sources */,
7D0EF528170885130003ED47 /* MLCrashPreventer.m in Sources */,
7D0EF529170885130003ED47 /* MLFile.m in Sources */,
7D0EF52A170885130003ED47 /* MLFileParserQueue.m in Sources */,
......
......@@ -8,6 +8,7 @@
*
* Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
* Felix Paul Kühne <fkuehne # videolan.org>
* Tobias Conradi <videolan # tobias-conradi.de
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
......@@ -73,16 +74,20 @@ NSString *kMLFileTypeAudio = @"audio";
return movies;
}
+ (NSArray *)fileForURL:(NSString *)url;
+ (NSArray *)fileForURL:(NSURL *)url;
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSManagedObjectContext *moc = [[MLMediaLibrary sharedMediaLibrary] managedObjectContext];
if (!moc || moc.persistentStoreCoordinator == nil)
return [NSArray array];
NSString *path = url.path;
#if TARGET_OS_IPHONE
path = [[MLMediaLibrary sharedMediaLibrary] pathRelativeToDocumentsFolderFromAbsolutPath:path];
#endif
NSEntityDescription *entity = [NSEntityDescription entityForName:@"File" inManagedObjectContext:moc];
[request setEntity:entity];
[request setPredicate:[NSPredicate predicateWithFormat:@"url == %@", url]];
[request setPredicate:[NSPredicate predicateWithFormat:@"path == %@", path]];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
[request setSortDescriptors:@[descriptor]];
......@@ -128,7 +133,7 @@ NSString *kMLFileTypeAudio = @"audio";
- (BOOL)isSupportedAudioFile
{
NSUInteger options = NSRegularExpressionSearch | NSCaseInsensitiveSearch;
return ([[self.url lastPathComponent] rangeOfString:@"\\.(aac|aiff|aif|amr|aob|ape|axa|caf|flac|it|m2a|m4a|m4b|mka|mlp|mod|mp1|mp2|mp3|mpa|mpc|oga|oma|opus|rmi|s3m|spx|tta|voc|vqf|w64|wav|wma|wv|xa|xm)$" options:options].location != NSNotFound);
return ([[self.path lastPathComponent] rangeOfString:@"\\.(aac|aiff|aif|amr|aob|ape|axa|caf|flac|it|m2a|m4a|m4b|mka|mlp|mod|mp1|mp2|mp3|mpa|mpc|oga|oma|opus|rmi|s3m|spx|tta|voc|vqf|w64|wav|wma|wv|xa|xm)$" options:options].location != NSNotFound);
}
- (NSString *)artworkURL
......@@ -232,45 +237,40 @@ NSString *kMLFileTypeAudio = @"audio";
}
}
- (NSString *)url
- (NSString *)path
{
[self willAccessValueForKey:@"url"];
NSString *ret = [self primitiveValueForKey:@"url"];
[self didAccessValueForKey:@"url"];
/* we need to make sure that current app path is still part of the file
* URL since app upgrades via iTunes or the App Store will change the
* absolute URL of our files (trac #11330) */
NSString *documentFolderPath = [[MLMediaLibrary sharedMediaLibrary] documentFolderPath];
if ([ret rangeOfString:documentFolderPath].location != NSNotFound)
return ret;
NSArray *pathComponents = [ret componentsSeparatedByString:@"/"];
NSUInteger componentCount = pathComponents.count;
if ([pathComponents[componentCount - 2] isEqualToString:@"Documents"])
ret = [NSString stringWithFormat:@"%@/%@", documentFolderPath, [ret lastPathComponent]];
else {
NSUInteger firstElement = [pathComponents indexOfObject:@"Documents"] + 1;
ret = documentFolderPath;
for (NSUInteger x = 0; x < componentCount - firstElement; x++)
ret = [ret stringByAppendingFormat:@"/%@", pathComponents[firstElement + x]];
}
APLog(@"returning modified URL! will return %@", ret);
[self willAccessValueForKey:@"path"];
NSString *ret = [self primitiveValueForKey:@"path"];
[self didAccessValueForKey:@"path"];
return ret;
}
- (void)setUrl:(NSString *)url
- (void)setPath:(NSString *)path
{
@try {
[self willChangeValueForKey:@"url"];
[self setPrimitiveValue:url forKey:@"url"];
[self didChangeValueForKey:@"url"];
[self willChangeValueForKey:@"path"];
[self setPrimitiveValue:path forKey:@"path"];
[self didChangeValueForKey:@"path"];
}
@catch (NSException *exception) {
APLog(@"setUrl raised exception");
}
}
- (void)setUrl:(NSURL *)url {
NSString *path = url.path;
#if TARGET_OS_IPHONE
path = [[MLMediaLibrary sharedMediaLibrary] pathRelativeToDocumentsFolderFromAbsolutPath:path];
#endif
self.path = path;
}
- (NSURL *)url {
NSString *path = self.path;
#if TARGET_OS_IPHONE
path = [[MLMediaLibrary sharedMediaLibrary] absolutPathFromPathRelativeToDocumentsFolder:path];
#endif
return [NSURL fileURLWithPath:path];
}
- (NSString *)thumbnailPath
{
......@@ -390,7 +390,7 @@ NSString *kMLFileTypeAudio = @"audio";
- (size_t)fileSizeInBytes
{
NSFileManager *manager = [NSFileManager defaultManager];
NSDictionary *fileAttributes = [manager attributesOfItemAtPath:[[[NSURL URLWithString:self.url] path] stringByResolvingSymlinksInPath] error:nil];
NSDictionary *fileAttributes = [manager attributesOfItemAtPath:[self.url path] error:nil];
NSNumber *fileSize = fileAttributes[NSFileSize];
return [fileSize unsignedLongLongValue];
}
......
/*****************************************************************************
* MLFileEntityMappingPolicy_2_5_to_2_5_2.m
* MobileMediaLibraryKit
*****************************************************************************
* Copyright (c) 2015 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Tobias Conradi <videolan # tobias-conradi.de>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import "MLFileEntityMappingPolicy_2_5_to_2_5_2.h"
@implementation MLFileEntityMappingPolicy_2_5_to_2_5_2
- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error
{
NSString *fullPath = [sInstance primitiveValueForKey:@"url"];
NSString *relativePath = [self relativePathForFullPath:fullPath];
if (relativePath) {
[sInstance setPrimitiveValue:relativePath forKey:@"url"];
}
BOOL success = [super createDestinationInstancesForSourceInstance:sInstance entityMapping:mapping manager:manager error:error];
return success;
}
- (NSString *)relativePathForFullPath:(NSString *)fullPath
{
NSArray *components = [fullPath componentsSeparatedByString:@"Documents"];
return [components.lastObject stringByRemovingPercentEncoding];
}
@end
......@@ -72,7 +72,7 @@
APLog(@"Starting parsing %@", file);
[[MLCrashPreventer sharedPreventer] willParseFile:file];
_media = [VLCMedia mediaWithURL:[NSURL URLWithString:file.url]];
_media = [VLCMedia mediaWithURL:file.url];
_media.delegate = self;
[_media parse];
MLFileParserQueue *parserQueue = [MLFileParserQueue sharedFileParserQueue];
......
......@@ -8,6 +8,7 @@
*
* Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
* Felix Paul Kühne <fkuehne # videolan.org>
* Tobias Conradi <videolan # tobias-conradi.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
......@@ -183,6 +184,7 @@ static NSString *kDecrapifyTitles = @"MLDecrapifyTitles";
return _managedObjectModel;
}
#pragma mark - Path handling
- (void)setLibraryBasePath:(NSString *)libraryBasePath
{
_libraryBasePath = [libraryBasePath copy];
......@@ -215,7 +217,7 @@ static NSString *kDecrapifyTitles = @"MLDecrapifyTitles";
}
int directory = NSDocumentDirectory;
NSArray *paths = NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES);
_documentFolderPath = [NSString stringWithFormat:@"file://%@", paths[0]];
_documentFolderPath = paths.firstObject;
return _documentFolderPath;
}
......@@ -229,6 +231,16 @@ static NSString *kDecrapifyTitles = @"MLDecrapifyTitles";
return _persistentStoreURL;
}
- (NSString *)pathRelativeToDocumentsFolderFromAbsolutPath:(NSString *)absolutPath
{
return [absolutPath stringByReplacingOccurrencesOfString:self.documentFolderPath withString:@""];
}
- (NSString *)absolutPathFromPathRelativeToDocumentsFolder:(NSString *)relativePath
{
return [self.documentFolderPath stringByAppendingPathComponent:relativePath];
}
#pragma mark -
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
......@@ -709,7 +721,7 @@ static NSString *kDecrapifyTitles = @"MLDecrapifyTitles";
NSNumber *size = attributes[NSFileSize]; // FIXME [result valueForAttribute:@"kMDItemFSSize"];
MLFile *file = [self createObjectForEntity:@"File"];
file.url = [url absoluteString];
file.url = url;
// Yes, this is a negative number. VLCTime nicely display negative time
// with "XX minutes remaining". And we are using this facility.
......@@ -747,40 +759,16 @@ static NSString *kDecrapifyTitles = @"MLDecrapifyTitles";
NSUInteger count = [filepaths count];
NSMutableArray *fetchPredicates = [NSMutableArray arrayWithCapacity:count];
NSMutableDictionary *urlToObject = [NSMutableDictionary dictionaryWithCapacity:count];
NSString *documentFolderPath = [[MLMediaLibrary sharedMediaLibrary] documentFolderPath];
// Prepare a fetch request for all items
NSArray *pathComponents;
NSUInteger componentCount;
for (NSString *path in filepaths) {
NSString *relativePath = path;
#if TARGET_OS_IPHONE
NSString *urlString;
NSString *componentString = @"";
pathComponents = [path componentsSeparatedByString:@"/"];
componentCount = pathComponents.count;
if ([pathComponents[componentCount - 2] isEqualToString:@"Documents"])
componentString = [path lastPathComponent];
else {
NSUInteger firstElement = [pathComponents indexOfObject:@"Documents"] + 1;
for (NSUInteger x = 0; x < componentCount - firstElement; x++) {
if (x == 0)
componentString = [componentString stringByAppendingFormat:@"%@", pathComponents[firstElement + x]];
else
componentString = [componentString stringByAppendingFormat:@"/%@", pathComponents[firstElement + x]];
}
}
/* compose and escape string */
urlString = [[NSString stringWithFormat:@"%@/%@", documentFolderPath, componentString] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
/* check for the end of the paths */
[fetchPredicates addObject:[NSPredicate predicateWithFormat:@"url CONTAINS %@", [urlString lastPathComponent]]];
[urlToObject setObject:path forKey:urlString];
#else
[fetchPredicates addObject:[NSPredicate predicateWithFormat:@"url == %@", path]];
// on iPhone we only save relative paths ins the DB
relativePath = [self pathRelativeToDocumentsFolderFromAbsolutPath:path];
#endif
[urlToObject setObject:path forKey:relativePath];
[fetchPredicates addObject:[NSPredicate predicateWithFormat:@"path == %@", relativePath]];
}
NSFetchRequest *request = [self fetchRequestForEntity:@"File"];
......@@ -797,8 +785,8 @@ static NSString *kDecrapifyTitles = @"MLDecrapifyTitles";
// Remove objects that are already in db.
for (MLFile *dbResult in dbResults) {
NSString *urlString = dbResult.url;
[filePathsToAdd removeObject:[urlToObject objectForKey:urlString]];
NSString *path = dbResult.path;
[filePathsToAdd removeObject:[urlToObject objectForKey:path]];
}
// Add only the newly added items
......@@ -837,8 +825,7 @@ static NSString *kDecrapifyTitles = @"MLDecrapifyTitles";
unsigned int count = (unsigned int)results.count;
for (unsigned int x = 0; x < count; x++) {
MLFile *file = results[x];
NSString *urlString = [file url];
NSURL *fileURL = [NSURL URLWithString:urlString];
NSURL *fileURL = file.url;
BOOL exists = [fileManager fileExistsAtPath:[fileURL path]];
if (!exists) {
APLog(@"Marking - %@", [fileURL absoluteString]);
......
......@@ -64,7 +64,7 @@
[[MLCrashPreventer sharedPreventer] willParseFile:self.file];
_media = [VLCMedia mediaWithURL:[NSURL URLWithString:self.file.url]];
_media = [VLCMedia mediaWithURL:self.file.url];
VLCMediaThumbnailer *thumbnailer = [VLCMediaThumbnailer thumbnailerWithMedia:_media delegate:self andVLCLibrary:_internalLibrary];
MLThumbnailerQueue *thumbnailerQueue = [MLThumbnailerQueue sharedThumbnailerQueue];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment