2 * Copyright (C) 2003-2009 The Music Player Daemon Project
3 * http://www.musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "directory.h"
24 #include "decoder_list.h"
25 #include "decoder_plugin.h"
33 #include <sys/types.h>
39 song_alloc(const char *url
, struct directory
*parent
)
47 song
= g_malloc(sizeof(*song
) - sizeof(song
->url
) + urllen
+ 1);
50 memcpy(song
->url
, url
, urllen
+ 1);
51 song
->parent
= parent
;
58 song_remote_new(const char *url
)
60 return song_alloc(url
, NULL
);
64 song_file_new(const char *path
, struct directory
*parent
)
66 assert((parent
== NULL
) == (*path
== '/'));
68 return song_alloc(path
, parent
);
72 song_file_load(const char *path
, struct directory
*parent
)
77 assert((parent
== NULL
) == (*path
== '/'));
78 assert(!uri_has_scheme(path
));
79 assert(strchr(path
, '\n') == NULL
);
81 song
= song_file_new(path
, parent
);
84 if (parent
!= NULL
&& parent
->device
== DEVICE_INARCHIVE
) {
85 ret
= song_file_update_inarchive(song
);
87 ret
= song_file_update(song
);
98 song_free(struct song
*song
)
106 * Attempts to load APE or ID3 tags from the specified file.
109 tag_load_fallback(const char *path
)
111 struct tag
*tag
= tag_ape_load(path
);
113 tag
= tag_id3_load(path
);
118 * The decoder plugin failed to load any tags: fall back to the APE or
122 tag_fallback(const char *path
, struct tag
*tag
)
124 struct tag
*fallback
= tag_load_fallback(path
);
126 if (fallback
!= NULL
) {
127 /* tag was successfully loaded: copy the song
128 duration, and destroy the old (empty) tag */
129 fallback
->time
= tag
->time
;
133 /* no APE/ID3 tag found: return the empty tag */
138 song_file_update(struct song
*song
)
142 const struct decoder_plugin
*plugin
;
145 assert(song_is_file(song
));
147 /* check if there's a suffix and a plugin */
149 suffix
= uri_get_suffix(song
->url
);
153 plugin
= decoder_plugin_from_suffix(suffix
, false);
157 path_fs
= map_song_fs(song
);
161 if (song
->tag
!= NULL
) {
166 if (stat(path_fs
, &st
) < 0 || !S_ISREG(st
.st_mode
)) {
171 song
->mtime
= st
.st_mtime
;
174 song
->tag
= plugin
->tag_dup(path_fs
);
175 if (song
->tag
!= NULL
)
178 plugin
= decoder_plugin_from_suffix(suffix
, true);
179 } while (plugin
!= NULL
);
181 if (song
->tag
!= NULL
&& tag_is_empty(song
->tag
))
182 song
->tag
= tag_fallback(path_fs
, song
->tag
);
185 return song
->tag
!= NULL
;
189 song_file_update_inarchive(struct song
*song
)
192 const struct decoder_plugin
*plugin
;
194 assert(song_is_file(song
));
196 /* check if there's a suffix and a plugin */
198 suffix
= uri_get_suffix(song
->url
);
202 plugin
= decoder_plugin_from_suffix(suffix
, false);
206 if (song
->tag
!= NULL
)
209 //accept every file that has music suffix
210 //because we dont support tag reading throught
212 song
->tag
= tag_new();
218 song_get_uri(const struct song
*song
)
220 assert(song
!= NULL
);
223 if (!song_in_database(song
) || directory_is_root(song
->parent
))
224 return g_strdup(song
->url
);
226 return g_strconcat(directory_get_path(song
->parent
),
227 "/", song
->url
, NULL
);