Bugfix : fixed typos in metadata type details tests.
[LibTracker-Client-Perl.git] / Client.xs
blobf5d72369fa72555669cea03e7c7c112f49bee781
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
5 #include "ppport.h"
7 #include <tracker.h>
10 /* SERVICE_ definitions */
11 #define  SERVICE_FILES                  0
12 #define  SERVICE_FOLDERS                1
13 #define  SERVICE_DOCUMENTS              2
14 #define  SERVICE_IMAGES                 3
15 #define  SERVICE_MUSIC                  4
16 #define  SERVICE_VIDEOS                 5
17 #define  SERVICE_TEXT_FILES             6
18 #define  SERVICE_DEVELOPMENT_FILES      7
19 #define  SERVICE_OTHER_FILES            8
20 #define  SERVICE_VFS_FILES              9
21 #define  SERVICE_VFS_FOLDERS           10
22 #define  SERVICE_VFS_DOCUMENTS         11
23 #define  SERVICE_VFS_IMAGES            12
24 #define  SERVICE_VFS_MUSIC             13
25 #define  SERVICE_VFS_VIDEOS            14
26 #define  SERVICE_VFS_TEXT_FILES        15
27 #define  SERVICE_VFS_DEVELOPMENT_FILES 16
28 #define  SERVICE_VFS_OTHER_FILES       17
29 #define  SERVICE_CONVERSATIONS         18
30 #define  SERVICE_PLAYLISTS             19
31 #define  SERVICE_APPLICATIONS          20
32 #define  SERVICE_CONTACTS              21
33 #define  SERVICE_EMAILS                22
34 #define  SERVICE_EMAILATTACHMENTS      23
35 #define  SERVICE_APPOINTMENTS          24
36 #define  SERVICE_TASKS                 25
37 #define  SERVICE_BOOKMARKS             26
38 #define  SERVICE_HISTORY               27
39 #define  SERVICE_PROJECTS              28
42 /* MetasataTypes definitions */
43 #define DATA_STRING_INDEXABLE           0
44 #define DATA_STRING                     1
45 #define DATA_NUMERIC                    2
46 #define DATA_DATE                       3
49 #include "const-c.inc"
51 SV* get_instance(char* class)
53         TrackerClient*  client = NULL;
54         SV*             obj_ref = newSViv(0);
55         SV*             obj = newSVrv(obj_ref, class);
57         client = tracker_connect(FALSE);
58         if(!client)
59                 return &PL_sv_undef;
61         sv_setiv(obj, (IV)client);
62         SvREADONLY_on(obj);
63         return obj_ref;
67 char* service_name(char* class, int type)
69         return tracker_type_to_service_name(type);
73 int service_type(char* class, const char* name)
75         return tracker_service_name_to_type(name);
79 void store_in_hash_and_free(gpointer key, gpointer value, gpointer perlhash)
81         hv_store(perlhash, key, strlen(key), newSVpvn(value, strlen(value)), 0);
82         free(key);
83         free(value);
86 void store_in_array(gpointer data, gpointer perlarray)
88         /* inspired from tracker-tag.c's get_meta_table_data */
89         char **meta, **meta_p;
90         int i = 0;
92         meta = (char **) data;
93         for(meta_p = meta; *meta_p; meta_p++) {
94                 if( i == 0 )
95                         av_push((AV *)perlarray, newSVpv(*meta_p, 0));
96                 i++;
97         }
100 void DESTROY(SV* obj) {
101         TrackerClient* client = (TrackerClient*) SvIV(SvRV(obj));
102         tracker_disconnect(client);
106 MODULE = LibTracker::Client             PACKAGE = LibTracker::Client            
107 PROTOTYPES: DISABLE
109 INCLUDE: const-xs.inc
112 get_instance (class)
113         char* class
116 char*
117 service_name (class, type)
118         char* class;
119         int type;
123 service_type (class, name)
124         char* class;
125         const char* name;
129 get_version (obj)
130                 SV* obj;
131         PREINIT:
132                 int ret;
133                 GError *error = NULL;
134                 TrackerClient* client;
135         CODE:
136                 client = (TrackerClient*) SvIV(SvRV(obj));
137                 ST(0) = sv_newmortal();
138                 ret = tracker_get_version(client, &error);
139                 if(error)
140                         ST(0) = &PL_sv_undef;
141                 else
142                         sv_setiv( ST(0), ret );
146 get_status (obj)
147                 SV* obj;
148         PREINIT:
149                 char* ret;
150                 GError *error = NULL;
151                 TrackerClient* client;
152         CODE:
153                 client = (TrackerClient*) SvIV(SvRV(obj));
154                 ST(0) = sv_newmortal();
155                 ret = tracker_get_status(client, &error);
156                 if(error)
157                         ST(0) = &PL_sv_undef;
158                 else
159                         sv_setpv( ST(0), ret );
160                 free(ret);
164 get_services (obj, main_only)
165                 SV* obj;
166                 bool main_only;
167         PREINIT:
168                 GHashTable* ret;
169                 GError *error = NULL;
170                 TrackerClient* client;
171         INIT:
172                 HV* rh;
173         CODE:
174                 main_only = (!!main_only);      /* either 0 or 1 */
175                 client = (TrackerClient*) SvIV(SvRV(obj));
176                 ret = tracker_get_services(client, main_only, &error);
177                 rh = (HV *) sv_2mortal( (SV *) newHV() );
178                 if(error)
179                         RETVAL = &PL_sv_undef;
180                 else {
181                         g_hash_table_foreach( ret, store_in_hash_and_free, (gpointer) rh );
182                         RETVAL = newRV( (SV *) rh);
183                 }
184         OUTPUT:
185                 RETVAL
189 get_metadata (obj, servicetype, id, keys)
190                 SV* obj;
191                 int servicetype;
192                 const char* id;
193                 SV* keys;
194         PREINIT:
195                 char** ret;
196                 char** _keys;
197                 char* placeholder;
198                 STRLEN length;
199                 GError *error = NULL;
200                 TrackerClient* client;
201         INIT:
202                 HV* rh;
203                 I32 numkeys = 0;
204                 int i;
205                 SV **current_val;
206                 if( (!SvROK(keys))
207                         || ( SvTYPE( SvRV(keys) ) != SVt_PVAV )
208                         || ( (numkeys = av_len( (AV *) SvRV(keys))) < 0 ) ) {
209                         XSRETURN_UNDEF;
210                 }
211                 /* convert keys to a char** - this is inspired from the
212                  * avref2charptrptr function from perldap
213                  */
214                 Newxz(_keys, numkeys + 2, char *);
215                 for (i = 0; i <= numkeys; i++) {
216                         current_val = av_fetch( (AV *) SvRV(keys), i, 0 );
217                         placeholder = SvPV(*current_val, length);
218                         /* store a copy in _keys */
219                         Newxz(_keys[i], length+1, char);
220                         Copy(placeholder, _keys[i], length+1, char);
221                 }
222                 _keys[i] = NULL;
223         CODE:
224                 client = (TrackerClient*) SvIV(SvRV(obj));
225                 ret = tracker_metadata_get(client, servicetype, id, _keys, &error);
226                 rh = (HV *) sv_2mortal( (SV *) newHV() );
227                 if(error)
228                         RETVAL = &PL_sv_undef;
229                 else {
230                         for(i = 0; _keys[i] && ret[i]; i++)
231                                 hv_store(rh, _keys[i], strlen(_keys[i]), newSVpv(ret[i], 0), 0);
232                         g_strfreev(ret);        /* don't leak anything */
233                         RETVAL = newRV( (SV *) rh);
234                 }
235         OUTPUT:
236                 RETVAL
240 set_metadata (obj, servicetype, id, data)
241                 SV* obj;
242                 int servicetype;
243                 const char* id;
244                 SV* data;
245         PREINIT:
246                 char** _keys;
247                 char** _values;
248                 char* placeholder;
249                 STRLEN length;
250                 I32 keylen;
251                 GError *error = NULL;
252                 TrackerClient* client;
253         INIT:
254                 I32 numkeys = 0;
255                 int i;
256                 SV* current_val;
257                 HV* datahash;
258                 /* the iter_init prepares the hash iterator and gives us
259                  * the number of keys in the hash
260                  */
261                 if( (!SvROK(data))
262                         || ( SvTYPE( SvRV(data) ) != SVt_PVHV )
263                         || ( (numkeys = hv_iterinit((HV *)SvRV(data))) < 1 ) ) {
264                         XSRETURN_UNDEF;
265                 }
266                 else {
267                         datahash = (HV *) SvRV(data);
268                 }
269                 /* convert keys to a char** - this is inspired from the
270                  * avref2charptrptr function from perldap
271                  */
272                 Newxz(_keys, numkeys + 1, char *);
273                 Newxz(_values, numkeys + 1, char *);
274                 for (i = 0; i < numkeys; i++) {
275                         current_val = hv_iternextsv(datahash, &placeholder, &keylen);
276                         /* store the copy of the key in _keys */
277                         Newxz(_keys[i], keylen + 1, char);
278                         Copy(placeholder, _keys[i], keylen + 1, char);
279                         /* store the copy of the value in _values */
280                         placeholder = SvPV(current_val, length);
281                         Newxz(_values[i], length + 1, char);
282                         Copy(placeholder, _values[i], length + 1, char);
283                 }
284                 _keys[i] = NULL;
285                 _values[i] = NULL;
286         CODE:
287                 client = (TrackerClient*) SvIV(SvRV(obj));
288                 tracker_metadata_set(client, servicetype, id, _keys, _values, &error);
289                 ST(0) = sv_newmortal();
290                 if(error)
291                         ST(0) = &PL_sv_undef;
292                 else
293                         sv_setiv( ST(0), numkeys );
296 void
297 register_metadata_type (obj, name, type)
298                 SV* obj;
299                 const char* name;
300                 int type;
301         PREINIT:
302                 GError *error = NULL;
303                 TrackerClient* client;
304         CODE:
305                 client = (TrackerClient*) SvIV(SvRV(obj));
306                 tracker_metadata_register_type(client, name, type, &error);
307                 if(error)
308                         croak("tracker_metadata_register_type failed with code %d (%s)", error->code, error->message);
312 get_metadata_type_details (obj, name)
313                 SV* obj;
314                 const char* name;
315         PREINIT:
316                 HV* args;
317                 I32 count;
318                 MetaDataTypeDetails* ret;
319                 GError *error = NULL;
320                 TrackerClient* client;
321         CODE:
322                 client = (TrackerClient*) SvIV(SvRV(obj));
323                 ret = tracker_metadata_get_type_details(client, name, &error);
324                 if(error)
325                         RETVAL = &PL_sv_undef;
326                 else {
327                         ENTER;
328                         SAVETMPS;
329                         /* set up a hashref for args to "new" */
330                         args = (HV *) sv_2mortal( (SV *) newHV() );
331                         hv_store(args, "type", 4, newSVpv(ret->type, 0), 0);
332                         hv_store(args, "is_embedded", 11, newSViv(ret->is_embedded), 0);
333                         hv_store(args, "is_writeable", 12, newSViv(ret->is_writeable), 0);
334                         free(ret);
335                         /* instantiate new MetadataTypeDetails object */
336                         PUSHMARK(SP);
337                         XPUSHs(sv_2mortal(newSVpv("LibTracker::Client::MetaDataTypeDetails", 0)));
338                         XPUSHs(sv_2mortal(newRV((SV*)args)));
339                         PUTBACK;
340                         count = call_method("new", G_SCALAR);
341                         SPAGAIN;
342                         if(count != 1)
343                                 croak("LibTracker::Client::MetaDataTypeDetails->new returned unexpected number of args. Expected 1, got %d", count);
344                         RETVAL = newSVsv((SV *)POPs);
345                         PUTBACK;
346                         FREETMPS;
347                         LEAVE;
348                 }
349         OUTPUT:
350                 RETVAL
354 get_registered_metadata_classes (obj)
355                 SV* obj;
356         PREINIT:
357                 char** ret;
358                 I32 i;
359                 GError *error = NULL;
360                 TrackerClient* client;
361                 AV* ra;
362         CODE:
363                 client = (TrackerClient*) SvIV(SvRV(obj));
364                 ret = tracker_metadata_get_registered_classes(client, &error);
365                 ra = (AV *) sv_2mortal( (SV *) newAV() );
366                 if(error)
367                         RETVAL = &PL_sv_undef;
368                 else {
369                         for(i = 0; ret[i]; i++)
370                                 av_push(ra, newSVpv(ret[i], 0));
371                         RETVAL = newRV( (SV *) ra);
372                         g_strfreev(ret);        /* don't leak */
373                 }
374         OUTPUT:
375                 RETVAL
379 get_registered_metadata_types (obj, classname)
380                 SV* obj;
381                 const char* classname;
382         PREINIT:
383                 char** ret;
384                 I32 i;
385                 GError *error = NULL;
386                 TrackerClient* client;
387                 AV* ra;
388         CODE:
389                 client = (TrackerClient*) SvIV(SvRV(obj));
390                 ret = tracker_metadata_get_registered_types(client, classname, &error);
391                 ra = (AV *) sv_2mortal( (SV *) newAV() );
392                 if(error)
393                         RETVAL = &PL_sv_undef;
394                 else {
395                         for(i = 0; ret[i]; i++)
396                                 av_push(ra, newSVpv(ret[i], 0));
397                         RETVAL = newRV( (SV *) ra);
398                         g_strfreev(ret);        /* don't leak */
399                 }
400         OUTPUT:
401                 RETVAL
405 get_writeable_metadata_types (obj, classname)
406                 SV* obj;
407                 const char* classname;
408         PREINIT:
409                 char** ret;
410                 I32 i;
411                 GError *error = NULL;
412                 TrackerClient* client;
413                 AV* ra;
414         CODE:
415                 client = (TrackerClient*) SvIV(SvRV(obj));
416                 ret = tracker_metadata_get_writeable_types(client, classname, &error);
417                 ra = (AV *) sv_2mortal( (SV *) newAV() );
418                 if(error)
419                         RETVAL = &PL_sv_undef;
420                 else {
421                         for(i = 0; ret[i]; i++)
422                                 av_push(ra, newSVpv(ret[i], 0));
423                         RETVAL = newRV( (SV *) ra);
424                         g_strfreev(ret);        /* don't leak */
425                 }
426         OUTPUT:
427                 RETVAL
431 get_all_keywords (obj, servicetype)
432                 SV* obj;
433                 int servicetype;
434         PREINIT:
435                 GPtrArray* ret;
436                 GError *error = NULL;
437                 TrackerClient* client;
438                 AV* ra;
439         CODE:
440                 client = (TrackerClient*) SvIV(SvRV(obj));
441                 ret = tracker_keywords_get_list(client, servicetype, &error);
442                 ra = (AV *) sv_2mortal( (SV *) newAV() );
443                 if(error)
444                         RETVAL = &PL_sv_undef;
445                 else {
446                         g_ptr_array_foreach(ret, store_in_array, (gpointer)ra);
447                         RETVAL = newRV( (SV *) ra);
448                         g_ptr_array_free(ret, TRUE);    /* don't leak */
449                 }
450         OUTPUT:
451                 RETVAL
455 get_keywords (obj, servicetype, id)
456                 SV* obj;
457                 int servicetype;
458                 const char* id;
459         PREINIT:
460                 char** ret;
461                 I32 i;
462                 GError *error = NULL;
463                 TrackerClient* client;
464                 AV* ra;
465         CODE:
466                 client = (TrackerClient*) SvIV(SvRV(obj));
467                 ret = tracker_keywords_get(client, servicetype, id, &error);
468                 ra = (AV *) sv_2mortal( (SV *) newAV() );
469                 if(error)
470                         RETVAL = &PL_sv_undef;
471                 else {
472                         for(i = 0; ret[i]; i++)
473                                 av_push(ra, newSVpv(ret[i], 0));
474                         RETVAL = newRV( (SV *) ra);
475                         g_strfreev(ret);        /* don't leak */
476                 }
477         OUTPUT:
478                 RETVAL
482 add_keywords (obj, servicetype, id, values)
483                 SV* obj;
484                 int servicetype;
485                 const char* id;
486                 SV* values;
487         PREINIT:
488                 char** _values;
489                 char* placeholder;
490                 STRLEN length;
491                 GError *error = NULL;
492                 TrackerClient* client;
493         INIT:
494                 I32 num = 0;
495                 I32 i;
496                 SV **current_val;
497                 if( (!SvROK(values))
498                         || ( SvTYPE( SvRV(values) ) != SVt_PVAV )
499                         || ( (num = av_len( (AV *) SvRV(values))) < 0 ) ) {
500                         XSRETURN_UNDEF;
501                 }
502                 /* convert keys to a char** - this is inspired from the
503                  * avref2charptrptr function from perldap
504                  */
505                 Newxz(_values, num + 2, char *); /* av_len returns elem-1 */
506                 for (i = 0; i <= num; i++) {
507                         current_val = av_fetch( (AV *) SvRV(values), i, 0 );
508                         placeholder = SvPV(*current_val, length);
509                         /* store a copy in _values */
510                         Newxz(_values[i], length+1, char);
511                         Copy(placeholder, _values[i], length+1, char);
512                 }
513                 _values[i] = NULL;
514         CODE:
515                 client = (TrackerClient*) SvIV(SvRV(obj));
516                 tracker_keywords_add(client, servicetype, id, _values, &error);
517                 ST(0) = sv_newmortal();
518                 if(error)
519                         ST(0) = &PL_sv_undef;
520                 else
521                         sv_setiv( ST(0), num + 1);
525 remove_keywords (obj, servicetype, id, values)
526                 SV* obj;
527                 int servicetype;
528                 const char* id;
529                 SV* values;
530         PREINIT:
531                 char** _values;
532                 char* placeholder;
533                 STRLEN length;
534                 GError *error = NULL;
535                 TrackerClient* client;
536         INIT:
537                 I32 num = 0;
538                 I32 i;
539                 SV **current_val;
540                 if( (!SvROK(values))
541                         || ( SvTYPE( SvRV(values) ) != SVt_PVAV )
542                         || ( (num = av_len( (AV *) SvRV(values))) < 0 ) ) {
543                         XSRETURN_UNDEF;
544                 }
545                 /* convert keys to a char** - this is inspired from the
546                  * avref2charptrptr function from perldap
547                  */
548                 Newxz(_values, num + 2, char *); /* av_len returns elem+1 */
549                 for (i = 0; i <= num; i++) {
550                         current_val = av_fetch( (AV *) SvRV(values), i, 0 );
551                         placeholder = SvPV(*current_val, length);
552                         /* store a copy in _values */
553                         Newxz(_values[i], length+1, char);
554                         Copy(placeholder, _values[i], length+1, char);
555                 }
556                 _values[i] = NULL;
557         CODE:
558                 client = (TrackerClient*) SvIV(SvRV(obj));
559                 tracker_keywords_remove(client, servicetype, id, _values, &error);
560                 ST(0) = sv_newmortal();
561                 if(error)
562                         ST(0) = &PL_sv_undef;
563                 else
564                         sv_setiv( ST(0), num + 1);
568 remove_all_keywords (obj, servicetype, id)
569                 SV* obj;
570                 int servicetype;
571                 const char* id;
572         PREINIT:
573                 GError *error = NULL;
574                 TrackerClient* client;
575         CODE:
576                 client = (TrackerClient*) SvIV(SvRV(obj));
577                 tracker_keywords_remove_all(client, servicetype, id, &error);
578                 ST(0) = sv_newmortal();
579                 if(error)
580                         ST(0) = &PL_sv_undef;
581                 else
582                         ST(0) = &PL_sv_yes;
586 search_keywords (obj, lqi, servicetype, keywords, offset, maxhits)
587                 SV* obj;
588                 int lqi;
589                 int servicetype;
590                 SV* keywords;
591                 int offset;
592                 int maxhits;
593         PREINIT:
594                 char** ret;
595                 char** _keywords;
596                 char* placeholder;
597                 STRLEN length;
598                 GError *error = NULL;
599                 TrackerClient* client;
600                 AV* ra;
601         INIT:
602                 I32 num = 0;
603                 I32 i;
604                 SV **current_val;
605                 if( (!SvROK(keywords))
606                         || ( SvTYPE( SvRV(keywords) ) != SVt_PVAV )
607                         || ( (num = av_len( (AV *) SvRV(keywords))) < 0 ) ) {
608                         XSRETURN_UNDEF;
609                 }
610                 /* convert keywords to a char** - this is inspired from the
611                  * avref2charptrptr function from perldap
612                  */
613                 Newxz(_keywords, num + 2, char *);
614                 for (i = 0; i <= num; i++) {
615                         current_val = av_fetch( (AV *) SvRV(keywords), i, 0 );
616                         placeholder = SvPV(*current_val, length);
617                         /* store a copy in _keywords */
618                         Newxz(_keywords[i], length+1, char);
619                         Copy(placeholder, _keywords[i], length+1, char);
620                 }
621                 _keywords[i] = NULL;
622         CODE:
623                 client = (TrackerClient*) SvIV(SvRV(obj));
624                 ret = tracker_keywords_search(client, lqi, servicetype, _keywords, offset, maxhits, &error);
625                 ra = (AV *) sv_2mortal( (SV *) newAV() );
626                 if(error)
627                         RETVAL = &PL_sv_undef;
628                 else {
629                         for(i = 0; ret[i]; i++)
630                                 av_push(ra, newSVpv(ret[i], 0));
631                         RETVAL = newRV( (SV *) ra);
632                         g_strfreev(ret);        /* don't leak */
633                 }
634         OUTPUT:
635                 RETVAL
639 search_text (obj, lqi, servicetype, searchtext, offset, maxhits)
640                 SV* obj;
641                 int lqi;
642                 int servicetype;
643                 const char* searchtext;
644                 int offset;
645                 int maxhits;
646         PREINIT:
647                 I32 i;
648                 char** ret;
649                 GError *error = NULL;
650                 TrackerClient* client;
651                 AV* ra;
652         CODE:
653                 client = (TrackerClient*) SvIV(SvRV(obj));
654                 ret = tracker_search_text(client, lqi, servicetype, searchtext, offset, maxhits, &error);
655                 ra = (AV *) sv_2mortal( (SV *) newAV() );
656                 if(error)
657                         RETVAL = &PL_sv_undef;
658                 else {
659                         for(i = 0; ret[i]; i++)
660                                 av_push(ra, newSVpv(ret[i], 0));
661                         RETVAL = newRV( (SV *) ra);
662                         g_strfreev(ret);        /* don't leak */
663                 }
664         OUTPUT:
665                 RETVAL
669 get_snippet (obj, servicetype, path, searchtext)
670                 SV* obj;
671                 int servicetype;
672                 const char* path;
673                 const char* searchtext;
674         PREINIT:
675                 char* ret;
676                 GError *error = NULL;
677                 TrackerClient* client;
678         CODE:
679                 client = (TrackerClient*) SvIV(SvRV(obj));
680                 ST(0) = sv_newmortal();
681                 ret = tracker_search_get_snippet(client, servicetype, path, searchtext, &error);
682                 if(error)
683                         ST(0) = &PL_sv_undef;
684                 else
685                         sv_setpv( ST(0), ret );
686                 free(ret);
690 search_metadata (obj, servicetype, field, searchtext, offset, maxhits)
691                 SV* obj;
692                 int servicetype;
693                 const char* field;
694                 const char* searchtext;
695                 int offset;
696                 int maxhits;
697         PREINIT:
698                 I32 i;
699                 char** ret;
700                 GError *error = NULL;
701                 TrackerClient* client;
702                 AV* ra;
703         CODE:
704                 client = (TrackerClient*) SvIV(SvRV(obj));
705                 ret = tracker_search_metadata(client, servicetype, field, searchtext, offset, maxhits, &error);
706                 ra = (AV *) sv_2mortal( (SV *) newAV() );
707                 if(error)
708                         RETVAL = &PL_sv_undef;
709                 else {
710                         for(i = 0; ret[i]; i++)
711                                 av_push(ra, newSVpv(ret[i], 0));
712                         RETVAL = newRV( (SV *) ra);
713                         g_strfreev(ret);        /* don't leak */
714                 }
715         OUTPUT:
716                 RETVAL
720 get_suggestion (obj, searchtext, maxdist)
721                 SV* obj;
722                 const char* searchtext;
723                 int maxdist;
724         PREINIT:
725                 char* ret;
726                 GError *error = NULL;
727                 TrackerClient* client;
728         CODE:
729                 client = (TrackerClient*) SvIV(SvRV(obj));
730                 ST(0) = sv_newmortal();
731                 ret = tracker_search_suggest(client,searchtext, maxdist, &error);
732                 if(error)
733                         ST(0) = &PL_sv_undef;
734                 else
735                         sv_setpv( ST(0), ret );
736                 free(ret);
740 get_files_by_service (obj, lqi, servicetype, offset, maxhits)
741                 SV* obj;
742                 int lqi;
743                 int servicetype;
744                 int offset;
745                 int maxhits;
746         PREINIT:
747                 I32 i;
748                 char** ret;
749                 GError *error = NULL;
750                 TrackerClient* client;
751                 AV* ra;
752         CODE:
753                 client = (TrackerClient*) SvIV(SvRV(obj));
754                 ret = tracker_files_get_by_service_type(client, lqi, servicetype, offset, maxhits, &error);
755                 ra = (AV *) sv_2mortal( (SV *) newAV() );
756                 if(error)
757                         RETVAL = &PL_sv_undef;
758                 else {
759                         for(i = 0; ret[i]; i++)
760                                 av_push(ra, newSVpv(ret[i], 0));
761                         RETVAL = newRV( (SV *) ra);
762                         g_strfreev(ret);        /* don't leak */
763                 }
764         OUTPUT:
765                 RETVAL
768 void
769 DESTROY (obj)
770                 SV* obj
771         PREINIT:
772                 I32* temp;
773         PPCODE:
774                 /* this is stolen from Inline::C documentation */
775                 temp = PL_markstack_ptr++;
776                 DESTROY(obj);
777                 if(PL_markstack_ptr != temp) {
778                         /* truly void, because dXSARGS not invoked */
779                         PL_markstack_ptr = temp;
780                         XSRETURN_EMPTY;
781                 }
782                 /* must have used dXSARGS; list context implied */
783                 return; /* assume stack size is correct */