Blame macosx/mdimporter/GetMetadataForFile.m

Packit df99a1
//
Packit df99a1
//  GetMetadataForFile.m
Packit df99a1
//  DjVu
Packit df99a1
//
Packit df99a1
//  Created by Jeff Sickel on 9/6/06.
Packit df99a1
//  Copyright (c) 2006 Corpus Callosum Corporation. All rights reserved.
Packit df99a1
//
Packit df99a1
Packit df99a1
#include <CoreFoundation/CoreFoundation.h>
Packit df99a1
#include <CoreServices/CoreServices.h> 
Packit df99a1
Packit df99a1
#import <Foundation/Foundation.h>
Packit df99a1
Packit df99a1
#include <stdio.h>
Packit df99a1
#include <stdlib.h>
Packit df99a1
#include <stdarg.h>
Packit df99a1
Packit df99a1
#include "libdjvu/miniexp.h"
Packit df99a1
#include "libdjvu/ddjvuapi.h"
Packit df99a1
Packit df99a1
ddjvu_context_t *ctx;
Packit df99a1
ddjvu_document_t *doc;
Packit df99a1
Packit df99a1
#pragma mark -
Packit df99a1
Packit df99a1
void
Packit df99a1
handle(int wait)
Packit df99a1
{
Packit df99a1
    const ddjvu_message_t *msg;
Packit df99a1
    if (!ctx)
Packit df99a1
        return;
Packit df99a1
    if (wait)
Packit df99a1
        msg = ddjvu_message_wait(ctx);
Packit df99a1
    while ((msg = ddjvu_message_peek(ctx)))
Packit df99a1
    {
Packit df99a1
        switch(msg->m_any.tag)
Packit df99a1
        {
Packit df99a1
            case DDJVU_ERROR:
Packit df99a1
                NSLog(@"%s", msg->m_error.message);
Packit df99a1
                if (msg->m_error.filename)
Packit df99a1
                    NSLog(@"'%s:%d'",
Packit df99a1
                            msg->m_error.filename, msg->m_error.lineno);
Packit df99a1
                    return;
Packit df99a1
                break; // never gets here
Packit df99a1
            default:
Packit df99a1
                break;
Packit df99a1
        }
Packit df99a1
        ddjvu_message_pop(ctx);
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
#pragma mark -
Packit df99a1
void
Packit df99a1
mdprint(NSMutableString *str, miniexp_t r)
Packit df99a1
{
Packit df99a1
    if (miniexp_consp(r)) {
Packit df99a1
        while (miniexp_consp(r)) {
Packit df99a1
            mdprint(str, miniexp_car(r));  
Packit df99a1
            r = miniexp_cdr(r);
Packit df99a1
        }
Packit df99a1
    } else if (miniexp_stringp(r)) {
Packit df99a1
        [str appendFormat:@" %s", miniexp_to_str(r)];
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
mdfprint(FILE *str, miniexp_t r)
Packit df99a1
{
Packit df99a1
    if (miniexp_consp(r)) {
Packit df99a1
        while (miniexp_consp(r)) {
Packit df99a1
            mdfprint(str, miniexp_car(r));  
Packit df99a1
            r = miniexp_cdr(r);
Packit df99a1
        }
Packit df99a1
    } else if (miniexp_stringp(r)) {
Packit df99a1
        fprintf(str, " %s", miniexp_to_str(r));
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
#pragma mark -
Packit df99a1
/* -----------------------------------------------------------------------------
Packit df99a1
    Get metadata attributes from file
Packit df99a1
   
Packit df99a1
   This function's job is to extract useful information your file format supports
Packit df99a1
   and return it as a dictionary
Packit df99a1
   ----------------------------------------------------------------------------- */
Packit df99a1
Packit df99a1
Boolean GetMetadataForFile(void* thisInterface, 
Packit df99a1
			   CFMutableDictionaryRef attributes, 
Packit df99a1
			   CFStringRef contentTypeUTI,
Packit df99a1
			   CFStringRef pathToFile)
Packit df99a1
{
Packit df99a1
    Boolean result = NO;
Packit df99a1
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Packit df99a1
    NSProcessInfo *pinfo = nil;
Packit df99a1
	NSString *path = (NSString *)pathToFile;
Packit df99a1
	NSMutableDictionary *dictionary = (NSMutableDictionary *)attributes;
Packit df99a1
    int npages;
Packit df99a1
    miniexp_t expr;
Packit df99a1
	    
Packit df99a1
	pinfo = [NSProcessInfo processInfo];
Packit df99a1
    if (! (ctx = ddjvu_context_create([[pinfo processName] cStringUsingEncoding:NSASCIIStringEncoding]))) {
Packit df99a1
        NSLog(@"Cannot create djvu conext for '%@'.", path);
Packit df99a1
        goto pop;
Packit df99a1
    }
Packit df99a1
    if (! (doc = ddjvu_document_create_by_filename(ctx, [path fileSystemRepresentation], TRUE))) {
Packit df99a1
        NSLog(@"Cannot open djvu document '%@'.", path);
Packit df99a1
        goto pop;
Packit df99a1
    }
Packit df99a1
Packit df99a1
    while (! ddjvu_document_decoding_done(doc))
Packit df99a1
        handle(TRUE);
Packit df99a1
            
Packit df99a1
    /* Pull any available metadata from the file at the specified path */
Packit df99a1
    /* Return the attribute keys and attribute values in the dict */
Packit df99a1
    /* Return TRUE if successful, FALSE if there was no data provided */
Packit df99a1
    
Packit df99a1
    npages = ddjvu_document_get_pagenum(doc);
Packit df99a1
    if (npages) {
Packit df99a1
        int i;
Packit df99a1
        ddjvu_status_t r;
Packit df99a1
        ddjvu_pageinfo_t info;
Packit df99a1
        double f = 1.0;
Packit df99a1
        NSMutableString *buf = [NSMutableString string];
Packit df99a1
        
Packit df99a1
        for (i=0; i
Packit df99a1
            while ((expr=ddjvu_document_get_pagetext(doc,i,"page")) == miniexp_dummy)
Packit df99a1
                handle(TRUE);
Packit df99a1
            if (expr)
Packit df99a1
                mdprint(buf, expr);
Packit df99a1
        }
Packit df99a1
        
Packit df99a1
        if ([buf length]) {
Packit df99a1
            // if it has searchable text content... it's really not just an image
Packit df99a1
            // we really want these to show up as documents
Packit df99a1
            NSMutableArray *typeTree = [dictionary objectForKey:@"kMDItemContentTypeTree"];
Packit df99a1
            if (typeTree && [typeTree containsObject:@"public.image"]) {
Packit df99a1
                [typeTree removeObject:@"public.image"];
Packit df99a1
            }
Packit df99a1
            
Packit df99a1
            [dictionary setObject:buf forKey:(NSString *)kMDItemTextContent];            
Packit df99a1
        }
Packit df99a1
        
Packit df99a1
        // this could be com.lizardtech.djvu or org.djvuzone.djvulibre.djvu
Packit df99a1
        // either way still needs to pick up the files from com.lizardtech.djvu
Packit df99a1
        // seems that public.djvu keeps getting picked up
Packit df99a1
        /*
Packit df99a1
        if (kCFCompareEqualTo != CFStringCompare(contentTypeUTI, CFSTR("com.lizardtech.djvu"), kCFCompareCaseInsensitive))
Packit df99a1
            [dictionary setObject:@"org.djvuzone.djvulibre.djvu" forKey:(NSString *)kMDItemContentType];
Packit df99a1
         
Packit df99a1
        // this is cheat that would purge the 'public.djvu' but then we need to
Packit df99a1
        // figure out what to do about the actual kMDItemContentType to use
Packit df99a1
        NSString *contentType = [dictionary objectForKey:(NSString*)kMDItemContentType];
Packit df99a1
        if (contentType && [contentType isEqualToString:@"public.djvu"]) {
Packit df99a1
            [dictionary removeObjectForKey:(NSString*)kMDItemContentType];
Packit df99a1
        }
Packit df99a1
         */
Packit df99a1
        
Packit df99a1
        while ((r = ddjvu_document_get_pageinfo(doc, 0, &info)) < DDJVU_JOB_OK)
Packit df99a1
            handle(TRUE);
Packit df99a1
        if (r >= DDJVU_JOB_FAILED)
Packit df99a1
            goto pop;
Packit df99a1
        
Packit df99a1
        f = 72.0 / (double)info.dpi;
Packit df99a1
        
Packit df99a1
#define DjAddIntKey(n,k) \
Packit df99a1
        [dictionary setObject:[NSNumber numberWithInt:n] forKey:(NSString *)k]
Packit df99a1
            
Packit df99a1
        DjAddIntKey(npages, kMDItemNumberOfPages);
Packit df99a1
        DjAddIntKey(info.height, kMDItemPixelHeight);
Packit df99a1
        DjAddIntKey(info.width, kMDItemPixelWidth);
Packit df99a1
        DjAddIntKey((int)(f * info.height), kMDItemPageHeight);
Packit df99a1
        DjAddIntKey((int)(f * info.width), kMDItemPageWidth);
Packit df99a1
        
Packit df99a1
        [dictionary setObject:[NSString stringWithFormat:@"%d", info.version] 
Packit df99a1
                       forKey:(NSString *)kMDItemVersion];
Packit df99a1
        
Packit df99a1
        /** Image orientation:
Packit df99a1
            0: no rotation      1: 90 degrees counter-clockwise
Packit df99a1
            2: 180 degrees      3: 270 degrees counter-clockwise
Packit df99a1
            trying to map to kMDItemOrientation:
Packit df99a1
            Values are 0 is "Landscape" or 1 is "Portrait"
Packit df99a1
        */
Packit df99a1
        DjAddIntKey(!(info.rotation), kMDItemOrientation);
Packit df99a1
        
Packit df99a1
        [dictionary setObject:@"DjVu File" forKey:(NSString *)kMDItemKind];
Packit df99a1
                
Packit df99a1
        // implement in next release ---
Packit df99a1
        // kMDItemDescription
Packit df99a1
        // kMDItemCodecs ??
Packit df99a1
        
Packit df99a1
        result = YES;
Packit df99a1
    }
Packit df99a1
    
Packit df99a1
pop:
Packit df99a1
    if (doc)
Packit df99a1
        ddjvu_document_release(doc);
Packit df99a1
    if (ctx)
Packit df99a1
        ddjvu_context_release(ctx);
Packit df99a1
        
Packit df99a1
    [pool release];
Packit df99a1
    
Packit df99a1
    return result;
Packit df99a1
}