Skip to content

Commit

Permalink
Added setting for default device to connect to on start. If no device…
Browse files Browse the repository at this point in the history
… specified, the user can choose which device to connect to.
  • Loading branch information
david-kuehn committed Dec 31, 2020
1 parent 2b5ed55 commit 9580e86
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 12 deletions.
44 changes: 36 additions & 8 deletions casita/casita.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,25 @@
import time
import cast_interface
import sys
import json
from os import path

# Class that handles menubar app itself
class CasitaApp:
def __init__(self):
global USER_SETTINGS

self.app = rumps.App("Casita", "🏡")

# Reusable, generic items
self.quit_btn = rumps.MenuItem(title="Quit", callback=rumps.quit_application)
self.separator = None

# Items to display when no device is connected
self.no_device_item = rumps.MenuItem(title="No Device Connected")
self.cast_devices_parent = rumps.MenuItem(title="Cast Devices")
self.not_connected_menu_items = [self.no_device_item, self.separator, self.cast_devices_parent]

# Items to display in menu while connecting to Cast device
self.connecting_item = rumps.MenuItem(title="Connecting...")
self.connecting_menu_items = [self.connecting_item]
Expand All @@ -25,25 +34,28 @@ def __init__(self):
self.skip_btn = rumps.MenuItem(title="Skip", callback=self.skip)
self.rewind_btn = rumps.MenuItem(title="Rewind", callback=self.rewind)
self.volume_slider = rumps.SliderMenuItem(value=0, min_value=0, max_value=100, dimensions=(150, 30), callback=self.change_volume)
self.cast_devices_parent = rumps.MenuItem(title="Cast Devices")
self.playing_menu_items = [self.track_title_item, self.track_album_artist_item, self.separator, self.volume_slider, self.pauseplay_btn, self.skip_btn, self.rewind_btn, self.separator, self.cast_devices_parent]

# Items to display in menu while connected, but no media is playing
self.no_song_item = rumps.MenuItem(title="No Song Playing")
self.idle_menu_items = [self.no_song_item, self.separator, self.volume_slider, self.separator, self.cast_devices_parent]

# On initialize, we want to show the connecting menu items
self.app.menu = self.connecting_menu_items
# If there is a default device assigned in the user settings, show the 'connecting' menu. Otherwise, show the 'not connected' menu
if USER_SETTINGS["default_device"] != "":
# Show the connecting menu items
self.app.menu = self.connecting_menu_items
else:
self.app.menu = self.not_connected_menu_items

# After initializing the menu UI, start the backend's thread
self.start_thread()
self.start_thread(USER_SETTINGS["default_device"])

def run(self):
self.app.run()

# Start new CastInterfaceThread
def start_thread(self):
CastInterfaceThread(parent=self, device_name="Kitchen Display")
def start_thread(self, device):
CastInterfaceThread(parent=self, device_name=device)

# Update track title + album/artist menu items
def update_track_details(self, new_details):
Expand Down Expand Up @@ -126,7 +138,9 @@ def set_connecting_status(self, device_name, is_connecting, is_reconnection):

# Switch the device we're monitoring
def change_selected_cast_device(self, new_device):
cast_interface.stop_listening()
# If currently connected, disconnect
if cast_interface.is_connected == True:
cast_interface.stop_listening()
cast_interface.start_listening(self, new_device.title, False)

# Toggle pause/play
Expand Down Expand Up @@ -155,10 +169,24 @@ def __init__(self, parent, device_name):
self.start()

def run(self):
cast_interface.start_listening(self.parent, self.device_name, is_reconnection=False)
# If there is a device passed, tell cast_interface to start listening to that device
# If not, tell cast_interface to just discover
if self.device_name != "":
cast_interface.start_listening(app_class_reference=self.parent, device_name=self.device_name, is_reconnection=False)
else:
# Just Discover
print("No default device. Attempting to start discovery.")
cast_interface.discover_devices(app_class_reference=self.parent)


# Execution loop
if __name__ == "__main__":
# Get user settings
global USER_SETTINGS
settings_file = open("user_settings.json")
USER_SETTINGS = json.loads(settings_file.read())
print(USER_SETTINGS)

# If there are arguments passed
if len(sys.argv) > 1:
if sys.argv[1] == "--debug":
Expand Down
29 changes: 26 additions & 3 deletions casita/cast_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
current_track_title = ""
current_volume_level = 0.0
previous_connection_status = ""
is_connected = False

def toggle_pause_play():
if current_media_status.player_is_paused == True:
Expand Down Expand Up @@ -83,13 +84,13 @@ def new_connection_status(self, connection_status):
# Identify whether or not the 'DISCONNECTED' message is preceded by a 'FAILED_RESOLVE'
# If it is, then attempt to reconnect. If it isn't, it's probably an intended disconnection
if previous_connection_status == "FAILED_RESOLVE" and connection_status.status == "DISCONNECTED":
start_listening(parent_to_update=app_class, device_name=name_for_reconnection, is_reconnection=True)
start_listening(app_class_reference=app_class, device_name=name_for_reconnection, is_reconnection=True)

previous_connection_status = connection_status.status

def start_listening(parent_to_update, device_name, is_reconnection):
def start_listening(app_class_reference, device_name, is_reconnection):
global app_class
app_class = parent_to_update
app_class = app_class_reference

# Tell the app class that we're starting the connection process
app_class.set_connecting_status(device_name=device_name, is_connecting=True, is_reconnection=is_reconnection)
Expand Down Expand Up @@ -136,6 +137,9 @@ def start_listening(parent_to_update, device_name, is_reconnection):

# Tell the app class that we're done connecting
app_class.set_connecting_status(device_name=device_name, is_connecting=False, is_reconnection=is_reconnection)

global is_connected
is_connected = True

def stop_listening():
global chromecast, listenerCast, listenerMedia
Expand All @@ -144,6 +148,25 @@ def stop_listening():
reset_app_class_details()
print("Disconnected")

global is_connected
is_connected = False

def discover_devices(app_class_reference):
global chromecasts, browser
chromecasts, browser = pychromecast.get_chromecasts()
if not chromecasts:
print("No chromecasts found.")

chromecast_names = []
for cast in chromecasts:
chromecast_names.append(cast.name)

global app_class
app_class = app_class_reference
app_class.update_cast_devices(chromecast_names, "")

print("Discovered cast devices.")

def reset_app_class_details():
global current_media_status
current_media_status = None
Expand Down
3 changes: 3 additions & 0 deletions casita/user_settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"default_device": ""
}
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from setuptools import setup

APP = ['casita/casita.py']
DATA_FILES = []
DATA_FILES = ['casita/user_settings.json']
OPTIONS = {
'argv_emulation': True,
'iconfile': 'house-icon.icns',
Expand Down

0 comments on commit 9580e86

Please sign in to comment.