Обнаружение типа пантомимы в памяти с Какао (OS X)? - PullRequest
4 голосов
/ 19 ноября 2008

Мое приложение представляет собой средство просмотра для пользовательского формата, zip-файла с четко определенным XML-манифестом и ресурсами, такими как изображения и фильмы. Я использую zlib, чтобы открыть zip-файл в памяти и затем перейти к отображению указанных ресурсов.

Одна проблема, с которой я столкнулся, заключается в том, что я не могу правильно отображать видео, очевидно, потому что QTMovie не может определить тип пантомимы. Фильм, загруженный из файла ([QTMovie movieWithFile]), работает отлично. Загруженный из памяти ([QTMovie movieWithData]) отказывается работать.

Это имеет смысл, поскольку из-за отсутствия расширения файла QTMovie не может определить информацию типа mime. После небольшого поиска я прибег к использованию QTDataReference следующим образом:

NSData *movieData = ...read from memory...;
QTDataReference *movieDataReference = [[QTDataReference alloc] initWithReferenceToData:movieData name:fileName MIMEType:@"video/x-m4v"];
QTMovie *mov = [QTMovie movieWithDataReference:movieDataReference error:&err];

Это хорошо работает, однако жесткое кодирование MIMEType далеко от идеала. У меня есть доступ к имени файла и расширению, поэтому я попытался найти MIME-тип с помощью UTI (спасибо замечательным людям из #macdev):

- (NSString*)mimeTypeForExtension:(NSString*)ext {

    CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,(CFStringRef)ext,NULL);
    return NSMakeCollectable(UTTypeCopyPreferredTagWithClass((CFStringRef)UTI,kUTTagClassMIMEType));
}

Это, однако, не работает. Очевидно, что где-то есть внутренняя база данных расширений OS X и соответствующих типов MIME. В противном случае фильмы с диска не будут работать. Как мне получить к нему доступ?

Спасибо!

Ответы [ 3 ]

8 голосов
/ 20 ноября 2008

Проблема в том, что у m4v и m4p нет типов mime, зарегистрированных в Launch Services (возможно, потому что тип mime для m4v и m4p не является стандартным). В любом случае, что вам, вероятно, следует сделать, это обработать крайние случаи, подобные этому, а затем проверить на nil, когда функция вернется (в случае, если расширение не зарегистрировано и не обработано вами).

Другое дело, что вы теряете память при текущем использовании. Я предполагаю, что вы используете сборщик мусора, но первый вызов создает CFString, которая никогда не освобождается. Вот предлагаемая реализация вашего метода:

-(NSString*)mimeTypeForExtension:(NSString*)ext
{
    NSAssert( ext, @"Extension cannot be nil" );
    NSString* mimeType = nil;

    CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,
        (CFStringRef)ext, NULL);
    if( !UTI ) return nil;

    CFStringRef registeredType = UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType);
    if( !registeredType ) // check for edge case
    {
        if( [ext isEqualToString:@"m4v"] )
            mimeType = @"video/x-m4v";
        else if( [ext isEqualToString:@"m4p"] )
            mimeType = @"audio/x-m4p";
        // handle anything else here that you know is not registered
    } else {
        mimeType = NSMakeCollectable(registeredType);
    }

    CFRelease(UTI);
    return mimeType;
}
5 голосов
/ 19 ноября 2009

Вы можете использовать NSWorkspace, чтобы система определяла UTI файла.

-(NSString *)mimeTypeForFileAtPath:(NSString *)path error:(NSError **)err {
  NSString *uti, *mimeType = nil;

  if (!(uti = [[NSWorkspace sharedWorkspace] typeOfFile:path error:err]))
    return nil;
  if (err)
    *err = nil;

  if ((mimeType = (NSString *)UTTypeCopyPreferredTagWithClass((CFStringRef)uti, kUTTagClassMIMEType)))
    mimeType = NSMakeCollectable(mimeType);

  return mimeType;
}
1 голос
/ 19 июля 2009

Предполагают, что люди изменяют возвращение на [автосимулятор mimeType]; - некоторые из нас все еще используют древние способы!

И спасибо! Это была большая помощь.

...