diff --git a/src/main.py b/src/main.py index 68acaf6..ce16dd0 100644 --- a/src/main.py +++ b/src/main.py @@ -1299,7 +1299,11 @@ class SignagePlayer(Widget): Logger.debug(f"SignagePlayer: Skipping play_current_media - player is paused") return - if not self.playlist or self.current_index >= len(self.playlist): + if not self.playlist: + Logger.warning("SignagePlayer: Cannot play - playlist is empty") + return + + if self.current_index >= len(self.playlist): # End of playlist, restart self.restart_playlist() return @@ -2068,6 +2072,10 @@ class SignagePlayer(Widget): def restart_playlist(self): """Restart playlist from beginning""" + if not self.playlist: + Logger.warning("SignagePlayer: Cannot restart - playlist is empty") + return + Logger.info("SignagePlayer: Restarting playlist") # Send restart feedback asynchronously (non-blocking) diff --git a/src/signage_player.kv b/src/signage_player.kv index 2c410f5..2492c4b 100644 --- a/src/signage_player.kv +++ b/src/signage_player.kv @@ -352,303 +352,316 @@ # Settings popup content : title: 'Player Settings' - size_hint: 0.8, 0.8 + size_hint: 0.9, 0.85 auto_dismiss: True BoxLayout: orientation: 'vertical' - padding: dp(20) - spacing: dp(15) + padding: [dp(15), dp(10)] + spacing: dp(8) - # Server configuration - BoxLayout: - orientation: 'horizontal' - size_hint_y: None - height: dp(40) - spacing: dp(10) - - Label: - text: 'Server IP:' - size_hint_x: 0.3 - text_size: self.size - halign: 'left' - valign: 'middle' + ScrollView: + BoxLayout: + orientation: 'vertical' + spacing: dp(8) + size_hint_y: None + height: self.minimum_height - TextInput: - id: server_input - size_hint_x: 0.7 - multiline: False - font_size: sp(14) - write_tab: False - on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None - - # Server port - BoxLayout: - orientation: 'horizontal' - size_hint_y: None - height: dp(40) - spacing: dp(10) - - Label: - text: 'Port:' - size_hint_x: 0.3 - text_size: self.size - halign: 'left' - valign: 'middle' + # Server configuration + BoxLayout: + orientation: 'horizontal' + size_hint_y: None + height: dp(36) + spacing: dp(8) + + Label: + text: 'Server IP:' + size_hint_x: 0.3 + text_size: self.size + halign: 'left' + valign: 'middle' + + TextInput: + id: server_input + size_hint_x: 0.7 + multiline: False + font_size: sp(13) + write_tab: False + on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None - TextInput: - id: port_input - size_hint_x: 0.7 - multiline: False - font_size: sp(14) - hint_text: '80 or 8080 (leave empty for default)' - input_filter: 'int' - write_tab: False - on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None - - # Screen name - BoxLayout: - orientation: 'horizontal' - size_hint_y: None - height: dp(40) - spacing: dp(10) - - Label: - text: 'Screen Name:' - size_hint_x: 0.3 - text_size: self.size - halign: 'left' - valign: 'middle' + # Server port + BoxLayout: + orientation: 'horizontal' + size_hint_y: None + height: dp(36) + spacing: dp(8) + + Label: + text: 'Port:' + size_hint_x: 0.3 + text_size: self.size + halign: 'left' + valign: 'middle' + + TextInput: + id: port_input + size_hint_x: 0.7 + multiline: False + font_size: sp(13) + hint_text: '80 or 8080 (leave empty for default)' + input_filter: 'int' + write_tab: False + on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None - TextInput: - id: screen_input - size_hint_x: 0.7 - multiline: False - font_size: sp(14) - write_tab: False - on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None - - # Quickconnect key - BoxLayout: - orientation: 'horizontal' - size_hint_y: None - height: dp(40) - spacing: dp(10) - - Label: - text: 'Quickconnect:' - size_hint_x: 0.3 - text_size: self.size - halign: 'left' - valign: 'middle' + # Screen name + BoxLayout: + orientation: 'horizontal' + size_hint_y: None + height: dp(36) + spacing: dp(8) + + Label: + text: 'Screen Name:' + size_hint_x: 0.3 + text_size: self.size + halign: 'left' + valign: 'middle' + + TextInput: + id: screen_input + size_hint_x: 0.7 + multiline: False + font_size: sp(13) + write_tab: False + on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None - TextInput: - id: quickconnect_input - size_hint_x: 0.7 - multiline: False - font_size: sp(14) - write_tab: False - on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None - - # Orientation - BoxLayout: - orientation: 'horizontal' - size_hint_y: None - height: dp(40) - spacing: dp(10) - - Label: - text: 'Orientation:' - size_hint_x: 0.3 - text_size: self.size - halign: 'left' - valign: 'middle' + # Quickconnect key + BoxLayout: + orientation: 'horizontal' + size_hint_y: None + height: dp(36) + spacing: dp(8) + + Label: + text: 'Quickconnect:' + size_hint_x: 0.3 + text_size: self.size + halign: 'left' + valign: 'middle' + + TextInput: + id: quickconnect_input + size_hint_x: 0.7 + multiline: False + font_size: sp(13) + write_tab: False + on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None - TextInput: - id: orientation_input - size_hint_x: 0.7 - multiline: False - font_size: sp(14) - write_tab: False - on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None - - # Touch - BoxLayout: - orientation: 'horizontal' - size_hint_y: None - height: dp(40) - spacing: dp(10) - - Label: - text: 'Touch:' - size_hint_x: 0.3 - text_size: self.size - halign: 'left' - valign: 'middle' + # Orientation + BoxLayout: + orientation: 'horizontal' + size_hint_y: None + height: dp(36) + spacing: dp(8) + + Label: + text: 'Orientation:' + size_hint_x: 0.3 + text_size: self.size + halign: 'left' + valign: 'middle' + + TextInput: + id: orientation_input + size_hint_x: 0.7 + multiline: False + font_size: sp(13) + write_tab: False + on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None - TextInput: - id: touch_input - size_hint_x: 0.7 - multiline: False - font_size: sp(14) - write_tab: False - on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None - - # Resolution - BoxLayout: - orientation: 'horizontal' - size_hint_y: None - height: dp(40) - spacing: dp(10) - - Label: - text: 'Max Resolution:' - size_hint_x: 0.3 - text_size: self.size - halign: 'left' - valign: 'middle' + # Touch + BoxLayout: + orientation: 'horizontal' + size_hint_y: None + height: dp(36) + spacing: dp(8) + + Label: + text: 'Touch:' + size_hint_x: 0.3 + text_size: self.size + halign: 'left' + valign: 'middle' + + TextInput: + id: touch_input + size_hint_x: 0.7 + multiline: False + font_size: sp(13) + write_tab: False + on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None - TextInput: - id: resolution_input - size_hint_x: 0.7 - multiline: False - font_size: sp(14) - hint_text: '1920x1080 or auto' - write_tab: False - on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None - - # Edit Feature Enable/Disable - BoxLayout: - orientation: 'horizontal' - size_hint_y: None - height: dp(40) - spacing: dp(10) - - Label: - text: 'Enable Edit Feature:' - size_hint_x: 0.3 - text_size: self.size - halign: 'left' - valign: 'middle' + # Resolution + BoxLayout: + orientation: 'horizontal' + size_hint_y: None + height: dp(36) + spacing: dp(8) + + Label: + text: 'Max Resolution:' + size_hint_x: 0.3 + text_size: self.size + halign: 'left' + valign: 'middle' + + TextInput: + id: resolution_input + size_hint_x: 0.7 + multiline: False + font_size: sp(13) + hint_text: '1920x1080 or auto' + write_tab: False + on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None - CheckBox: - id: edit_enabled_checkbox - size_hint_x: None - width: dp(40) - active: True - on_active: root.on_edit_feature_toggle(self.active) - - Label: - text: '(Allow editing images on this player)' - size_hint_x: 0.4 - font_size: sp(12) - text_size: self.size - halign: 'left' - valign: 'middle' - color: 0.7, 0.7, 0.7, 1 + # Edit Feature Enable/Disable + BoxLayout: + orientation: 'horizontal' + size_hint_y: None + height: dp(36) + spacing: dp(8) + + Label: + text: 'Enable Edit:' + size_hint_x: 0.3 + text_size: self.size + halign: 'left' + valign: 'middle' + + CheckBox: + id: edit_enabled_checkbox + size_hint_x: None + width: dp(36) + active: True + on_active: root.on_edit_feature_toggle(self.active) + + Label: + text: '(Allow editing images)' + size_hint_x: 0.4 + font_size: sp(11) + text_size: self.size + halign: 'left' + valign: 'middle' + color: 0.7, 0.7, 0.7, 1 + + # Separator + Widget: + size_hint_y: None + height: dp(5) + + # Reset Buttons Section + Label: + text: 'Reset Options:' + size_hint_y: None + height: dp(26) + text_size: self.size + halign: 'left' + valign: 'middle' + bold: True + font_size: sp(14) + + # Reset Buttons Row + BoxLayout: + orientation: 'horizontal' + size_hint_y: None + height: dp(44) + spacing: dp(8) + + Button: + id: reset_auth_btn + text: 'Reset Player Auth' + background_color: 0.8, 0.4, 0.2, 1 + font_size: sp(12) + on_press: root.reset_player_auth() + + Button: + id: reset_playlist_btn + text: 'Reset Playlist to v0' + background_color: 0.8, 0.4, 0.2, 1 + font_size: sp(12) + on_press: root.reset_playlist_version() + + Button: + id: restart_player_btn + text: 'Restart Player' + background_color: 0.2, 0.6, 0.8, 1 + font_size: sp(12) + on_press: root.restart_player() + + # Test Connection Button + Button: + id: test_connection_btn + text: 'Test Server Connection' + size_hint_y: None + height: dp(44) + background_color: 0.2, 0.4, 0.8, 1 + font_size: sp(13) + on_press: root.test_connection() + + # Connection Status Label + Label: + id: connection_status + text: 'Click button to test connection' + size_hint_y: None + height: dp(32) + text_size: self.size + halign: 'center' + valign: 'middle' + font_size: sp(11) + color: 0.7, 0.7, 0.7, 1 + + # Separator + Widget: + size_hint_y: None + height: dp(5) + + # Status information row + BoxLayout: + orientation: 'horizontal' + size_hint_y: None + height: dp(26) + spacing: dp(8) + + Label: + id: playlist_info + text: 'Playlist: N/A' + text_size: self.size + halign: 'center' + valign: 'middle' + font_size: sp(11) + + Label: + id: media_count_info + text: 'Media: 0' + text_size: self.size + halign: 'center' + valign: 'middle' + font_size: sp(11) + + Label: + id: status_info + text: 'Status: Idle' + text_size: self.size + halign: 'center' + valign: 'middle' + font_size: sp(11) - Widget: - size_hint_y: 0.05 - - # Reset Buttons Section - Label: - text: 'Reset Options:' - size_hint_y: None - height: dp(30) - text_size: self.size - halign: 'left' - valign: 'middle' - bold: True - font_size: sp(16) - - # Reset Buttons Row + # Action buttons (always visible, outside scroll) BoxLayout: orientation: 'horizontal' size_hint_y: None - height: dp(50) - spacing: dp(10) - - Button: - id: reset_auth_btn - text: 'Reset Player Auth' - background_color: 0.8, 0.4, 0.2, 1 - on_press: root.reset_player_auth() - - Button: - id: reset_playlist_btn - text: 'Reset Playlist to v0' - background_color: 0.8, 0.4, 0.2, 1 - on_press: root.reset_playlist_version() - - Button: - id: restart_player_btn - text: 'Restart Player' - background_color: 0.2, 0.6, 0.8, 1 - on_press: root.restart_player() - - # Test Connection Button - Button: - id: test_connection_btn - text: 'Test Server Connection' - size_hint_y: None - height: dp(50) - background_color: 0.2, 0.4, 0.8, 1 - on_press: root.test_connection() - - # Connection Status Label - Label: - id: connection_status - text: 'Click button to test connection' - size_hint_y: None - height: dp(40) - text_size: self.size - halign: 'center' - valign: 'middle' - color: 0.7, 0.7, 0.7, 1 - - Widget: - size_hint_y: 0.05 - - # Status information row - BoxLayout: - orientation: 'horizontal' - size_hint_y: None - height: dp(30) - spacing: dp(10) - - Label: - id: playlist_info - text: 'Playlist: N/A' - text_size: self.size - halign: 'center' - valign: 'middle' - font_size: sp(12) - - Label: - id: media_count_info - text: 'Media: 0' - text_size: self.size - halign: 'center' - valign: 'middle' - font_size: sp(12) - - Label: - id: status_info - text: 'Status: Idle' - text_size: self.size - halign: 'center' - valign: 'middle' - font_size: sp(12) - - Widget: - size_hint_y: 0.05 - - # Action buttons - BoxLayout: - orientation: 'horizontal' - size_hint_y: None - height: dp(50) - spacing: dp(20) + height: dp(44) + spacing: dp(15) Button: text: 'Save & Close'