Project

General

Profile

m3u.diff

m3u.cc diff - Jim Turner, March 07, 2019 03:51

View differences:

m3u.cc 2019-03-06 21:35:06.823531414 -0600
18 18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 19
 */
20 20

  
21
#include <stdlib.h>
21 22
#include <string.h>
22 23

  
24
#include <libaudcore/preferences.h>
23 25
#include <libaudcore/audstrings.h>
24 26
#include <libaudcore/i18n.h>
25 27
#include <libaudcore/plugin.h>
28
#include <libaudcore/runtime.h>
26 29

  
27 30
static const char * const m3u_exts[] = {"m3u", "m3u8"};
28 31

  
29 32
class M3ULoader : public PlaylistPlugin
30 33
{
31 34
public:
32
    static constexpr PluginInfo info = {N_("M3U Playlists"), PACKAGE};
35
    static const PreferencesWidget widgets[];
36
    static const PluginPreferences prefs;
37
    static constexpr PluginInfo info = {
38
        N_("M3U Playlists"),
39
        PACKAGE,
40
        nullptr,
41
        & prefs
42
    };
33 43

  
34 44
    constexpr M3ULoader () : PlaylistPlugin (info, m3u_exts, true) {}
35 45

  
......
37 47
     Index<PlaylistAddItem> & items);
38 48
    bool save (const char * filename, VFSFile & file, const char * title,
39 49
     const Index<PlaylistAddItem> & items);
50

  
51
private:
52
    bool Extended_m3u = false;
53
    Tuple tuple;
40 54
};
41 55

  
42 56
EXPORT M3ULoader aud_plugin_instance;
......
58 72
bool M3ULoader::load (const char * filename, VFSFile & file, String & title,
59 73
 Index<PlaylistAddItem> & items)
60 74
{
75
    Extended_m3u = false;
76
    tuple = Tuple ();
77

  
61 78
    Index<char> text = file.read_all ();
62 79
    if (! text.len ())
63 80
        return false;
......
68 85
    if (! strncmp (parse, "\xef\xbb\xbf", 3)) /* byte order mark */
69 86
        parse += 3;
70 87

  
88
    bool firstline = true;
71 89
    while (parse)
72 90
    {
73 91
        char * next = split_line (parse);
......
75 93
        while (* parse == ' ' || * parse == '\t')
76 94
            parse ++;
77 95

  
78
        if (* parse && * parse != '#')
96
        if (* parse)
79 97
        {
80
            StringBuf s = uri_construct (parse, filename);
81
            if (s)
82
                items.append (String (s));
98
            if (* parse != '#')
99
            {
100
                String s = String (uri_construct (parse, filename));
101

  
102
                if (s && s[0])
103
                {
104
                    if (! strncmp (s, "file://", 7) && strstr (parse, "cue?"))  // CUESHEET:
105
                        s = String (str_decode_percent (s));  // UNESCAPE THE "?" ESCAPED BY uri_construct ().
106

  
107
                    if (Extended_m3u)
108
                    {
109
                        tuple.set_filename (s);
110
                        items.append (String (s), std::move (tuple));  // NOTE:NEVER SET TUPLE VALID (FORCE RESCAN)!
111
                    }
112
                    else
113
                        items.append (String (s));
114
                }
115
            }
116
            else if (Extended_m3u && ! strncmp (parse, "#EXTINF", 7))  // WE'RE A TITLE LINE (EXTENDED M3U):
117
            {
118
                tuple = Tuple ();
119
                parse += 7;
120
                if (parse < next && * parse == ':')
121
                {
122
                    ++parse;
123
                    while (parse < next && * parse == ' ')
124
                        ++parse;
125

  
126
                    if (* parse && parse < next)
127
                    {
128
                        Index<String> headerparts = str_list_to_index (parse, ",");
129
                        if (headerparts.len () > 1)
130
                        {
131
                            int tlen = atoi (headerparts[0]) * 1000;
132
                            if (tlen <= 0)
133
                                tuple.unset (Tuple::Length);
134
                            else
135
                                tuple.set_int (Tuple::Length, tlen);
136

  
137
                            // FIND THE TITLE AND MOVEPAST ANY LEADING SPACES IN IT:
138
                            char * c = parse;
139
                            while (c < next && * c != ',')
140
                                ++c;
141
                            if (c < next && * c)
142
                                ++c;
143
                            while (c < next && * c == ' ')
144
                                ++c;
145
                            if (* c)
146
                                tuple.set_str (Tuple::Title, c);
147
                        }
148
                        else if (headerparts.len () > 0)
149
                        {
150
                            tuple.unset (Tuple::Length);
151
                            tuple.set_str (Tuple::Title, headerparts[0]);
152
                        }
153
                    }
154
                }
155
            }
156
            else if (firstline && ! strncmp (parse, "#EXTM3U", 7))  // WE'RE AN EXTENDED M3U:
157
                Extended_m3u = true;
83 158
        }
84 159

  
160
        firstline = false;
85 161
        parse = next;
86 162
    }
87 163

  
......
91 167
bool M3ULoader::save (const char * filename, VFSFile & file, const char * title,
92 168
 const Index<PlaylistAddItem> & items)
93 169
{
170
    Extended_m3u = aud_get_bool ("m3u", "saveas_extended_m3u");
171
    if (Extended_m3u && file.fwrite (str_copy("#EXTM3U\n"), 1, 8) != 8)
172
        return false;
173

  
94 174
    for (auto & item : items)
95 175
    {
96 176
        StringBuf path = uri_deconstruct (item.filename, filename);
177
        if (Extended_m3u && item.tuple.state () == Tuple::Valid)
178
        {
179
            int tuplen = item.tuple.get_int (Tuple::Length);
180
            if (tuplen >= 0)
181
                tuplen /= 1000;
182
            String tupstr = item.tuple.get_str (Tuple::Title);
183
            if (!tupstr)
184
                tupstr = String (filename_get_base (item.filename));
185
            StringBuf line = str_printf ("#EXTINF:%d, %s\n", tuplen, (const char *) tupstr);
186
            if (file.fwrite (line, 1, line.len ()) != line.len ())
187
                return false;
188
        }
97 189
        StringBuf line = str_concat ({path, "\n"});
98 190
        if (file.fwrite (line, 1, line.len ()) != line.len ())
99 191
            return false;
......
101 193

  
102 194
    return true;
103 195
}
196

  
197
const PreferencesWidget M3ULoader::widgets[] = {
198
    WidgetLabel(N_("<b>M3U Configuration</b>")),
199
    WidgetCheck(N_("Save in Extended M3U format?"), WidgetBool("m3u", "saveas_extended_m3u")),
200
};
201

  
202
const PluginPreferences M3ULoader::prefs = {{widgets}};