2 * Copyright (c) 2006-2011 Ed Schouten <ed@80386.nl>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * @file vfs_playlist.c
28 * @brief M3U and PLS playlist file access.
34 #include "vfs_modules.h"
37 * @brief Open a VFS entry by relative Win32 pathname and add it to the
38 * tail of the current entry.
41 vfs_playlist_add_tail(struct vfsent
*ve
, char *fn
, char *title
, char *dirname
)
45 #if G_DIR_SEPARATOR != '\\'
46 /* Convert to proper separator */
47 g_strdelimit(fn
, "\\", G_DIR_SEPARATOR
);
49 nvr
= vfs_lookup(fn
, title
, dirname
, 0);
52 vfs_list_insert_tail(&ve
->population
, nvr
);
60 vfs_pls_match(struct vfsent
*ve
, int isdir
)
62 /* In order to speed up the process, we only match *.pls */
63 if (isdir
|| !g_str_has_suffix(ve
->name
, ".pls"))
71 vfs_pls_populate(struct vfsent
*ve
)
83 if ((fio
= fopen(ve
->filename
, "r")) == NULL
)
85 dn
= g_path_get_dirname(ve
->filename
);
87 while (vfs_fgets(fbuf
, sizeof fbuf
, fio
) == 0) {
88 if (strncmp(fbuf
, "File", 4) == 0) {
92 } else if (strncmp(fbuf
, "Title", 5) == 0) {
100 /* Parse the index number */
101 if ((nidx
= atoi(fbuf
+ idxoff
)) == 0)
104 /* See if we have a value */
105 ch
= strchr(fbuf
+ idxoff
, '=');
106 if ((ch
== NULL
) || (ch
[1] == '\0'))
110 /* We've arrived at the next entry */
112 vfs_playlist_add_tail(ve
, fn
, title
, dn
);
114 g_free(fn
); fn
= NULL
;
115 g_free(title
); title
= NULL
;
119 /* Copy the new value */
121 *out
= g_strdup(ch
+ 1);
124 /* Don't forget our trailing entry */
126 vfs_playlist_add_tail(ve
, fn
, title
, dn
);
138 vfs_pls_write(const struct vfslist
*vl
, const char *filename
)
140 const char *base
= NULL
;
144 unsigned int idx
= 1;
146 fio
= fopen(filename
, "w");
150 /* Directory name length of .pls filename */
151 base
= strrchr(filename
, G_DIR_SEPARATOR
);
152 g_assert(base
!= NULL
);
153 cmplen
= base
- filename
+ 1;
155 fprintf(fio
, "[playlist]\nNumberOfEntries=%u\n",
157 VFS_LIST_FOREACH(vl
, vr
) {
158 /* Skip directory name when relative is possible */
159 base
= vfs_filename(vr
);
160 if (strncmp(filename
, base
, cmplen
) == 0)
163 fprintf(fio
, "File%u=%s\nTitle%u=%s\n",
178 vfs_m3u_match(struct vfsent
*ve
, int isdir
)
180 /* In order to speed up the process, we only match *.m3u */
181 if (isdir
|| !g_str_has_suffix(ve
->name
, ".m3u"))
189 vfs_m3u_populate(struct vfsent
*ve
)
196 if ((fio
= fopen(ve
->filename
, "r")) == NULL
)
198 dn
= g_path_get_dirname(ve
->filename
);
200 while (vfs_fgets(fbuf
, sizeof fbuf
, fio
) == 0) {
201 if (fbuf
[0] == '#') {
202 /* Only EXTINF is supported */
203 if (strncmp(fbuf
, "#EXTINF:", 8) == 0) {
204 /* Consolidate double lines */
205 g_free(title
); title
= NULL
;
207 /* Remove the duration in seconds */
208 if (((ch
= strchr(fbuf
+ 8, ',')) != NULL
)
210 title
= g_strdup(ch
+ 1);
212 } else if (fbuf
[0] != '\0') {
213 vfs_playlist_add_tail(ve
, fbuf
, title
, dn
);
214 g_free(title
); title
= NULL
;
218 /* Trailing EXTINF */
228 vfs_m3u_write(const struct vfslist
*vl
, const char *filename
)
230 const char *base
= NULL
;
235 fio
= fopen(filename
, "w");
239 /* Directory name length of .meu filename */
240 base
= strrchr(filename
, G_DIR_SEPARATOR
);
241 g_assert(base
!= NULL
);
242 cmplen
= base
- filename
+ 1;
244 fprintf(fio
, "#EXTM3U\n");
245 VFS_LIST_FOREACH(vl
, vr
) {
246 /* Skip directory name when relative is possible */
247 base
= vfs_filename(vr
);
248 if (strncmp(filename
, base
, cmplen
) == 0)
251 fprintf(fio
, "#EXTINF:-1,%s\n%s\n", vfs_name(vr
), base
);