2

I'm trying to create a QuickLook plugin to play audio from within a package for that package's QuickLook preview, but my attempts only display the default QL preview - a larger file icon, file name, type, size and modification date.

I've successfully displayed a test string as kUTTPlainText with my XCode setup for the targeted UTI type, and verified that the CFDataRef passed to QLPreviewRequestSetDataRepresentation isn't NULL.

Here is the basic code I've got inside my GeneratePreviewForURL function:

NSURL *audioFilePath = @"the file path";
CFDataRef data = (__bridge CFDataRef)[NSData dataWithContentsOfURL:audioFilePath];
QLPreviewRequestSetDataRepresentation(preview, data, kUTTypeAudio, NULL);
return noErr;

Any ideas? Is playing audio from a QuickLook preview even possible?

Benjineer
  • 1,530
  • 18
  • 22
  • I suspect you need to pass a more specific type to `QLPreviewRequestSetDataRepresentation` (not just `kUTTypeAudio` but something that identifies the audio format). Also make sure you're following the debugging steps in the [programming guide](https://developer.apple.com/library/mac/documentation/userexperience/conceptual/quicklook_programming_guide/Articles/QLDebugTest.html#//apple_ref/doc/uid/TP40005020-CH14-SW4) so you can be sure it's not a plugin registration problem. – rickster Dec 01 '13 at 17:59
  • From Apple's docs on [QLPreviewRequestSetDataRepresentation](https://developer.apple.com/library/mac/documentation/userexperience/Reference/QLPreviewRequest_Ref/Reference/reference.html#apple_ref/c/func/QLPreviewRequestSetDataRepresentation): "The content data of the preview must be of a native Quick Look type. Currently supported UTIs for these types are: kUTTypeImage, kUTTypePDF, kUTTypeHTML, kUTTypeXML, kUTTypePlainText, kUTTypeRTF, kUTTypeMovie, and kUTTypeAudio." – Benjineer Dec 02 '13 at 01:38
  • I've also verified my debugging setup as mentioned - can anyone verify that playing audio is possible? The docs seem to hint that it is, but provide no example. – Benjineer Dec 02 '13 at 01:41
  • I've since tried displaying some HTML with an ` – Benjineer Dec 08 '13 at 09:29

2 Answers2

0

I'm basing this answer on my personal experience.

With Xcode 4.2 on OSX 10.6.8 it was possible to load an audio file inside a HTML-based QuickLook plugin simply using the <src> attribute of the <audio> tag:

OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options)
{
    @autoreleasepool {

        if (QLPreviewRequestIsCancelled(preview)) return noErr;

        NSMutableString *html=[[NSMutableString alloc] init];
        NSDictionary *props;

        props=@{
            (__bridge NSString *)kQLPreviewPropertyTextEncodingNameKey:@"UTF-8",
            (__bridge NSString *)kQLPreviewPropertyMIMETypeKey:@"text/html",
            };

        [html appendString:@"<html>"];
        [html appendString:@"<body>"];
        [html appendString:@"<audio src=\"/tmp/AudioFile.mp3\" type=\"audio/mpeg\" controls=\"true\" autoplay=\"true\" />"];
        [html appendString:@"</body>"];
        [html appendString:@"</html>"];

        QLPreviewRequestSetDataRepresentation(preview,(CFDataRef)[html dataUsingEncoding:NSUTF8StringEncoding],kUTTypeHTML,(CFDictionaryRef)props);
    }

    return noErr;
}

Now, with Xcode 5.1 on Mavericks, it seems that neither using the cid: scheme (I'll post an example below) does the job:

OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options)
{
    @autoreleasepool {

        if (QLPreviewRequestIsCancelled(preview)) return noErr;

        NSMutableString *html=[[NSMutableString alloc] init];
        NSDictionary *props;
        NSData *audioData=[NSData dataWithContentsOfFile:@"/tmp/AudioFile.mp3"];

        props=@{
            (__bridge NSString *)kQLPreviewPropertyTextEncodingNameKey:@"UTF-8",
            (__bridge NSString *)kQLPreviewPropertyMIMETypeKey:@"text/html",
            (__bridge NSString *)kQLPreviewPropertyAttachmentsKey:@{
                    @"AUDIO":@{
                            (__bridge NSString *)kQLPreviewPropertyMIMETypeKey:@"audio/mpeg",
                            (__bridge NSString *)kQLPreviewPropertyAttachmentDataKey: audioData,
                            },
                    },
            };

        [html appendString:@"<html>"];
        [html appendString:@"<body>"];
        [html appendString:@"<audio src=\"cid:AUDIO\" type=\"audio/mpeg\" controls=\"true\" autoplay=\"true\" />"];
        [html appendString:@"</body>"];
        [html appendString:@"</html>"];

        QLPreviewRequestSetDataRepresentation(preview,(CFDataRef)[html dataUsingEncoding:NSUTF8StringEncoding],kUTTypeHTML,(CFDictionaryRef)props);
    }

    return noErr;
}

I recon that you should report a bug to Apple for that!

  • So you had success using an audio tag under OSX10.6? I had no luck under OSX10.7. Is it a new requirement to use a content ID in the source tag? Can you point me to any docs referring to this? – Benjineer Jun 09 '14 at 05:00
  • Since declaring the URL inside the `` attribute didn't (sadly) work anymore, I started thinking that the usage of the Content ID could be a good solution once I looked at the sample code inside the 'Generating Enriched HTML' paragraph of the 'Dynamically Generating Previews' chapter from the QuickLook Programming Guide. Here's the link: https://developer.apple.com/library/mac/documentation/userexperience/conceptual/quicklook_programming_guide/Articles/QLDynamicGeneration.html#//apple_ref/doc/uid/TP40005020-CH15-SW2 – user3559460 Jun 09 '14 at 11:55
  • Hey...any news about it, mate? Did you manage to reach your goal? – user3559460 Nov 10 '14 at 14:29
0

Some of the comments here refer to using audio in HTML-based Quicklook plugins (sorry, not enough reputation yet to add additional comments ).

I recently had the same problem in a project I worked on where I needed to embed an audio file, but as noted by others, trying to use that data referenced as a 'CID:' object within the Quicklook plugin fails.

The solution I found was to embed the data as Base64 encoded within the HTML, like so:

<audio src="data:audio/wav;base64,{base64Data}">

with {base64Data} replaced with the actual Base64 data. Any NSData object can be converted to a Base64 string using:

[dataObject base64EncodedStringWithOptions:0]

Alternatively if you need to refer to that data more than once in your HTML code, you can create a Javascript URL object and use that instead:

let soundURL = new URL("data:audio/wav;base64,{base64Data}");
audioElement.src = soundURL;
coderSeb
  • 111
  • 1
  • 6