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
* This file is part of Audacious.
6
*
7
* Audacious is free software: you can redistribute it and/or modify it under
8
* the terms of the GNU General Public License as published by the Free Software
9
* Foundation, version 2 or version 3 of the License.
10
*
11
* Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
12
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License along with
16
* Audacious. If not, see <http://www.gnu.org/licenses/>.
17
*
18
* The Audacious team does not consider modular code linking to Audacious or
19
* using our public API to be a derived work.
20
*/
21
22
#include <errno.h>
23
#include <glib.h>
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include <unistd.h>
28
29
#include <
libaudcore/audstrings.h
>
30
#include <
libaudcore/hook.h
>
31
32
#include "
main.h
"
33
#include "
misc.h
"
34
#include "
playlist.h
"
35
#include "
util.h
"
36
37
typedef
struct
{
38
char
*
song_file
;
/* pooled */
39
int
refcount
;
40
41
/* album art as JPEG or PNG data */
42
void
*
data
;
43
int64_t
len
;
44
45
/* album art as (possibly a temporary) file */
46
char
*
art_file
;
47
bool_t
is_temp
;
48
}
ArtItem
;
49
50
static
GHashTable *
art_items
;
51
static
char
*
current_file
;
/* pooled */
52
53
static
void
art_item_free
(
ArtItem
* item)
54
{
55
/* delete temporary file */
56
if
(item->
art_file
&& item->
is_temp
)
57
{
58
char
* unixname =
uri_to_filename
(item->
art_file
);
59
if
(unixname)
60
{
61
unlink (unixname);
62
g_free (unixname);
63
}
64
}
65
66
str_unref
(item->
song_file
);
67
g_free (item->
data
);
68
g_free (item->
art_file
);
69
g_slice_free (
ArtItem
, item);
70
}
71
72
static
ArtItem
*
art_item_new
(
const
char
* file)
73
{
74
/* local files only */
75
if
(strncmp (file,
"file://"
, 7))
76
return
NULL
;
77
78
ArtItem
* item = g_slice_new0 (
ArtItem
);
79
item->
song_file
=
str_get
(file);
80
81
/* try to load embedded album art */
82
PluginHandle
*
decoder
=
file_find_decoder
(file,
FALSE
);
83
if
(decoder)
84
file_read_image
(file, decoder, & item->
data
, & item->
len
);
85
86
if
(item->
data
)
87
return
item;
88
89
/* try to find external image file */
90
char
* unixname =
get_associated_image_file
(file);
91
if
(unixname)
92
{
93
item->
art_file
=
filename_to_uri
(unixname);
94
g_free (unixname);
95
}
96
97
if
(item->
art_file
)
98
return
item;
99
100
/* failed */
101
art_item_free
(item);
102
return
NULL
;
103
}
104
105
static
ArtItem
*
art_item_get
(
const
char
* file)
106
{
107
if
(!
art_items
)
108
art_items
= g_hash_table_new_full (g_str_hash, g_str_equal,
109
NULL
, (GDestroyNotify)
art_item_free
);
110
111
ArtItem
* item = g_hash_table_lookup (
art_items
, file);
112
if
(item)
113
{
114
item->
refcount
++;
115
return
item;
116
}
117
118
item =
art_item_new
(file);
119
if
(! item)
120
return
NULL
;
121
122
g_hash_table_insert (
art_items
, item->
song_file
, item);
123
item->
refcount
= 1;
124
return
item;
125
}
126
127
static
void
art_item_unref
(
ArtItem
* item)
128
{
129
if
(! -- item->
refcount
)
130
{
131
/* keep album art for current entry */
132
if
(
current_file
&& ! strcmp (
current_file
, item->
song_file
))
133
return
;
134
135
g_hash_table_remove (
art_items
, item->
song_file
);
136
}
137
}
138
139
static
void
release_current
(
void
)
140
{
141
if
(!
art_items
|| !
current_file
)
142
return
;
143
144
/* free album art for previous entry */
145
ArtItem
* item = g_hash_table_lookup (
art_items
,
current_file
);
146
if
(item && ! item->
refcount
)
147
g_hash_table_remove (
art_items
,
current_file
);
148
}
149
150
static
void
position_hook
(
void
*
data
,
void
* user)
151
{
152
release_current
();
153
str_unref
(
current_file
);
154
155
int
list =
playlist_get_playing
();
156
int
entry
= (list >= 0) ?
playlist_get_position
(list) : -1;
157
current_file
= (entry >= 0) ?
playlist_entry_get_filename
(list, entry) :
NULL
;
158
}
159
160
void
art_init
(
void
)
161
{
162
hook_associate
(
"playlist position"
,
position_hook
,
NULL
);
163
hook_associate
(
"playlist set playing"
,
position_hook
,
NULL
);
164
}
165
166
void
art_cleanup
(
void
)
167
{
168
hook_dissociate
(
"playlist position"
,
position_hook
);
169
hook_dissociate
(
"playlist set playing"
,
position_hook
);
170
171
release_current
();
172
str_unref
(
current_file
);
173
current_file
=
NULL
;
174
175
if
(
art_items
&& g_hash_table_size (
art_items
))
176
{
177
fprintf (stderr,
"Album art not freed\n"
);
178
abort ();
179
}
180
181
if
(
art_items
)
182
{
183
g_hash_table_destroy (
art_items
);
184
art_items
=
NULL
;
185
}
186
}
187
188
void
art_get_data
(
const
char
* file,
const
void
* *
data
, int64_t * len)
189
{
190
* data =
NULL
;
191
* len = 0;
192
193
ArtItem
* item =
art_item_get
(file);
194
if
(! item)
195
return
;
196
197
/* load data from external image file */
198
if
(! item->
data
&& item->
art_file
)
199
vfs_file_get_contents
(item->
art_file
, & item->
data
, & item->
len
);
200
201
if
(! item->
data
)
202
{
203
art_item_unref
(item);
204
return
;
205
}
206
207
* data = item->
data
;
208
* len = item->
len
;
209
}
210
211
const
char
*
art_get_file
(
const
char
* file)
212
{
213
ArtItem
* item =
art_item_get
(file);
214
if
(! item)
215
return
NULL
;
216
217
/* save data to temporary file */
218
if
(item->
data
&& ! item->
art_file
)
219
{
220
char
* unixname =
write_temp_file
(item->
data
, item->
len
);
221
if
(unixname)
222
{
223
item->
art_file
=
filename_to_uri
(unixname);
224
item->
is_temp
=
TRUE
;
225
g_free (unixname);
226
}
227
}
228
229
if
(! item->
art_file
)
230
{
231
art_item_unref
(item);
232
return
NULL
;
233
}
234
235
return
item->
art_file
;
236
}
237
238
void
art_unref
(
const
char
* file)
239
{
240
ArtItem
* item =
art_items
? g_hash_table_lookup (
art_items
, file) :
NULL
;
241
if
(item)
242
art_item_unref
(item);
243
}
Generated by
1.8.1.1