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.onkyo.internal;
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.net.MalformedURLException;
19 import java.net.URLConnection;
20 import java.util.Arrays;
22 import org.eclipse.jdt.annotation.NonNull;
23 import org.openhab.core.util.HexUtils;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * Class to handle Onkyo Album Arts.
30 * @author Pauli Anttila - Initial contribution
31 * @author Stewart Cossey - fixed bug in getAlbumArt function
33 public class OnkyoAlbumArt {
35 private final Logger logger = LoggerFactory.getLogger(OnkyoAlbumArt.class);
45 private enum ImageType {
53 private StringBuilder albumArtStringBuilder = new StringBuilder();
54 private ImageType imageType = ImageType.UNKNOWN;
55 private State state = State.NOTSTARTED;
56 private String coverArtUrl;
58 public boolean isAlbumCoverTransferStarted() {
59 return state == State.STARTED;
62 public boolean isAlbumCoverReady() {
63 return state == State.READY;
66 public void clearAlbumArt() {
67 albumArtStringBuilder.setLength(0);
68 imageType = ImageType.UNKNOWN;
69 state = State.NOTSTARTED;
73 public void addFrame(String data) {
74 if (data.length() <= 2) {
78 char imgType = data.charAt(0);
79 imageType = getImageType(imgType);
81 char packetFlag = data.charAt(1);
82 String packetFlagStr = "unknown";
86 if (state == State.NOTSTARTED || state == State.INVALID) {
87 state = State.STARTED;
89 state = State.INVALID;
91 packetFlagStr = "Start";
92 albumArtStringBuilder.setLength(0);
95 packetFlagStr = "Next";
96 if (state == State.STARTED || state == State.NEXT) {
99 state = State.INVALID;
103 packetFlagStr = "End";
104 if (state == State.STARTED || state == State.NEXT) {
107 state = State.INVALID;
111 packetFlagStr = "notUsed";
115 state = State.INVALID;
116 logger.debug("Unknown album art packet flag '{}'", packetFlag);
119 if (state != State.INVALID) {
123 String picData = data.substring(2, data.length());
124 logger.debug("Received album art fragment in '{}' format, packet flag '{}', picData '{}'",
125 imageType, packetFlagStr, picData);
126 albumArtStringBuilder.append(picData);
129 coverArtUrl = data.substring(2);
130 logger.debug("Received album art url '{}'", coverArtUrl);
133 logger.debug("Received information: album art not available");
139 logger.debug("Received album art fragment in wrong order, format '{}', packet flag '{}'", imageType,
144 public byte[] getAlbumArt() throws IllegalArgumentException {
147 if (state == State.READY) {
151 data = HexUtils.hexToBytes(albumArtStringBuilder.toString());
154 data = downloadAlbumArt(coverArtUrl);
155 // Workaround firmware bug providing incorrect headers causing them to be seen as body instead.
157 int bodyLength = data.length;
158 int i = new String(data).indexOf("image/");
160 while (i < bodyLength && (data[i] != '\r' && data[i] != '\n')) {
163 while (i < bodyLength && (data[i] == '\r' || data[i] == '\n')) {
166 data = Arrays.copyOfRange(data, i, bodyLength);
167 logger.trace("Onkyo fixed picture data @ {}: {} ", i, new String(data));
177 throw new IllegalArgumentException("Illegal Album Art");
180 private byte[] downloadAlbumArt(String albumArtUrl) {
182 URL url = new URL(albumArtUrl);
183 URLConnection connection = url.openConnection();
184 try (InputStream inputStream = connection.getInputStream()) {
185 return inputStream.readAllBytes();
187 } catch (MalformedURLException e) {
188 logger.warn("Album Art download failed from url '{}', reason {}", albumArtUrl, e.getMessage());
189 } catch (IOException e) {
190 logger.warn("Album Art download failed from url '{}', reason {}", albumArtUrl, e.getMessage());
196 private ImageType getImageType(char imgType) {
197 ImageType it = ImageType.UNKNOWN;
212 it = ImageType.UNKNOWN;
218 public @NonNull String getAlbumArtMimeType() {
219 String mimeType = "";
222 mimeType = "image/bmp";
225 mimeType = "image/jpeg";