2 * Copyright (c) 2010-2020 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.apache.commons.io.IOUtils;
23 import org.eclipse.jdt.annotation.NonNull;
24 import org.openhab.core.util.HexUtils;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
29 * Class to handle Onkyo Album Arts.
31 * @author Pauli Anttila - Initial contribution
32 * @author Stewart Cossey - fixed bug in getAlbumArt function
34 public class OnkyoAlbumArt {
36 private final Logger logger = LoggerFactory.getLogger(OnkyoAlbumArt.class);
46 private enum ImageType {
54 private StringBuilder albumArtStringBuilder = new StringBuilder();
55 private ImageType imageType = ImageType.UNKNOWN;
56 private State state = State.NOTSTARTED;
57 private String coverArtUrl;
59 public boolean isAlbumCoverTransferStarted() {
60 return state == State.STARTED;
63 public boolean isAlbumCoverReady() {
64 return state == State.READY;
67 public void clearAlbumArt() {
68 albumArtStringBuilder.setLength(0);
69 imageType = ImageType.UNKNOWN;
70 state = State.NOTSTARTED;
74 public void addFrame(String data) {
75 if (data.length() <= 2) {
79 char imgType = data.charAt(0);
80 imageType = getImageType(imgType);
82 char packetFlag = data.charAt(1);
83 String packetFlagStr = "unknown";
87 if (state == State.NOTSTARTED || state == State.INVALID) {
88 state = State.STARTED;
90 state = State.INVALID;
92 packetFlagStr = "Start";
93 albumArtStringBuilder.setLength(0);
96 packetFlagStr = "Next";
97 if (state == State.STARTED || state == State.NEXT) {
100 state = State.INVALID;
104 packetFlagStr = "End";
105 if (state == State.STARTED || state == State.NEXT) {
108 state = State.INVALID;
112 packetFlagStr = "notUsed";
116 state = State.INVALID;
117 logger.debug("Unknown album art packet flag '{}'", packetFlag);
120 if (state != State.INVALID) {
124 String picData = data.substring(2, data.length());
125 logger.debug("Received album art fragment in '{}' format, packet flag '{}', picData '{}'",
126 imageType, packetFlagStr, picData);
127 albumArtStringBuilder.append(picData);
130 coverArtUrl = data.substring(2);
131 logger.debug("Received album art url '{}'", coverArtUrl);
134 logger.debug("Received information: album art not available");
140 logger.debug("Received album art fragment in wrong order, format '{}', packet flag '{}'", imageType,
145 public byte[] getAlbumArt() throws IllegalArgumentException {
148 if (state == State.READY) {
152 data = HexUtils.hexToBytes(albumArtStringBuilder.toString());
155 data = downloadAlbumArt(coverArtUrl);
156 // Workaround firmware bug providing incorrect headers causing them to be seen as body instead.
158 int bodyLength = data.length;
159 int i = new String(data).indexOf("image/");
161 while (i < bodyLength && (data[i] != '\r' && data[i] != '\n')) {
164 while (i < bodyLength && (data[i] == '\r' || data[i] == '\n')) {
167 data = Arrays.copyOfRange(data, i, bodyLength);
168 logger.trace("Onkyo fixed picture data @ {}: {} ", i, new String(data));
178 throw new IllegalArgumentException("Illegal Album Art");
181 private byte[] downloadAlbumArt(String albumArtUrl) {
183 URL url = new URL(albumArtUrl);
184 URLConnection connection = url.openConnection();
185 InputStream inputStream = connection.getInputStream();
187 return IOUtils.toByteArray(inputStream);
189 IOUtils.closeQuietly(inputStream);
191 } catch (MalformedURLException e) {
192 logger.warn("Album Art download failed from url '{}', reason {}", albumArtUrl, e.getMessage());
193 } catch (IOException e) {
194 logger.warn("Album Art download failed from url '{}', reason {}", albumArtUrl, e.getMessage());
200 private ImageType getImageType(char imgType) {
201 ImageType it = ImageType.UNKNOWN;
216 it = ImageType.UNKNOWN;
222 public @NonNull String getAlbumArtMimeType() {
223 String mimeType = "";
226 mimeType = "image/bmp";
229 mimeType = "image/jpeg";