First Cut
This commit is contained in:
parent
68c83f2c9a
commit
15e4793ba8
|
@ -4,11 +4,13 @@ import 'package:cwtch/main.dart';
|
|||
import 'package:cwtch/models/appstate.dart';
|
||||
import 'package:cwtch/models/contact.dart';
|
||||
import 'package:cwtch/models/message.dart';
|
||||
import 'package:cwtch/models/messages/VidMessage.dart';
|
||||
import 'package:cwtch/models/profilelist.dart';
|
||||
import 'package:cwtch/models/profileservers.dart';
|
||||
import 'package:cwtch/models/remoteserver.dart';
|
||||
import 'package:cwtch/models/servers.dart';
|
||||
import 'package:cwtch/notification_manager.dart';
|
||||
import 'package:cwtch/views/vidchatview.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
@ -187,6 +189,24 @@ class CwtchNotifier {
|
|||
break;
|
||||
case "NewMessageFromPeer":
|
||||
var identifier = int.parse(data["ConversationID"]);
|
||||
dynamic message = jsonDecode(data["Data"]);
|
||||
var overlay = int.parse(message['o'].toString());
|
||||
|
||||
if (overlay == VideoOverlay) {
|
||||
try {
|
||||
VidMessage vmsg = VidMessage.fromJson(message);
|
||||
EnvironmentConfig.debugLog("send latency = ${DateTime.now().toUtc().difference(vmsg.s ?? DateTime.now()).inMilliseconds}");
|
||||
EnvironmentConfig.debugLog("tor latency = ${DateTime.now().toUtc().difference(vmsg.t ?? DateTime.now()).inMilliseconds}");
|
||||
EnvironmentConfig.debugLog("recv latency = ${DateTime.now().toUtc().difference(vmsg.r ?? DateTime.now()).inMilliseconds}");
|
||||
|
||||
profileCN.getProfile(data["ProfileOnion"])!.contactList.getContact(identifier)!.vid = vmsg.d;
|
||||
} catch (e) {
|
||||
EnvironmentConfig.debugLog("error decoding video stream: $e: ${message['d']}");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
var messageID = int.parse(data["Index"]);
|
||||
var timestamp = DateTime.tryParse(data['TimestampReceived'])!;
|
||||
var senderHandle = data['RemotePeer'];
|
||||
|
|
|
@ -648,4 +648,20 @@ class MaterialLocalizationLu extends MaterialLocalizations {
|
|||
@override
|
||||
// TODO: implement scanTextButtonLabel
|
||||
String get scanTextButtonLabel => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
// TODO: implement lookUpButtonLabel
|
||||
String get lookUpButtonLabel => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
// TODO: implement menuDismissLabel
|
||||
String get menuDismissLabel => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
// TODO: implement searchWebButtonLabel
|
||||
String get searchWebButtonLabel => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
// TODO: implement shareButtonLabel
|
||||
String get shareButtonLabel => throw UnimplementedError();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:ffi';
|
||||
|
||||
import 'package:cwtch/config.dart';
|
||||
import 'package:cwtch/main.dart';
|
||||
import 'package:cwtch/models/message_draft.dart';
|
||||
import 'package:cwtch/models/profile.dart';
|
||||
|
@ -7,6 +9,7 @@ import 'package:cwtch/models/redaction.dart';
|
|||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:cwtch/views/contactsview.dart';
|
||||
import 'package:cwtch/widgets/messagerow.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
@ -133,6 +136,14 @@ class ContactInfoState extends ChangeNotifier {
|
|||
MessageDraft get messageDraft => this._messageDraft;
|
||||
|
||||
DateTime get lastRetryTime => this._lastRetryTime;
|
||||
|
||||
Uint8List _vid = Uint8List(0);
|
||||
Uint8List get vid => _vid;
|
||||
set vid(data) {
|
||||
this._vid = data;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
set lastRetryTime(DateTime lastRetryTime) {
|
||||
this._lastRetryTime = lastRetryTime;
|
||||
notifyListeners();
|
||||
|
|
|
@ -20,7 +20,7 @@ const QuotedMessageOverlay = 10;
|
|||
const SuggestContactOverlay = 100;
|
||||
const InviteGroupOverlay = 101;
|
||||
const FileShareOverlay = 200;
|
||||
|
||||
const VideoOverlay = 0xF07;
|
||||
// Defines the length of the tor v3 onion address. Code using this constant will
|
||||
// need to updated when we allow multiple different identifiers. At which time
|
||||
// it will likely be prudent to define a proper Contact wrapper.
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import 'package:cwtch/third_party/base85/base_85_encoder.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../../third_party/base85/base_85_codec.dart';
|
||||
|
||||
class VidMessage {
|
||||
final int o;
|
||||
final Uint8List d;
|
||||
DateTime? s;
|
||||
DateTime? r;
|
||||
DateTime? t;
|
||||
|
||||
VidMessage({required this.o, required this.d});
|
||||
|
||||
VidMessage.fromJson(Map<String, dynamic> json)
|
||||
: o = json['o'],
|
||||
d = Base85Codec.new().decode(json['d']),
|
||||
s = DateTime.tryParse(json['s'] ?? ""),
|
||||
t = DateTime.tryParse(json['t'] ?? ""),
|
||||
r = DateTime.tryParse(json['r'] ?? "");
|
||||
|
||||
Map<String, dynamic> toJson() => {'o': o, 'd': Base85Codec.new().encode(d), 's': DateTime.now().toUtc().toIso8601String()};
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 51d8c18dd869702fbef77ce574493078a2acf54d
|
|
@ -0,0 +1,31 @@
|
|||
## 0.0.1
|
||||
|
||||
* Initial release.
|
||||
|
||||
## 0.0.2
|
||||
|
||||
* Fixes in core API.
|
||||
|
||||
## 0.0.3
|
||||
|
||||
* Created API for storing frame into Base64 Image.
|
||||
|
||||
## 0.0.4
|
||||
|
||||
* Code refractor
|
||||
|
||||
## 0.0.5
|
||||
|
||||
* Converted API functions into asyc functions.
|
||||
|
||||
## 0.0.6
|
||||
|
||||
* Dart SDK version changed to 3.1.0
|
||||
|
||||
## 0.0.7
|
||||
|
||||
* OpenCV Dependencies added statically
|
||||
|
||||
## 0.0.8
|
||||
|
||||
* OpenCV static dependencies removed
|
|
@ -0,0 +1,60 @@
|
|||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2023, Open Privacy Research Society
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----
|
||||
Original License Follows...
|
||||
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2023, Muhammad Islam
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,93 @@
|
|||
# camera_linux
|
||||
|
||||
Camera Linux is a Flutter FFI plugin designed specifically for the Linux platform. This plugin allows Flutter developers to access and capture images from the Linux camera, seamlessly integrating native code invocation using Dart's FFI.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Dart FFI Integration: Built on top of Flutter's FFI (Foreign Function Interface) to directly invoke native functions.
|
||||
Platform-Specific: Tailored for Linux, ensuring optimal performance and compatibility.
|
||||
Easy Access to Camera: Provides straightforward functions to capture images directly from the Linux camera.
|
||||
|
||||
## Project structure
|
||||
|
||||
This template uses the following structure:
|
||||
|
||||
* `src`: Contains the native source code, and a CmakeFile.txt file for building
|
||||
that source code into a dynamic library.
|
||||
|
||||
* `lib`: Contains the Dart code that defines the API of the plugin, and which
|
||||
calls into the native code using `dart:ffi`.
|
||||
|
||||
* platform folder (`linux`): Contains the build files
|
||||
for building and bundling the native code library with the platform application.
|
||||
|
||||
## Building and bundling native code
|
||||
|
||||
The `pubspec.yaml` specifies FFI plugins as follows:
|
||||
|
||||
```yaml
|
||||
plugin:
|
||||
platforms:
|
||||
some_platform:
|
||||
ffiPlugin: true
|
||||
```
|
||||
|
||||
This configuration invokes the native build for the various target platforms
|
||||
and bundles the binaries in Flutter applications using these FFI plugins.
|
||||
|
||||
This can be combined with dartPluginClass, such as when FFI is used for the
|
||||
implementation of one platform in a federated plugin:
|
||||
|
||||
```yaml
|
||||
plugin:
|
||||
implements: some_other_plugin
|
||||
platforms:
|
||||
some_platform:
|
||||
dartPluginClass: SomeClass
|
||||
ffiPlugin: true
|
||||
```
|
||||
|
||||
A plugin can have both FFI and method channels:
|
||||
|
||||
```yaml
|
||||
plugin:
|
||||
platforms:
|
||||
some_platform:
|
||||
pluginClass: SomeName
|
||||
ffiPlugin: true
|
||||
```
|
||||
|
||||
The native build systems that are invoked by FFI (and method channel) plugin is:
|
||||
|
||||
* For Linux and Windows: CMake.
|
||||
* See the documentation in linux/CMakeLists.txt.
|
||||
* See the documentation in windows/CMakeLists.txt.
|
||||
|
||||
## Binding to native code
|
||||
|
||||
Instead of manually writing the Dart bindings to native code, they are auto-generated from the header file (src/camera_linux.h) using the package:ffigen. To refresh these bindings, execute:
|
||||
|
||||
`flutter pub run ffigen --config ffigen.yaml`
|
||||
|
||||
## Invoking native code
|
||||
|
||||
Very short-running native functions can be directly invoked from any isolate.
|
||||
For example, see `sum` in `lib/camera_linux.dart`.
|
||||
|
||||
Longer-running functions should be invoked on a helper isolate to avoid
|
||||
dropping frames in Flutter applications.
|
||||
For example, see `sumAsync` in `lib/camera_linux.dart`.
|
||||
|
||||
## Getting Started with the Plugin
|
||||
|
||||
Add the camera_linux plugin to your pubspec.yaml:
|
||||
|
||||
```dependencies:
|
||||
camera_linux: ^0.1.0
|
||||
```
|
||||
|
||||
Execute the following command to fetch the package:
|
||||
`flutter pub get`
|
||||
|
||||
## Further Assistance
|
||||
For comprehensive guidance on Flutter, visit the official documentation, offering tutorials, samples, mobile development insights, and a complete API reference.
|
|
@ -0,0 +1,19 @@
|
|||
# Run with `flutter pub run ffigen --config ffigen.yaml`.
|
||||
name: CameraLinuxBindings
|
||||
description: |
|
||||
Bindings for `src/camera_linux.h`.
|
||||
|
||||
Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
|
||||
output: 'lib/camera_linux_bindings_generated.dart'
|
||||
headers:
|
||||
entry-points:
|
||||
- 'src/camera_linux.h'
|
||||
include-directives:
|
||||
- 'src/camera_linux.h'
|
||||
preamble: |
|
||||
// ignore_for_file: always_specify_types
|
||||
// ignore_for_file: camel_case_types
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
comments:
|
||||
style: any
|
||||
length: full
|
|
@ -0,0 +1,38 @@
|
|||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
import 'dart:typed_data';
|
||||
import 'camera_linux_bindings_generated.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class CameraLinux {
|
||||
late CameraLinuxBindings _bindings;
|
||||
|
||||
CameraLinux() {
|
||||
final dylib = DynamicLibrary.open('libcamera_linux.so');
|
||||
_bindings = CameraLinuxBindings(dylib);
|
||||
}
|
||||
|
||||
// Open Default Camera
|
||||
Future<void> initializeCamera() async {
|
||||
_bindings.startVideoCaptureInThread();
|
||||
}
|
||||
|
||||
// Close The Camera
|
||||
void stopCamera() {
|
||||
_bindings.stopVideoCapture();
|
||||
}
|
||||
|
||||
// Capture The Frame
|
||||
Future<Uint8List> captureImage() async {
|
||||
final lengthPtr = calloc<Int>();
|
||||
Pointer<Uint8> framePointer = _bindings.getLatestFrameBytes(lengthPtr);
|
||||
final latestFrame = getLatestFrameData(framePointer, lengthPtr.value);
|
||||
return latestFrame;
|
||||
}
|
||||
|
||||
// Get The Latest Frame
|
||||
Uint8List getLatestFrameData(Pointer<Uint8> framePointer, frameSize) {
|
||||
List<int> frameList = framePointer.asTypedList(frameSize);
|
||||
return Uint8List.fromList(frameList);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// ignore_for_file: always_specify_types
|
||||
// ignore_for_file: camel_case_types
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
//
|
||||
// Generated by `package:ffigen`.
|
||||
import 'dart:ffi' as ffi;
|
||||
|
||||
/// Bindings for `src/camera_linux.h`.
|
||||
///
|
||||
/// Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
|
||||
///
|
||||
class CameraLinuxBindings {
|
||||
/// Holds the symbol lookup function.
|
||||
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName) _lookup;
|
||||
|
||||
/// The symbols are looked up in [dynamicLibrary].
|
||||
CameraLinuxBindings(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup;
|
||||
|
||||
/// The symbols are looked up with [lookup].
|
||||
CameraLinuxBindings.fromLookup(ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName) lookup) : _lookup = lookup;
|
||||
|
||||
void startVideoCaptureInThread() {
|
||||
return _startVideoCaptureInThread();
|
||||
}
|
||||
|
||||
late final _startVideoCaptureInThreadPtr = _lookup<ffi.NativeFunction<ffi.Void Function()>>('startVideoCaptureInThread');
|
||||
late final _startVideoCaptureInThread = _startVideoCaptureInThreadPtr.asFunction<void Function()>();
|
||||
|
||||
void stopVideoCapture() {
|
||||
return _stopVideoCapture();
|
||||
}
|
||||
|
||||
late final _stopVideoCapturePtr = _lookup<ffi.NativeFunction<ffi.Void Function()>>('stopVideoCapture');
|
||||
late final _stopVideoCapture = _stopVideoCapturePtr.asFunction<void Function()>();
|
||||
|
||||
ffi.Pointer<ffi.Uint8> getLatestFrameBytes(
|
||||
ffi.Pointer<ffi.Int> length,
|
||||
) {
|
||||
return _getLatestFrameBytes(
|
||||
length,
|
||||
);
|
||||
}
|
||||
|
||||
late final _getLatestFrameBytesPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Uint8> Function(ffi.Pointer<ffi.Int>)>>('getLatestFrameBytes');
|
||||
late final _getLatestFrameBytes = _getLatestFrameBytesPtr.asFunction<ffi.Pointer<ffi.Uint8> Function(ffi.Pointer<ffi.Int>)>();
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
# The Flutter tooling requires that developers have CMake 3.10 or later
|
||||
# installed. You should not increase this version, as doing so will cause
|
||||
# the plugin to fail to compile for some customers of the plugin.
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
# Project-level configuration.
|
||||
set(PROJECT_NAME "camera_linux")
|
||||
project(${PROJECT_NAME} LANGUAGES CXX)
|
||||
|
||||
# Invoke the build for native code shared with the other target platforms.
|
||||
# This can be changed to accommodate different builds.
|
||||
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
|
||||
|
||||
# List of absolute paths to libraries that should be bundled with the plugin.
|
||||
# This list could contain prebuilt libraries, or libraries created by an
|
||||
# external build triggered from this build file.
|
||||
set(camera_linux_bundled_libraries
|
||||
# Defined in ../src/CMakeLists.txt.
|
||||
# This can be changed to accommodate different builds.
|
||||
$<TARGET_FILE:camera_linux>
|
||||
PARENT_SCOPE
|
||||
)
|
|
@ -0,0 +1,74 @@
|
|||
name: camera_linux
|
||||
description: Take pictures from camere on linux platform.
|
||||
version: 0.0.8
|
||||
homepage: https://github.com/islamroshan/camera-linux.git
|
||||
|
||||
environment:
|
||||
sdk: '>=3.1.0 <4.0.0'
|
||||
flutter: '>=3.3.0'
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.0.2
|
||||
ffi: ^2.0.1
|
||||
|
||||
dev_dependencies:
|
||||
ffigen: ^6.1.2
|
||||
image: ^3.0.1
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^2.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
# This section identifies this Flutter project as a plugin project.
|
||||
# The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.)
|
||||
# which should be registered in the plugin registry. This is required for
|
||||
# using method channels.
|
||||
# The Android 'package' specifies package in which the registered class is.
|
||||
# This is required for using method channels on Android.
|
||||
# The 'ffiPlugin' specifies that native code should be built and bundled.
|
||||
# This is required for using `dart:ffi`.
|
||||
# All these are used by the tooling to maintain consistency when
|
||||
# adding or updating assets for this project.
|
||||
#
|
||||
# Please refer to README.md for a detailed explanation.
|
||||
plugin:
|
||||
platforms:
|
||||
linux:
|
||||
ffiPlugin: true
|
||||
|
||||
# To add assets to your plugin package, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
#
|
||||
# For details regarding assets in packages, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
#
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||
|
||||
# To add custom fonts to your plugin package, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts in packages, see
|
||||
# https://flutter.dev/custom-fonts/#from-packages
|
|
@ -0,0 +1,20 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
project(camera_linux_library VERSION 0.0.1 LANGUAGES C CXX)
|
||||
|
||||
set(SOURCE_FILES opencv_wrapper.cpp)
|
||||
add_library(opencv_wrapper SHARED ${SOURCE_FILES})
|
||||
|
||||
find_package(OpenCV REQUIRED)
|
||||
include_directories(${OpenCV_INCLUDE_DIRS})
|
||||
|
||||
target_link_libraries(opencv_wrapper ${OpenCV_LIBS})
|
||||
|
||||
add_library(camera_linux SHARED "camera_linux.c")
|
||||
target_link_libraries(camera_linux opencv_wrapper)
|
||||
|
||||
set_target_properties(camera_linux PROPERTIES
|
||||
PUBLIC_HEADER camera_linux.h
|
||||
OUTPUT_NAME "camera_linux"
|
||||
)
|
||||
|
||||
target_compile_definitions(camera_linux PUBLIC DART_SHARED_LIB)
|
|
@ -0,0 +1,5 @@
|
|||
#include "camera_linux.h"
|
||||
|
||||
void startVideoCaptureInThread();
|
||||
void stopVideoCapture();
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void startVideoCaptureInThread();
|
||||
void stopVideoCapture();
|
||||
uint8_t* getLatestFrameBytes(int* length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
#include <iostream>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
std::thread videoThread;
|
||||
std::atomic<bool> stopFlag(false);
|
||||
Mat latestFrame;
|
||||
|
||||
// Extern C block to expose the function to C
|
||||
extern "C" {
|
||||
// Function to capture video frames
|
||||
void runVideoCapture() {
|
||||
VideoCapture cap;
|
||||
int deviceID = 0; // 0 = open default camera
|
||||
int apiID = cv::CAP_ANY; // 0 = autodetect default API
|
||||
cap.open(deviceID, apiID);
|
||||
cap.set(cv::CAP_PROP_FRAME_WIDTH, 160);
|
||||
cap.set(cv::CAP_PROP_FRAME_HEIGHT, 120);
|
||||
if (!cap.isOpened()) {
|
||||
cerr << "ERROR! Unable to open camera\n";
|
||||
return ;
|
||||
}
|
||||
|
||||
while (!stopFlag.load()) {
|
||||
cap >> latestFrame;
|
||||
if (latestFrame.empty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
cap.release();
|
||||
}
|
||||
|
||||
void startVideoCaptureInThread() {
|
||||
stopFlag = false;
|
||||
videoThread = std::thread(runVideoCapture);
|
||||
videoThread.detach();
|
||||
}
|
||||
|
||||
void stopVideoCapture() {
|
||||
stopFlag = true;
|
||||
if (videoThread.joinable()) {
|
||||
videoThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* getLatestFrameBytes(int* length) {
|
||||
// Ensure the pointer is valid
|
||||
if (!length) {
|
||||
return nullptr;
|
||||
}
|
||||
*length = 0; // Initialize length to 0
|
||||
if (latestFrame.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
vector<int> compression_params;
|
||||
compression_params.push_back(IMWRITE_JPEG_QUALITY);
|
||||
compression_params.push_back(50);
|
||||
// Encode the frame as JPEG
|
||||
vector<uint8_t> buf;
|
||||
bool encodeSuccess = imencode(".jpg", latestFrame, buf, compression_params );
|
||||
|
||||
// Check if encoding was successful
|
||||
if (!encodeSuccess || buf.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
*length = static_cast<int>(buf.size());
|
||||
cout << buf.size() << endl;
|
||||
// Allocate memory and copy data
|
||||
uint8_t* data = new uint8_t[(*length)];
|
||||
|
||||
if (!data) {
|
||||
cout << "Memory allocation failed." << endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
memcpy(data, buf.data(), *length);
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
/pubspec.lock
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
build/
|
|
@ -0,0 +1,42 @@
|
|||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "41456452f29d64e8deb623a3c927524bcf9f111b"
|
||||
channel: "stable"
|
||||
|
||||
project_type: plugin
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
||||
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
||||
- platform: android
|
||||
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
||||
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
||||
- platform: ios
|
||||
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
||||
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
||||
- platform: linux
|
||||
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
||||
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
||||
- platform: macos
|
||||
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
||||
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
||||
- platform: windows
|
||||
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
||||
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
|
@ -0,0 +1,3 @@
|
|||
## 0.0.1
|
||||
|
||||
* TODO: Describe initial release.
|
|
@ -0,0 +1 @@
|
|||
TODO: Add your license here.
|
|
@ -0,0 +1,15 @@
|
|||
# miniaudio
|
||||
|
||||
A new Flutter plugin project.
|
||||
|
||||
## Getting Started
|
||||
|
||||
This project is a starting point for a Flutter
|
||||
[plug-in package](https://flutter.dev/developing-packages/),
|
||||
a specialized package that includes platform-specific implementation code for
|
||||
Android and/or iOS.
|
||||
|
||||
For help getting started with Flutter development, view the
|
||||
[online documentation](https://flutter.dev/docs), which offers tutorials,
|
||||
samples, guidance on mobile development, and a full API reference.
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.cxx
|
|
@ -0,0 +1,68 @@
|
|||
group 'com.example.miniaudio'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.7.10'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.3.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
if (project.android.hasProperty("namespace")) {
|
||||
namespace 'com.example.miniaudio'
|
||||
}
|
||||
|
||||
compileSdkVersion 33
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
test.java.srcDirs += 'src/test/kotlin'
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 19
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'org.jetbrains.kotlin:kotlin-test'
|
||||
testImplementation 'org.mockito:mockito-core:5.0.0'
|
||||
}
|
||||
|
||||
testOptions {
|
||||
unitTests.all {
|
||||
useJUnitPlatform()
|
||||
|
||||
testLogging {
|
||||
events "passed", "skipped", "failed", "standardOut", "standardError"
|
||||
outputs.upToDateWhen {false}
|
||||
showStandardStreams = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
rootProject.name = 'miniaudio'
|
|
@ -0,0 +1,3 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.miniaudio">
|
||||
</manifest>
|
35
lib/third_party/miniaudio/android/src/main/kotlin/com/example/miniaudio/MiniaudioPlugin.kt
vendored
Normal file
35
lib/third_party/miniaudio/android/src/main/kotlin/com/example/miniaudio/MiniaudioPlugin.kt
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
package com.example.miniaudio
|
||||
|
||||
import androidx.annotation.NonNull
|
||||
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
|
||||
import io.flutter.plugin.common.MethodChannel.Result
|
||||
|
||||
/** MiniaudioPlugin */
|
||||
class MiniaudioPlugin: FlutterPlugin, MethodCallHandler {
|
||||
/// The MethodChannel that will the communication between Flutter and native Android
|
||||
///
|
||||
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
|
||||
/// when the Flutter Engine is detached from the Activity
|
||||
private lateinit var channel : MethodChannel
|
||||
|
||||
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "miniaudio")
|
||||
channel.setMethodCallHandler(this)
|
||||
}
|
||||
|
||||
override fun onMethodCall(call: MethodCall, result: Result) {
|
||||
if (call.method == "getPlatformVersion") {
|
||||
result.success("Android ${android.os.Build.VERSION.RELEASE}")
|
||||
} else {
|
||||
result.notImplemented()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
||||
channel.setMethodCallHandler(null)
|
||||
}
|
||||
}
|
27
lib/third_party/miniaudio/android/src/test/kotlin/com/example/miniaudio/MiniaudioPluginTest.kt
vendored
Normal file
27
lib/third_party/miniaudio/android/src/test/kotlin/com/example/miniaudio/MiniaudioPluginTest.kt
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
package com.example.miniaudio
|
||||
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import kotlin.test.Test
|
||||
import org.mockito.Mockito
|
||||
|
||||
/*
|
||||
* This demonstrates a simple unit test of the Kotlin portion of this plugin's implementation.
|
||||
*
|
||||
* Once you have built the plugin's example app, you can run these tests from the command
|
||||
* line by running `./gradlew testDebugUnitTest` in the `example/android/` directory, or
|
||||
* you can run them directly from IDEs that support JUnit such as Android Studio.
|
||||
*/
|
||||
|
||||
internal class MiniaudioPluginTest {
|
||||
@Test
|
||||
fun onMethodCall_getPlatformVersion_returnsExpectedValue() {
|
||||
val plugin = MiniaudioPlugin()
|
||||
|
||||
val call = MethodCall("getPlatformVersion", null)
|
||||
val mockResult: MethodChannel.Result = Mockito.mock(MethodChannel.Result::class.java)
|
||||
plugin.onMethodCall(call, mockResult)
|
||||
|
||||
Mockito.verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
import 'miniaudio_platform_interface.dart';
|
||||
|
||||
class Miniaudio {
|
||||
Future<String?> getPlatformVersion() {
|
||||
return MiniaudioPlatform.instance.getPlatformVersion();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'miniaudio_platform_interface.dart';
|
||||
|
||||
/// An implementation of [MiniaudioPlatform] that uses method channels.
|
||||
class MethodChannelMiniaudio extends MiniaudioPlatform {
|
||||
/// The method channel used to interact with the native platform.
|
||||
@visibleForTesting
|
||||
final methodChannel = const MethodChannel('miniaudio');
|
||||
|
||||
@override
|
||||
Future<String?> getPlatformVersion() async {
|
||||
final version = await methodChannel.invokeMethod<String>('getPlatformVersion');
|
||||
return version;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||
|
||||
import 'miniaudio_method_channel.dart';
|
||||
|
||||
abstract class MiniaudioPlatform extends PlatformInterface {
|
||||
/// Constructs a MiniaudioPlatform.
|
||||
MiniaudioPlatform() : super(token: _token);
|
||||
|
||||
static final Object _token = Object();
|
||||
|
||||
static MiniaudioPlatform _instance = MethodChannelMiniaudio();
|
||||
|
||||
/// The default instance of [MiniaudioPlatform] to use.
|
||||
///
|
||||
/// Defaults to [MethodChannelMiniaudio].
|
||||
static MiniaudioPlatform get instance => _instance;
|
||||
|
||||
/// Platform-specific implementations should set this with their own
|
||||
/// platform-specific class that extends [MiniaudioPlatform] when
|
||||
/// they register themselves.
|
||||
static set instance(MiniaudioPlatform instance) {
|
||||
PlatformInterface.verifyToken(instance, _token);
|
||||
_instance = instance;
|
||||
}
|
||||
|
||||
Future<String?> getPlatformVersion() {
|
||||
throw UnimplementedError('platformVersion() has not been implemented.');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
# The Flutter tooling requires that developers have CMake 3.10 or later
|
||||
# installed. You should not increase this version, as doing so will cause
|
||||
# the plugin to fail to compile for some customers of the plugin.
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
# Project-level configuration.
|
||||
set(PROJECT_NAME "miniaudio")
|
||||
project(${PROJECT_NAME} LANGUAGES CXX)
|
||||
|
||||
# This value is used when generating builds using this plugin, so it must
|
||||
# not be changed.
|
||||
set(PLUGIN_NAME "miniaudio_plugin")
|
||||
|
||||
# Any new source files that you add to the plugin should be added here.
|
||||
list(APPEND PLUGIN_SOURCES
|
||||
"miniaudio_plugin.cc"
|
||||
)
|
||||
|
||||
# Define the plugin library target. Its name must not be changed (see comment
|
||||
# on PLUGIN_NAME above).
|
||||
add_library(${PLUGIN_NAME} SHARED
|
||||
${PLUGIN_SOURCES}
|
||||
)
|
||||
|
||||
# Apply a standard set of build settings that are configured in the
|
||||
# application-level CMakeLists.txt. This can be removed for plugins that want
|
||||
# full control over build settings.
|
||||
apply_standard_settings(${PLUGIN_NAME})
|
||||
|
||||
# Symbols are hidden by default to reduce the chance of accidental conflicts
|
||||
# between plugins. This should not be removed; any symbols that should be
|
||||
# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro.
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES
|
||||
CXX_VISIBILITY_PRESET hidden)
|
||||
target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
|
||||
|
||||
# Source include directories and library dependencies. Add any plugin-specific
|
||||
# dependencies here.
|
||||
target_include_directories(${PLUGIN_NAME} INTERFACE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter)
|
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK)
|
||||
|
||||
# List of absolute paths to libraries that should be bundled with the plugin.
|
||||
# This list could contain prebuilt libraries, or libraries created by an
|
||||
# external build triggered from this build file.
|
||||
set(miniaudio_bundled_libraries
|
||||
""
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
# === Tests ===
|
||||
# These unit tests can be run from a terminal after building the example.
|
||||
|
||||
# Only enable test builds when building the example (which sets this variable)
|
||||
# so that plugin clients aren't building the tests.
|
||||
if (${include_${PROJECT_NAME}_tests})
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.11.0")
|
||||
message("Unit tests require CMake 3.11.0 or later")
|
||||
else()
|
||||
set(TEST_RUNNER "${PROJECT_NAME}_test")
|
||||
enable_testing()
|
||||
|
||||
# Add the Google Test dependency.
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/release-1.11.0.zip
|
||||
)
|
||||
# Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
# Disable install commands for gtest so it doesn't end up in the bundle.
|
||||
set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE)
|
||||
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
# The plugin's exported API is not very useful for unit testing, so build the
|
||||
# sources directly into the test binary rather than using the shared library.
|
||||
add_executable(${TEST_RUNNER}
|
||||
test/miniaudio_plugin_test.cc
|
||||
${PLUGIN_SOURCES}
|
||||
)
|
||||
apply_standard_settings(${TEST_RUNNER})
|
||||
target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE flutter)
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GTK)
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock)
|
||||
|
||||
# Enable automatic test discovery.
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(${TEST_RUNNER})
|
||||
|
||||
endif() # CMake version check
|
||||
endif() # include_${PROJECT_NAME}_tests
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef FLUTTER_PLUGIN_MINIAUDIO_PLUGIN_H_
|
||||
#define FLUTTER_PLUGIN_MINIAUDIO_PLUGIN_H_
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifdef FLUTTER_PLUGIN_IMPL
|
||||
#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define FLUTTER_PLUGIN_EXPORT
|
||||
#endif
|
||||
|
||||
typedef struct _MiniaudioPlugin MiniaudioPlugin;
|
||||
typedef struct {
|
||||
GObjectClass parent_class;
|
||||
} MiniaudioPluginClass;
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT GType miniaudio_plugin_get_type();
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT void miniaudio_plugin_register_with_registrar(
|
||||
FlPluginRegistrar* registrar);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif // FLUTTER_PLUGIN_MINIAUDIO_PLUGIN_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,87 @@
|
|||
#include "include/miniaudio/miniaudio_plugin.h"
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "miniaudio_plugin_private.h"
|
||||
#include "miniaudio.h"
|
||||
|
||||
#define MINIAUDIO_PLUGIN(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), miniaudio_plugin_get_type(), \
|
||||
MiniaudioPlugin))
|
||||
|
||||
struct _MiniaudioPlugin {
|
||||
GObject parent_instance;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(MiniaudioPlugin, miniaudio_plugin, g_object_get_type())
|
||||
|
||||
// Called when a method call is received from Flutter.
|
||||
static void miniaudio_plugin_handle_method_call(
|
||||
MiniaudioPlugin* self,
|
||||
FlMethodCall* method_call) {
|
||||
g_autoptr(FlMethodResponse) response = nullptr;
|
||||
|
||||
const gchar* method = fl_method_call_get_name(method_call);
|
||||
//const FlValue* args = fl_method_call_get_args(method_call);
|
||||
|
||||
if (strcmp(method, "getPlatformVersion") == 0) {
|
||||
response = get_platform_version();
|
||||
}else if (strcmp(method, "playAudio") == 0) {
|
||||
// ma_decoder decoder;
|
||||
// ma_result result;
|
||||
// result = ma_decoder_init_file(fl_value_get_string(0), NULL, &decoder);
|
||||
// if (result != MA_SUCCESS) {
|
||||
/// printf("Could not load file: %s\n", fl_value_get_string(0));
|
||||
// }
|
||||
|
||||
//response = nullptr;
|
||||
} else {
|
||||
response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
|
||||
}
|
||||
|
||||
fl_method_call_respond(method_call, response, nullptr);
|
||||
}
|
||||
|
||||
FlMethodResponse* get_platform_version() {
|
||||
struct utsname uname_data = {};
|
||||
uname(&uname_data);
|
||||
g_autofree gchar *version = g_strdup_printf("Linux %s", uname_data.version);
|
||||
g_autoptr(FlValue) result = fl_value_new_string(version);
|
||||
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
|
||||
}
|
||||
|
||||
static void miniaudio_plugin_dispose(GObject* object) {
|
||||
G_OBJECT_CLASS(miniaudio_plugin_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void miniaudio_plugin_class_init(MiniaudioPluginClass* klass) {
|
||||
G_OBJECT_CLASS(klass)->dispose = miniaudio_plugin_dispose;
|
||||
}
|
||||
|
||||
static void miniaudio_plugin_init(MiniaudioPlugin* self) {}
|
||||
|
||||
static void method_call_cb(FlMethodChannel* channel, FlMethodCall* method_call,
|
||||
gpointer user_data) {
|
||||
MiniaudioPlugin* plugin = MINIAUDIO_PLUGIN(user_data);
|
||||
miniaudio_plugin_handle_method_call(plugin, method_call);
|
||||
}
|
||||
|
||||
void miniaudio_plugin_register_with_registrar(FlPluginRegistrar* registrar) {
|
||||
MiniaudioPlugin* plugin = MINIAUDIO_PLUGIN(
|
||||
g_object_new(miniaudio_plugin_get_type(), nullptr));
|
||||
|
||||
g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
|
||||
g_autoptr(FlMethodChannel) channel =
|
||||
fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar),
|
||||
"miniaudio",
|
||||
FL_METHOD_CODEC(codec));
|
||||
fl_method_channel_set_method_call_handler(channel, method_call_cb,
|
||||
g_object_ref(plugin),
|
||||
g_object_unref);
|
||||
|
||||
g_object_unref(plugin);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#include <flutter_linux/flutter_linux.h>
|
||||
|
||||
#include "include/miniaudio/miniaudio_plugin.h"
|
||||
|
||||
// This file exposes some plugin internals for unit testing. See
|
||||
// https://github.com/flutter/flutter/issues/88724 for current limitations
|
||||
// in the unit-testable API.
|
||||
|
||||
// Handles the getPlatformVersion method call.
|
||||
FlMethodResponse *get_platform_version();
|
|
@ -0,0 +1,31 @@
|
|||
#include <flutter_linux/flutter_linux.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "include/miniaudio/miniaudio_plugin.h"
|
||||
#include "miniaudio_plugin_private.h"
|
||||
|
||||
// This demonstrates a simple unit test of the C portion of this plugin's
|
||||
// implementation.
|
||||
//
|
||||
// Once you have built the plugin's example app, you can run these tests
|
||||
// from the command line. For instance, for a plugin called my_plugin
|
||||
// built for x64 debug, run:
|
||||
// $ build/linux/x64/debug/plugins/my_plugin/my_plugin_test
|
||||
|
||||
namespace miniaudio {
|
||||
namespace test {
|
||||
|
||||
TEST(MiniaudioPlugin, GetPlatformVersion) {
|
||||
g_autoptr(FlMethodResponse) response = get_platform_version();
|
||||
ASSERT_NE(response, nullptr);
|
||||
ASSERT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
|
||||
FlValue* result = fl_method_success_response_get_result(
|
||||
FL_METHOD_SUCCESS_RESPONSE(response));
|
||||
ASSERT_EQ(fl_value_get_type(result), FL_VALUE_TYPE_STRING);
|
||||
// The full string varies, so just validate that it has the right format.
|
||||
EXPECT_THAT(fl_value_get_string(result), testing::StartsWith("Linux "));
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace miniaudio
|
|
@ -0,0 +1,19 @@
|
|||
import Cocoa
|
||||
import FlutterMacOS
|
||||
|
||||
public class MiniaudioPlugin: NSObject, FlutterPlugin {
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
let channel = FlutterMethodChannel(name: "miniaudio", binaryMessenger: registrar.messenger)
|
||||
let instance = MiniaudioPlugin()
|
||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
||||
}
|
||||
|
||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
switch call.method {
|
||||
case "getPlatformVersion":
|
||||
result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString)
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#
|
||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
|
||||
# Run `pod lib lint miniaudio.podspec` to validate before publishing.
|
||||
#
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'miniaudio'
|
||||
s.version = '0.0.1'
|
||||
s.summary = 'A new Flutter plugin project.'
|
||||
s.description = <<-DESC
|
||||
A new Flutter plugin project.
|
||||
DESC
|
||||
s.homepage = 'http://example.com'
|
||||
s.license = { :file => '../LICENSE' }
|
||||
s.author = { 'Your Company' => 'email@example.com' }
|
||||
|
||||
s.source = { :path => '.' }
|
||||
s.source_files = 'Classes/**/*'
|
||||
s.dependency 'FlutterMacOS'
|
||||
|
||||
s.platform = :osx, '10.11'
|
||||
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
|
||||
s.swift_version = '5.0'
|
||||
end
|
|
@ -0,0 +1,78 @@
|
|||
name: miniaudio
|
||||
description: "A new Flutter plugin project."
|
||||
version: 0.0.1
|
||||
homepage:
|
||||
|
||||
environment:
|
||||
sdk: '>=3.2.6 <4.0.0'
|
||||
flutter: '>=3.3.0'
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^2.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
# This section identifies this Flutter project as a plugin project.
|
||||
# The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.)
|
||||
# which should be registered in the plugin registry. This is required for
|
||||
# using method channels.
|
||||
# The Android 'package' specifies package in which the registered class is.
|
||||
# This is required for using method channels on Android.
|
||||
# The 'ffiPlugin' specifies that native code should be built and bundled.
|
||||
# This is required for using `dart:ffi`.
|
||||
# All these are used by the tooling to maintain consistency when
|
||||
# adding or updating assets for this project.
|
||||
plugin:
|
||||
platforms:
|
||||
android:
|
||||
package: com.example.miniaudio
|
||||
pluginClass: MiniaudioPlugin
|
||||
ios:
|
||||
pluginClass: MiniaudioPlugin
|
||||
linux:
|
||||
pluginClass: MiniaudioPlugin
|
||||
macos:
|
||||
pluginClass: MiniaudioPlugin
|
||||
windows:
|
||||
pluginClass: MiniaudioPluginCApi
|
||||
|
||||
# To add assets to your plugin package, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
#
|
||||
# For details regarding assets in packages, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
#
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||
|
||||
# To add custom fonts to your plugin package, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts in packages, see
|
||||
# https://flutter.dev/custom-fonts/#from-packages
|
|
@ -0,0 +1,27 @@
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:miniaudio/miniaudio_method_channel.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
MethodChannelMiniaudio platform = MethodChannelMiniaudio();
|
||||
const MethodChannel channel = MethodChannel('miniaudio');
|
||||
|
||||
setUp(() {
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(
|
||||
channel,
|
||||
(MethodCall methodCall) async {
|
||||
return '42';
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(channel, null);
|
||||
});
|
||||
|
||||
test('getPlatformVersion', () async {
|
||||
expect(await platform.getPlatformVersion(), '42');
|
||||
});
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:miniaudio/miniaudio.dart';
|
||||
import 'package:miniaudio/miniaudio_platform_interface.dart';
|
||||
import 'package:miniaudio/miniaudio_method_channel.dart';
|
||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||
|
||||
class MockMiniaudioPlatform
|
||||
with MockPlatformInterfaceMixin
|
||||
implements MiniaudioPlatform {
|
||||
|
||||
@override
|
||||
Future<String?> getPlatformVersion() => Future.value('42');
|
||||
}
|
||||
|
||||
void main() {
|
||||
final MiniaudioPlatform initialPlatform = MiniaudioPlatform.instance;
|
||||
|
||||
test('$MethodChannelMiniaudio is the default instance', () {
|
||||
expect(initialPlatform, isInstanceOf<MethodChannelMiniaudio>());
|
||||
});
|
||||
|
||||
test('getPlatformVersion', () async {
|
||||
Miniaudio miniaudioPlugin = Miniaudio();
|
||||
MockMiniaudioPlatform fakePlatform = MockMiniaudioPlatform();
|
||||
MiniaudioPlatform.instance = fakePlatform;
|
||||
|
||||
expect(await miniaudioPlugin.getPlatformVersion(), '42');
|
||||
});
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
flutter/
|
||||
|
||||
# Visual Studio user-specific files.
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# Visual Studio build-related files.
|
||||
x64/
|
||||
x86/
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
|
@ -0,0 +1,100 @@
|
|||
# The Flutter tooling requires that developers have a version of Visual Studio
|
||||
# installed that includes CMake 3.14 or later. You should not increase this
|
||||
# version, as doing so will cause the plugin to fail to compile for some
|
||||
# customers of the plugin.
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
# Project-level configuration.
|
||||
set(PROJECT_NAME "miniaudio")
|
||||
project(${PROJECT_NAME} LANGUAGES CXX)
|
||||
|
||||
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||
# versions of CMake.
|
||||
cmake_policy(VERSION 3.14...3.25)
|
||||
|
||||
# This value is used when generating builds using this plugin, so it must
|
||||
# not be changed
|
||||
set(PLUGIN_NAME "miniaudio_plugin")
|
||||
|
||||
# Any new source files that you add to the plugin should be added here.
|
||||
list(APPEND PLUGIN_SOURCES
|
||||
"miniaudio_plugin.cpp"
|
||||
"miniaudio_plugin.h"
|
||||
)
|
||||
|
||||
# Define the plugin library target. Its name must not be changed (see comment
|
||||
# on PLUGIN_NAME above).
|
||||
add_library(${PLUGIN_NAME} SHARED
|
||||
"include/miniaudio/miniaudio_plugin_c_api.h"
|
||||
"miniaudio_plugin_c_api.cpp"
|
||||
${PLUGIN_SOURCES}
|
||||
)
|
||||
|
||||
# Apply a standard set of build settings that are configured in the
|
||||
# application-level CMakeLists.txt. This can be removed for plugins that want
|
||||
# full control over build settings.
|
||||
apply_standard_settings(${PLUGIN_NAME})
|
||||
|
||||
# Symbols are hidden by default to reduce the chance of accidental conflicts
|
||||
# between plugins. This should not be removed; any symbols that should be
|
||||
# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro.
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES
|
||||
CXX_VISIBILITY_PRESET hidden)
|
||||
target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
|
||||
|
||||
# Source include directories and library dependencies. Add any plugin-specific
|
||||
# dependencies here.
|
||||
target_include_directories(${PLUGIN_NAME} INTERFACE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin)
|
||||
|
||||
# List of absolute paths to libraries that should be bundled with the plugin.
|
||||
# This list could contain prebuilt libraries, or libraries created by an
|
||||
# external build triggered from this build file.
|
||||
set(miniaudio_bundled_libraries
|
||||
""
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
# === Tests ===
|
||||
# These unit tests can be run from a terminal after building the example, or
|
||||
# from Visual Studio after opening the generated solution file.
|
||||
|
||||
# Only enable test builds when building the example (which sets this variable)
|
||||
# so that plugin clients aren't building the tests.
|
||||
if (${include_${PROJECT_NAME}_tests})
|
||||
set(TEST_RUNNER "${PROJECT_NAME}_test")
|
||||
enable_testing()
|
||||
|
||||
# Add the Google Test dependency.
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/release-1.11.0.zip
|
||||
)
|
||||
# Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
# Disable install commands for gtest so it doesn't end up in the bundle.
|
||||
set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
# The plugin's C API is not very useful for unit testing, so build the sources
|
||||
# directly into the test binary rather than using the DLL.
|
||||
add_executable(${TEST_RUNNER}
|
||||
test/miniaudio_plugin_test.cpp
|
||||
${PLUGIN_SOURCES}
|
||||
)
|
||||
apply_standard_settings(${TEST_RUNNER})
|
||||
target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE flutter_wrapper_plugin)
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock)
|
||||
# flutter_wrapper_plugin has link dependencies on the Flutter DLL.
|
||||
add_custom_command(TARGET ${TEST_RUNNER} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${FLUTTER_LIBRARY}" $<TARGET_FILE_DIR:${TEST_RUNNER}>
|
||||
)
|
||||
|
||||
# Enable automatic test discovery.
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(${TEST_RUNNER})
|
||||
endif()
|
23
lib/third_party/miniaudio/windows/include/miniaudio/miniaudio_plugin_c_api.h
vendored
Normal file
23
lib/third_party/miniaudio/windows/include/miniaudio/miniaudio_plugin_c_api.h
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef FLUTTER_PLUGIN_MINIAUDIO_PLUGIN_C_API_H_
|
||||
#define FLUTTER_PLUGIN_MINIAUDIO_PLUGIN_C_API_H_
|
||||
|
||||
#include <flutter_plugin_registrar.h>
|
||||
|
||||
#ifdef FLUTTER_PLUGIN_IMPL
|
||||
#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT void MiniaudioPluginCApiRegisterWithRegistrar(
|
||||
FlutterDesktopPluginRegistrarRef registrar);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // FLUTTER_PLUGIN_MINIAUDIO_PLUGIN_C_API_H_
|
|
@ -0,0 +1,59 @@
|
|||
#include "miniaudio_plugin.h"
|
||||
|
||||
// This must be included before many other Windows headers.
|
||||
#include <windows.h>
|
||||
|
||||
// For getPlatformVersion; remove unless needed for your plugin implementation.
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
#include <flutter/method_channel.h>
|
||||
#include <flutter/plugin_registrar_windows.h>
|
||||
#include <flutter/standard_method_codec.h>
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
namespace miniaudio {
|
||||
|
||||
// static
|
||||
void MiniaudioPlugin::RegisterWithRegistrar(
|
||||
flutter::PluginRegistrarWindows *registrar) {
|
||||
auto channel =
|
||||
std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
|
||||
registrar->messenger(), "miniaudio",
|
||||
&flutter::StandardMethodCodec::GetInstance());
|
||||
|
||||
auto plugin = std::make_unique<MiniaudioPlugin>();
|
||||
|
||||
channel->SetMethodCallHandler(
|
||||
[plugin_pointer = plugin.get()](const auto &call, auto result) {
|
||||
plugin_pointer->HandleMethodCall(call, std::move(result));
|
||||
});
|
||||
|
||||
registrar->AddPlugin(std::move(plugin));
|
||||
}
|
||||
|
||||
MiniaudioPlugin::MiniaudioPlugin() {}
|
||||
|
||||
MiniaudioPlugin::~MiniaudioPlugin() {}
|
||||
|
||||
void MiniaudioPlugin::HandleMethodCall(
|
||||
const flutter::MethodCall<flutter::EncodableValue> &method_call,
|
||||
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
|
||||
if (method_call.method_name().compare("getPlatformVersion") == 0) {
|
||||
std::ostringstream version_stream;
|
||||
version_stream << "Windows ";
|
||||
if (IsWindows10OrGreater()) {
|
||||
version_stream << "10+";
|
||||
} else if (IsWindows8OrGreater()) {
|
||||
version_stream << "8";
|
||||
} else if (IsWindows7OrGreater()) {
|
||||
version_stream << "7";
|
||||
}
|
||||
result->Success(flutter::EncodableValue(version_stream.str()));
|
||||
} else {
|
||||
result->NotImplemented();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace miniaudio
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef FLUTTER_PLUGIN_MINIAUDIO_PLUGIN_H_
|
||||
#define FLUTTER_PLUGIN_MINIAUDIO_PLUGIN_H_
|
||||
|
||||
#include <flutter/method_channel.h>
|
||||
#include <flutter/plugin_registrar_windows.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace miniaudio {
|
||||
|
||||
class MiniaudioPlugin : public flutter::Plugin {
|
||||
public:
|
||||
static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar);
|
||||
|
||||
MiniaudioPlugin();
|
||||
|
||||
virtual ~MiniaudioPlugin();
|
||||
|
||||
// Disallow copy and assign.
|
||||
MiniaudioPlugin(const MiniaudioPlugin&) = delete;
|
||||
MiniaudioPlugin& operator=(const MiniaudioPlugin&) = delete;
|
||||
|
||||
// Called when a method is called on this plugin's channel from Dart.
|
||||
void HandleMethodCall(
|
||||
const flutter::MethodCall<flutter::EncodableValue> &method_call,
|
||||
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
|
||||
};
|
||||
|
||||
} // namespace miniaudio
|
||||
|
||||
#endif // FLUTTER_PLUGIN_MINIAUDIO_PLUGIN_H_
|
|
@ -0,0 +1,12 @@
|
|||
#include "include/miniaudio/miniaudio_plugin_c_api.h"
|
||||
|
||||
#include <flutter/plugin_registrar_windows.h>
|
||||
|
||||
#include "miniaudio_plugin.h"
|
||||
|
||||
void MiniaudioPluginCApiRegisterWithRegistrar(
|
||||
FlutterDesktopPluginRegistrarRef registrar) {
|
||||
miniaudio::MiniaudioPlugin::RegisterWithRegistrar(
|
||||
flutter::PluginRegistrarManager::GetInstance()
|
||||
->GetRegistrar<flutter::PluginRegistrarWindows>(registrar));
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
#include <flutter/method_call.h>
|
||||
#include <flutter/method_result_functions.h>
|
||||
#include <flutter/standard_method_codec.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
#include "miniaudio_plugin.h"
|
||||
|
||||
namespace miniaudio {
|
||||
namespace test {
|
||||
|
||||
namespace {
|
||||
|
||||
using flutter::EncodableMap;
|
||||
using flutter::EncodableValue;
|
||||
using flutter::MethodCall;
|
||||
using flutter::MethodResultFunctions;
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(MiniaudioPlugin, GetPlatformVersion) {
|
||||
MiniaudioPlugin plugin;
|
||||
// Save the reply value from the success callback.
|
||||
std::string result_string;
|
||||
plugin.HandleMethodCall(
|
||||
MethodCall("getPlatformVersion", std::make_unique<EncodableValue>()),
|
||||
std::make_unique<MethodResultFunctions<>>(
|
||||
[&result_string](const EncodableValue* result) {
|
||||
result_string = std::get<std::string>(*result);
|
||||
},
|
||||
nullptr, nullptr));
|
||||
|
||||
// Since the exact string varies by host, just ensure that it's a string
|
||||
// with the expected format.
|
||||
EXPECT_TRUE(result_string.rfind("Windows ", 0) == 0);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace miniaudio
|
|
@ -15,6 +15,7 @@ import 'package:cwtch/models/messages/quotedmessage.dart';
|
|||
import 'package:cwtch/models/profile.dart';
|
||||
import 'package:cwtch/themes/opaque.dart';
|
||||
import 'package:cwtch/third_party/linkify/flutter_linkify.dart';
|
||||
import 'package:cwtch/views/vidchatview.dart';
|
||||
import 'package:cwtch/widgets/malformedbubble.dart';
|
||||
import 'package:cwtch/widgets/messageloadingbubble.dart';
|
||||
import 'package:cwtch/widgets/profileimage.dart';
|
||||
|
@ -102,6 +103,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
appBarButtons.add(IconButton(
|
||||
splashRadius: Material.defaultSplashRadius / 2, icon: Icon(CwtchIcons.manage_files), tooltip: AppLocalizations.of(context)!.manageSharedFiles, onPressed: _pushFileSharingSettings));
|
||||
}
|
||||
appBarButtons.add(IconButton(splashRadius: Material.defaultSplashRadius / 2, icon: Icon(Icons.videocam), tooltip: AppLocalizations.of(context)!.manageSharedFiles, onPressed: _pushVidChat));
|
||||
|
||||
if (Provider.of<ContactInfoState>(context, listen: false).isOnline()) {
|
||||
appBarButtons.add(IconButton(
|
||||
|
@ -279,6 +281,23 @@ class _MessageViewState extends State<MessageView> {
|
|||
return true;
|
||||
}
|
||||
|
||||
void _pushVidChat() {
|
||||
var profileInfoState = Provider.of<ProfileInfoState>(context, listen: false);
|
||||
var contactInfoState = Provider.of<ContactInfoState>(context, listen: false);
|
||||
Navigator.of(context).push(
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (builderContext, a1, a2) {
|
||||
return MultiProvider(
|
||||
providers: [ChangeNotifierProvider.value(value: profileInfoState), ChangeNotifierProvider.value(value: contactInfoState)],
|
||||
child: VidChatView(),
|
||||
);
|
||||
},
|
||||
transitionsBuilder: (c, anim, a2, child) => FadeTransition(opacity: anim, child: child),
|
||||
transitionDuration: Duration(milliseconds: 200),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _pushFileSharingSettings() {
|
||||
var profileInfoState = Provider.of<ProfileInfoState>(context, listen: false);
|
||||
var contactInfoState = Provider.of<ContactInfoState>(context, listen: false);
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:ui';
|
||||
import 'package:cwtch/config.dart';
|
||||
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||
import 'package:cwtch/models/appstate.dart';
|
||||
import 'package:cwtch/models/contact.dart';
|
||||
import 'package:cwtch/widgets/camfeed.dart';
|
||||
import 'package:cwtch/widgets/profileimage.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:cwtch/widgets/buttontextfield.dart';
|
||||
import 'package:cwtch/widgets/cwtchlabel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cwtch/settings.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:camera_linux/camera_linux.dart';
|
||||
import '../main.dart';
|
||||
import '../themes/opaque.dart';
|
||||
|
||||
class VidChatView extends StatefulWidget {
|
||||
@override
|
||||
_VidChatViewState createState() => _VidChatViewState();
|
||||
}
|
||||
|
||||
class _VidChatViewState extends State<VidChatView> {
|
||||
final _cameraLinuxPlugin = CameraLinux();
|
||||
bool _isCameraOpen = false;
|
||||
late String _base64Image;
|
||||
@override
|
||||
void dispose() {
|
||||
_cameraLinuxPlugin.stopCamera();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var handle = Provider.of<ContactInfoState>(context).nickname;
|
||||
if (handle.isEmpty) {
|
||||
handle = Provider.of<ContactInfoState>(context).onion;
|
||||
}
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Container(
|
||||
height: Provider.of<Settings>(context).fontScaling * 24.0,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
decoration: BoxDecoration(),
|
||||
child: Text(handle + " " + AppLocalizations.of(context)!.conversationSettings)),
|
||||
),
|
||||
body: _buildVidChat(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildVidChat() {
|
||||
return Column(children: [
|
||||
CameraFeed(_cameraLinuxPlugin),
|
||||
Image.memory(
|
||||
Provider.of<ContactInfoState>(context).vid,
|
||||
width: 320,
|
||||
height: 240,
|
||||
gaplessPlayback: true,
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
EnvironmentConfig.debugLog("error ${Provider.of<ContactInfoState>(context).vid.length}");
|
||||
return Container();
|
||||
},
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
import 'package:cwtch/config.dart';
|
||||
import 'package:cwtch/models/message.dart';
|
||||
import 'package:cwtch/third_party/base85/base_85_codec.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:camera_linux/camera_linux.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../main.dart';
|
||||
import '../models/contact.dart';
|
||||
import '../models/messages/VidMessage.dart';
|
||||
|
||||
class CameraFeed extends StatefulWidget {
|
||||
final CameraLinux cameraLinuxPlugin;
|
||||
CameraFeed(this.cameraLinuxPlugin, {super.key});
|
||||
|
||||
@override
|
||||
State<CameraFeed> createState() => _CameraFeed();
|
||||
}
|
||||
|
||||
class _CameraFeed extends State<CameraFeed> {
|
||||
Uint8List _Image = Uint8List(0);
|
||||
late Timer timer;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_initializeCamera();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
timer.cancel();
|
||||
}
|
||||
|
||||
// Open Default Camera
|
||||
Future<void> _initializeCamera() async {
|
||||
await widget.cameraLinuxPlugin.initializeCamera().then((value) {
|
||||
timer = new Timer.periodic(
|
||||
Duration(milliseconds: 150),
|
||||
(Timer t) => widget.cameraLinuxPlugin.captureImage().then((value) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_Image = value;
|
||||
try {
|
||||
Provider.of<FlwtchState>(context, listen: false).cwtch.SendMessage(Provider.of<ContactInfoState>(context, listen: false).profileOnion,
|
||||
Provider.of<ContactInfoState>(context, listen: false).identifier, jsonEncode(VidMessage(o: VideoOverlay, d: _Image)));
|
||||
} catch (e) {
|
||||
EnvironmentConfig.debugLog("could not send ${Base85Codec.new().encode(_Image)}: $e");
|
||||
}
|
||||
});
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Image.memory(
|
||||
_Image,
|
||||
width: 320,
|
||||
height: 240,
|
||||
gaplessPlayback: true,
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return Container();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -6,11 +6,15 @@
|
|||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <miniaudio/miniaudio_plugin.h>
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
#include <window_manager/window_manager_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) miniaudio_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "MiniaudioPlugin");
|
||||
miniaudio_plugin_register_with_registrar(miniaudio_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);
|
||||
|
|
|
@ -3,12 +3,14 @@
|
|||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
miniaudio
|
||||
screen_retriever
|
||||
url_launcher_linux
|
||||
window_manager
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
camera_linux
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
|
|
@ -7,6 +7,7 @@ import Foundation
|
|||
|
||||
import connectivity_plus
|
||||
import flutter_local_notifications
|
||||
import miniaudio
|
||||
import package_info_plus
|
||||
import path_provider_foundation
|
||||
import screen_retriever
|
||||
|
@ -16,6 +17,7 @@ import window_manager
|
|||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
|
||||
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
|
||||
MiniaudioPlugin.register(with: registry.registrar(forPlugin: "MiniaudioPlugin"))
|
||||
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
|
||||
|
|
50
pubspec.lock
50
pubspec.lock
|
@ -113,6 +113,13 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.6.1"
|
||||
camera_linux:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "lib/third_party/camera_linux"
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.8"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -157,10 +164,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.2"
|
||||
version: "1.18.0"
|
||||
connectivity_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -471,10 +478,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
|
||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
version: "1.10.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -483,6 +490,13 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
miniaudio:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "lib/third_party/miniaudio"
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
msix:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
|
@ -591,10 +605,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
|
||||
sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
version: "3.1.2"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -724,18 +738,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.11.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
stream_transform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -772,10 +786,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.0"
|
||||
version: "0.6.1"
|
||||
timezone:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -884,10 +898,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: c620a6f783fa22436da68e42db7ebbf18b8c44b9a46ab911f666ff09ffd9153f
|
||||
sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.7.1"
|
||||
version: "11.10.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -900,10 +914,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.4-beta"
|
||||
version: "0.3.0"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -961,7 +975,7 @@ packages:
|
|||
source: hosted
|
||||
version: "6.3.0"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: yaml
|
||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||
|
@ -969,5 +983,5 @@ packages:
|
|||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.1.0-185.0.dev <4.0.0"
|
||||
dart: ">=3.2.6 <4.0.0"
|
||||
flutter: ">=3.7.0"
|
||||
|
|
|
@ -54,6 +54,10 @@ dependencies:
|
|||
dbus: ^0.7.8
|
||||
connectivity_plus:
|
||||
path: lib/third_party/connectivity_plus/connectivity_plus
|
||||
camera_linux:
|
||||
path: lib/third_party/camera_linux
|
||||
miniaudio:
|
||||
path: lib/third_party/miniaudio
|
||||
# misc plugins
|
||||
qr_flutter: ^4.0.0
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
|
||||
#include <miniaudio/miniaudio_plugin_c_api.h>
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
#include <win_toast/win_toast_plugin.h>
|
||||
|
@ -15,6 +16,8 @@
|
|||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
|
||||
MiniaudioPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("MiniaudioPluginCApi"));
|
||||
ScreenRetrieverPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
connectivity_plus
|
||||
miniaudio
|
||||
screen_retriever
|
||||
url_launcher_windows
|
||||
win_toast
|
||||
|
|
Loading…
Reference in New Issue