Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
Sarah Jamie Lewis | f8a9b2c67f | |
Sarah Jamie Lewis | 15e4793ba8 |
Binary file not shown.
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:cwtch/config.dart';
|
||||
import 'package:cwtch/third_party/miniaudio/lib/miniaudio.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
enum ModalState { none, storageMigration, shutdown }
|
||||
|
@ -28,6 +29,10 @@ class AppState extends ChangeNotifier {
|
|||
|
||||
void SetCwtchInit() {
|
||||
cwtchInit = true;
|
||||
var audio = MiniAudio();
|
||||
audio.initAudio().then((value) {
|
||||
audio.playAudio("assets/sounds_online.wav");
|
||||
});
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
|
|
@ -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,73 @@
|
|||
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: 11.0.0
|
||||
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,87 @@
|
|||
#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,19 @@
|
|||
# Run with `flutter pub run ffigen --config ffigen.yaml`.
|
||||
name: MiniAudioBindings
|
||||
description: |
|
||||
Bindings for `src/audio.h`.
|
||||
|
||||
Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
|
||||
output: 'lib/miniaudio_bindings_generated.dart'
|
||||
headers:
|
||||
entry-points:
|
||||
- 'src/audio.h'
|
||||
include-directives:
|
||||
- 'src/audio.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,27 @@
|
|||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
import 'dart:typed_data';
|
||||
import 'package:miniaudio/miniaudio_bindings_generated.dart';
|
||||
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class MiniAudio {
|
||||
late MiniAudioBindings _bindings;
|
||||
|
||||
MiniAudio() {
|
||||
final dylib = DynamicLibrary.open('libminiaudio.so');
|
||||
_bindings = MiniAudioBindings(dylib);
|
||||
}
|
||||
|
||||
Future<void> initAudio() async {
|
||||
_bindings.initAudio();
|
||||
}
|
||||
|
||||
// Open Default Camera
|
||||
Future<void> playAudio(String file) async {
|
||||
var filePtr = file.toNativeUtf8();
|
||||
_bindings.playAudio(filePtr.cast());
|
||||
malloc.free(filePtr);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
// 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/audio.h`.
|
||||
///
|
||||
/// Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
|
||||
///
|
||||
class MiniAudioBindings {
|
||||
/// Holds the symbol lookup function.
|
||||
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
|
||||
_lookup;
|
||||
|
||||
/// The symbols are looked up in [dynamicLibrary].
|
||||
MiniAudioBindings(ffi.DynamicLibrary dynamicLibrary)
|
||||
: _lookup = dynamicLibrary.lookup;
|
||||
|
||||
/// The symbols are looked up with [lookup].
|
||||
MiniAudioBindings.fromLookup(
|
||||
ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
|
||||
lookup)
|
||||
: _lookup = lookup;
|
||||
|
||||
void initAudio() {
|
||||
return _initAudio();
|
||||
}
|
||||
|
||||
late final _initAudioPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function()>>('initAudio');
|
||||
late final _initAudio = _initAudioPtr.asFunction<void Function()>();
|
||||
|
||||
void playAudio(
|
||||
ffi.Pointer<ffi.Char> file,
|
||||
) {
|
||||
return _playAudio(
|
||||
file,
|
||||
);
|
||||
}
|
||||
|
||||
late final _playAudioPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Char>)>>(
|
||||
'playAudio');
|
||||
late final _playAudio =
|
||||
_playAudioPtr.asFunction<void Function(ffi.Pointer<ffi.Char>)>();
|
||||
}
|
|
@ -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 "miniaudio")
|
||||
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(miniaudio_bundled_libraries
|
||||
# Defined in ../src/CMakeLists.txt.
|
||||
# This can be changed to accommodate different builds.
|
||||
$<TARGET_FILE:miniaudio>
|
||||
PARENT_SCOPE
|
||||
)
|
|
@ -0,0 +1,333 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.10"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.11.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
cli_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cli_util
|
||||
sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.5"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
ffi:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
ffigen:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: ffigen
|
||||
sha256: ec6a2439159d27c871d92862fb9f3012ef19d9ec4b0fa383c69c8553b2dd2ac5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
image:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: image
|
||||
sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.0"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: "4186c61b32f99e60f011f7160e32c89a758ae9b1d0c6d28e2c02ef0382300e2b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.0"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.3"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.2"
|
||||
plugin_platform_interface:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
pointycastle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.7.4"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: quiver
|
||||
sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.5.0"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.2.0 <4.0.0"
|
||||
flutter: ">=3.3.0"
|
|
@ -0,0 +1,73 @@
|
|||
name: miniaudio
|
||||
description: Play audio
|
||||
version: 0.0.1
|
||||
|
||||
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,13 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
project(audio_library VERSION 0.0.1 LANGUAGES C CXX)
|
||||
|
||||
add_library(miniaudio SHARED "audio.c")
|
||||
target_link_libraries(miniaudio)
|
||||
|
||||
set_target_properties(miniaudio PROPERTIES
|
||||
PUBLIC_HEADER audio.h
|
||||
PUBLIC_HEADER miniaudio.h
|
||||
OUTPUT_NAME "miniaudio"
|
||||
)
|
||||
|
||||
target_compile_definitions(miniaudio PUBLIC DART_SHARED_LIB)
|
|
@ -0,0 +1,67 @@
|
|||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "miniaudio.h"
|
||||
#include <stdio.h>
|
||||
|
||||
ma_device recording_device;
|
||||
ma_engine engine;
|
||||
void initAudio() {
|
||||
ma_result result;
|
||||
result = ma_engine_init(NULL, &engine);
|
||||
if (result != MA_SUCCESS) {
|
||||
printf("Could not init engine\n");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void playAudio(char * file) {
|
||||
ma_engine_play_sound(&engine, file, NULL);
|
||||
}
|
||||
|
||||
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||
{
|
||||
ma_encoder* pEncoder = (ma_encoder*)pDevice->pUserData;
|
||||
MA_ASSERT(pEncoder != NULL);
|
||||
|
||||
ma_encoder_write_pcm_frames(pEncoder, pInput, frameCount, NULL);
|
||||
|
||||
(void)pOutput;
|
||||
}
|
||||
|
||||
void startRecording() {
|
||||
ma_result result;
|
||||
ma_encoder_config encoderConfig;
|
||||
ma_encoder encoder;
|
||||
ma_device_config deviceConfig;
|
||||
|
||||
encoderConfig = ma_encoder_config_init(ma_encoding_format_wav, ma_format_f32, 2, 44100);
|
||||
deviceConfig = ma_device_config_init(ma_device_type_capture);
|
||||
deviceConfig.capture.format = encoder.config.format;
|
||||
deviceConfig.capture.channels = encoder.config.channels;
|
||||
deviceConfig.sampleRate = encoder.config.sampleRate;
|
||||
deviceConfig.dataCallback = data_callback;
|
||||
deviceConfig.pUserData = &encoder;
|
||||
|
||||
if (ma_encoder_init_file("test.wav", &encoderConfig, &encoder) != MA_SUCCESS) {
|
||||
printf("Failed to initialize output file.\n");
|
||||
return ;
|
||||
}
|
||||
|
||||
result = ma_device_init(NULL, &deviceConfig, &recording_device);
|
||||
if (result != MA_SUCCESS) {
|
||||
printf("Failed to initialize capture device.\n");
|
||||
return ;
|
||||
}
|
||||
|
||||
result = ma_device_start(&recording_device);
|
||||
if (result != MA_SUCCESS) {
|
||||
printf("Failed to start device.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void stopRecording() {
|
||||
ma_result result;
|
||||
result = ma_device_stop(&recording_device);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#include <stdint.h>
|
||||
#include "miniaudio.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void initAudio();
|
||||
void playAudio(char * file);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -9,6 +9,8 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
camera_linux
|
||||
miniaudio
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
|
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.0-194.0.dev <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
|
||||
|
||||
|
|
Loading…
Reference in New Issue