Skip to content

Commit

Permalink
Release beta18 (#263)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdlukaa authored Sep 9, 2024
2 parents 53e7a28 + b62ecbc commit ef0b93b
Show file tree
Hide file tree
Showing 27 changed files with 202 additions and 131 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
submodules: recursive
# We need to enforce java 17 because newer Flutter packages are
# requiring this Java Version.
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
cache: 'gradle'
check-latest: true
- uses: subosito/[email protected]
with:
channel: "stable"
Expand Down
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ lib
packages
├───unity_multi_window [multi-window support for desktop platforms.]
├───unity_multi_window [multi-window support for desktop platforms.]
├───unity_video_player
│ ├───unity_video_player [the core video player logic.]
Expand All @@ -165,6 +165,22 @@ packages

Feel free to send any pull-requests to add any features you wish or fix any bugs you notice.

### Video Rendering

We support multiple platforms and each platform uses its own rendering backend.

| Platform | Rendering Backend | Flutter Package |
| ------------ | ----------------- | --------------- |
| Android | MPV | media_kit |
| iOS | MPV | media_kit |
| Windows | MPV | media_kit |
| MacOS | MPV | media_kit |
| Web | HTML5 | fvp |
| Linux | MDK | fvp |
| Raspberry Pi | MDK | fvp |

MDK is used for Linux and Raspberry Pi because MPV has shown to be unstable on these platforms, causing crashes. Additionally, `fvp` doesn't require the user to install any additional dependencies.

### Build

The build process is pretty straight-forward. You need to have [Flutter](https://flutter.dev/docs/get-started/install) installed on your system.
Expand Down Expand Up @@ -192,4 +208,4 @@ When running on debug, you must disable the CORS policy in your browser. Note th

```bash
flutter run -d chrome --web-browser-flag "--disable-web-security"
```
```
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ android {
ndkVersion flutter.ndkVersion

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}

kotlinOptions {
Expand Down
5 changes: 5 additions & 0 deletions bluecherry_appcast.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle">
<channel>
<title>Bluecherry - Appcast</title>
<item>
<title>Version 3.0.0-beta19</title>
<description>Linux and Timeline enhancements.</description>
<pubDate>Mon, 09 Sep 2024</pubDate>
</item>
<item>
<title>Version 3.0.0-beta18</title>
<description>Time Filter for Events; Fixed crash on newer versions of Windows.</description>
Expand Down
2 changes: 1 addition & 1 deletion installer/windows-installer.iss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "Bluecherry DVR"
#define MyAppVersion "3.0.0-beta18"
#define MyAppVersion "3.0.0-beta19"
#define MyAppPublisher "Bluecherry DVR"
#define MyAppURL "https://www.bluecherrydvr.com/"
#define MyAppExeName "bluecherry_client.exe"
Expand Down
18 changes: 9 additions & 9 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
*/

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:bluecherry_client/api/api.dart';
Expand Down Expand Up @@ -117,12 +116,12 @@ Future<void> main(List<String> args) async {
await SettingsProvider.ensureInitialized();
await DesktopViewProvider.ensureInitialized();

final windowType = MultiWindowType.values[int.tryParse(args[1]) ?? 0];
final themeMode = ThemeMode.values[int.tryParse(args[3]) ?? 0];
final (windowType, themeMode, map) =
LayoutWindowExtension.fromArgs(args);

switch (windowType) {
case MultiWindowType.device:
final device = Device.fromJson(json.decode(args[2]));
final device = Device.fromJson(map);
configureWindowTitle(device.fullName);

runApp(AlternativeWindow(
Expand All @@ -131,7 +130,7 @@ Future<void> main(List<String> args) async {
));
break;
case MultiWindowType.layout:
final layout = Layout.fromJson(args[2]);
final layout = Layout.fromMap(map);
configureWindowTitle(layout.name);

runApp(AlternativeWindow(
Expand Down Expand Up @@ -268,10 +267,11 @@ class _UnityAppState extends State<UnityApp>
case NetworkUsage.wifiOnly:
debugPrint('Pausing all streams');
final connectionType = await Connectivity().checkConnectivity();
if (connectionType == ConnectivityResult.mobile ||
connectionType == ConnectivityResult.bluetooth) {
UnityPlayers.pauseAll();
}
if ([
ConnectivityResult.bluetooth,
ConnectivityResult.mobile,
].any(connectionType.contains)) UnityPlayers.pauseAll();

break;
case NetworkUsage.never:
break;
Expand Down
5 changes: 0 additions & 5 deletions lib/models/layout.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import 'dart:convert';
import 'dart:io';

import 'package:bluecherry_client/models/device.dart';
Expand Down Expand Up @@ -107,10 +106,6 @@ class Layout {
);
}

String toJson() => json.encode(toMap());

factory Layout.fromJson(String source) => Layout.fromMap(json.decode(source));

Layout copyWith({
String? name,
List<Device>? devices,
Expand Down
2 changes: 2 additions & 0 deletions lib/providers/desktop_view_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ class DesktopViewProvider extends UnityProvider {
return save(notifyListeners: false);
}

Iterable<Device> get allDevices => layouts.expand((layout) => layout.devices);

/// Removes all the [devices] provided
///
/// This is usually used when a server is deleted
Expand Down
42 changes: 38 additions & 4 deletions lib/providers/home_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
*/

import 'package:bluecherry_client/main.dart';
import 'package:bluecherry_client/providers/desktop_view_provider.dart';
import 'package:bluecherry_client/providers/server_provider.dart';
import 'package:bluecherry_client/providers/settings_provider.dart';
import 'package:bluecherry_client/providers/update_provider.dart';
import 'package:bluecherry_client/utils/methods.dart';
import 'package:bluecherry_client/utils/video_player.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
Expand Down Expand Up @@ -91,19 +93,51 @@ class HomeProvider extends ChangeNotifier {

List<UnityLoadingReason> loadReasons = [];

/// Stores the volume of each device.
///
/// These are filled when the user leaves the Devices tab and cleared when
/// they come back.
Map<String, double> volumes = {};

Future<void> setTab(UnityTab tab, BuildContext context) async {
if (tab == this.tab) return;

final currentTab = this.tab;
final nextTab = tab;

this.tab = tab;

if (tab != UnityTab.downloads) {
initiallyExpandedDownloadEventId = null;
}
if (nextTab != UnityTab.downloads) initiallyExpandedDownloadEventId = null;

if (tab != UnityTab.addServer) {
if (nextTab != UnityTab.addServer) {
automaticallyGoToAddServersScreen = false;
}

if (currentTab == UnityTab.deviceGrid) {
// If we're moving out of the device grid tab, we should not be able to
// hear the live feed anymore.

final devices = DesktopViewProvider.instance.allDevices;
final players = UnityPlayers.players.entries
.where((entry) => devices.any((device) => device.uuid == entry.key))
.toList();

for (final player in players) {
volumes[player.key] = player.value.volume;
player.value.setVolume(0.0);
}
} else if (nextTab == UnityTab.deviceGrid) {
// When the user comes back to the device grid, we should restore the
// volume of the devices.

for (final entry in volumes.entries) {
final player = UnityPlayers.players[entry.key];
if (player != null) player.setVolume(entry.value);
}

volumes.clear();
}

refreshDeviceOrientation(context);
updateWakelock(context);
notifyListeners();
Expand Down
2 changes: 2 additions & 0 deletions lib/screens/events_timeline/events_playback.dart
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ class _EventsPlaybackState extends EventsScreenState<EventsPlayback> {
initialPosition: switch (settings.kTimelineInitialPoint.value) {
TimelineInitialPoint.beginning => Duration.zero,
TimelineInitialPoint.firstEvent => () {
if (parsedTiles.isEmpty) return Duration.zero;

final firstEvent = parsedTiles
.map((e) {
final earliestEvent = e.events.reduce(
Expand Down
17 changes: 11 additions & 6 deletions lib/screens/layouts/desktop/layout_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -246,17 +246,22 @@ class LayoutView extends StatelessWidget {
);
}

final isAlternativeWindow = AlternativeWindow.maybeOf(context) != null;
final parent = context.findAncestorWidgetOfExactType<LargeDeviceGrid>();
final isReversed =
context.findAncestorWidgetOfExactType<LargeDeviceGrid>()!.width <=
_kReverseBreakpoint;
parent == null ? false : parent.width <= _kReverseBreakpoint;

return Material(
color: Colors.black,
shape: RoundedRectangleBorder(
borderRadius: BorderRadiusDirectional.only(
topStart: isReversed ? Radius.zero : const Radius.circular(8.0),
topEnd: isReversed ? const Radius.circular(8.0) : Radius.zero,
),
borderRadius: isAlternativeWindow
? BorderRadius.zero
: BorderRadiusDirectional.only(
topStart:
isReversed ? Radius.zero : const Radius.circular(8.0),
topEnd:
isReversed ? const Radius.circular(8.0) : Radius.zero,
),
),
child: SafeArea(
child: Column(
Expand Down
1 change: 1 addition & 0 deletions lib/screens/layouts/device_grid.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import 'package:bluecherry_client/screens/layouts/desktop/external_stream.dart';
import 'package:bluecherry_client/screens/layouts/desktop/layout_manager.dart';
import 'package:bluecherry_client/screens/layouts/desktop/viewport.dart';
import 'package:bluecherry_client/screens/layouts/mobile/device_view.dart';
import 'package:bluecherry_client/screens/multi_window/window.dart';
import 'package:bluecherry_client/utils/app_links/app_links.dart' as app_links;
import 'package:bluecherry_client/utils/constants.dart';
import 'package:bluecherry_client/utils/extensions.dart';
Expand Down
2 changes: 1 addition & 1 deletion lib/utils/app_links/app_links_real.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ void listen() {
// See https://github.com/llfbandit/app_links/issues/20 for more info.
if (isDesktopPlatform && !Platform.isLinux) {
WidgetsBinding.instance.addPostFrameCallback((_) {
instance.allUriLinkStream.listen((uri) async {
instance.uriLinkStream.listen((uri) async {
debugPrint('Received URI: $uri');
await writeLogToFile('Received URI $uri');
final handleType = await _handleUri(uri);
Expand Down
14 changes: 11 additions & 3 deletions lib/utils/window.dart
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,25 @@ extension DeviceWindowExtension on Device {

debugPrint('Opening a new window');
final window = await MultiWindow.run([
'multi_window',
'${MultiWindowType.device.index}',
json.encode(toJson()),
'${SettingsProvider.instance.kThemeMode.value.index}',
json.encode(toJson()),
]);

debugPrint('Opened window with id ${window.windowId}');
}
}

extension LayoutWindowExtension on Layout {
static (MultiWindowType, ThemeMode, Map<String, dynamic>) fromArgs(
List<String> args,
) {
final type = MultiWindowType.values[int.parse(args[0])];
final themeMode = ThemeMode.values[int.parse(args[1])];
final map = json.decode(args[2]);
return (type, themeMode, map);
}

Future<void> openInANewWindow() async {
assert(
isDesktopPlatform,
Expand All @@ -118,8 +126,8 @@ extension LayoutWindowExtension on Layout {
debugPrint('Opening a new window');
final window = await MultiWindow.run([
'${MultiWindowType.layout.index}',
json.encode(toMap()),
'${SettingsProvider.instance.kThemeMode.value.index}',
json.encode(toMap()),
]);

debugPrint('Opened window with id ${window.windowId}');
Expand Down
2 changes: 1 addition & 1 deletion linux/debian/DEBIAN/control
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: bluecherrydvr
Version: 3.0.0-beta18
Version: 3.0.0-beta19
Section: base
Priority: optional
Homepage: https://www.bluecherrydvr.com/
Expand Down
1 change: 1 addition & 0 deletions linux/debian/usr/share/metainfo/bluecherry.appdata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
<launchable type="desktop-id">bluecherrydvr.desktop</launchable>
<releases>
<!-- <release version="VERSION" date="YYYY-MM-DD" />| -->
<release version="3.0.0-beta19" date="2024-09-09" />|
<release version="3.0.0-beta18" date="2024-07-10" />|
<release version="3.0.0-beta17" date="2024-06-07" />|
<release version="3.0.0-beta16" date="2024-04-15" />|
Expand Down
8 changes: 0 additions & 8 deletions linux/flutter/generated_plugin_registrant.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@
#include <awesome_notifications/awesome_notifications_plugin.h>
#include <fvp/fvp_plugin.h>
#include <gtk/gtk_plugin.h>
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
#include <media_kit_video/media_kit_video_plugin.h>
#include <screen_retriever/screen_retriever_plugin.h>
#include <system_date_time_format/system_date_time_format_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
#include <window_manager/window_manager_plugin.h>

Expand All @@ -26,18 +24,12 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) gtk_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "GtkPlugin");
gtk_plugin_register_with_registrar(gtk_registrar);
g_autoptr(FlPluginRegistrar) media_kit_libs_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitLibsLinuxPlugin");
media_kit_libs_linux_plugin_register_with_registrar(media_kit_libs_linux_registrar);
g_autoptr(FlPluginRegistrar) media_kit_video_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitVideoPlugin");
media_kit_video_plugin_register_with_registrar(media_kit_video_registrar);
g_autoptr(FlPluginRegistrar) screen_retriever_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin");
screen_retriever_plugin_register_with_registrar(screen_retriever_registrar);
g_autoptr(FlPluginRegistrar) system_date_time_format_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "SystemDateTimeFormatPlugin");
system_date_time_format_plugin_register_with_registrar(system_date_time_format_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
Expand Down
2 changes: 0 additions & 2 deletions linux/flutter/generated_plugins.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ list(APPEND FLUTTER_PLUGIN_LIST
awesome_notifications
fvp
gtk
media_kit_libs_linux
media_kit_video
screen_retriever
system_date_time_format
url_launcher_linux
window_manager
)
Expand Down
2 changes: 1 addition & 1 deletion linux/rpm/bluecherry.spec
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Name: bluecherrydvr
Version: 3.0.0_beta18
Version: 3.0.0_beta19
Release: 1
Summary: Bluecherry client written in Flutter.
License: EULA
Expand Down
Loading

0 comments on commit ef0b93b

Please sign in to comment.