add QuickLook plugin for OS X, it’s embedded in the .app
This commit is contained in:
23
QLPlugin/GeneratePreviewForURL.c
Normal file
23
QLPlugin/GeneratePreviewForURL.c
Normal file
@@ -0,0 +1,23 @@
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <QuickLook/QuickLook.h>
|
||||
|
||||
OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options);
|
||||
void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview);
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Generate a preview for file
|
||||
|
||||
This function's job is to create preview for designated file
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options)
|
||||
{
|
||||
// To complete your generator please implement the function GeneratePreviewForURL in GeneratePreviewForURL.c
|
||||
return noErr;
|
||||
}
|
||||
|
||||
void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview)
|
||||
{
|
||||
// Implement only if supported
|
||||
}
|
||||
102
QLPlugin/GenerateThumbnailForURL.c
Normal file
102
QLPlugin/GenerateThumbnailForURL.c
Normal file
@@ -0,0 +1,102 @@
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <QuickLook/QuickLook.h>
|
||||
|
||||
OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize);
|
||||
void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail);
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Generate a thumbnail for file
|
||||
|
||||
This function's job is to create thumbnail for designated file as fast as possible
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
struct PPIThumb
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int comp;
|
||||
/*
|
||||
bool valid()
|
||||
{
|
||||
return (width == 128 && height == 128 && comp == 4);
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
struct PPIDocVersion
|
||||
{
|
||||
int major;
|
||||
int minor;
|
||||
};
|
||||
|
||||
struct PPISoftVersion
|
||||
{
|
||||
int major;
|
||||
int minor;
|
||||
int fix;
|
||||
int build;
|
||||
};
|
||||
|
||||
struct PPIHeader
|
||||
{
|
||||
char magic[4];
|
||||
struct PPIDocVersion doc_version;
|
||||
struct PPISoftVersion soft_version;
|
||||
struct PPIThumb thumb_header;
|
||||
/*
|
||||
bool valid()
|
||||
{
|
||||
if (strcmp(magic, "PPI") != 0)
|
||||
return false;
|
||||
if (doc_version.major != 0 || doc_version.minor != 1)
|
||||
return false;
|
||||
if (!thumb_header.valid())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize)
|
||||
{
|
||||
// To complete your generator please implement the function GenerateThumbnailForURL in GenerateThumbnailForURL.c
|
||||
//maxSize = CGSizeMake(128, 128);
|
||||
CGContextRef context = QLThumbnailRequestCreateContext(thumbnail, maxSize, true, NULL);
|
||||
CGRect renderRect = CGRectMake(0., 0., maxSize.width, maxSize.height);
|
||||
|
||||
CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
|
||||
const char* path_string = CFStringGetCStringPtr(path, kCFStringEncodingUTF8);
|
||||
|
||||
FILE* fp = fopen(path_string, "rb");
|
||||
if (fp)
|
||||
{
|
||||
struct PPIHeader header;
|
||||
fread(&header, sizeof(struct PPIHeader), 1, fp);
|
||||
int w = header.thumb_header.width;
|
||||
int h = header.thumb_header.height;
|
||||
int c = header.thumb_header.comp;
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGContextRef bmp = CGBitmapContextCreate(NULL, w, h, 8, w * c, colorSpace, kCGImageAlphaPremultipliedLast);
|
||||
uint8_t* data = CGBitmapContextGetData(bmp);
|
||||
fread(data, w * h * c, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
CGImageRef img = CGBitmapContextCreateImage(bmp);
|
||||
CGContextDrawImage(context, renderRect, img);
|
||||
}
|
||||
else
|
||||
{
|
||||
CGContextSetRGBFillColor(context, 1, 0, 0, 1);
|
||||
CGContextFillRect(context, CGRectMake(0, 0, maxSize.width, maxSize.height));
|
||||
}
|
||||
QLThumbnailRequestFlushContext(thumbnail, context);
|
||||
CFRelease(context);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail)
|
||||
{
|
||||
// Implement only if supported
|
||||
}
|
||||
91
QLPlugin/Info.plist
Normal file
91
QLPlugin/Info.plist
Normal file
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>ppi</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>image/ppi</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>PPI</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>QLGenerator</string>
|
||||
<key>LSItemContentTypes</key>
|
||||
<array>
|
||||
<string>public.panorama-image</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CFPlugInDynamicRegisterFunction</key>
|
||||
<string></string>
|
||||
<key>CFPlugInDynamicRegistration</key>
|
||||
<string>NO</string>
|
||||
<key>CFPlugInFactories</key>
|
||||
<dict>
|
||||
<key>10D308F3-0D60-4B28-A618-2A599683A839</key>
|
||||
<string>QuickLookGeneratorPluginFactory</string>
|
||||
</dict>
|
||||
<key>CFPlugInTypes</key>
|
||||
<dict>
|
||||
<key>5E2D9680-5022-40FA-B806-43349622E5B9</key>
|
||||
<array>
|
||||
<string>10D308F3-0D60-4B28-A618-2A599683A839</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>CFPlugInUnloadFunction</key>
|
||||
<string></string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2018 OmixLab ltd. All rights reserved.</string>
|
||||
<key>QLNeedsToBeRunInMainThread</key>
|
||||
<false/>
|
||||
<key>QLPreviewHeight</key>
|
||||
<real>600</real>
|
||||
<key>QLPreviewWidth</key>
|
||||
<real>800</real>
|
||||
<key>QLSupportsConcurrentRequests</key>
|
||||
<false/>
|
||||
<key>QLThumbnailMinimumSize</key>
|
||||
<real>17</real>
|
||||
<key>UTImportedTypeDeclarations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>public.panorama-image</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.mime-type</key>
|
||||
<string>image/ppi</string>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>ppi</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
218
QLPlugin/main.c
Normal file
218
QLPlugin/main.c
Normal file
@@ -0,0 +1,218 @@
|
||||
//==============================================================================
|
||||
//
|
||||
// DO NO MODIFY THE CONTENT OF THIS FILE
|
||||
//
|
||||
// This file contains the generic CFPlug-in code necessary for your generator
|
||||
// To complete your generator implement the function in GenerateThumbnailForURL/GeneratePreviewForURL.c
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreFoundation/CFPlugInCOM.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <QuickLook/QuickLook.h>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// constants
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Don't modify this line
|
||||
#define PLUGIN_ID "B8F1FFE9-38A4-46C0-A51A-75C338E4C87E"
|
||||
|
||||
//
|
||||
// Below is the generic glue code for all plug-ins.
|
||||
//
|
||||
// You should not have to modify this code aside from changing
|
||||
// names if you decide to change the names defined in the Info.plist
|
||||
//
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// typedefs
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// The thumbnail generation function to be implemented in GenerateThumbnailForURL.c
|
||||
OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize);
|
||||
void CancelThumbnailGeneration(void* thisInterface, QLThumbnailRequestRef thumbnail);
|
||||
|
||||
// The preview generation function to be implemented in GeneratePreviewForURL.c
|
||||
OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options);
|
||||
void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview);
|
||||
|
||||
// The layout for an instance of QuickLookGeneratorPlugIn
|
||||
typedef struct __QuickLookGeneratorPluginType
|
||||
{
|
||||
void *conduitInterface;
|
||||
CFUUIDRef factoryID;
|
||||
UInt32 refCount;
|
||||
} QuickLookGeneratorPluginType;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// prototypes
|
||||
// -----------------------------------------------------------------------------
|
||||
// Forward declaration for the IUnknown implementation.
|
||||
//
|
||||
|
||||
QuickLookGeneratorPluginType *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID);
|
||||
void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance);
|
||||
HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv);
|
||||
void *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID);
|
||||
ULONG QuickLookGeneratorPluginAddRef(void *thisInstance);
|
||||
ULONG QuickLookGeneratorPluginRelease(void *thisInstance);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// myInterfaceFtbl definition
|
||||
// -----------------------------------------------------------------------------
|
||||
// The QLGeneratorInterfaceStruct function table.
|
||||
//
|
||||
static QLGeneratorInterfaceStruct myInterfaceFtbl = {
|
||||
NULL,
|
||||
QuickLookGeneratorQueryInterface,
|
||||
QuickLookGeneratorPluginAddRef,
|
||||
QuickLookGeneratorPluginRelease,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// AllocQuickLookGeneratorPluginType
|
||||
// -----------------------------------------------------------------------------
|
||||
// Utility function that allocates a new instance.
|
||||
// You can do some initial setup for the generator here if you wish
|
||||
// like allocating globals etc...
|
||||
//
|
||||
QuickLookGeneratorPluginType *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID)
|
||||
{
|
||||
QuickLookGeneratorPluginType *theNewInstance;
|
||||
|
||||
theNewInstance = (QuickLookGeneratorPluginType *)malloc(sizeof(QuickLookGeneratorPluginType));
|
||||
memset(theNewInstance,0,sizeof(QuickLookGeneratorPluginType));
|
||||
|
||||
/* Point to the function table Malloc enough to store the stuff and copy the filler from myInterfaceFtbl over */
|
||||
theNewInstance->conduitInterface = malloc(sizeof(QLGeneratorInterfaceStruct));
|
||||
memcpy(theNewInstance->conduitInterface,&myInterfaceFtbl,sizeof(QLGeneratorInterfaceStruct));
|
||||
|
||||
/* Retain and keep an open instance refcount for each factory. */
|
||||
theNewInstance->factoryID = CFRetain(inFactoryID);
|
||||
CFPlugInAddInstanceForFactory(inFactoryID);
|
||||
|
||||
/* This function returns the IUnknown interface so set the refCount to one. */
|
||||
theNewInstance->refCount = 1;
|
||||
return theNewInstance;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// DeallocQuickLookGeneratorPluginType
|
||||
// -----------------------------------------------------------------------------
|
||||
// Utility function that deallocates the instance when
|
||||
// the refCount goes to zero.
|
||||
// In the current implementation generator interfaces are never deallocated
|
||||
// but implement this as this might change in the future
|
||||
//
|
||||
void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance)
|
||||
{
|
||||
CFUUIDRef theFactoryID;
|
||||
|
||||
theFactoryID = thisInstance->factoryID;
|
||||
/* Free the conduitInterface table up */
|
||||
free(thisInstance->conduitInterface);
|
||||
|
||||
/* Free the instance structure */
|
||||
free(thisInstance);
|
||||
if (theFactoryID){
|
||||
CFPlugInRemoveInstanceForFactory(theFactoryID);
|
||||
CFRelease(theFactoryID);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// QuickLookGeneratorQueryInterface
|
||||
// -----------------------------------------------------------------------------
|
||||
// Implementation of the IUnknown QueryInterface function.
|
||||
//
|
||||
HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv)
|
||||
{
|
||||
CFUUIDRef interfaceID;
|
||||
|
||||
interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault,iid);
|
||||
|
||||
if (CFEqual(interfaceID,kQLGeneratorCallbacksInterfaceID)){
|
||||
/* If the Right interface was requested, bump the ref count,
|
||||
* set the ppv parameter equal to the instance, and
|
||||
* return good status.
|
||||
*/
|
||||
((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GenerateThumbnailForURL = GenerateThumbnailForURL;
|
||||
((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelThumbnailGeneration = CancelThumbnailGeneration;
|
||||
((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GeneratePreviewForURL = GeneratePreviewForURL;
|
||||
((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelPreviewGeneration = CancelPreviewGeneration;
|
||||
((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType*)thisInstance)->conduitInterface)->AddRef(thisInstance);
|
||||
*ppv = thisInstance;
|
||||
CFRelease(interfaceID);
|
||||
return S_OK;
|
||||
}else{
|
||||
/* Requested interface unknown, bail with error. */
|
||||
*ppv = NULL;
|
||||
CFRelease(interfaceID);
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// QuickLookGeneratorPluginAddRef
|
||||
// -----------------------------------------------------------------------------
|
||||
// Implementation of reference counting for this type. Whenever an interface
|
||||
// is requested, bump the refCount for the instance. NOTE: returning the
|
||||
// refcount is a convention but is not required so don't rely on it.
|
||||
//
|
||||
ULONG QuickLookGeneratorPluginAddRef(void *thisInstance)
|
||||
{
|
||||
((QuickLookGeneratorPluginType *)thisInstance )->refCount += 1;
|
||||
return ((QuickLookGeneratorPluginType*) thisInstance)->refCount;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// QuickLookGeneratorPluginRelease
|
||||
// -----------------------------------------------------------------------------
|
||||
// When an interface is released, decrement the refCount.
|
||||
// If the refCount goes to zero, deallocate the instance.
|
||||
//
|
||||
ULONG QuickLookGeneratorPluginRelease(void *thisInstance)
|
||||
{
|
||||
((QuickLookGeneratorPluginType*)thisInstance)->refCount -= 1;
|
||||
if (((QuickLookGeneratorPluginType*)thisInstance)->refCount == 0){
|
||||
DeallocQuickLookGeneratorPluginType((QuickLookGeneratorPluginType*)thisInstance );
|
||||
return 0;
|
||||
}else{
|
||||
return ((QuickLookGeneratorPluginType*) thisInstance )->refCount;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// QuickLookGeneratorPluginFactory
|
||||
// -----------------------------------------------------------------------------
|
||||
void *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID)
|
||||
{
|
||||
QuickLookGeneratorPluginType *result;
|
||||
CFUUIDRef uuid;
|
||||
|
||||
/* If correct type is being requested, allocate an
|
||||
* instance of kQLGeneratorTypeID and return the IUnknown interface.
|
||||
*/
|
||||
if (CFEqual(typeID,kQLGeneratorTypeID)){
|
||||
uuid = CFUUIDCreateFromString(kCFAllocatorDefault,CFSTR(PLUGIN_ID));
|
||||
result = AllocQuickLookGeneratorPluginType(uuid);
|
||||
CFRelease(uuid);
|
||||
return result;
|
||||
}
|
||||
/* If the requested type is incorrect, return NULL. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user