Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
# StreamController
**A new Linux app for the Elgato Stream Deck.**

A nice GTK4 app to control your Elgato Stream Decks.
Release: coming soon
![main_screen](https://core447.com/assets/screenshots/main_screen.png)
background image by [kvacm](https://kvacm.artstation.com)

## Features
* **Plugin support with store**
* **Background images and videos**
* **Screen saver**
* **Automatic page switching based on the opened window**
Currently available for Gnome and Hyprland

## Warning
StreamController is still in beta.
All normal features like actions and pages are completely tested and can be considered stable. Background videos may cause problems (mainly height memory usage) in some edge cases. Feel free to report any isssues you're encoutering.

## Contributing
Feel free to open Pull requests

## Links
[Website](https://core447.com) - [Wiki](https://streamcontroller.github.io/docs) - [Discord](https://discord.gg/MSyHM8TN3u)
5 changes: 5 additions & 0 deletions flatpak/com.core447.StreamController.metainfo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@
<url type="contribute">https://github.com/StreamController/StreamController</url>

<releases>
<release version="1.3.1-beta" date="2024-03-30">
<description translatable="no">
<p>Bugfixes</p>
</description>
</release>
<release version="1.3.0-beta" date="2024-03-30">
<description translatable="no">
<p>Bugfixes</p>
Expand Down
3 changes: 1 addition & 2 deletions globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,13 @@
store: "Store" = None # Only if opened


app_version: str = "1.3.0-beta" # In breaking.feature.fix-state format
app_version: str = "1.3.1-beta" # In breaking.feature.fix-state format
exact_app_version_check: bool = False
argparser: argparse.ArgumentParser = None
logs: list[str] = []

release_notes: str = "<ul> \
<li>Now available as a Flatpak</li>\
<li>New page manager</li> \
<li>Bugfixes</li> \
<li>First Release</li> \
</ul>"
17 changes: 12 additions & 5 deletions src/backend/WindowGrabber/Integrations/Gnome.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,25 @@ def install_extension(self) -> None:


def connect_dbus(self) -> None:
bus = dbus.SessionBus()
try:
self.proxy = bus.get_object("org.gnome.Shell", "/org/gnome/Shell/Extensions/StreamController")
self.bus = dbus.SessionBus()
self.proxy = self.bus.get_object("org.gnome.Shell", "/org/gnome/Shell/Extensions/StreamController")
self.interface = dbus.Interface(self.proxy, "org.gnome.Shell.Extensions.StreamController")
self.interface.connect_to_signal("FocusedWindowChanged", self.on_window_changed)
except dbus.exceptions.DBusException as e:
log.error(f"Failed to connect to D-Bus: {e}")
pass

self.interface.connect_to_signal("FocusedWindowChanged", self.on_window_changed)

def on_window_changed(self, answer: str) -> None:
answer = json.loads(answer)
window = Window(answer.get("wm_class"), answer.get("title"))
self.window_grabber.on_active_window_changed(window=window)


def get_all_windows(self) -> list[Window]:
if not self.get_is_connected():
return []

answer = json.loads(self.interface.GetAllWindows())
windows: list[Window] = []

Expand All @@ -84,7 +86,12 @@ def get_all_windows(self) -> list[Window]:
return windows

def get_active_window (self) -> Window:
if not self.get_is_connected():
return None
answer = json.loads(self.interface.GetFocusedWindow())
wm_class = answer.get("wm_class")
title = answer.get("title")
return Window(wm_class, title)
return Window(wm_class, title)

def get_is_connected(self) -> bool:
return None not in (self.bus, self.proxy, self.interface)
3 changes: 2 additions & 1 deletion src/windows/PageManager/elements/PageEditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,8 @@ def __init__(self, page_editor: PageEditor):

def build(self):
matches = gl.page_manager.get_all_deck_serial_numbers_with_page_as_default(path=self.page_editor.active_page_path)
self.row = MultiDeckSelectorRow(source_window=self.page_editor.page_manager, title="Default page", subtitle="Select for which decks this page should be opened by default",
self.row = MultiDeckSelectorRow(source_window=self.page_editor.page_manager, title=gl.lm.get("page-manager.page-editor.default-page.row.title"),
subtitle=gl.lm.get("page-manager.page-editor.default-page.row.subtitle"),
callback=self.on_changed, selected_deck_serials=matches)
self.add(self.row)

Expand Down
2 changes: 1 addition & 1 deletion src/windows/mainWindow/elements/NoPagesError.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def build(self):
self.append(self.create_new_button)

def on_create_new(self, button):
dial = EntryDialog(parent_window=self.page_manager,
dial = EntryDialog(parent_window=gl.app.main_win,
dialog_title=gl.lm.get("page-manager.page-selector.add-dialog.title"),
placeholder=gl.lm.get("page-manager.page-selector.add-dialog.placeholder"),
confirm_label=gl.lm.get("page-manager.page-selector.add-dialog.confirm"),
Expand Down
20 changes: 14 additions & 6 deletions src/windows/mainWindow/mainWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,28 +63,34 @@ def on_close(self, *args, **kwargs):

@log.catch
def build(self):
#TODO: Put the objects in classes
log.trace("Building main window")
self.split_view = Adw.NavigationSplitView()
self.set_content(self.split_view)

self.content_page = Adw.NavigationPage(title="StreamController")
self.split_view.set_content(self.content_page)

self.main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, hexpand=True)
self.content_page.set_child(self.main_box)

# Add a main stack containing the normal ui and error pages
self.main_stack = Gtk.Stack(hexpand=True, vexpand=True)
self.main_content_page = Adw.NavigationPage(title="StreamController", child=self.main_stack)
self.main_box.append(self.main_stack)

# Add the main stack as the content widget of the split view
self.split_view.set_content(self.main_content_page)
self.split_view.set_show_content(self.main_content_page)
self.split_view.set_show_content(self.content_page)

# Main toast
self.toast_overlay = Adw.ToastOverlay()
self.main_stack.add_titled(self.toast_overlay, "main", "Main")

# Add a box for the main content (right side)
self.main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, hexpand=True)
self.toast_overlay.set_child(self.main_box)
self.content_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, hexpand=True)
self.toast_overlay.set_child(self.content_box)

self.leftArea = LeftArea(self, deck_manager=self.deck_manager, margin_end=3, width_request=500, margin_bottom=10)
self.main_box.append(self.leftArea)
self.content_box.append(self.leftArea)

self.sidebar = Sidebar(main_window=self, margin_start=4, width_request=300, margin_end=4)
# self.mainPaned.set_end_child(self.sidebar)
Expand Down Expand Up @@ -192,6 +198,7 @@ def set_main_error(self, error: str=None):
GLib.idle_add(self.deck_switcher.set_show_switcher, True)
GLib.idle_add(self.split_view.set_collapsed, False)
GLib.idle_add(self.sidebar_toggle_button.set_visible, True)
GLib.idle_add(self.menu_button.set_visible, True)
return

elif error == "no-decks":
Expand All @@ -203,6 +210,7 @@ def set_main_error(self, error: str=None):
GLib.idle_add(self.deck_switcher.set_show_switcher, False)
GLib.idle_add(self.split_view.set_collapsed, True)
GLib.idle_add(self.sidebar_toggle_button.set_visible, False)
GLib.idle_add(self.menu_button.set_visible, False)

def check_for_errors(self):
if len(gl.deck_manager.deck_controller) == 0:
Expand Down