File: GetMetadataForFile.m

package info (click to toggle)
djview4 4.12.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,792 kB
  • sloc: cpp: 22,307; ansic: 9,746; sh: 392; makefile: 229; awk: 94; xml: 84
file content (203 lines) | stat: -rw-r--r-- 6,597 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
//
//  GetMetadataForFile.m
//  DjVu
//
//  Created by Jeff Sickel on 9/6/06.
//  Copyright (c) 2006 Corpus Callosum Corporation. All rights reserved.
//

#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h> 

#import <Foundation/Foundation.h>

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#include "libdjvu/miniexp.h"
#include "libdjvu/ddjvuapi.h"

ddjvu_context_t *ctx;
ddjvu_document_t *doc;

#pragma mark -

void
handle(int wait)
{
    const ddjvu_message_t *msg;
    if (!ctx)
        return;
    if (wait)
        msg = ddjvu_message_wait(ctx);
    while ((msg = ddjvu_message_peek(ctx)))
    {
        switch(msg->m_any.tag)
        {
            case DDJVU_ERROR:
                NSLog(@"%s", msg->m_error.message);
                if (msg->m_error.filename)
                    NSLog(@"'%s:%d'",
                            msg->m_error.filename, msg->m_error.lineno);
                    return;
                break; // never gets here
            default:
                break;
        }
        ddjvu_message_pop(ctx);
    }
}

#pragma mark -
void
mdprint(NSMutableString *str, miniexp_t r)
{
    if (miniexp_consp(r)) {
        while (miniexp_consp(r)) {
            mdprint(str, miniexp_car(r));  
            r = miniexp_cdr(r);
        }
    } else if (miniexp_stringp(r)) {
        [str appendFormat:@" %s", miniexp_to_str(r)];
    }
}

void
mdfprint(FILE *str, miniexp_t r)
{
    if (miniexp_consp(r)) {
        while (miniexp_consp(r)) {
            mdfprint(str, miniexp_car(r));  
            r = miniexp_cdr(r);
        }
    } else if (miniexp_stringp(r)) {
        fprintf(str, " %s", miniexp_to_str(r));
    }
}

#pragma mark -
/* -----------------------------------------------------------------------------
    Get metadata attributes from file
   
   This function's job is to extract useful information your file format supports
   and return it as a dictionary
   ----------------------------------------------------------------------------- */

Boolean GetMetadataForFile(void* thisInterface, 
               CFMutableDictionaryRef attributes, 
               CFStringRef contentTypeUTI,
               CFStringRef pathToFile)
{
    Boolean result = NO;
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSProcessInfo *pinfo = nil;
    NSString *path = (NSString *)pathToFile;
    NSMutableDictionary *dictionary = (NSMutableDictionary *)attributes;
    int npages;
    miniexp_t expr;
        
    pinfo = [NSProcessInfo processInfo];
    if (! (ctx = ddjvu_context_create([[pinfo processName] cStringUsingEncoding:NSASCIIStringEncoding]))) {
        NSLog(@"Cannot create djvu conext for '%@'.", path);
        goto pop;
    }
    if (! (doc = ddjvu_document_create_by_filename(ctx, [path fileSystemRepresentation], TRUE))) {
        NSLog(@"Cannot open djvu document '%@'.", path);
        goto pop;
    }

    while (! ddjvu_document_decoding_done(doc))
        handle(TRUE);
            
    /* Pull any available metadata from the file at the specified path */
    /* Return the attribute keys and attribute values in the dict */
    /* Return TRUE if successful, FALSE if there was no data provided */
    
    npages = ddjvu_document_get_pagenum(doc);
    if (npages) {
        int i;
        ddjvu_status_t r;
        ddjvu_pageinfo_t info;
        double f = 1.0;
        NSMutableString *buf = [NSMutableString string];
        
        for (i=0; i<npages; i++) {
            while ((expr=ddjvu_document_get_pagetext(doc,i,"page")) == miniexp_dummy)
                handle(TRUE);
            if (expr)
                mdprint(buf, expr);
        }
        
        if ([buf length]) {
            // if it has searchable text content... it's really not just an image
            // we really want these to show up as documents
            NSMutableArray *typeTree = [dictionary objectForKey:@"kMDItemContentTypeTree"];
            if (typeTree && [typeTree containsObject:@"public.image"]) {
                [typeTree removeObject:@"public.image"];
            }
            
            [dictionary setObject:buf forKey:(NSString *)kMDItemTextContent];            
        }
        
        // this could be com.lizardtech.djvu or org.djvuzone.djvulibre.djvu
        // either way still needs to pick up the files from com.lizardtech.djvu
        // seems that public.djvu keeps getting picked up
        /*
        if (kCFCompareEqualTo != CFStringCompare(contentTypeUTI, CFSTR("com.lizardtech.djvu"), kCFCompareCaseInsensitive))
            [dictionary setObject:@"org.djvuzone.djvulibre.djvu" forKey:(NSString *)kMDItemContentType];
         
        // this is cheat that would purge the 'public.djvu' but then we need to
        // figure out what to do about the actual kMDItemContentType to use
        NSString *contentType = [dictionary objectForKey:(NSString*)kMDItemContentType];
        if (contentType && [contentType isEqualToString:@"public.djvu"]) {
            [dictionary removeObjectForKey:(NSString*)kMDItemContentType];
        }
         */
        
        while ((r = ddjvu_document_get_pageinfo(doc, 0, &info)) < DDJVU_JOB_OK)
            handle(TRUE);
        if (r >= DDJVU_JOB_FAILED)
            goto pop;
        
        f = 72.0 / (double)info.dpi;
        
#define DjAddIntKey(n,k) \
        [dictionary setObject:[NSNumber numberWithInt:n] forKey:(NSString *)k]
            
        DjAddIntKey(npages, kMDItemNumberOfPages);
        DjAddIntKey(info.height, kMDItemPixelHeight);
        DjAddIntKey(info.width, kMDItemPixelWidth);
        DjAddIntKey((int)(f * info.height), kMDItemPageHeight);
        DjAddIntKey((int)(f * info.width), kMDItemPageWidth);
        
        [dictionary setObject:[NSString stringWithFormat:@"%d", info.version] 
                       forKey:(NSString *)kMDItemVersion];
        
        /** Image orientation:
            0: no rotation      1: 90 degrees counter-clockwise
            2: 180 degrees      3: 270 degrees counter-clockwise
            trying to map to kMDItemOrientation:
            Values are 0 is "Landscape" or 1 is "Portrait"
        */
        DjAddIntKey(!(info.rotation), kMDItemOrientation);
        
        [dictionary setObject:@"DjVu File" forKey:(NSString *)kMDItemKind];
                
        // implement in next release ---
        // kMDItemDescription
        // kMDItemCodecs ??
        
        result = YES;
    }
    
pop:
    if (doc)
        ddjvu_document_release(doc);
    if (ctx)
        ddjvu_context_release(ctx);
        
    [pool release];
    
    return result;
}