├── docs
├── .nojekyll
├── _sidebar.md
├── _coverpage.md
├── contributing.md
├── index.html
├── README.md
└── quickstart.md
├── .fvm
├── flutter_sdk
└── fvm_config.json
├── ios
├── Flutter
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ └── AppFrameworkInfo.plist
├── Runner
│ ├── Runner-Bridging-Header.h
│ ├── Assets.xcassets
│ │ ├── LaunchImage.imageset
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ ├── README.md
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ └── Contents.json
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.storyboard
│ └── Info.plist
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── WorkspaceSettings.xcsettings
│ │ └── IDEWorkspaceChecks.plist
├── Runner.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ └── project.pbxproj
└── .gitignore
├── assets
├── icons
│ ├── Icon.png
│ ├── Icon_BG.png
│ └── Icon_FG.png
└── images
│ ├── Mute.png
│ ├── Sound.png
│ ├── Hidden.png
│ ├── Visible.png
│ ├── Disconnect.png
│ ├── Pause Recording.png
│ ├── Start Recording.png
│ ├── Start Streaming.png
│ ├── Stop Recording.png
│ ├── Stop Streaming.png
│ ├── Switch Scenes.png
│ └── Resume Recording.png
├── android
├── gradle.properties
├── app
│ ├── src
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── drawable-hdpi
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── drawable-mdpi
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── drawable-xhdpi
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── drawable-xxhdpi
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── drawable-xxxhdpi
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── mipmap-anydpi-v26
│ │ │ │ │ └── ic_launcher.xml
│ │ │ │ ├── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ │ └── values
│ │ │ │ │ └── styles.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── streamdeck
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── AndroidManifest.xml
│ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ └── profile
│ │ │ └── AndroidManifest.xml
│ └── build.gradle
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── .gitignore
├── settings.gradle
└── build.gradle
├── lib
├── utils
│ ├── enums.dart
│ └── layouts.dart
├── main.dart
├── screens
│ ├── connect_screen.dart
│ └── deck_screen.dart
└── widgets
│ └── deck_button.dart
├── .circleci
└── config.yml
├── .metadata
├── test
└── widget_test.dart
├── .gitignore
├── README.md
├── pubspec.yaml
├── CODE_OF_CONDUCT.md
├── python_server
└── server.py
├── pubspec.lock
└── LICENSE
/docs/.nojekyll:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.fvm/flutter_sdk:
--------------------------------------------------------------------------------
1 | C:/Users/Leo/fvm/versions/stable
--------------------------------------------------------------------------------
/.fvm/fvm_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "flutterSdkVersion": "stable"
3 | }
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/assets/icons/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/icons/Icon.png
--------------------------------------------------------------------------------
/assets/images/Mute.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/images/Mute.png
--------------------------------------------------------------------------------
/assets/images/Sound.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/images/Sound.png
--------------------------------------------------------------------------------
/assets/icons/Icon_BG.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/icons/Icon_BG.png
--------------------------------------------------------------------------------
/assets/icons/Icon_FG.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/icons/Icon_FG.png
--------------------------------------------------------------------------------
/assets/images/Hidden.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/images/Hidden.png
--------------------------------------------------------------------------------
/assets/images/Visible.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/images/Visible.png
--------------------------------------------------------------------------------
/assets/images/Disconnect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/images/Disconnect.png
--------------------------------------------------------------------------------
/assets/images/Pause Recording.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/images/Pause Recording.png
--------------------------------------------------------------------------------
/assets/images/Start Recording.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/images/Start Recording.png
--------------------------------------------------------------------------------
/assets/images/Start Streaming.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/images/Start Streaming.png
--------------------------------------------------------------------------------
/assets/images/Stop Recording.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/images/Stop Recording.png
--------------------------------------------------------------------------------
/assets/images/Stop Streaming.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/images/Stop Streaming.png
--------------------------------------------------------------------------------
/assets/images/Switch Scenes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/images/Switch Scenes.png
--------------------------------------------------------------------------------
/assets/images/Resume Recording.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/assets/images/Resume Recording.png
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 | android.enableR8=true
5 |
--------------------------------------------------------------------------------
/docs/_sidebar.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | - [Home](/)
4 | - [Getting Started](quickstart.md)
5 | - [Contribution](contributing.md)
6 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-hdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/drawable-hdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-mdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/drawable-mdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/drawable-xhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xxhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/drawable-xxhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ecrax/streamdeck/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/lib/utils/enums.dart:
--------------------------------------------------------------------------------
1 | enum Functionality {
2 | muteAudio,
3 | switchScene,
4 | hideSource,
5 | toggleStream,
6 | toggleRecording,
7 | pauseRecording,
8 | disconnect,
9 | }
10 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/streamdeck/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.streamdeck
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/docs/_coverpage.md:
--------------------------------------------------------------------------------
1 | # docsify 3.5
2 |
3 | > A magical documentation site generator.
4 |
5 | - Simple and lightweight
6 | - No statically built html files
7 | - Multiple themes
8 |
9 | [GitHub](https://github.com/docsifyjs/docsify/)
10 | [Get Started](#streamdeck)
11 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
7 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 | jobs:
3 | build:
4 | docker:
5 | - image: cirrusci/flutter
6 | steps:
7 | - checkout
8 | - run: flutter doctor
9 | - run: flutter test
10 | - run: flutter build apk --release
11 | - store_artifacts:
12 | path: build/app/outputs/flutter-apk/app-release.apk
13 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 84f3d28555368a70270e9ac8390a9441df95e752
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter_test/flutter_test.dart';
9 |
10 | void main() {
11 | testWidgets('Main App test', (WidgetTester tester) async {
12 | /* SharedPreferences prefs = await SharedPreferences.getInstance();
13 | await tester.pumpWidget(MyApp(prefs)); */
14 | });
15 | }
16 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.5.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:hive/hive.dart';
3 | import 'package:hive_flutter/hive_flutter.dart';
4 | import 'package:Streamdeck/screens/connect_screen.dart';
5 |
6 | void main() async {
7 | WidgetsFlutterBinding.ensureInitialized();
8 | await Hive.initFlutter();
9 | await Hive.openBox('prefs');
10 | runApp(MyApp());
11 | }
12 |
13 | class MyApp extends StatelessWidget {
14 | @override
15 | Widget build(BuildContext context) {
16 | return MaterialApp(
17 | title: 'Stream Deck',
18 | theme: ThemeData(
19 | brightness: Brightness.light,
20 | accentColor: Color(0xFF5E5CE6),
21 | ),
22 | home: ConnectScreen(),
23 | );
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | **/ios/Flutter/.last_build_id
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Web related
35 | lib/generated_plugin_registrant.dart
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 | android/app/build.gradle
43 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 9.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/docs/contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | You are very welcome to contribute to this project, that is why it is open source. But to ensure a high-quality product we only accept serious Pull Requests and ask you to test your changes before you create a PR.
4 |
5 | ## Steps to contribute
6 |
7 | 1. Fork and clone the repo from `https://github.com/product-ride/styled-wind`
8 | 2. Make necessary changes within the `lib` directory.
9 | 3. Run tests to make sure nothing breaks
10 | 4. Follow the below steps and test your changes before creating the PR
11 |
12 | ## Steps to run before creating a PR
13 |
14 | 1. Run `flutter test` (and make sure it completes it successfully :D)
15 | 2. Build the project with `flutter build apk --release` (for android) and make sure all your changes work as expected
16 | 3. Remove all prints statements from your code
17 | 4. Try to refactor your code as far as you can
18 |
19 | ?> When you completed all the steps you are very welcome to create a Pull Request
20 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | streamdeck
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
12 |
16 |
22 |
23 |
27 |
32 |
33 |
34 |
44 |
45 |
46 |
47 |
55 |
56 |
57 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # streamdeck
2 |
3 | > An alternative to an Elgato Stream Deck.
4 |
5 | ## What is this about?
6 |
7 | Streamdeck is an app and a python script, developed by two students from Germany, which allows you to use your Phone to remotely control the open-source screen recording program OBS. The app is built entirely with the open-source framework Flutter. The python script on the other hand serves the server and runs inside of OBS to handle the requests coming from the app.
8 |
9 | ## Why Streamdeck?
10 |
11 | - Open Source
12 | - Built only with open source technology
13 | - No big tech companies involved
14 | - Nice and intuitive interface
15 | - Resource-efficient
16 | - No software running in the background, except a small Python script
17 | - Easy setup
18 | - No external software to install
19 |
20 | ## Motivation
21 |
22 | We always liked the idea of streaming, so we wanted to try it as well. The only problem was that, even though we had two or even three monitors, we would get lost quickly in our streaming setup. That is where normally an Elgato Stream Deck would fit in perfectly. But of course, we did not want to pay for it, so we built it ourselves. And this is how Streamdeck was born.
23 |
24 | ## Features
25 |
26 | - Muting audio
27 | - Switching to a scene
28 | - Hiding a source
29 | - Toggle your stream on and off
30 | - Toggle your recording on and off
31 | - Pause and resume your recording
32 | - Cross-platform
33 | - App:
34 | - Android
35 | - (iOS) **coming soon**
36 | - Computer:
37 | - Linux
38 | - Windows
39 | - macOS
40 |
41 | ## Roadmap / TODO
42 |
43 | > Contributions and Suggestions are very welcome :)
44 |
45 | - iOS support
46 | - iOS documentation
47 | - Add images to this documentation
48 |
49 | All todos are on our GitHub pages issue tracker ([here](https://github.com/ecrax/streamdeck/issues))
50 |
51 | ## Community
52 |
53 | The creators and maintainers of this project are Jonathan Kron and Leo Kling. Here are their socials:
54 |
55 | - Jonathan Kron: [YouTube](https://www.youtube.com/jonathankron)
56 | - Leo Kling: [YouTube](https://www.youtube.com/ecrax_official)
57 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | def keystoreProperties = new Properties()
29 | def keystorePropertiesFile = rootProject.file('key.properties')
30 | if (keystorePropertiesFile.exists()) {
31 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
32 | }
33 |
34 | android {
35 | compileSdkVersion 29
36 |
37 | sourceSets {
38 | main.java.srcDirs += 'src/main/kotlin'
39 | }
40 |
41 | lintOptions {
42 | disable 'InvalidPackage'
43 | }
44 |
45 | defaultConfig {
46 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
47 | applicationId "com.indistinctstudios.streamdeck"
48 | minSdkVersion 16
49 | targetSdkVersion 29
50 | versionCode flutterVersionCode.toInteger()
51 | versionName flutterVersionName
52 | }
53 |
54 | signingConfigs {
55 | release {
56 | keyAlias keystoreProperties['keyAlias']
57 | keyPassword keystoreProperties['keyPassword']
58 | storeFile file(keystoreProperties['storeFile'])
59 | storePassword keystoreProperties['storePassword']
60 | }
61 | }
62 |
63 | buildTypes {
64 | release {
65 | signingConfig signingConfigs.release
66 | }
67 | }
68 | }
69 |
70 | flutter {
71 | source '../..'
72 | }
73 |
74 | dependencies {
75 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
76 | }
77 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/docs/quickstart.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ### Download
4 |
5 | - Go to the [GitHub releases](https://github.com/ecrax/streamdeck/releases) section and download the newest stable release on/for your phone.
6 |
7 | - Download the Python script that comes with the newest stable release from the [GitHub releases](https://github.com/ecrax/streamdeck/releases) section.
8 |
9 | ### Install
10 |
11 | #### Phone
12 |
13 | - Install the downloaded apk or plist file (depending on your phone OS). You may have to do some additional configuration because it is an app that is not on the Google Play Store nor the Apple App Store.
14 |
15 | ?> On Android to install from unknown sources you can follow [this](https://www.verizon.com/support/knowledge-base-222186/) guide.
16 |
17 | ?> On iOS you may have to do something similar to [this](https://support.doforms.com/hc/en-us/articles/204409074-How-to-download-and-install-the-iOS-app-from-the-doForms-website#:~:text=From%20the%20web%20browser%20on,%22Untrusted%20Enterprise%20Developer%22%20message.).
18 |
19 | #### Computer
20 |
21 | - Move the Python script to a safe space on your computer where it will not be deleted (_Downloads_ is not a safe folder!).
22 | - Open OBS, go to **Tools** -> **Scripts**
23 | - In the window that opens, click on the small plus in the bottom left corner and choose the Python script (_server.py_)
24 |
25 | !> You may have to add a firewall exception for incoming connections to your OS for the port you want to use.
26 |
27 | ### Usage
28 |
29 | Click on the _Start/Stop Server_ button inside of OBS and leave the two text fields empty for now (Except you have to use a different IP or Port. If you are not sure just leave them empty.).
30 | When clicking on _Script Log_ you should see _Server Started..._ and _Server Running..._ in the console that opens.
31 |
32 | Now you can open the Streamdeck app on your mobile device and connect to the values that are displayed or that you entered manually. Then click on _Connect_.
33 |
34 | When connected, you are all set up. You can keep using the default layout, or change to another template, by swiping from the very left to right and clicking on one. You can also customize it further.
35 |
36 | ### Customization
37 |
38 | If you want to change the function of a button (for example from switching a scene to muting an audio track), simply long-press a button until a dialog opens. There you can choose from a variety of functions a button can have:
39 |
40 | - Muting audio
41 | - Switching to a scene
42 | - Hiding a source
43 | - Toggle your stream on and off
44 | - Toggle your recording on and off
45 | - Pause and resume your recording
46 | - Disconnect / close the connection
47 |
48 | Depending on the function you assign, you might e.g. also have to enter the index (starting at 1) of the scene you want the button to switch to or the name of the audio track you want your button to mute/unmute.
49 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
8 |
9 |
10 |
14 |
21 |
25 |
29 |
34 |
38 |
39 |
40 |
41 |
42 |
43 |
45 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # streamdeck
2 |
3 | > An alternative to an Elgato Stream Deck.
4 |
5 | [](https://app.circleci.com/pipelines/github/ecrax/streamdeck)
6 | [](https://github.com/ecrax/streamdeck/issues)
7 | 
8 | [](https://github.com/ecrax/streamdeck/blob/master/LICENSE)
9 |
10 | ## What is this about?
11 |
12 | Streamdeck is an app and a python script, developed by two students from Germany, which allows you to use your Phone to remotely control the open-source screen recording program OBS. The app is built entirely with the open-source framework Flutter. The python script on the other hand serves the server and runs inside of OBS to handle the requests coming from the app.
13 |
14 | ## Why Streamdeck?
15 |
16 | - Open Source
17 | - Built only with open source technology
18 | - No big tech companies involved
19 | - Nice and intuitive interface
20 | - Resource-efficient
21 | - No software running in the background, except a small Python script
22 | - Easy setup
23 | - No external software to install
24 |
25 | ## Documentation
26 |
27 | You will find the entire documentation, covering various topics, [here](https://ecrax.github.io/streamdeck/#/).
28 |
29 | ## Motivation
30 |
31 | We always liked the idea of streaming, so we wanted to try it as well. The only problem was that, even though we had two or even three monitors, we would get lost quickly in our streaming setup. That is where normally an Elgato Stream Deck would fit in perfectly. But of course, we did not want to pay for it, so we built it ourselves. And this is how Streamdeck was born.
32 |
33 | ## Features
34 |
35 | - Muting audio
36 | - Switching to a scene
37 | - Hiding a source
38 | - Toggle your stream on and off
39 | - Toggle your recording on and off
40 | - Pause and resume your recording
41 | - Cross-platform
42 | - App:
43 | - Android
44 | - (iOS) **coming soon**
45 | - Computer:
46 | - Linux
47 | - Windows
48 | - macOS
49 |
50 | ## Roadmap / TODO
51 |
52 | > Contributions and Suggestions are very welcome :)
53 |
54 | - iOS support
55 | - iOS documentation
56 | - Add images to this documentation
57 |
58 | All todos are on our GitHub pages issue tracker ([here](https://github.com/ecrax/streamdeck/issues))
59 |
60 | ## Contributing
61 |
62 | Contributions are very welcome!
63 | You can find a guide on how you can contribute [here](https://ecrax.github.io/streamdeck/#/contributing).
64 |
65 | ## Community
66 |
67 | The creators and maintainers of this project are Jonathan Kron and Leo Kling. Here are their socials:
68 |
69 | - Jonathan Kron: [YouTube](https://www.youtube.com/jonathankron)
70 | - Leo Kling: [YouTube](https://www.youtube.com/ecrax_official)
71 |
72 | ## License
73 |
74 | Streamdeck is released as open source software under the GPL v3 license, see the [LICENSE](https://github.com/ecrax/streamdeck/blob/master/LICENSE) file in the project root for the full license text.
75 |
76 | Streamdeck has been developed by Jonathan Kron and Leo Kling.
77 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: Streamdeck
2 | description: An alternative to an Elgato Stream Deck.
3 |
4 | # The following line prevents the package from being accidentally published to
5 | # pub.dev using `pub publish`. This is preferred for private packages.
6 | publish_to: "none" # Remove this line if you wish to publish to pub.dev
7 |
8 | # The following defines the version and build number for your application.
9 | # A version number is three numbers separated by dots, like 1.2.43
10 | # followed by an optional build number separated by a +.
11 | # Both the version and the builder number may be overridden in flutter
12 | # build by specifying --build-name and --build-number, respectively.
13 | # In Android, build-name is used as versionName while build-number used as versionCode.
14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
16 | # Read more about iOS versioning at
17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
18 | version: 1.0.0+3
19 |
20 | environment:
21 | sdk: ">=2.7.0 <3.0.0"
22 |
23 | dependencies:
24 | flutter:
25 | sdk: flutter
26 |
27 | # The following adds the Cupertino Icons font to your application.
28 | # Use with the CupertinoIcons class for iOS style icons.
29 | cupertino_icons: ^1.0.0
30 | focused_menu: ^1.0.1
31 | hive: ^1.4.4+1
32 | hive_flutter: ^0.3.1
33 | url_launcher: ^5.7.10
34 |
35 | flutter_icons:
36 | android: true
37 | ios: true
38 | image_path_android: "assets/icons/Icon.png"
39 | image_path_ios: "assets/icons/Icon.png"
40 | adaptive_icon_background: assets/icons/Icon_BG.png
41 | adaptive_icon_foreground: assets/icons/Icon_FG.png
42 |
43 | dev_dependencies:
44 | flutter_launcher_icons: ^0.8.1
45 | flutter_test:
46 | sdk: flutter
47 |
48 | # For information on the generic Dart part of this file, see the
49 | # following page: https://dart.dev/tools/pub/pubspec
50 |
51 | # The following section is specific to Flutter.
52 | flutter:
53 | # The following line ensures that the Material Icons font is
54 | # included with your application, so that you can use the icons in
55 | # the material Icons class.
56 | uses-material-design: true
57 |
58 | # To add assets to your application, add an assets section, like this:
59 | assets:
60 | - assets/images/
61 |
62 | # An image asset can refer to one or more resolution-specific "variants", see
63 | # https://flutter.dev/assets-and-images/#resolution-aware.
64 |
65 | # For details regarding adding assets from package dependencies, see
66 | # https://flutter.dev/assets-and-images/#from-packages
67 |
68 | # To add custom fonts to your application, add a fonts section here,
69 | # in this "flutter" section. Each entry in this list should have a
70 | # "family" key with the font family name, and a "fonts" key with a
71 | # list giving the asset and other descriptors for the font. For
72 | # example:
73 | # fonts:
74 | # - family: Schyler
75 | # fonts:
76 | # - asset: fonts/Schyler-Regular.ttf
77 | # - asset: fonts/Schyler-Italic.ttf
78 | # style: italic
79 | # - family: Trajan Pro
80 | # fonts:
81 | # - asset: fonts/TrajanPro.ttf
82 | # - asset: fonts/TrajanPro_Bold.ttf
83 | # weight: 700
84 | #
85 | # For details regarding fonts from package dependencies,
86 | # see https://flutter.dev/custom-fonts/#from-packages
87 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at leo@indistinctstudios.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/lib/utils/layouts.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:Streamdeck/widgets/deck_button.dart';
3 | import 'package:Streamdeck/screens/deck_screen.dart';
4 |
5 | Widget verticalLayout(
6 | List loadedData, DeckScreen widget, BuildContext context) {
7 | return Row(
8 | mainAxisAlignment: MainAxisAlignment.center,
9 | children: [
10 | Column(
11 | children: [
12 | DeckButton(
13 | id: 1,
14 | socket: widget.socket,
15 | loadedData: loadedData,
16 | ),
17 | DeckButton(
18 | id: 4,
19 | socket: widget.socket,
20 | loadedData: loadedData,
21 | ),
22 | DeckButton(
23 | id: 7,
24 | socket: widget.socket,
25 | loadedData: loadedData,
26 | ),
27 | DeckButton(
28 | id: 10,
29 | socket: widget.socket,
30 | loadedData: loadedData,
31 | ),
32 | DeckButton(
33 | id: 13,
34 | socket: widget.socket,
35 | loadedData: loadedData,
36 | ),
37 | DeckButton(
38 | id: 16,
39 | socket: widget.socket,
40 | loadedData: loadedData,
41 | ),
42 | ],
43 | ),
44 | Column(
45 | children: [
46 | DeckButton(
47 | id: 2,
48 | socket: widget.socket,
49 | loadedData: loadedData,
50 | ),
51 | DeckButton(
52 | id: 5,
53 | socket: widget.socket,
54 | loadedData: loadedData,
55 | ),
56 | DeckButton(
57 | id: 8,
58 | socket: widget.socket,
59 | loadedData: loadedData,
60 | ),
61 | DeckButton(
62 | id: 11,
63 | socket: widget.socket,
64 | loadedData: loadedData,
65 | ),
66 | DeckButton(
67 | id: 14,
68 | socket: widget.socket,
69 | loadedData: loadedData,
70 | ),
71 | DeckButton(
72 | id: 17,
73 | socket: widget.socket,
74 | loadedData: loadedData,
75 | ),
76 | ],
77 | ),
78 | Column(
79 | children: [
80 | DeckButton(
81 | id: 3,
82 | socket: widget.socket,
83 | loadedData: loadedData,
84 | ),
85 | DeckButton(
86 | id: 6,
87 | socket: widget.socket,
88 | loadedData: loadedData,
89 | ),
90 | DeckButton(
91 | id: 9,
92 | socket: widget.socket,
93 | loadedData: loadedData,
94 | ),
95 | DeckButton(
96 | id: 12,
97 | socket: widget.socket,
98 | loadedData: loadedData,
99 | ),
100 | DeckButton(
101 | id: 15,
102 | socket: widget.socket,
103 | loadedData: loadedData,
104 | ),
105 | DeckButton(
106 | id: 18,
107 | socket: widget.socket,
108 | loadedData: loadedData,
109 | ),
110 | ],
111 | ),
112 | ],
113 | );
114 | }
115 |
116 | Widget horizontalLayout(List loadedData, DeckScreen widget) {
117 | return Row(
118 | mainAxisAlignment: MainAxisAlignment.center,
119 | crossAxisAlignment: CrossAxisAlignment.center,
120 | children: [
121 | Column(
122 | mainAxisAlignment: MainAxisAlignment.center,
123 | children: [
124 | DeckButton(
125 | id: 1,
126 | socket: widget.socket,
127 | loadedData: loadedData,
128 | ),
129 | DeckButton(
130 | id: 4,
131 | socket: widget.socket,
132 | loadedData: loadedData,
133 | ),
134 | DeckButton(
135 | id: 7,
136 | socket: widget.socket,
137 | loadedData: loadedData,
138 | ),
139 | ],
140 | ),
141 | Column(
142 | mainAxisAlignment: MainAxisAlignment.center,
143 | children: [
144 | DeckButton(
145 | id: 2,
146 | socket: widget.socket,
147 | loadedData: loadedData,
148 | ),
149 | DeckButton(
150 | id: 5,
151 | socket: widget.socket,
152 | loadedData: loadedData,
153 | ),
154 | DeckButton(
155 | id: 8,
156 | socket: widget.socket,
157 | loadedData: loadedData,
158 | ),
159 | ],
160 | ),
161 | Column(
162 | mainAxisAlignment: MainAxisAlignment.center,
163 | children: [
164 | DeckButton(
165 | id: 3,
166 | socket: widget.socket,
167 | loadedData: loadedData,
168 | ),
169 | DeckButton(
170 | id: 6,
171 | socket: widget.socket,
172 | loadedData: loadedData,
173 | ),
174 | DeckButton(
175 | id: 9,
176 | socket: widget.socket,
177 | loadedData: loadedData,
178 | ),
179 | ],
180 | ),
181 | Column(
182 | mainAxisAlignment: MainAxisAlignment.center,
183 | children: [
184 | DeckButton(
185 | id: 10,
186 | socket: widget.socket,
187 | loadedData: loadedData,
188 | ),
189 | DeckButton(
190 | id: 13,
191 | socket: widget.socket,
192 | loadedData: loadedData,
193 | ),
194 | DeckButton(
195 | id: 16,
196 | socket: widget.socket,
197 | loadedData: loadedData,
198 | ),
199 | ],
200 | ),
201 | Column(
202 | mainAxisAlignment: MainAxisAlignment.center,
203 | children: [
204 | DeckButton(
205 | id: 11,
206 | socket: widget.socket,
207 | loadedData: loadedData,
208 | ),
209 | DeckButton(
210 | id: 14,
211 | socket: widget.socket,
212 | loadedData: loadedData,
213 | ),
214 | DeckButton(
215 | id: 17,
216 | socket: widget.socket,
217 | loadedData: loadedData,
218 | ),
219 | ],
220 | ),
221 | Column(
222 | mainAxisAlignment: MainAxisAlignment.center,
223 | children: [
224 | DeckButton(
225 | id: 12,
226 | socket: widget.socket,
227 | loadedData: loadedData,
228 | ),
229 | DeckButton(
230 | id: 15,
231 | socket: widget.socket,
232 | loadedData: loadedData,
233 | ),
234 | DeckButton(
235 | id: 18,
236 | socket: widget.socket,
237 | loadedData: loadedData,
238 | ),
239 | ],
240 | ),
241 | ],
242 | );
243 | }
244 |
--------------------------------------------------------------------------------
/lib/screens/connect_screen.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:Streamdeck/screens/deck_screen.dart';
5 | import 'package:url_launcher/url_launcher.dart';
6 |
7 | class ConnectScreen extends StatefulWidget {
8 | @override
9 | _ConnectScreenState createState() => _ConnectScreenState();
10 | }
11 |
12 | class _ConnectScreenState extends State {
13 | Socket socket;
14 |
15 | String ip;
16 | String port;
17 |
18 | @override
19 | void dispose() {
20 | socket.close();
21 | super.dispose();
22 | }
23 |
24 | @override
25 | Widget build(BuildContext context) {
26 | return SafeArea(
27 | child: Scaffold(
28 | backgroundColor: Colors.grey[900],
29 | body: SingleChildScrollView(
30 | child: Padding(
31 | padding: const EdgeInsets.all(16.0),
32 | child: Column(
33 | crossAxisAlignment: CrossAxisAlignment.start,
34 | children: [
35 | Container(
36 | child: Column(
37 | crossAxisAlignment: CrossAxisAlignment.start,
38 | children: [
39 | SizedBox(
40 | height: 16,
41 | ),
42 | Text(
43 | "Welcome back!",
44 | style: TextStyle(
45 | color: Colors.white,
46 | fontWeight: FontWeight.bold,
47 | fontSize: 32,
48 | ),
49 | ),
50 | SizedBox(
51 | height: 8,
52 | ),
53 | Text(
54 | "Connect to the server",
55 | style: TextStyle(
56 | color: Colors.grey[500],
57 | ),
58 | ),
59 | ],
60 | ),
61 | ),
62 | SizedBox(
63 | height: 32,
64 | ),
65 | Container(
66 | decoration: BoxDecoration(
67 | color: Colors.grey[700],
68 | borderRadius: BorderRadius.circular(7),
69 | ),
70 | child: Row(
71 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
72 | children: [
73 | SizedBox(
74 | width: 16,
75 | ),
76 | Text(
77 | "IP Address:",
78 | style: TextStyle(
79 | color: Colors.grey[300],
80 | ),
81 | ),
82 | SizedBox(
83 | width: 8,
84 | ),
85 | Expanded(
86 | child: TextField(
87 | autofocus: false,
88 | keyboardAppearance: Brightness.dark,
89 | decoration: InputDecoration(
90 | hintText: "e.g. 192.186.420.69",
91 | border: InputBorder.none,
92 | hintStyle: TextStyle(
93 | color: Colors.grey[500],
94 | ),
95 | ),
96 | style: TextStyle(
97 | color: Colors.white,
98 | fontSize: 14,
99 | ),
100 | keyboardType: TextInputType.number,
101 | onChanged: (value) {
102 | ip = value;
103 | },
104 | ),
105 | ),
106 | ],
107 | ),
108 | ),
109 | SizedBox(
110 | height: 16,
111 | ),
112 | Container(
113 | decoration: BoxDecoration(
114 | color: Colors.grey[700],
115 | borderRadius: BorderRadius.circular(7),
116 | ),
117 | child: Row(
118 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
119 | children: [
120 | SizedBox(
121 | width: 16,
122 | ),
123 | Text(
124 | "Port:",
125 | style: TextStyle(
126 | color: Colors.grey[300],
127 | ),
128 | ),
129 | SizedBox(
130 | width: 8,
131 | ),
132 | Expanded(
133 | child: TextField(
134 | autofocus: false,
135 | decoration: InputDecoration(
136 | border: InputBorder.none,
137 | hintText: "e.g. 6969",
138 | hintStyle: TextStyle(
139 | color: Colors.grey[500],
140 | ),
141 | ),
142 | style: TextStyle(
143 | color: Colors.white,
144 | fontSize: 14,
145 | ),
146 | keyboardType: TextInputType.number,
147 | onChanged: (value) {
148 | port = value;
149 | },
150 | ),
151 | ),
152 | ],
153 | ),
154 | ),
155 | SizedBox(
156 | height: 16,
157 | ),
158 | Align(
159 | alignment: Alignment.centerRight,
160 | child: GestureDetector(
161 | onTap: () async {
162 | const url = 'https://ecrax.github.io/streamdeck/#/';
163 | if (await canLaunch(url)) {
164 | await launch(url);
165 | } else {
166 | throw 'Could not launch $url';
167 | }
168 | },
169 | child: Text(
170 | "Need help?",
171 | style: TextStyle(
172 | fontWeight: FontWeight.bold, color: Colors.white),
173 | ),
174 | ),
175 | ),
176 | SizedBox(
177 | height: 32,
178 | ),
179 | ButtonTheme(
180 | minWidth: MediaQuery.of(context).size.width,
181 | height: 50,
182 | child: RaisedButton(
183 | shape: RoundedRectangleBorder(
184 | borderRadius: BorderRadius.circular(7)),
185 | child: Text(
186 | "Connect",
187 | style: TextStyle(
188 | color: Colors.white,
189 | fontSize: 18,
190 | ),
191 | ),
192 | color: Color(0xFF5E5CE6),
193 | onPressed: () async {
194 | if (ip != null && port != null) {
195 | FocusScope.of(context).unfocus();
196 | socket = await Socket.connect(ip, int.parse(port));
197 | Navigator.push(
198 | context,
199 | MaterialPageRoute(
200 | builder: (context) => DeckScreen(
201 | socket: socket,
202 | ip: ip,
203 | port: port,
204 | ),
205 | ),
206 | );
207 | }
208 | },
209 | ),
210 | ),
211 | ],
212 | ),
213 | ),
214 | ),
215 | ),
216 | );
217 | }
218 | }
219 |
--------------------------------------------------------------------------------
/python_server/server.py:
--------------------------------------------------------------------------------
1 | import socket
2 | import threading
3 | import obspython as obs
4 | import sys
5 | import os
6 | import subprocess
7 |
8 | c_port = ""
9 | c_ipA = ""
10 | stopServer = False
11 | runServer = True
12 |
13 |
14 | def getIP():
15 | LocalIP = socket.gethostbyname_ex(socket.gethostname())
16 | LocalIP = LocalIP[-1]
17 | for ip in LocalIP:
18 | if not ip.endswith(".1"):
19 | return ip
20 |
21 |
22 | HEADER = 64
23 | PORT = 7071
24 | ADDR = (getIP(), PORT)
25 | FORMAT = "utf-8"
26 | DISCONNECT_MESSAGE = "stop"
27 |
28 |
29 | def start():
30 |
31 | print(c_ipA)
32 | print(c_port)
33 |
34 | # Open Port?
35 | """
36 | #open Port
37 | if (c_port != ""):
38 | cmd = 'netsh advfirewall firewall add rule name= \"Open Port ' + str(c_port) + '\" dir=in action=allow protocol=TCP localport='+str(c_port)
39 | #os.system('cmd /k ' + cmd)
40 | subprocess.call(['runas', '/user:Administrator', cmd])
41 | else:
42 | #cmd = "echo Hello"#"netsh advfirewall firewall add rule name= \"Open Port \" dir=in action=allow protocol=TCP localport=80"
43 | #os.system('cmd /k ' + cmd)
44 | pass
45 | """
46 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
47 | s.settimeout(5)
48 | if c_ipA != "" and c_port != "":
49 | print("Connecting with custom ip adress and port...")
50 | s.bind((c_ipA, int(c_port)))
51 | elif c_ipA == "" and c_port != "":
52 | print("Connecting with custom port...")
53 | s.bind((getIP(), int(c_port)))
54 | elif c_ipA != "" and c_port == "":
55 | print("Connecting with custom ip adress...")
56 | s.bind((c_ipA, PORT))
57 | else:
58 | print("Connecting with default values...")
59 | s.bind(ADDR)
60 | s.listen()
61 | print("Server Started...")
62 |
63 | global runServer
64 | global stopServer
65 | while runServer:
66 | print("Server Running...")
67 | try:
68 | conn, addr = s.accept()
69 | conn.settimeout(5)
70 | with conn:
71 | print("connected by", addr)
72 | connected = True
73 | while connected:
74 | try:
75 | msg = conn.recv(1024)
76 | if not msg:
77 | break
78 |
79 | msg = msg.decode(FORMAT)
80 |
81 | if "scene" in msg:
82 | try:
83 | scene = int(msg[5:])
84 | scenes = obs.obs_frontend_get_scenes()
85 | if len(scenes) >= (scene + 1):
86 | obs.obs_frontend_set_current_scene(
87 | scenes[scene]
88 | )
89 | except:
90 | pass
91 | elif "s_mute" in msg:
92 | try:
93 | msource = str(msg[6:])
94 | source = obs.obs_get_source_by_name(msource)
95 | if source is not None:
96 | obs.obs_source_set_muted(source, True)
97 | except:
98 | pass
99 | elif "s_unmute" in msg:
100 | try:
101 | umsource = str(msg[8:])
102 | source = obs.obs_get_source_by_name(umsource)
103 | if source is not None:
104 | obs.obs_source_set_muted(source, False)
105 | except:
106 | pass
107 | elif "s_hide" in msg:
108 | try:
109 | hsource = str(msg[6:])
110 | source = obs.obs_get_source_by_name(hsource)
111 | if source is not None:
112 | obs.obs_source_set_enabled(source, False)
113 | except:
114 | pass
115 | elif "s_unhide" in msg:
116 | try:
117 | uhsource = str(msg[8:])
118 | source = obs.obs_get_source_by_name(uhsource)
119 | if source is not None:
120 | obs.obs_source_set_enabled(source, True)
121 | except:
122 | pass
123 |
124 | elif "st_start" in msg:
125 | try:
126 | obs.obs_frontend_streaming_start()
127 | except:
128 | pass
129 | elif "st_stop" in msg:
130 | try:
131 | obs.obs_frontend_streaming_stop()
132 | except:
133 | pass
134 | elif "re_start" in msg:
135 | try:
136 | obs.obs_frontend_recording_start()
137 | except:
138 | pass
139 | elif "re_stop" in msg:
140 | try:
141 | obs.obs_frontend_recording_stop()
142 | except:
143 | pass
144 | elif "re_pause" in msg:
145 | try:
146 | if obs.obs_frontend_recording_paused():
147 | obs.obs_frontend_recording_pause(False)
148 | else:
149 | obs.obs_frontend_recording_pause(True)
150 | except:
151 | pass
152 |
153 | if "server_stop" in msg:
154 | connected = False
155 | runServer = False
156 | stopServer = False
157 | except:
158 | if runServer == False:
159 | connected = False
160 |
161 | print("Closing Connection")
162 | conn.close()
163 | print("Server Stopped...")
164 | sys.exit()
165 | except:
166 | pass
167 |
168 | print("Server Stopped...")
169 | sys.exit()
170 |
171 |
172 | def startstop_server(prps, prop):
173 | global runServer
174 | global stopServer
175 | if stopServer == True:
176 | print("Stopping Server...")
177 | stopServer = False
178 | runServer = False
179 | else:
180 | runServer = True
181 | stopServer = True
182 | thread = threading.Thread(target=start)
183 | thread.start()
184 |
185 |
186 | def script_description():
187 | return (
188 | "Connect to "
189 | + getIP()
190 | + " on Port "
191 | + str(PORT)
192 | + "\n \nor use custom values if you want to use another port or the given ip adress is incorrect:"
193 | )
194 |
195 |
196 | def script_update(settings):
197 | global c_ipA
198 | global c_port
199 |
200 | c_ipA = obs.obs_data_get_string(settings, "c_ipA")
201 | c_port = obs.obs_data_get_string(settings, "c_port")
202 |
203 |
204 | def script_properties():
205 |
206 | props = obs.obs_properties_create()
207 |
208 | obs.obs_properties_add_text(
209 | props, "c_ipA", "Custom Ip Adress", obs.OBS_TEXT_DEFAULT
210 | )
211 | obs.obs_properties_add_text(props, "c_port", "Custom Port", obs.OBS_TEXT_DEFAULT)
212 |
213 | obs.obs_properties_add_button(
214 | props, "button", "Start/Stop Server", startstop_server
215 | )
216 |
217 | return props
218 |
219 |
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | archive:
5 | dependency: transitive
6 | description:
7 | name: archive
8 | url: "https://pub.dartlang.org"
9 | source: hosted
10 | version: "2.0.13"
11 | args:
12 | dependency: transitive
13 | description:
14 | name: args
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "1.6.0"
18 | async:
19 | dependency: transitive
20 | description:
21 | name: async
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "2.5.0-nullsafety.1"
25 | boolean_selector:
26 | dependency: transitive
27 | description:
28 | name: boolean_selector
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "2.1.0-nullsafety.1"
32 | characters:
33 | dependency: transitive
34 | description:
35 | name: characters
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.1.0-nullsafety.3"
39 | charcode:
40 | dependency: transitive
41 | description:
42 | name: charcode
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "1.2.0-nullsafety.1"
46 | clock:
47 | dependency: transitive
48 | description:
49 | name: clock
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "1.1.0-nullsafety.1"
53 | collection:
54 | dependency: transitive
55 | description:
56 | name: collection
57 | url: "https://pub.dartlang.org"
58 | source: hosted
59 | version: "1.15.0-nullsafety.3"
60 | convert:
61 | dependency: transitive
62 | description:
63 | name: convert
64 | url: "https://pub.dartlang.org"
65 | source: hosted
66 | version: "2.1.1"
67 | crypto:
68 | dependency: transitive
69 | description:
70 | name: crypto
71 | url: "https://pub.dartlang.org"
72 | source: hosted
73 | version: "2.1.5"
74 | cupertino_icons:
75 | dependency: "direct main"
76 | description:
77 | name: cupertino_icons
78 | url: "https://pub.dartlang.org"
79 | source: hosted
80 | version: "1.0.0"
81 | fake_async:
82 | dependency: transitive
83 | description:
84 | name: fake_async
85 | url: "https://pub.dartlang.org"
86 | source: hosted
87 | version: "1.2.0-nullsafety.1"
88 | ffi:
89 | dependency: transitive
90 | description:
91 | name: ffi
92 | url: "https://pub.dartlang.org"
93 | source: hosted
94 | version: "0.1.3"
95 | file:
96 | dependency: transitive
97 | description:
98 | name: file
99 | url: "https://pub.dartlang.org"
100 | source: hosted
101 | version: "5.2.1"
102 | flutter:
103 | dependency: "direct main"
104 | description: flutter
105 | source: sdk
106 | version: "0.0.0"
107 | flutter_launcher_icons:
108 | dependency: "direct dev"
109 | description:
110 | name: flutter_launcher_icons
111 | url: "https://pub.dartlang.org"
112 | source: hosted
113 | version: "0.8.1"
114 | flutter_test:
115 | dependency: "direct dev"
116 | description: flutter
117 | source: sdk
118 | version: "0.0.0"
119 | flutter_web_plugins:
120 | dependency: transitive
121 | description: flutter
122 | source: sdk
123 | version: "0.0.0"
124 | focused_menu:
125 | dependency: "direct main"
126 | description:
127 | name: focused_menu
128 | url: "https://pub.dartlang.org"
129 | source: hosted
130 | version: "1.0.1"
131 | hive:
132 | dependency: "direct main"
133 | description:
134 | name: hive
135 | url: "https://pub.dartlang.org"
136 | source: hosted
137 | version: "1.4.4+1"
138 | hive_flutter:
139 | dependency: "direct main"
140 | description:
141 | name: hive_flutter
142 | url: "https://pub.dartlang.org"
143 | source: hosted
144 | version: "0.3.1"
145 | image:
146 | dependency: transitive
147 | description:
148 | name: image
149 | url: "https://pub.dartlang.org"
150 | source: hosted
151 | version: "2.1.19"
152 | intl:
153 | dependency: transitive
154 | description:
155 | name: intl
156 | url: "https://pub.dartlang.org"
157 | source: hosted
158 | version: "0.16.1"
159 | matcher:
160 | dependency: transitive
161 | description:
162 | name: matcher
163 | url: "https://pub.dartlang.org"
164 | source: hosted
165 | version: "0.12.10-nullsafety.1"
166 | meta:
167 | dependency: transitive
168 | description:
169 | name: meta
170 | url: "https://pub.dartlang.org"
171 | source: hosted
172 | version: "1.3.0-nullsafety.3"
173 | path:
174 | dependency: transitive
175 | description:
176 | name: path
177 | url: "https://pub.dartlang.org"
178 | source: hosted
179 | version: "1.8.0-nullsafety.1"
180 | path_provider:
181 | dependency: transitive
182 | description:
183 | name: path_provider
184 | url: "https://pub.dartlang.org"
185 | source: hosted
186 | version: "1.6.24"
187 | path_provider_linux:
188 | dependency: transitive
189 | description:
190 | name: path_provider_linux
191 | url: "https://pub.dartlang.org"
192 | source: hosted
193 | version: "0.0.1+2"
194 | path_provider_macos:
195 | dependency: transitive
196 | description:
197 | name: path_provider_macos
198 | url: "https://pub.dartlang.org"
199 | source: hosted
200 | version: "0.0.4+6"
201 | path_provider_platform_interface:
202 | dependency: transitive
203 | description:
204 | name: path_provider_platform_interface
205 | url: "https://pub.dartlang.org"
206 | source: hosted
207 | version: "1.0.4"
208 | path_provider_windows:
209 | dependency: transitive
210 | description:
211 | name: path_provider_windows
212 | url: "https://pub.dartlang.org"
213 | source: hosted
214 | version: "0.0.4+3"
215 | petitparser:
216 | dependency: transitive
217 | description:
218 | name: petitparser
219 | url: "https://pub.dartlang.org"
220 | source: hosted
221 | version: "3.1.0"
222 | platform:
223 | dependency: transitive
224 | description:
225 | name: platform
226 | url: "https://pub.dartlang.org"
227 | source: hosted
228 | version: "2.2.1"
229 | plugin_platform_interface:
230 | dependency: transitive
231 | description:
232 | name: plugin_platform_interface
233 | url: "https://pub.dartlang.org"
234 | source: hosted
235 | version: "1.0.3"
236 | process:
237 | dependency: transitive
238 | description:
239 | name: process
240 | url: "https://pub.dartlang.org"
241 | source: hosted
242 | version: "3.0.13"
243 | sky_engine:
244 | dependency: transitive
245 | description: flutter
246 | source: sdk
247 | version: "0.0.99"
248 | source_span:
249 | dependency: transitive
250 | description:
251 | name: source_span
252 | url: "https://pub.dartlang.org"
253 | source: hosted
254 | version: "1.8.0-nullsafety.2"
255 | stack_trace:
256 | dependency: transitive
257 | description:
258 | name: stack_trace
259 | url: "https://pub.dartlang.org"
260 | source: hosted
261 | version: "1.10.0-nullsafety.1"
262 | stream_channel:
263 | dependency: transitive
264 | description:
265 | name: stream_channel
266 | url: "https://pub.dartlang.org"
267 | source: hosted
268 | version: "2.1.0-nullsafety.1"
269 | string_scanner:
270 | dependency: transitive
271 | description:
272 | name: string_scanner
273 | url: "https://pub.dartlang.org"
274 | source: hosted
275 | version: "1.1.0-nullsafety.1"
276 | term_glyph:
277 | dependency: transitive
278 | description:
279 | name: term_glyph
280 | url: "https://pub.dartlang.org"
281 | source: hosted
282 | version: "1.2.0-nullsafety.1"
283 | test_api:
284 | dependency: transitive
285 | description:
286 | name: test_api
287 | url: "https://pub.dartlang.org"
288 | source: hosted
289 | version: "0.2.19-nullsafety.2"
290 | typed_data:
291 | dependency: transitive
292 | description:
293 | name: typed_data
294 | url: "https://pub.dartlang.org"
295 | source: hosted
296 | version: "1.3.0-nullsafety.3"
297 | url_launcher:
298 | dependency: "direct main"
299 | description:
300 | name: url_launcher
301 | url: "https://pub.dartlang.org"
302 | source: hosted
303 | version: "5.7.10"
304 | url_launcher_linux:
305 | dependency: transitive
306 | description:
307 | name: url_launcher_linux
308 | url: "https://pub.dartlang.org"
309 | source: hosted
310 | version: "0.0.1+4"
311 | url_launcher_macos:
312 | dependency: transitive
313 | description:
314 | name: url_launcher_macos
315 | url: "https://pub.dartlang.org"
316 | source: hosted
317 | version: "0.0.1+9"
318 | url_launcher_platform_interface:
319 | dependency: transitive
320 | description:
321 | name: url_launcher_platform_interface
322 | url: "https://pub.dartlang.org"
323 | source: hosted
324 | version: "1.0.9"
325 | url_launcher_web:
326 | dependency: transitive
327 | description:
328 | name: url_launcher_web
329 | url: "https://pub.dartlang.org"
330 | source: hosted
331 | version: "0.1.5+1"
332 | url_launcher_windows:
333 | dependency: transitive
334 | description:
335 | name: url_launcher_windows
336 | url: "https://pub.dartlang.org"
337 | source: hosted
338 | version: "0.0.1+3"
339 | vector_math:
340 | dependency: transitive
341 | description:
342 | name: vector_math
343 | url: "https://pub.dartlang.org"
344 | source: hosted
345 | version: "2.1.0-nullsafety.3"
346 | win32:
347 | dependency: transitive
348 | description:
349 | name: win32
350 | url: "https://pub.dartlang.org"
351 | source: hosted
352 | version: "1.7.4"
353 | xdg_directories:
354 | dependency: transitive
355 | description:
356 | name: xdg_directories
357 | url: "https://pub.dartlang.org"
358 | source: hosted
359 | version: "0.1.2"
360 | xml:
361 | dependency: transitive
362 | description:
363 | name: xml
364 | url: "https://pub.dartlang.org"
365 | source: hosted
366 | version: "4.5.1"
367 | yaml:
368 | dependency: transitive
369 | description:
370 | name: yaml
371 | url: "https://pub.dartlang.org"
372 | source: hosted
373 | version: "2.2.1"
374 | sdks:
375 | dart: ">=2.10.0-110 <2.11.0"
376 | flutter: ">=1.22.0 <2.0.0"
377 |
--------------------------------------------------------------------------------
/lib/screens/deck_screen.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:hive/hive.dart';
5 | import 'package:Streamdeck/utils/enums.dart';
6 | import 'package:Streamdeck/utils/layouts.dart';
7 |
8 | class DeckScreen extends StatefulWidget {
9 | const DeckScreen({
10 | Key key,
11 | this.ip,
12 | this.port,
13 | @required this.socket,
14 | }) : super(key: key);
15 |
16 | final Socket socket;
17 | final String ip;
18 | final String port;
19 |
20 | @override
21 | _DeckScreenState createState() => _DeckScreenState();
22 | }
23 |
24 | class _DeckScreenState extends State {
25 | List