mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-06-05 21:49:48 +02:00
added music info (controls WIP)
This commit is contained in:
@@ -61,6 +61,8 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
|
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes;
|
import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCallback;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCallback;
|
||||||
@@ -314,6 +316,20 @@ public class QHybridSupport extends QHybridBaseSupport {
|
|||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSetMusicInfo(MusicSpec musicSpec) {
|
||||||
|
super.onSetMusicInfo(musicSpec);
|
||||||
|
|
||||||
|
watchAdapter.setMusicInfo(musicSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSetMusicState(MusicStateSpec stateSpec) {
|
||||||
|
super.onSetMusicState(stateSpec);
|
||||||
|
|
||||||
|
watchAdapter.setMusicState(stateSpec);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFetchRecordedData(int dataTypes) {
|
public void onFetchRecordedData(int dataTypes) {
|
||||||
if ((dataTypes & RecordedDataTypes.TYPE_ACTIVITY) != 0) {
|
if ((dataTypes & RecordedDataTypes.TYPE_ACTIVITY) != 0) {
|
||||||
|
@@ -24,6 +24,8 @@ import java.util.ArrayList;
|
|||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationConfiguration;
|
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationConfiguration;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.PlayNotificationRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.PlayNotificationRequest;
|
||||||
|
|
||||||
@@ -97,4 +99,10 @@ public abstract class WatchAdapter {
|
|||||||
|
|
||||||
public void setCommuteMenuMessage(String message, boolean finished) {
|
public void setCommuteMenuMessage(String message, boolean finished) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMusicInfo(MusicSpec musicSpec) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMusicState(MusicStateSpec stateSpec) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,8 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.HRConfigActivity;
|
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.HRConfigActivity;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationHRConfiguration;
|
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationHRConfiguration;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
|
||||||
@@ -35,14 +37,20 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.Image;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.Image;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.ImagesPutRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.ImagesPutRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.menu.SetCommuteMenuMessage;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.menu.SetCommuteMenuMessage;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicControlRequest;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicInfoSetRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationFilterPutHRRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationFilterPutHRRequest;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationImagePutRequest;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationImagePutRequest;
|
||||||
|
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicControlRequest.*;
|
||||||
|
|
||||||
public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
||||||
private byte[] secretKey = new byte[]{(byte) 0x60, (byte) 0x26, (byte) 0xB7, (byte) 0xFD, (byte) 0xB2, (byte) 0x6D, (byte) 0x05, (byte) 0x5E, (byte) 0xDA, (byte) 0xF7, (byte) 0x4B, (byte) 0x49, (byte) 0x98, (byte) 0x78, (byte) 0x02, (byte) 0x38};
|
private byte[] secretKey = new byte[]{(byte) 0x60, (byte) 0x26, (byte) 0xB7, (byte) 0xFD, (byte) 0xB2, (byte) 0x6D, (byte) 0x05, (byte) 0x5E, (byte) 0xDA, (byte) 0xF7, (byte) 0x4B, (byte) 0x49, (byte) 0x98, (byte) 0x78, (byte) 0x02, (byte) 0x38};
|
||||||
private byte[] phoneRandomNumber;
|
private byte[] phoneRandomNumber;
|
||||||
private byte[] watchRandomNumber;
|
private byte[] watchRandomNumber;
|
||||||
|
|
||||||
|
MusicSpec currentSpec = null;
|
||||||
|
|
||||||
public FossilHRWatchAdapter(QHybridSupport deviceSupport) {
|
public FossilHRWatchAdapter(QHybridSupport deviceSupport) {
|
||||||
super(deviceSupport);
|
super(deviceSupport);
|
||||||
}
|
}
|
||||||
@@ -93,7 +101,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|||||||
|
|
||||||
setTime();
|
setTime();
|
||||||
|
|
||||||
overwriteButtons(null);
|
// overwriteButtons(null);
|
||||||
|
|
||||||
// negotiateSymmetricKey();
|
// negotiateSymmetricKey();
|
||||||
// queueWrite(
|
// queueWrite(
|
||||||
@@ -103,6 +111,13 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|||||||
// )
|
// )
|
||||||
// );
|
// );
|
||||||
|
|
||||||
|
queueWrite(new MusicInfoSetRequest(
|
||||||
|
"This is an artist",
|
||||||
|
"Some stupid album",
|
||||||
|
"What the Track!",
|
||||||
|
this
|
||||||
|
));
|
||||||
|
|
||||||
queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZED));
|
queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZED));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +146,33 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBackgroundImages(Image background, Image[] complications){
|
@Override
|
||||||
|
public void setMusicInfo(MusicSpec musicSpec) {
|
||||||
|
if (
|
||||||
|
currentSpec != null
|
||||||
|
&& currentSpec.album.equals(musicSpec.album)
|
||||||
|
&& currentSpec.artist.equals(musicSpec.artist)
|
||||||
|
&& currentSpec.track.equals(musicSpec.track)
|
||||||
|
) return;
|
||||||
|
currentSpec = musicSpec;
|
||||||
|
queueWrite(new MusicInfoSetRequest(
|
||||||
|
musicSpec.artist,
|
||||||
|
musicSpec.album,
|
||||||
|
musicSpec.track,
|
||||||
|
this
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMusicState(MusicStateSpec stateSpec) {
|
||||||
|
super.setMusicState(stateSpec);
|
||||||
|
|
||||||
|
queueWrite(new MusicControlRequest(
|
||||||
|
stateSpec.state == MusicStateSpec.STATE_PLAYING ? MUSIC_PHONE_REQUEST.MUSIC_REQUEST_SET_PLAYING : MUSIC_PHONE_REQUEST.MUSIC_REQUEST_SET_PAUSED
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBackgroundImages(Image background, Image[] complications) {
|
||||||
background.setAngle(0);
|
background.setAngle(0);
|
||||||
background.setDistance(0);
|
background.setDistance(0);
|
||||||
background.setIndexZ(0);
|
background.setIndexZ(0);
|
||||||
@@ -193,7 +234,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|||||||
GBApplication.getPrefs().getString(HRConfigActivity.CONFIG_KEY_Q_ACTIONS, "[]")
|
GBApplication.getPrefs().getString(HRConfigActivity.CONFIG_KEY_Q_ACTIONS, "[]")
|
||||||
);
|
);
|
||||||
String[] menuItems = new String[jsonArray.length()];
|
String[] menuItems = new String[jsonArray.length()];
|
||||||
for(int i = 0; i < jsonArray.length(); i++) menuItems[i] = jsonArray.getString(i);
|
for (int i = 0; i < jsonArray.length(); i++) menuItems[i] = jsonArray.getString(i);
|
||||||
|
|
||||||
queueWrite(new ButtonConfigurationPutRequest(
|
queueWrite(new ButtonConfigurationPutRequest(
|
||||||
menuItems,
|
menuItems,
|
||||||
@@ -210,6 +251,13 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|||||||
|
|
||||||
byte[] value = characteristic.getValue();
|
byte[] value = characteristic.getValue();
|
||||||
|
|
||||||
|
byte requestType = value[1];
|
||||||
|
|
||||||
|
if (requestType == (byte) 0x05) {
|
||||||
|
handleMusicRequest(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int eventId = value[2];
|
int eventId = value[2];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -221,7 +269,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|||||||
String startStop = requestJson.getJSONObject("req").getJSONObject("commuteApp._.config.commute_info")
|
String startStop = requestJson.getJSONObject("req").getJSONObject("commuteApp._.config.commute_info")
|
||||||
.getString("action");
|
.getString("action");
|
||||||
|
|
||||||
if(startStop.equals("stop")){
|
if (startStop.equals("stop")) {
|
||||||
// overwriteButtons(null);
|
// overwriteButtons(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -236,6 +284,29 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleMusicRequest(byte[] value) {
|
||||||
|
byte command = value[3];
|
||||||
|
|
||||||
|
MUSIC_WATCH_REQUEST request = MUSIC_WATCH_REQUEST.fromCommandByte(command);
|
||||||
|
|
||||||
|
MusicControlRequest r = new MusicControlRequest(MUSIC_PHONE_REQUEST.MUSIC_REQUEST_PLAY_PAUSE);
|
||||||
|
|
||||||
|
switch (request) {
|
||||||
|
case MUSIC_REQUEST_PLAY_PAUSE: {
|
||||||
|
queueWrite(new MusicControlRequest(MUSIC_PHONE_REQUEST.MUSIC_REQUEST_PLAY_PAUSE));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MUSIC_REQUEST_LOUDER: {
|
||||||
|
queueWrite(new MusicControlRequest(MUSIC_PHONE_REQUEST.MUSIC_REQUEST_LOUDER));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MUSIC_REQUEST_QUITER: {
|
||||||
|
queueWrite(new MusicControlRequest(MUSIC_PHONE_REQUEST.MUSIC_REQUEST_QUITER));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCommuteMenuMessage(String message, boolean finished) {
|
public void setCommuteMenuMessage(String message, boolean finished) {
|
||||||
queueWrite(new SetCommuteMenuMessage(message, finished, this));
|
queueWrite(new SetCommuteMenuMessage(message, finished, this));
|
||||||
|
@@ -0,0 +1,72 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FossilRequest;
|
||||||
|
|
||||||
|
public class MusicControlRequest extends FossilRequest {
|
||||||
|
private MUSIC_PHONE_REQUEST request;
|
||||||
|
|
||||||
|
public MusicControlRequest(MUSIC_PHONE_REQUEST request) {
|
||||||
|
this.request = request;
|
||||||
|
|
||||||
|
this.data = new byte[]{
|
||||||
|
(byte) 0x02,
|
||||||
|
(byte) 0x05,
|
||||||
|
this.request.getCommandByte(),
|
||||||
|
(byte) 0x00
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFinished() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getStartSequence() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getRequestUUID() {
|
||||||
|
return UUID.fromString("3dda0006-957f-7d4a-34a6-74696673696d");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum MUSIC_WATCH_REQUEST{
|
||||||
|
MUSIC_REQUEST_PLAY_PAUSE((byte) 0x02),
|
||||||
|
MUSIC_REQUEST_LOUDER((byte) 0x05),
|
||||||
|
MUSIC_REQUEST_QUITER((byte) 0x06),
|
||||||
|
;
|
||||||
|
private byte commandByte;
|
||||||
|
|
||||||
|
MUSIC_WATCH_REQUEST(byte commandByte) {
|
||||||
|
this.commandByte = commandByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MUSIC_WATCH_REQUEST fromCommandByte(byte commandByte){
|
||||||
|
for(MUSIC_WATCH_REQUEST request : MUSIC_WATCH_REQUEST.values()){
|
||||||
|
if(request.commandByte == commandByte) return request;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum MUSIC_PHONE_REQUEST{
|
||||||
|
MUSIC_REQUEST_SET_PLAYING((byte) 0x00),
|
||||||
|
MUSIC_REQUEST_SET_PAUSED((byte) 0x01),
|
||||||
|
MUSIC_REQUEST_PLAY_PAUSE((byte) 0x02),
|
||||||
|
MUSIC_REQUEST_LOUDER((byte) 0x05),
|
||||||
|
MUSIC_REQUEST_QUITER((byte) 0x06),
|
||||||
|
;
|
||||||
|
private byte commandByte;
|
||||||
|
|
||||||
|
public byte getCommandByte() {
|
||||||
|
return commandByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MUSIC_PHONE_REQUEST(byte commandByte) {
|
||||||
|
this.commandByte = commandByte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,41 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FilePutRequest;
|
||||||
|
|
||||||
|
public class MusicInfoSetRequest extends FilePutRequest {
|
||||||
|
public MusicInfoSetRequest(String artist, String album, String title, FossilWatchAdapter adapter) {
|
||||||
|
super((short) 0x0400, createFile(artist, album, title), adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] createFile(String artist, String album, String title){
|
||||||
|
int length = artist.length() + album.length() + title.length()
|
||||||
|
+ 3 // null terminators
|
||||||
|
+ 8; // length and header
|
||||||
|
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(length);
|
||||||
|
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
|
buffer.putShort((short) length);
|
||||||
|
buffer.put((byte) 0x01); // dunno
|
||||||
|
buffer.put((byte) (title.length() + 1));
|
||||||
|
buffer.put((byte) (artist.length() + 1));
|
||||||
|
buffer.put((byte) (album.length() + 1));
|
||||||
|
buffer.put((byte) 0x0C); // dunno
|
||||||
|
buffer.put((byte) 0x00); // dunno
|
||||||
|
|
||||||
|
buffer.put(title.getBytes())
|
||||||
|
.put((byte) 0x00); // null terminator
|
||||||
|
|
||||||
|
buffer.put(artist.getBytes())
|
||||||
|
.put((byte) 0x00); // null terminator
|
||||||
|
|
||||||
|
buffer.put(album.getBytes())
|
||||||
|
.put((byte) 0x00); // null terminator
|
||||||
|
|
||||||
|
return buffer.array();
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user