diff --git a/app/android/app/src/main/java/com/thejeffcooper/hassmic/BackgroundTaskService.java b/app/android/app/src/main/java/com/thejeffcooper/hassmic/BackgroundTaskService.java index c5fa69a..e32b127 100644 --- a/app/android/app/src/main/java/com/thejeffcooper/hassmic/BackgroundTaskService.java +++ b/app/android/app/src/main/java/com/thejeffcooper/hassmic/BackgroundTaskService.java @@ -109,32 +109,61 @@ public void onEvents(Player p, Player.Events events) { // Loop over each media player event in this tick and fire it back // to JS + // + // We don't want to send duplicate messages, so keep track of + // the types we might need to deduplicate + boolean hasPlaybackStateChangedEvent = false; + boolean hasIsPlayingChangedEvent = false; + for (int i = 0; i < events.size(); i++) { + hasPlaybackStateChangedEvent |= + events.get(i) == Player.EVENT_PLAYBACK_STATE_CHANGED; + hasIsPlayingChangedEvent |= events.get(i) == Player.EVENT_IS_PLAYING_CHANGED; + } + for (int i = 0; i < events.size(); i++) { @Player.Event int e = events.get(i); ClientEvent.Builder protob = ClientEvent.newBuilder(); + // some common info + @Player.Event int playbackState = p.getPlaybackState(); + boolean isPlaying = p.isPlaying(); + + // Don't send duplicate messages: + // - If we have both IS_PLAYING_CHANGED and + // PLAYBACK_STATE_CHANGED events, ignore one or the + // other. + if (hasIsPlayingChangedEvent && hasPlaybackStateChangedEvent) { + if ((isPlaying && e == Player.EVENT_PLAYBACK_STATE_CHANGED) + || (!isPlaying && e == Player.EVENT_IS_PLAYING_CHANGED)) { + continue; + } + } + switch (e) { case Player.EVENT_PLAYBACK_STATE_CHANGED: + case Player.EVENT_IS_PLAYING_CHANGED: ClientEvent.MediaPlayerStateChange.Builder b = ClientEvent.MediaPlayerStateChange.newBuilder().setPlayer(which_player); - switch (p.getPlaybackState()) { - case Player.STATE_IDLE: - b.setNewState(MediaPlayerState.STATE_IDLE); - break; - case Player.STATE_BUFFERING: - b.setNewState(MediaPlayerState.STATE_BUFFERING); - break; - case Player.STATE_READY: - if (p.isPlaying()) { - b.setNewState(MediaPlayerState.STATE_PLAYING); - } else { - b.setNewState(MediaPlayerState.STATE_PAUSED); - } - break; - case Player.STATE_ENDED: - b.setNewState(MediaPlayerState.STATE_ENDED); - break; + + MediaPlayerState newState = null; + + if (playbackState == Player.STATE_READY) { + newState = + (isPlaying) + ? MediaPlayerState.STATE_PLAYING + : MediaPlayerState.STATE_PAUSED; + } else if (playbackState == Player.STATE_BUFFERING) { + newState = MediaPlayerState.STATE_BUFFERING; + } else if (playbackState == Player.STATE_IDLE + || playbackState == Player.STATE_ENDED) { + newState = MediaPlayerState.STATE_IDLE; + } else { + Log.w( + "HassmicBackgroundTaskService", + "Unhandled playback state: " + playbackState); } + + b.setNewState(newState); protob.setMediaPlayerStateChange(b.build()); break; } diff --git a/app/android/app/src/main/java/com/thejeffcooper/hassmic/proto/MediaPlayerState.java b/app/android/app/src/main/java/com/thejeffcooper/hassmic/proto/MediaPlayerState.java index 8435fcc..7ef4e6d 100644 --- a/app/android/app/src/main/java/com/thejeffcooper/hassmic/proto/MediaPlayerState.java +++ b/app/android/app/src/main/java/com/thejeffcooper/hassmic/proto/MediaPlayerState.java @@ -19,14 +19,10 @@ public enum MediaPlayerState implements com.google.protobuf.Internal.EnumLite { STATE_IDLE(1), /** STATE_BUFFERING = 2; */ STATE_BUFFERING(2), - /** STATE_READY = 3; */ - STATE_READY(3), - /** STATE_ENDED = 4; */ - STATE_ENDED(4), - /** STATE_PLAYING = 5; */ - STATE_PLAYING(5), - /** STATE_PAUSED = 6; */ - STATE_PAUSED(6), + /** STATE_PLAYING = 3; */ + STATE_PLAYING(3), + /** STATE_PAUSED = 4; */ + STATE_PAUSED(4), UNRECOGNIZED(-1), ; @@ -39,17 +35,11 @@ public enum MediaPlayerState implements com.google.protobuf.Internal.EnumLite { /** STATE_BUFFERING = 2; */ public static final int STATE_BUFFERING_VALUE = 2; - /** STATE_READY = 3; */ - public static final int STATE_READY_VALUE = 3; + /** STATE_PLAYING = 3; */ + public static final int STATE_PLAYING_VALUE = 3; - /** STATE_ENDED = 4; */ - public static final int STATE_ENDED_VALUE = 4; - - /** STATE_PLAYING = 5; */ - public static final int STATE_PLAYING_VALUE = 5; - - /** STATE_PAUSED = 6; */ - public static final int STATE_PAUSED_VALUE = 6; + /** STATE_PAUSED = 4; */ + public static final int STATE_PAUSED_VALUE = 4; @java.lang.Override public final int getNumber() { @@ -79,12 +69,8 @@ public static MediaPlayerState forNumber(int value) { case 2: return STATE_BUFFERING; case 3: - return STATE_READY; - case 4: - return STATE_ENDED; - case 5: return STATE_PLAYING; - case 6: + case 4: return STATE_PAUSED; default: return null; diff --git a/app/app/proto/hassmic.ts b/app/app/proto/hassmic.ts index 9856816..c89659a 100644 --- a/app/app/proto/hassmic.ts +++ b/app/app/proto/hassmic.ts @@ -219,21 +219,13 @@ export enum MediaPlayerState { */ STATE_BUFFERING = 2, /** - * @generated from protobuf enum value: STATE_READY = 3; + * @generated from protobuf enum value: STATE_PLAYING = 3; */ - STATE_READY = 3, + STATE_PLAYING = 3, /** - * @generated from protobuf enum value: STATE_ENDED = 4; + * @generated from protobuf enum value: STATE_PAUSED = 4; */ - STATE_ENDED = 4, - /** - * @generated from protobuf enum value: STATE_PLAYING = 5; - */ - STATE_PLAYING = 5, - /** - * @generated from protobuf enum value: STATE_PAUSED = 6; - */ - STATE_PAUSED = 6 + STATE_PAUSED = 4 } /** * The different media players available diff --git a/custom_components/hassmic/hassmic.py b/custom_components/hassmic/hassmic.py index aa00931..0cf28bd 100644 --- a/custom_components/hassmic/hassmic.py +++ b/custom_components/hassmic/hassmic.py @@ -145,7 +145,7 @@ def _handle_connection_state_change(self, new_state: bool): def _handle_client_event(self, event: ClientEvent): """Handle a state change from the connection manager.""" - _LOGGER.debug("Got connection change to state: %s", repr(event)) + _LOGGER.debug("Got client event: %s", repr(event)) for e in self._entities: hce = getattr(e, "handle_client_event", None) if hce is not None and callable(hce): @@ -175,7 +175,6 @@ async def handle_incoming_message(self, reader) -> ClientInfo: _LOGGER.debug("Got client info: %s", repr(val)) case "client_event": - _LOGGER.debug("Got client event: %s", repr(val)) self._handle_client_event(val) case "ping": diff --git a/custom_components/hassmic/media_player/player.py b/custom_components/hassmic/media_player/player.py index 2c088a3..b27e788 100644 --- a/custom_components/hassmic/media_player/player.py +++ b/custom_components/hassmic/media_player/player.py @@ -92,10 +92,8 @@ def handle_client_event(self, event: proto.ClientEvent): self._attr_state = MediaPlayerState.PLAYING case proto.MediaPlayerState.STATE_PAUSED: self._attr_state = MediaPlayerState.PAUSED - case proto.MediaPlayerState.STATE_ENDED | proto.MediaPlayerState.STATE_IDLE: + case proto.MediaPlayerState.STATE_IDLE: self._attr_state = MediaPlayerState.IDLE - case proto.MediaPlayerState.STATE_READY: - pass case _: _LOGGER.warning( "Got unhandled media player state %s", val.new_state diff --git a/custom_components/hassmic/proto/hassmic.py b/custom_components/hassmic/proto/hassmic.py index af0214c..87908e0 100644 --- a/custom_components/hassmic/proto/hassmic.py +++ b/custom_components/hassmic/proto/hassmic.py @@ -14,10 +14,8 @@ class MediaPlayerState(betterproto.Enum): STATE_UNKNOWN = 0 STATE_IDLE = 1 STATE_BUFFERING = 2 - STATE_READY = 3 - STATE_ENDED = 4 - STATE_PLAYING = 5 - STATE_PAUSED = 6 + STATE_PLAYING = 3 + STATE_PAUSED = 4 class MediaPlayerId(betterproto.Enum): diff --git a/proto/hassmic.proto b/proto/hassmic.proto index 5a29a95..d5417b7 100644 --- a/proto/hassmic.proto +++ b/proto/hassmic.proto @@ -26,10 +26,8 @@ enum MediaPlayerState { STATE_UNKNOWN = 0; STATE_IDLE = 1; STATE_BUFFERING = 2; - STATE_READY = 3; - STATE_ENDED = 4; - STATE_PLAYING = 5; - STATE_PAUSED = 6; + STATE_PLAYING = 3; + STATE_PAUSED = 4; } // The different media players available