commit 48f1dc2a7780c531319279d9bc1d9481c08d855c Author: ske087 Date: Wed Mar 19 16:52:03 2025 +0200 main data diff --git a/README.md b/README.md new file mode 100644 index 0000000..f6631de --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# Kivy Media Player + +This project is a media player application built using Kivy. It allows users to play video files, display images, and manage settings for quick connect codes and server configurations. The application checks for updates to the playlist every five minutes while running in full screen. + +## Project Structure + +``` +kivy-media-player +├── src +│ ├── main.py # Entry point of the Kivy application +│ ├── settings.py # Manages the settings page +│ ├── media_player.py # Handles media playback +│ ├── utils.py # Utility functions for downloading files and updating playlists +│ ├── kv +│ │ ├── main.kv # Layout for the main application window +│ │ ├── settings.kv # Layout for the settings page +│ │ └── media_player.kv # Layout for the media player screen +│ └── assets +│ ├── images # Directory for image files +│ └── videos # Directory for video files +├── requirements.txt # Project dependencies +└── README.md # Documentation for the project +``` + +## Setup Instructions + +1. Clone the repository: + ``` + git clone + cd kivy-media-player + ``` + +2. Install the required dependencies: + ``` + pip install -r requirements.txt + ``` + +3. Run the application: + ``` + python src/main.py + ``` + +## Usage Guidelines + +- Upon launching the application, users can navigate to the settings page to enter their quick connect code and server IP/domain. +- The media player screen allows users to view images and play videos from the playlist. +- The application automatically checks for updates to the playlist every five minutes. + +## Contributing + +Contributions are welcome! Please feel free to submit a pull request or open an issue for any suggestions or improvements. + +## License + +This project is licensed under the MIT License. See the LICENSE file for more details. \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..123b3c6 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +kivy +requests +watchdog +Pillow \ No newline at end of file diff --git a/src/__pycache__/media_player.cpython-311.pyc b/src/__pycache__/media_player.cpython-311.pyc new file mode 100644 index 0000000..852ca68 Binary files /dev/null and b/src/__pycache__/media_player.cpython-311.pyc differ diff --git a/src/__pycache__/settings.cpython-311.pyc b/src/__pycache__/settings.cpython-311.pyc new file mode 100644 index 0000000..d5243d0 Binary files /dev/null and b/src/__pycache__/settings.cpython-311.pyc differ diff --git a/src/assets/images b/src/assets/images new file mode 100644 index 0000000..aa46a7c --- /dev/null +++ b/src/assets/images @@ -0,0 +1 @@ +This file is intentionally left blank. \ No newline at end of file diff --git a/src/assets/videos b/src/assets/videos new file mode 100644 index 0000000..c4d457e --- /dev/null +++ b/src/assets/videos @@ -0,0 +1 @@ +# This directory is intended to contain video files for the media player application. \ No newline at end of file diff --git a/src/instance/dashboard.db b/src/instance/dashboard.db new file mode 100644 index 0000000..c7310f7 Binary files /dev/null and b/src/instance/dashboard.db differ diff --git a/src/kv/main.kv b/src/kv/main.kv new file mode 100644 index 0000000..cfd6a60 --- /dev/null +++ b/src/kv/main.kv @@ -0,0 +1,45 @@ + + +: + MainScreen: + SettingsScreen: + +: + name: 'main' + BoxLayout: + orientation: 'vertical' + Label: + text: 'Welcome to the Media Player' + font_size: 32 + size_hint_y: None + height: 50 + Button: + text: 'Go to Settings' + on_press: root.manager.current = 'settings' + Button: + text: 'Play Media' + on_press: app.play_media() + +: + name: 'settings' + BoxLayout: + orientation: 'vertical' + Label: + text: 'Settings' + font_size: 32 + size_hint_y: None + height: 50 + TextInput: + id: quick_connect_code + hint_text: 'Enter Quick Connect Code' + multiline: False + TextInput: + id: server_ip + hint_text: 'Enter Server IP or Domain' + multiline: False + Button: + text: 'Save Settings' + on_press: app.save_settings(quick_connect_code.text, server_ip.text) + Button: + text: 'Back to Main' + on_press: root.manager.current = 'main' \ No newline at end of file diff --git a/src/kv/media_player.kv b/src/kv/media_player.kv new file mode 100644 index 0000000..ce28080 --- /dev/null +++ b/src/kv/media_player.kv @@ -0,0 +1,52 @@ + + +: + name: 'media_player' + BoxLayout: + orientation: 'vertical' + + Video: + id: video_player + state: 'stop' + options: {'eos': 'stop'} + + BoxLayout: + size_hint_y: None + height: '50dp' + Button: + text: 'Play' + on_press: root.play_video() + Button: + text: 'Pause' + on_press: root.pause_video() + Button: + text: 'Stop' + on_press: root.stop_video() + Button: + text: 'Next' + on_press: root.next_video() + + Image: + id: image_display + allow_stretch: True + keep_ratio: True + size_hint_y: None + height: '300dp' + + Label: + id: playlist_label + text: 'Playlist' + size_hint_y: None + height: '30dp' + + ScrollView: + size_hint_y: None + height: '200dp' + GridLayout: + id: playlist + cols: 1 + size_hint_y: None + height: self.minimum_height + +: + on_enter: root.load_playlist() \ No newline at end of file diff --git a/src/kv/settings.kv b/src/kv/settings.kv new file mode 100644 index 0000000..60d5550 --- /dev/null +++ b/src/kv/settings.kv @@ -0,0 +1,32 @@ + +: + BoxLayout: + orientation: 'vertical' + padding: 10 + spacing: 10 + + Label: + text: 'Settings' + font_size: 24 + size_hint_y: None + height: 40 + + Label: + text: 'Quick Connect Code:' + TextInput: + id: quick_connect_code + multiline: False + + Label: + text: 'Server IP/Domain Name:' + TextInput: + id: server_ip + multiline: False + + Button: + text: 'Save Settings' + on_press: app.save_settings(quick_connect_code.text, server_ip.text) + + Button: + text: 'Back to Main' + on_press: app.change_screen('main') \ No newline at end of file diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..ed7ce00 --- /dev/null +++ b/src/main.py @@ -0,0 +1,21 @@ +from kivy.app import App +from kivy.uix.screenmanager import ScreenManager, Screen +from kivy.clock import Clock +from settings import Settings +from media_player import MediaPlayer + +class MainApp(App): + def build(self): + self.title = "Kivy Media Player" + self.sm = ScreenManager() + self.sm.add_widget(Settings(name='settings')) + self.sm.add_widget(MediaPlayer(name='media_player')) + Clock.schedule_interval(self.check_playlist_updates, 300) # Check for updates every 5 minutes + return self.sm + + def check_playlist_updates(self, dt): + # Logic to check for updates in the playlist + pass + +if __name__ == '__main__': + MainApp().run() \ No newline at end of file diff --git a/src/media_player.py b/src/media_player.py new file mode 100644 index 0000000..ca0c4d6 --- /dev/null +++ b/src/media_player.py @@ -0,0 +1,64 @@ +from kivy.app import App +from kivy.uix.screenmanager import ScreenManager, Screen +from kivy.clock import Clock +from kivy.core.window import Window +from kivy.uix.video import Video +from kivy.uix.image import Image +from kivy.uix.boxlayout import BoxLayout +import requests +import os +import json + +class MediaPlayer(Screen): + def __init__(self, **kwargs): + super(MediaPlayer, self).__init__(**kwargs) + self.playlist = [] + self.current_index = 0 + self.video_player = Video() + self.image_display = Image() + self.layout = BoxLayout(orientation='vertical') + self.layout.add_widget(self.video_player) + self.layout.add_widget(self.image_display) + self.add_widget(self.layout) + Clock.schedule_interval(self.check_playlist_updates, 300) # Check for updates every 5 minutes + + def on_enter(self): + self.load_playlist() + self.play_media() + + def load_playlist(self): + # Load playlist from the server or local storage + try: + response = requests.get('http://yourserver.com/api/playlist') + response.raise_for_status() # Raise an exception for HTTP errors + self.playlist = response.json() + except requests.exceptions.RequestException as e: + print(f"Failed to load playlist: {e}") + except json.JSONDecodeError: + print("Failed to parse playlist JSON") + + def play_media(self): + if self.playlist: + media = self.playlist[self.current_index] + if media['type'] == 'video': + self.video_player.source = media['url'] + self.video_player.play() + self.image_display.source = '' + elif media['type'] == 'image': + self.image_display.source = media['url'] + self.video_player.source = '' + self.image_display.reload() + + def check_playlist_updates(self, dt): + self.load_playlist() + self.play_media() + +class MediaPlayerApp(App): + def build(self): + Window.fullscreen = True + sm = ScreenManager() + sm.add_widget(MediaPlayer(name='media_player')) + return sm + +if __name__ == '__main__': + MediaPlayerApp().run() \ No newline at end of file diff --git a/src/settings.json b/src/settings.json new file mode 100644 index 0000000..585d118 --- /dev/null +++ b/src/settings.json @@ -0,0 +1 @@ +{"settings": {"quick_connect_code": "", "server_ip": ""}} \ No newline at end of file diff --git a/src/settings.py b/src/settings.py new file mode 100644 index 0000000..e9cbdb1 --- /dev/null +++ b/src/settings.py @@ -0,0 +1,51 @@ +from kivy.app import App +from kivy.uix.screenmanager import Screen +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.label import Label +from kivy.uix.textinput import TextInput +from kivy.uix.button import Button +from kivy.properties import StringProperty +from kivy.storage.jsonstore import JsonStore + +class Settings(Screen): + quick_connect_code = StringProperty("") + server_ip = StringProperty("") + + def __init__(self, **kwargs): + super(Settings, self).__init__(**kwargs) + self.store = JsonStore('settings.json') + self.load_settings() + + self.layout = BoxLayout(orientation='vertical') + + self.server_ip_input = TextInput(hint_text='Server IP or Domain') + self.quick_connect_code_input = TextInput(hint_text='Quick Connect Code') + + self.layout.add_widget(Label(text='Server IP or Domain:')) + self.layout.add_widget(self.server_ip_input) + self.layout.add_widget(Label(text='Quick Connect Code:')) + self.layout.add_widget(self.quick_connect_code_input) + + self.save_button = Button(text='Save', on_press=self.save_settings) + self.layout.add_widget(self.save_button) + + self.add_widget(self.layout) + + def load_settings(self): + if self.store.exists('settings'): + settings = self.store.get('settings') + self.quick_connect_code = settings.get('quick_connect_code', "") + self.server_ip = settings.get('server_ip', "") + + def save_settings(self, instance=None): + self.store.put('settings', quick_connect_code=self.quick_connect_code, server_ip=self.server_ip) + server_ip = self.server_ip_input.text + quick_connect_code = self.quick_connect_code_input.text + # Save the settings (e.g., to a file or database) + print(f'Settings saved: Server IP = {server_ip}, Quick Connect Code = {quick_connect_code}') + + def on_quick_connect_code(self, instance, value): + self.save_settings() + + def on_server_ip(self, instance, value): + self.save_settings() \ No newline at end of file diff --git a/src/utils.py b/src/utils.py new file mode 100644 index 0000000..29055c8 --- /dev/null +++ b/src/utils.py @@ -0,0 +1,29 @@ +def download_file(url, destination): + import requests + response = requests.get(url) + if response.status_code == 200: + with open(destination, 'wb') as f: + f.write(response.content) + return True + return False + +def check_for_playlist_updates(playlist_url, current_playlist): + import requests + response = requests.get(playlist_url) + if response.status_code == 200: + new_playlist = response.json() + if new_playlist != current_playlist: + return new_playlist + return None + +def schedule_playlist_update(playlist_url, current_playlist, update_interval=300): + from threading import Timer + + def check_updates(): + new_playlist = check_for_playlist_updates(playlist_url, current_playlist) + if new_playlist: + current_playlist.clear() + current_playlist.extend(new_playlist) + Timer(update_interval, check_updates).start() + + check_updates() \ No newline at end of file