|
| 1 | +package com.doublesymmetry.trackplayer.model |
| 2 | + |
| 3 | +import android.os.Bundle |
| 4 | +import com.google.android.exoplayer2.MediaMetadata |
| 5 | +import com.google.android.exoplayer2.metadata.Metadata |
| 6 | +import com.google.android.exoplayer2.metadata.flac.VorbisComment |
| 7 | +import com.google.android.exoplayer2.metadata.icy.IcyHeaders |
| 8 | +import com.google.android.exoplayer2.metadata.icy.IcyInfo |
| 9 | +import com.google.android.exoplayer2.metadata.id3.ChapterFrame |
| 10 | +import com.google.android.exoplayer2.metadata.id3.TextInformationFrame |
| 11 | +import com.google.android.exoplayer2.metadata.id3.UrlLinkFrame |
| 12 | +import com.google.android.exoplayer2.metadata.mp4.MdtaMetadataEntry |
| 13 | +import timber.log.Timber |
| 14 | + |
| 15 | +sealed class MetadataAdapter { |
| 16 | + companion object { |
| 17 | + fun fromMetadata(metadata: Metadata): List<Bundle> { |
| 18 | + val group = mutableListOf<Bundle>() |
| 19 | + |
| 20 | + (0 until metadata.length()).forEach { i -> |
| 21 | + group.add(Bundle().apply { |
| 22 | + val rawEntries = mutableListOf<Bundle>() |
| 23 | + |
| 24 | + when (val entry = metadata[i]) { |
| 25 | + is ChapterFrame -> { |
| 26 | + Timber.d("ChapterFrame: ${entry.id}") |
| 27 | + } |
| 28 | + is TextInformationFrame -> { |
| 29 | + val rawEntry = Bundle() |
| 30 | + |
| 31 | + when (entry.id.uppercase()) { |
| 32 | + "TIT2", "TT2" -> { |
| 33 | + putString("title", entry.value) |
| 34 | + rawEntry.putString("commonKey", "title") |
| 35 | + } |
| 36 | + "TALB", "TOAL", "TAL" -> { |
| 37 | + putString("albumName", entry.value) |
| 38 | + rawEntry.putString("commonKey", "albumName") |
| 39 | + } |
| 40 | + "TOPE", "TPE1", "TP1" -> { |
| 41 | + putString("artist", entry.value) |
| 42 | + rawEntry.putString("commonKey", "artist") |
| 43 | + } |
| 44 | + "TDRC", "TOR" -> { |
| 45 | + putString("creationDate", entry.value) |
| 46 | + rawEntry.putString("commonKey", "creationDate") |
| 47 | + } |
| 48 | + "TCON", "TCO" -> { |
| 49 | + putString("genre", entry.value) |
| 50 | + rawEntry.putString("commonKey", "genre") |
| 51 | + } |
| 52 | + } |
| 53 | + |
| 54 | + rawEntry.putString("key", entry.id.uppercase()) |
| 55 | + rawEntry.putString("keySpace", "org.id3") |
| 56 | + rawEntry.putString("value", entry.value) |
| 57 | + rawEntry.putString("time", "-1") |
| 58 | + rawEntries.add(rawEntry) |
| 59 | + } |
| 60 | + |
| 61 | + is UrlLinkFrame -> { |
| 62 | + rawEntries.add(Bundle().apply { |
| 63 | + putString("value", entry.url) |
| 64 | + putString("key", entry.id.uppercase()) |
| 65 | + putString("keySpace", "org.id3") |
| 66 | + putString("time", "-1") |
| 67 | + }) |
| 68 | + } |
| 69 | + |
| 70 | + is IcyHeaders -> { |
| 71 | + putString("title", entry.name) |
| 72 | + putString("genre", entry.genre) |
| 73 | + |
| 74 | + rawEntries.add(Bundle().apply { |
| 75 | + putString("value", entry.name) |
| 76 | + putString("commonKey", "title") |
| 77 | + putString("key", "StreamTitle") |
| 78 | + putString("keySpace", "icy") |
| 79 | + putString("time", "-1") |
| 80 | + }) |
| 81 | + |
| 82 | + rawEntries.add(Bundle().apply { |
| 83 | + putString("value", entry.url) |
| 84 | + putString("key", "StreamURL") |
| 85 | + putString("keySpace", "icy") |
| 86 | + putString("time", "-1") |
| 87 | + }) |
| 88 | + |
| 89 | + rawEntries.add(Bundle().apply { |
| 90 | + putString("value", entry.genre) |
| 91 | + putString("commonKey", "genre") |
| 92 | + putString("key", "StreamGenre") |
| 93 | + putString("keySpace", "icy") |
| 94 | + putString("time", "-1") |
| 95 | + }) |
| 96 | + } |
| 97 | + |
| 98 | + is IcyInfo -> { |
| 99 | + putString("title", entry.title) |
| 100 | + |
| 101 | + rawEntries.add(Bundle().apply { |
| 102 | + putString("value", entry.url) |
| 103 | + putString("key", "StreamURL") |
| 104 | + putString("keySpace", "icy") |
| 105 | + putString("time", "-1") |
| 106 | + }) |
| 107 | + |
| 108 | + rawEntries.add(Bundle().apply { |
| 109 | + putString("value", entry.title) |
| 110 | + putString("commonKey", "title") |
| 111 | + putString("key", "StreamTitle") |
| 112 | + putString("keySpace", "icy") |
| 113 | + putString("time", "-1") |
| 114 | + }) |
| 115 | + } |
| 116 | + |
| 117 | + is VorbisComment -> { |
| 118 | + val rawEntry = Bundle() |
| 119 | + |
| 120 | + when (entry.key) { |
| 121 | + "TITLE" -> { |
| 122 | + putString("title", entry.value) |
| 123 | + rawEntry.putString("commonKey", "title") |
| 124 | + } |
| 125 | + "ARTIST" -> { |
| 126 | + putString("artist", entry.value) |
| 127 | + rawEntry.putString("commonKey", "artist") |
| 128 | + } |
| 129 | + "ALBUM" -> { |
| 130 | + putString("albumName", entry.value) |
| 131 | + rawEntry.putString("commonKey", "albumName") |
| 132 | + } |
| 133 | + "DATE" -> { |
| 134 | + putString("creationDate", entry.value) |
| 135 | + rawEntry.putString("commonKey", "creationDate") |
| 136 | + } |
| 137 | + "GENRE" -> { |
| 138 | + putString("genre", entry.value) |
| 139 | + rawEntry.putString("commonKey", "genre") |
| 140 | + } |
| 141 | + "URL" -> { |
| 142 | + putString("url", entry.value) |
| 143 | + } |
| 144 | + } |
| 145 | + |
| 146 | + rawEntry.putString("key", entry.key) |
| 147 | + rawEntry.putString("keySpace", "org.vorbis") |
| 148 | + rawEntry.putString("value", entry.value) |
| 149 | + rawEntry.putString("time", "-1") |
| 150 | + rawEntries.add(rawEntry) |
| 151 | + } |
| 152 | + |
| 153 | + is MdtaMetadataEntry -> { |
| 154 | + val rawEntry = Bundle() |
| 155 | + when (entry.key) { |
| 156 | + "com.apple.quicktime.title" -> { |
| 157 | + putString("title", entry.value.toString()) |
| 158 | + rawEntry.putString("commonKey", "title") |
| 159 | + } |
| 160 | + "com.apple.quicktime.artist" -> { |
| 161 | + putString("artist", entry.value.toString()) |
| 162 | + rawEntry.putString("commonKey", "artist") |
| 163 | + } |
| 164 | + "com.apple.quicktime.album" -> { |
| 165 | + putString("albumName", entry.value.toString()) |
| 166 | + rawEntry.putString("commonKey", "albumName") |
| 167 | + } |
| 168 | + "com.apple.quicktime.creationdate" -> { |
| 169 | + putString("creationDate", entry.value.toString()) |
| 170 | + rawEntry.putString("commonKey", "creationDate") |
| 171 | + } |
| 172 | + "com.apple.quicktime.genre" -> { |
| 173 | + putString("genre", entry.value.toString()) |
| 174 | + rawEntry.putString("commonKey", "genre") |
| 175 | + } |
| 176 | + } |
| 177 | + |
| 178 | + rawEntry.putString("key", entry.key.substringAfterLast(".")) |
| 179 | + rawEntry.putString("keySpace", "com.apple.quicktime") |
| 180 | + rawEntry.putString("value", entry.value.toString()) |
| 181 | + rawEntry.putString("time", "-1") |
| 182 | + rawEntries.add(rawEntry) |
| 183 | + } |
| 184 | + } |
| 185 | + |
| 186 | + putParcelableArray("raw", rawEntries.toTypedArray()) |
| 187 | + }) |
| 188 | + } |
| 189 | + |
| 190 | + return group |
| 191 | + } |
| 192 | + |
| 193 | + fun fromMediaMetadata(metadata: MediaMetadata): Bundle { |
| 194 | + return Bundle().apply { |
| 195 | + metadata.title?.let { putString("title", it.toString()) } |
| 196 | + metadata.artist?.let { putString("artist", it.toString()) } |
| 197 | + metadata.albumTitle?.let { putString("albumName", it.toString()) } |
| 198 | + metadata.subtitle?.let { putString("subtitle", it.toString()) } |
| 199 | + metadata.description?.let { putString("description", it.toString()) } |
| 200 | + metadata.artworkUri?.let { putString("artworkUri", it.toString()) } |
| 201 | + metadata.trackNumber?.let { putInt("trackNumber", it) } |
| 202 | + metadata.composer?.let { putString("composer", it.toString()) } |
| 203 | + metadata.conductor?.let { putString("conductor", it.toString()) } |
| 204 | + metadata.genre?.let { putString("genre", it.toString()) } |
| 205 | + metadata.compilation?.let { putString("compilation", it.toString()) } |
| 206 | + metadata.station?.let { putString("station", it.toString()) } |
| 207 | + metadata.mediaType?.let { putInt("mediaType", it) } |
| 208 | + |
| 209 | + // This is how SwiftAudioEx outputs it in the metadata dictionary |
| 210 | + (metadata.recordingDay to metadata.recordingMonth).let { (day, month) -> |
| 211 | + // if both are not null, combine them into a single string |
| 212 | + if (day != null && month != null) { |
| 213 | + putString("creationDate", "${String.format("%02d", day)}${String.format("%02d", month)}") |
| 214 | + } else if (day != null) { |
| 215 | + putString("creationDate", String.format("%02d", day)) |
| 216 | + } else if (month != null) { |
| 217 | + putString("creationDate", String.format("%02d", month)) |
| 218 | + } |
| 219 | + } |
| 220 | + metadata.recordingYear?.let { putString("creationYear", it.toString()) } |
| 221 | + } |
| 222 | + } |
| 223 | + } |
| 224 | +} |
0 commit comments