macOS/QuickLook: support rich thumbnail #107072
|
@ -57,12 +57,12 @@ if(UNIX AND NOT APPLE)
|
|||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(SRC
|
||||
set(SRC_APPEX
|
||||
src/ThumbnailProvider.mm
|
||||
src/ThumbnailProvider.h
|
||||
)
|
||||
|
||||
add_executable(blender-thumbnailer MACOSX_BUNDLE ${SRC})
|
||||
add_executable(blender-thumbnailer MACOSX_BUNDLE ${SRC} ${SRC_APPEX})
|
||||
setup_platform_linker_flags(blender-thumbnailer)
|
||||
target_link_libraries(blender-thumbnailer
|
||||
bf_blenlib
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
|
||||
ankitm marked this conversation as resolved
Outdated
|
||||
#include "ThumbnailProvider.h"
|
||||
|
||||
#include <AppKit/NSImage.h>
|
||||
#include <CoreGraphics/CGDataProvider.h>
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_filereader.h"
|
||||
#include "blendthumb.hh"
|
||||
ankitm marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
Add newline before this. Add newline before this.
|
||||
|
||||
/**
|
||||
* This section intends to list the important steps for creating a thumbnail extension.
|
||||
* qlgenerator has been deprecated and removed in platforms we support. App extensions are the way
|
||||
|
@ -38,17 +47,88 @@
|
|||
*
|
||||
* # Troubleshooting
|
||||
* - Is it registered with lsregister and there isn't a conflict with another plugin taking
|
||||
* precendence?
|
||||
* - Is it codesigned and sandboxed?
|
||||
* precendence? `lsregister -dump | grep Blender.app/`
|
||||
* - Is it codesigned and sandboxed? `codesign -d --entitlements - /path/to/plugin`
|
||||
* - Sometimes blender-thumbnailer running in background can be killed.
|
||||
* - qlmanage -r && killall Finder
|
||||
* - lsregister -dump | grep Blender.app/
|
||||
*
|
||||
* # Triggering a thumbnail
|
||||
* - qlmanage -t /path/to/file.blend
|
||||
* - qlmanage -t -s 512 -o /tmp/ /path/to/file.blend
|
||||
*/
|
||||
|
||||
class FileReaderRAII {
|
||||
int src_file_ = -1;
|
||||
|
||||
public:
|
||||
explicit FileReaderRAII(int src_file) : src_file_(src_file) {}
|
||||
~FileReaderRAII()
|
||||
{
|
||||
if (src_file_ != -1) {
|
||||
close(src_file_);
|
||||
}
|
||||
}
|
||||
|
||||
bool good()
|
||||
{
|
||||
return src_file_ != -1;
|
||||
}
|
||||
|
||||
int get()
|
||||
{
|
||||
return src_file_;
|
||||
}
|
||||
};
|
||||
|
||||
static NSError *createErrorFromStr(NSString *errorStr)
|
||||
ankitm marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
`snake_case` for function names
Ankit Meel
commented
Java habit from work .. Java habit from work ..
|
||||
{
|
||||
NSLog(@"Blender Thumbnailer Error: %@", errorStr);
|
||||
return [NSError errorWithDomain:@"com.blenderfoundation.blender.thumbnailer"
|
||||
code:-1
|
||||
userInfo:@{NSLocalizedDescriptionKey : errorStr}];
|
||||
}
|
||||
|
||||
static NSImage *generateNSImageForFile(const char *src_blend_path, NSError **error)
|
||||
ankitm marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
`snake_case` for function names
|
||||
{
|
||||
|
||||
ankitm marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
Remove empty line Remove empty line
|
||||
/* Open source file `src_blend`. */
|
||||
FileReaderRAII src_file_fd = FileReaderRAII(BLI_open(src_blend_path, O_BINARY | O_RDONLY, 0));
|
||||
ankitm marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
This name is confusing to me, it's not RAII for the This name is confusing to me, it's not RAII for the `FileReader` type below. Would also be better to put `BLI_open` inside the class constructor I think.
|
||||
if (!src_file_fd.good()) {
|
||||
*error = createErrorFromStr(@"Failed to open blend");
|
||||
return nil;
|
||||
}
|
||||
|
||||
FileReader *file_content = BLI_filereader_new_file(src_file_fd.get());
|
||||
if (file_content == nullptr) {
|
||||
*error = createErrorFromStr(@"Failed to read from blend");
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* Extract thumbnail from file. */
|
||||
Thumbnail thumb;
|
||||
eThumbStatus err = blendthumb_create_thumb_from_file(file_content, &thumb);
|
||||
if (err != BT_OK) {
|
||||
*error = createErrorFromStr(@"Failed to create thumbnail from file");
|
||||
return nil;
|
||||
}
|
||||
|
||||
std::optional<blender::Vector<uint8_t>> png_buf_opt = blendthumb_create_png_data_from_thumb(
|
||||
&thumb);
|
||||
if (!png_buf_opt) {
|
||||
*error = createErrorFromStr(@"Failed to create png data from thumbnail");
|
||||
return nil;
|
||||
}
|
||||
NSData *data = [NSData dataWithBytes:png_buf_opt->data() length:png_buf_opt->size()];
|
||||
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
|
||||
CGImageRef image = CGImageCreateWithPNGDataProvider(
|
||||
provider, nullptr, true, kCGRenderingIntentDefault);
|
||||
CGDataProviderRelease(provider);
|
||||
NSImage *uiimage = [[NSImage alloc] initWithCGImage:image size:NSZeroSize];
|
||||
ankitm marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
Not sure why this is called Not sure why this is called `uiimage`, maybe copied from example code?
|
||||
CGImageRelease(image);
|
||||
CGDataProviderRelease(provider);
|
||||
ankitm marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
Don't call Don't call `CGDataProviderRelease` twice
|
||||
return uiimage;
|
||||
}
|
||||
|
||||
@implementation ThumbnailProvider
|
||||
|
||||
- (void)provideThumbnailForFileRequest:(QLFileThumbnailRequest *)request
|
||||
|
@ -56,13 +136,24 @@
|
|||
NSError *_Nullable error))handler
|
||||
{
|
||||
|
||||
NSLog(@"hello world from blender");
|
||||
NSURL *foo = [[NSURL alloc] initFileURLWithFileSystemRepresentation:""
|
||||
isDirectory:NO
|
||||
relativeToURL:nil];
|
||||
QLThumbnailReply *reply = [QLThumbnailReply replyWithImageFileURL:foo];
|
||||
|
||||
handler(reply, nil);
|
||||
NSLog(@"Generating thumbnail for %@", request.fileURL.path);
|
||||
@autoreleasepool {
|
||||
NSError *error = nil;
|
||||
NSImage *image = generateNSImageForFile(request.fileURL.path.UTF8String, &error);
|
||||
if (image == nil) {
|
||||
handler(nil, error);
|
||||
return;
|
||||
}
|
||||
handler([QLThumbnailReply replyWithContextSize:request.maximumSize
|
||||
currentContextDrawingBlock:^BOOL {
|
||||
[image drawInRect:NSMakeRect(0,
|
||||
0,
|
||||
request.maximumSize.width,
|
||||
request.maximumSize.height)];
|
||||
return YES;
|
||||
}],
|
||||
nil);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in New Issue
snake_case for filenames