1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.providers.media.playlist;
18 
19 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
20 import static org.xmlpull.v1.XmlPullParser.START_TAG;
21 
22 import android.util.Xml;
23 
24 import androidx.annotation.NonNull;
25 
26 import org.xmlpull.v1.XmlPullParser;
27 import org.xmlpull.v1.XmlPullParserException;
28 import org.xmlpull.v1.XmlSerializer;
29 
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.OutputStream;
33 import java.nio.charset.StandardCharsets;
34 import java.nio.file.FileSystem;
35 import java.nio.file.FileSystems;
36 import java.nio.file.Path;
37 import java.util.List;
38 
39 public class XspfPlaylistPersister implements PlaylistPersister {
40     private static final String TAG_PLAYLIST = "playlist";
41     private static final String TAG_TRACK_LIST = "trackList";
42     private static final String TAG_TRACK = "track";
43     private static final String TAG_LOCATION = "location";
44 
45     @Override
read(@onNull InputStream in, @NonNull List<Path> items)46     public void read(@NonNull InputStream in, @NonNull List<Path> items) throws IOException {
47         final FileSystem fs = FileSystems.getDefault();
48         try {
49             final XmlPullParser parser = Xml.newPullParser();
50             parser.setInput(in, StandardCharsets.UTF_8.name());
51 
52             int type;
53             while ((type = parser.next()) != END_DOCUMENT) {
54                 if (type != START_TAG) continue;
55 
56                 if (TAG_LOCATION.equals(parser.getName())) {
57                     final String src = parser.nextText();
58                     if (src != null) {
59                         items.add(fs.getPath(src.replace('\\', '/')));
60                     }
61                 }
62             }
63         } catch (XmlPullParserException e) {
64             throw new IOException(e);
65         }
66     }
67 
68     @Override
write(@onNull OutputStream out, @NonNull List<Path> items)69     public void write(@NonNull OutputStream out, @NonNull List<Path> items) throws IOException {
70         final XmlSerializer doc = Xml.newSerializer();
71         doc.setOutput(out, StandardCharsets.UTF_8.name());
72         doc.startDocument(null, true);
73         doc.startTag(null, TAG_PLAYLIST);
74         doc.startTag(null, TAG_TRACK_LIST);
75         for (Path item : items) {
76             doc.startTag(null, TAG_TRACK);
77             doc.startTag(null, TAG_LOCATION);
78             doc.text(item.toString());
79             doc.endTag(null, TAG_LOCATION);
80             doc.endTag(null, TAG_TRACK);
81         }
82         doc.endTag(null, TAG_TRACK_LIST);
83         doc.endTag(null, TAG_PLAYLIST);
84         doc.endDocument();
85     }
86 }
87