2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.sonos.internal.handler;
15 import java.util.ArrayList;
16 import java.util.List;
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.openhab.binding.sonos.internal.SonosMetaData;
21 import org.openhab.binding.sonos.internal.SonosXMLParser;
24 * The {@link SonosMediaInformation} is responsible for extracting media information from XML metadata
26 * @author Laurent Garnier - Initial contribution
29 public class SonosMediaInformation {
31 private @Nullable String artist;
32 private @Nullable String album;
33 private @Nullable String title;
34 private @Nullable String combinedInfo;
35 private boolean needsUpdate;
37 public SonosMediaInformation() {
41 public SonosMediaInformation(boolean needsUpdate) {
42 this(null, null, null, null, needsUpdate);
45 public SonosMediaInformation(@Nullable String artist, @Nullable String album, @Nullable String title,
46 @Nullable String combinedInfo, boolean needsUpdate) {
50 this.combinedInfo = combinedInfo;
51 this.needsUpdate = needsUpdate;
54 public @Nullable String getArtist() {
58 public @Nullable String getAlbum() {
62 public @Nullable String getTitle() {
66 public @Nullable String getCombinedInfo() {
70 public boolean needsUpdate() {
74 public static SonosMediaInformation parseTuneInMediaInfo(@Nullable String opmlData, @Nullable String radioTitle,
75 @Nullable SonosMetaData trackMetaData) {
77 String combinedInfo = null;
78 if (opmlData != null) {
79 List<String> fields = SonosXMLParser.getRadioTimeFromXML(opmlData);
80 if (!fields.isEmpty()) {
81 title = fields.get(0);
82 combinedInfo = String.join(" - ", fields);
83 return new SonosMediaInformation(null, null, title, combinedInfo, true);
86 if (radioTitle != null && !radioTitle.isEmpty()) {
89 if (trackMetaData != null && !trackMetaData.getStreamContent().isEmpty()) {
90 combinedInfo += " - " + trackMetaData.getStreamContent();
92 return new SonosMediaInformation(null, null, title, combinedInfo, true);
94 return new SonosMediaInformation(false);
97 public static SonosMediaInformation parseRadioAppMediaInfo(@Nullable String radioTitle,
98 @Nullable SonosMetaData trackMetaData) {
99 if (radioTitle != null && !radioTitle.isEmpty()) {
100 String artist = null;
102 String title = radioTitle;
103 String combinedInfo = title;
104 if (trackMetaData != null) {
105 String[] contents = trackMetaData.getStreamContent().split("\\|");
106 String contentTitle = null;
107 for (int i = 0; i < contents.length; i++) {
108 if (contents[i].startsWith("TITLE ")) {
109 contentTitle = contents[i].substring(6).trim();
111 if (contents[i].startsWith("ARTIST ")) {
112 artist = contents[i].substring(7).trim();
114 if (contents[i].startsWith("ALBUM ")) {
115 album = contents[i].substring(6).trim();
118 if ((artist == null || artist.isEmpty()) && contentTitle != null && !contentTitle.isEmpty()
119 && !contentTitle.startsWith("Advertisement_")) {
120 // Try to extract artist and song title from contentTitle
121 int idx = contentTitle.indexOf(" - ");
123 artist = contentTitle.substring(0, idx);
124 title = contentTitle.substring(idx + 3);
126 } else if (artist != null && !artist.isEmpty() && album != null && !album.isEmpty()
127 && contentTitle != null && !contentTitle.isEmpty()) {
128 title = contentTitle;
130 if (artist != null && !artist.isEmpty()) {
131 combinedInfo += " - " + artist;
133 if (album != null && !album.isEmpty()) {
134 combinedInfo += " - " + album;
136 if (!radioTitle.equals(title)) {
137 combinedInfo += " - " + title;
138 } else if (contentTitle != null && !contentTitle.isEmpty()
139 && !contentTitle.startsWith("Advertisement_")) {
140 combinedInfo += " - " + contentTitle;
143 return new SonosMediaInformation(artist, album, title, combinedInfo, true);
145 return new SonosMediaInformation(false);
148 public static SonosMediaInformation parseTrack(@Nullable SonosMetaData trackMetaData) {
149 if (trackMetaData != null) {
150 List<String> infos = new ArrayList<>();
151 String artist = !trackMetaData.getAlbumArtist().isEmpty() ? trackMetaData.getAlbumArtist()
152 : trackMetaData.getCreator();
153 if (!artist.isEmpty()) {
156 String album = trackMetaData.getAlbum();
157 if (!album.isEmpty()) {
160 String title = trackMetaData.getTitle();
161 if (!title.isEmpty()) {
164 return new SonosMediaInformation(artist, album, title, String.join(" - ", infos), true);
166 return new SonosMediaInformation(false);
169 public static SonosMediaInformation parseTrackTitle(@Nullable SonosMetaData trackMetaData) {
170 if (trackMetaData != null) {
171 String title = trackMetaData.getTitle();
172 return new SonosMediaInformation(null, null, title, title, true);
174 return new SonosMediaInformation(false);