Audacious
$Id:Doxyfile42802007-03-2104:39:00Znenolod$
Main Page
Related Pages
Classes
Files
File List
File Members
src
audacious
art.c
Go to the documentation of this file.
1
/*
2
* art.c
3
* Copyright 2011 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 <errno.h>
21
#include <glib.h>
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include <unistd.h>
26
27
#include <
libaudcore/audstrings.h
>
28
#include <
libaudcore/hook.h
>
29
30
#include "
main.h
"
31
#include "
misc.h
"
32
#include "
playlist.h
"
33
#include "
util.h
"
34
35
typedef
struct
{
36
char
*
song_file
;
/* pooled */
37
int
refcount
;
38
39
/* album art as JPEG or PNG data */
40
void
*
data
;
41
int64_t
len
;
42
43
/* album art as (possibly a temporary) file */
44
char
*
art_file
;
45
bool_t
is_temp
;
46
}
ArtItem
;
47
48
static
GHashTable *
art_items
;
49
static
char
*
current_file
;
/* pooled */
50
51
static
void
art_item_free
(
ArtItem
* item)
52
{
53
/* delete temporary file */
54
if
(item->
art_file
&& item->
is_temp
)
55
{
56
char
* unixname =
uri_to_filename
(item->
art_file
);
57
if
(unixname)
58
{
59
unlink (unixname);
60
g_free (unixname);
61
}
62
}
63
64
str_unref
(item->
song_file
);
65
g_free (item->
data
);
66
g_free (item->
art_file
);
67
g_slice_free (
ArtItem
, item);
68
}
69
70
static
ArtItem
*
art_item_new
(
const
char
* file)
71
{
72
/* local files only */
73
if
(strncmp (file,
"file://"
, 7))
74
return
NULL
;
75
76
ArtItem
* item = g_slice_new0 (
ArtItem
);
77
item->
song_file
=
str_get
(file);
78
79
/* try to load embedded album art */
80
PluginHandle
* decoder =
file_find_decoder
(file,
FALSE
);
81
if
(decoder)
82
file_read_image
(file, decoder, & item->
data
, & item->
len
);
83
84
if
(item->
data
)
85
return
item;
86
87
/* try to find external image file */
88
char
* unixname =
get_associated_image_file
(file);
89
if
(unixname)
90
{
91
item->
art_file
=
filename_to_uri
(unixname);
92
g_free (unixname);
93
}
94
95
if
(item->
art_file
)
96
return
item;
97
98
/* failed */
99
art_item_free
(item);
100
return
NULL
;
101
}
102
103
static
ArtItem
*
art_item_get
(
const
char
* file)
104
{
105
if
(!
art_items
)
106
art_items
= g_hash_table_new_full (g_str_hash, g_str_equal,
107
NULL
, (GDestroyNotify)
art_item_free
);
108
109
ArtItem
* item = g_hash_table_lookup (
art_items
, file);
110
if
(item)
111
{
112
item->
refcount
++;
113
return
item;
114
}
115
116
item =
art_item_new
(file);
117
if
(! item)
118
return
NULL
;
119
120
g_hash_table_insert (
art_items
, item->
song_file
, item);
121
item->
refcount
= 1;
122
return
item;
123
}
124
125
static
void
art_item_unref
(
ArtItem
* item)
126
{
127
if
(! -- item->
refcount
)
128
{
129
/* keep album art for current entry */
130
if
(
current_file
&& ! strcmp (
current_file
, item->
song_file
))
131
return
;
132
133
g_hash_table_remove (
art_items
, item->
song_file
);
134
}
135
}
136
137
static
void
release_current
(
void
)
138
{
139
if
(!
art_items
|| !
current_file
)
140
return
;
141
142
/* free album art for previous entry */
143
ArtItem
* item = g_hash_table_lookup (
art_items
,
current_file
);
144
if
(item && ! item->
refcount
)
145
g_hash_table_remove (
art_items
,
current_file
);
146
}
147
148
static
void
position_hook
(
void
* data,
void
* user)
149
{
150
release_current
();
151
str_unref
(
current_file
);
152
153
int
list =
playlist_get_playing
();
154
int
entry
= (list >= 0) ?
playlist_get_position
(list) : -1;
155
current_file
= (entry >= 0) ?
playlist_entry_get_filename
(list, entry) :
NULL
;
156
}
157
158
void
art_init
(
void
)
159
{
160
hook_associate
(
"playlist position"
,
position_hook
,
NULL
);
161
hook_associate
(
"playlist set playing"
,
position_hook
,
NULL
);
162
}
163
164
void
art_cleanup
(
void
)
165
{
166
hook_dissociate
(
"playlist position"
,
position_hook
);
167
hook_dissociate
(
"playlist set playing"
,
position_hook
);
168
169
release_current
();
170
str_unref
(
current_file
);
171
current_file
=
NULL
;
172
173
if
(
art_items
&& g_hash_table_size (
art_items
))
174
{
175
fprintf (stderr,
"Album art not freed\n"
);
176
abort ();
177
}
178
179
if
(
art_items
)
180
{
181
g_hash_table_destroy (
art_items
);
182
art_items
=
NULL
;
183
}
184
}
185
186
void
art_get_data
(
const
char
* file,
const
void
* * data, int64_t * len)
187
{
188
* data =
NULL
;
189
* len = 0;
190
191
ArtItem
* item =
art_item_get
(file);
192
if
(! item)
193
return
;
194
195
/* load data from external image file */
196
if
(! item->
data
&& item->
art_file
)
197
vfs_file_get_contents
(item->
art_file
, & item->
data
, & item->
len
);
198
199
if
(! item->
data
)
200
{
201
art_item_unref
(item);
202
return
;
203
}
204
205
* data = item->
data
;
206
* len = item->
len
;
207
}
208
209
const
char
*
art_get_file
(
const
char
* file)
210
{
211
ArtItem
* item =
art_item_get
(file);
212
if
(! item)
213
return
NULL
;
214
215
/* save data to temporary file */
216
if
(item->
data
&& ! item->
art_file
)
217
{
218
char
* unixname =
write_temp_file
(item->
data
, item->
len
);
219
if
(unixname)
220
{
221
item->
art_file
=
filename_to_uri
(unixname);
222
item->
is_temp
=
TRUE
;
223
g_free (unixname);
224
}
225
}
226
227
if
(! item->
art_file
)
228
{
229
art_item_unref
(item);
230
return
NULL
;
231
}
232
233
return
item->
art_file
;
234
}
235
236
void
art_unref
(
const
char
* file)
237
{
238
ArtItem
* item =
art_items
? g_hash_table_lookup (
art_items
, file) :
NULL
;
239
if
(item)
240
art_item_unref
(item);
241
}
Generated by
1.8.1.2