Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
scanner.c
Go to the documentation of this file.
1 /*
2  * scanner.c
3  * Copyright 2012 John Lindgren
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions, and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions, and the following disclaimer in the documentation
13  * provided with the distribution.
14  *
15  * This software is provided "as is" and without any warranty, express or
16  * implied. In no event shall the authors be liable for any damages arising from
17  * the use of this software.
18  */
19 
20 #include <glib.h>
21 #include <pthread.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include <libaudcore/audstrings.h>
26 
27 #include "main.h"
28 #include "misc.h"
29 #include "scanner.h"
30 
31 struct _ScanRequest {
32  char * filename; /* pooled */
33  int flags;
36  Tuple * tuple;
37  void * image_data;
38  int64_t image_len;
39  char * image_file;
40 };
41 
42 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
43 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
44 
45 static GQueue requests = G_QUEUE_INIT;
46 
47 static pthread_t scan_threads[SCAN_THREADS];
48 
50 
51 ScanRequest * scan_request (const char * filename, int flags,
52  PluginHandle * decoder, ScanCallback callback)
53 {
54  ScanRequest * request = g_slice_new0 (ScanRequest);
55 
56  request->filename = str_get (filename);
57  request->flags = flags;
58  request->decoder = decoder;
59  request->callback = callback;
60 
61  pthread_mutex_lock (& mutex);
62 
63  g_queue_push_tail (& requests, request);
64  pthread_cond_signal (& cond);
65 
66  pthread_mutex_unlock (& mutex);
67  return request;
68 }
69 
70 static void scan_request_free (ScanRequest * request)
71 {
72  if (request->tuple)
73  tuple_unref (request->tuple);
74 
75  str_unref (request->filename);
76  free (request->image_data);
77  free (request->image_file);
78  g_slice_free (ScanRequest, request);
79 }
80 
81 static void * scan_worker (void * unused)
82 {
83  pthread_mutex_lock (& mutex);
84 
85  while (! quit_flag)
86  {
87  ScanRequest * request = g_queue_pop_head (& requests);
88 
89  if (! request)
90  {
91  pthread_cond_wait (& cond, & mutex);
92  continue;
93  }
94 
95  pthread_mutex_unlock (& mutex);
96 
97  if (! request->decoder)
98  request->decoder = file_find_decoder (request->filename, FALSE);
99 
100  if (request->decoder && (request->flags & SCAN_TUPLE))
101  request->tuple = file_read_tuple (request->filename, request->decoder);
102 
103  if (request->decoder && (request->flags & SCAN_IMAGE))
104  {
105  file_read_image (request->filename, request->decoder,
106  & request->image_data, & request->image_len);
107 
108  if (! request->image_data)
109  request->image_file = get_associated_image_file (request->filename);
110  }
111 
112  request->callback (request);
113  scan_request_free (request);
114 
115  pthread_mutex_lock (& mutex);
116  }
117 
118  pthread_mutex_unlock (& mutex);
119  return NULL;
120 }
121 
122 const char * scan_request_get_filename (ScanRequest * request)
123 {
124  return request->filename;
125 }
126 
127 PluginHandle * scan_request_get_decoder (ScanRequest * request)
128 {
129  return request->decoder;
130 }
131 
132 Tuple * scan_request_get_tuple (ScanRequest * request)
133 {
134  Tuple * tuple = request->tuple;
135  request->tuple = NULL;
136  return tuple;
137 }
138 
139 void scan_request_get_image_data (ScanRequest * request, void * * data, int64_t * len)
140 {
141  * data = request->image_data;
142  * len = request->image_len;
143  request->image_data = NULL;
144  request->image_len = 0;
145 }
146 
147 char * scan_request_get_image_file (ScanRequest * request)
148 {
149  char * image_file = request->image_file;
150  request->image_file = NULL;
151  return image_file;
152 }
153 
154 void scanner_init (void)
155 {
156  for (int i = 0; i < SCAN_THREADS; i ++)
157  pthread_create (& scan_threads[i], 0, scan_worker, NULL);
158 }
159 
160 void scanner_cleanup (void)
161 {
162  pthread_mutex_lock (& mutex);
163 
164  quit_flag = TRUE;
165  pthread_cond_broadcast (& cond);
166 
167  pthread_mutex_unlock (& mutex);
168 
169  for (int i = 0; i < SCAN_THREADS; i ++)
170  pthread_join (scan_threads[i], NULL);
171 
172  ScanRequest * request;
173  while ((request = g_queue_pop_head (& requests)))
174  scan_request_free (request);
175 
176  quit_flag = FALSE;
177 }
file_read_tuple
Definition: misc-api.h:85
#define SCAN_IMAGE
Definition: scanner.h:27
const char filename
Definition: misc-api.h:85
static void scan_request_free(ScanRequest *request)
Definition: scanner.c:70
PluginHandle * file_find_decoder(const char *filename, bool_t fast)
Definition: probe.c:160
const char * scan_request_get_filename(ScanRequest *request)
Definition: scanner.c:122
bool_t file_read_image(const char *filename, PluginHandle *decoder, void **data, int64_t *size)
Definition: probe.c:214
void * image_data
Definition: scanner.c:37
PluginHandle * decoder
Definition: scanner.c:34
#define FALSE
Definition: core.h:35
Index Index bool_t
Definition: playlist-api.h:122
char * filename
Definition: scanner.c:32
void scanner_cleanup(void)
Definition: scanner.c:160
Tuple * scan_request_get_tuple(ScanRequest *request)
Definition: scanner.c:132
#define NULL
Definition: core.h:27
static void * scan_worker(void *unused)
Definition: scanner.c:81
ScanRequest * scan_request(const char *filename, int flags, PluginHandle *decoder, ScanCallback callback)
Definition: scanner.c:51
EXPORT void tuple_unref(Tuple *tuple)
Definition: tuple.c:284
void scan_request_get_image_data(ScanRequest *request, void **data, int64_t *len)
Definition: scanner.c:139
#define TRUE
Definition: core.h:37
#define SCAN_THREADS
Definition: scanner.h:29
static bool_t quit_flag
Definition: scanner.c:49
void str_unref(char *str)
Definition: strpool.c:89
void scanner_init(void)
Definition: scanner.c:154
static pthread_t scan_threads[SCAN_THREADS]
Definition: scanner.c:47
#define SCAN_TUPLE
Definition: scanner.h:26
char * scan_request_get_image_file(ScanRequest *request)
Definition: scanner.c:147
Tuple * tuple
Definition: scanner.c:36
ScanCallback callback
Definition: scanner.c:35
static pthread_mutex_t mutex
Definition: scanner.c:42
static GQueue requests
Definition: scanner.c:45
char * image_file
Definition: scanner.c:39
void(* ScanCallback)(ScanRequest *request)
Definition: scanner.h:34
char * str_get(const char *str)
Definition: strpool.c:42
PluginHandle * scan_request_get_decoder(ScanRequest *request)
Definition: scanner.c:127
int64_t image_len
Definition: scanner.c:38
char * get_associated_image_file(const char *filename)
Definition: ui_albumart.c:189
static pthread_cond_t cond
Definition: scanner.c:43
int flags
Definition: scanner.c:33