1 /*
2  * This file is part of Krita
3  *
4  * Copyright (c) 2020 L. E. Segovia <amy@amyspark.me>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21 
22 /* clang-format off */
23 
24 
25 
26 
27 //==============================================================================
28 //
29 //  DO NO MODIFY THE CONTENT OF THIS FILE
30 //
31 //  This file contains the generic CFPlug-in code necessary for your importer
32 //  To complete your importer implement the function in GetMetadataForFile.c
33 //
34 //==============================================================================
35 
36 
37 
38 
39 
40 #import <CoreFoundation/CoreFoundation.h>
41 #import <CoreFoundation/CFPlugInCOM.h>
42 #import <CoreServices/CoreServices.h>
43 
44 // -----------------------------------------------------------------------------
45 //  constants
46 // -----------------------------------------------------------------------------
47 
48 
49 #define PLUGIN_ID "23FE92B0-6256-49C0-B1A6-942FB9B86A82"
50 
51 //
52 // Below is the generic glue code for all plug-ins.
53 //
54 // You should not have to modify this code aside from changing
55 // names if you decide to change the names defined in the Info.plist
56 //
57 
58 
59 // -----------------------------------------------------------------------------
60 //  typedefs
61 // -----------------------------------------------------------------------------
62 
63 // The import function to be implemented in GetMetadataForFile.c
64 Boolean GetMetadataForFile(void *thisInterface,
65                CFMutableDictionaryRef attributes,
66                CFStringRef contentTypeUTI,
67                CFStringRef pathToFile);
68 
69 // The layout for an instance of MetaDataImporterPlugIn
70 typedef struct __MetadataImporterPluginType
71 {
72     MDImporterInterfaceStruct *conduitInterface;
73     CFUUIDRef                 factoryID;
74     UInt32                    refCount;
75 } MetadataImporterPluginType;
76 
77 // -----------------------------------------------------------------------------
78 //  prototypes
79 // -----------------------------------------------------------------------------
80 //  Forward declaration for the IUnknown implementation.
81 //
82 
83 MetadataImporterPluginType  *AllocMetadataImporterPluginType(CFUUIDRef inFactoryID);
84 void                      DeallocMetadataImporterPluginType(MetadataImporterPluginType *thisInstance);
85 HRESULT                   MetadataImporterQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv);
86 void                     *MetadataImporterPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID);
87 ULONG                     MetadataImporterPluginAddRef(void *thisInstance);
88 ULONG                     MetadataImporterPluginRelease(void *thisInstance);
89 // -----------------------------------------------------------------------------
90 //  testInterfaceFtbl    definition
91 // -----------------------------------------------------------------------------
92 //  The TestInterface function table.
93 //
94 
95 static MDImporterInterfaceStruct testInterfaceFtbl = {
96     NULL,
97     MetadataImporterQueryInterface,
98     MetadataImporterPluginAddRef,
99     MetadataImporterPluginRelease,
100     GetMetadataForFile
101 };
102 
103 
104 // -----------------------------------------------------------------------------
105 //  AllocMetadataImporterPluginType
106 // -----------------------------------------------------------------------------
107 //  Utility function that allocates a new instance.
108 //      You can do some initial setup for the importer here if you wish
109 //      like allocating globals etc...
110 //
AllocMetadataImporterPluginType(CFUUIDRef inFactoryID)111 MetadataImporterPluginType *AllocMetadataImporterPluginType(CFUUIDRef inFactoryID)
112 {
113     MetadataImporterPluginType *theNewInstance;
114 
115     theNewInstance = (MetadataImporterPluginType *)malloc(sizeof(MetadataImporterPluginType));
116     memset(theNewInstance,0,sizeof(MetadataImporterPluginType));
117 
118         /* Point to the function table */
119     theNewInstance->conduitInterface = &testInterfaceFtbl;
120 
121         /*  Retain and keep an open instance refcount for each factory. */
122     theNewInstance->factoryID = CFRetain(inFactoryID);
123     CFPlugInAddInstanceForFactory(inFactoryID);
124 
125         /* This function returns the IUnknown interface so set the refCount to one. */
126     theNewInstance->refCount = 1;
127     return theNewInstance;
128 }
129 
130 // -----------------------------------------------------------------------------
131 //    DeallockritaspotlightMDImporterPluginType
132 // -----------------------------------------------------------------------------
133 //  Utility function that deallocates the instance when
134 //  the refCount goes to zero.
135 //      In the current implementation importer interfaces are never deallocated
136 //      but implement this as this might change in the future
137 //
DeallocMetadataImporterPluginType(MetadataImporterPluginType * thisInstance)138 void DeallocMetadataImporterPluginType(MetadataImporterPluginType *thisInstance)
139 {
140     CFUUIDRef theFactoryID;
141 
142     theFactoryID = thisInstance->factoryID;
143     free(thisInstance);
144     if (theFactoryID){
145         CFPlugInRemoveInstanceForFactory(theFactoryID);
146         CFRelease(theFactoryID);
147     }
148 }
149 
150 // -----------------------------------------------------------------------------
151 //  MetadataImporterQueryInterface
152 // -----------------------------------------------------------------------------
153 //  Implementation of the IUnknown QueryInterface function.
154 //
MetadataImporterQueryInterface(void * thisInstance,REFIID iid,LPVOID * ppv)155 HRESULT MetadataImporterQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv)
156 {
157     CFUUIDRef interfaceID;
158 
159     interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault,iid);
160 
161     if (CFEqual(interfaceID,kMDImporterInterfaceID)){
162             /* If the Right interface was requested, bump the ref count,
163              * set the ppv parameter equal to the instance, and
164              * return good status.
165              */
166         ((MetadataImporterPluginType*)thisInstance)->conduitInterface->AddRef(thisInstance);
167         *ppv = thisInstance;
168         CFRelease(interfaceID);
169         return S_OK;
170     }else{
171         if (CFEqual(interfaceID,IUnknownUUID)){
172                 /* If the IUnknown interface was requested, same as above. */
173             ((MetadataImporterPluginType*)thisInstance )->conduitInterface->AddRef(thisInstance);
174             *ppv = thisInstance;
175             CFRelease(interfaceID);
176             return S_OK;
177         }else{
178                 /* Requested interface unknown, bail with error. */
179             *ppv = NULL;
180             CFRelease(interfaceID);
181             return E_NOINTERFACE;
182         }
183     }
184 }
185 
186 // -----------------------------------------------------------------------------
187 //  MetadataImporterPluginAddRef
188 // -----------------------------------------------------------------------------
189 //  Implementation of reference counting for this type. Whenever an interface
190 //  is requested, bump the refCount for the instance. NOTE: returning the
191 //  refcount is a convention but is not required so don't rely on it.
192 //
MetadataImporterPluginAddRef(void * thisInstance)193 ULONG MetadataImporterPluginAddRef(void *thisInstance)
194 {
195     ((MetadataImporterPluginType *)thisInstance )->refCount += 1;
196     return ((MetadataImporterPluginType*) thisInstance)->refCount;
197 }
198 
199 // -----------------------------------------------------------------------------
200 // SampleCMPluginRelease
201 // -----------------------------------------------------------------------------
202 //  When an interface is released, decrement the refCount.
203 //  If the refCount goes to zero, deallocate the instance.
204 //
MetadataImporterPluginRelease(void * thisInstance)205 ULONG MetadataImporterPluginRelease(void *thisInstance)
206 {
207     ((MetadataImporterPluginType*)thisInstance)->refCount -= 1;
208     if (((MetadataImporterPluginType*)thisInstance)->refCount == 0){
209         DeallocMetadataImporterPluginType((MetadataImporterPluginType*)thisInstance );
210         return 0;
211     }else{
212         return ((MetadataImporterPluginType*) thisInstance )->refCount;
213     }
214 }
215 
216 // -----------------------------------------------------------------------------
217 //  kritaspotlightMDImporterPluginFactory
218 // -----------------------------------------------------------------------------
219 //  Implementation of the factory function for this type.
220 //
MetadataImporterPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID)221 void *MetadataImporterPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID)
222 {
223     MetadataImporterPluginType *result;
224     CFUUIDRef                 uuid;
225 
226         /* If correct type is being requested, allocate an
227          * instance of TestType and return the IUnknown interface.
228          */
229     if (CFEqual(typeID,kMDImporterTypeID)){
230         uuid = CFUUIDCreateFromString(kCFAllocatorDefault,CFSTR(PLUGIN_ID));
231         result = AllocMetadataImporterPluginType(uuid);
232         CFRelease(uuid);
233         return result;
234     }
235         /* If the requested type is incorrect, return NULL. */
236     return NULL;
237 }
238 
239