Compare commits
	
		
			17 Commits 
		
	
	
		
			master
			...
			embedder_t
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								 | 
						ec4b86573c | 2 years ago | 
| 
							
							
								 | 
						32a481b213 | 2 years ago | 
| 
							
							
								 | 
						4db615def4 | 2 years ago | 
| 
							
							
								 | 
						0ccba5006e | 2 years ago | 
| 
							
							
								 | 
						c4556091dc | 2 years ago | 
| 
							
							
								 | 
						4d898d36a5 | 2 years ago | 
| 
							
							
								 | 
						e6e3352e7f | 2 years ago | 
| 
							
							
								 | 
						f79d080cf3 | 2 years ago | 
| 
							
							
								 | 
						96795f33f0 | 2 years ago | 
| 
							
							
								 | 
						1761211ba1 | 2 years ago | 
| 
							
							
								 | 
						4e6ff5e419 | 2 years ago | 
| 
							
							
								 | 
						edfa81bca0 | 2 years ago | 
| 
							
							
								 | 
						013245d9bb | 2 years ago | 
| 
							
							
								 | 
						fed1031ab4 | 2 years ago | 
| 
							
							
								 | 
						80e1758cc8 | 2 years ago | 
| 
							
							
								 | 
						3413ecd9a3 | 2 years ago | 
| 
							
							
								 | 
						4b7268cee0 | 2 years ago | 
				 39 changed files with 1754 additions and 17 deletions
			
			
		@ -0,0 +1,22 @@ | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> | 
				
			||||||
 | 
					// SPDX-License-Identifier: BSD-3-Clause | 
				
			||||||
 | 
					import 'package:flutter/widgets.dart'; | 
				
			||||||
 | 
					import 'package:scoped_model/scoped_model.dart'; | 
				
			||||||
 | 
					import 'package:xdga_directories/xdga_directories.dart' as xdga; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Model for [EmbedderTexturePage] | 
				
			||||||
 | 
					class EmbedderTextureModel extends Model { | 
				
			||||||
 | 
					  /// Get [ScopedModel] | 
				
			||||||
 | 
					  static EmbedderTextureModel of(BuildContext context) => | 
				
			||||||
 | 
					      ScopedModel.of<EmbedderTextureModel>(context); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Error | 
				
			||||||
 | 
					  String? _error; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Public error | 
				
			||||||
 | 
					  String? get error => _error; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Public is error | 
				
			||||||
 | 
					  bool get isError => _error != null; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,25 @@ | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> | 
				
			||||||
 | 
					// SPDX-License-Identifier: BSD-3-Clause | 
				
			||||||
 | 
					import 'package:flutter_example_packages/base/package/package_page.dart'; | 
				
			||||||
 | 
					import 'package:flutter_example_packages/packages/embedder_texture/page.dart'; | 
				
			||||||
 | 
					import 'package:get_it/get_it.dart'; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'model.dart'; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Package values | 
				
			||||||
 | 
					final packageEmbedderTexture = PackagePage( | 
				
			||||||
 | 
					  key: 'Embedder Texture', | 
				
			||||||
 | 
					  descEN: ''' | 
				
			||||||
 | 
					    Test Embedder texture plugin | 
				
			||||||
 | 
					    ''', | 
				
			||||||
 | 
					  descRU: ''' | 
				
			||||||
 | 
					    Тестирование текстур Embedder | 
				
			||||||
 | 
					    ''', | 
				
			||||||
 | 
					  version: '0.0.1', | 
				
			||||||
 | 
					  isPlatformDependent: true, | 
				
			||||||
 | 
					  page: () => EmbedderTexturePage(), | 
				
			||||||
 | 
					  init: () { | 
				
			||||||
 | 
					    GetIt.instance | 
				
			||||||
 | 
					        .registerFactory<EmbedderTextureModel>(() => EmbedderTextureModel()); | 
				
			||||||
 | 
					  }, | 
				
			||||||
 | 
					); | 
				
			||||||
@ -0,0 +1,53 @@ | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> | 
				
			||||||
 | 
					// SPDX-License-Identifier: BSD-3-Clause | 
				
			||||||
 | 
					import 'package:flutter/material.dart'; | 
				
			||||||
 | 
					import 'package:flutter_example_packages/base/di/app_di.dart'; | 
				
			||||||
 | 
					import 'package:flutter_example_packages/base/package/package.dart'; | 
				
			||||||
 | 
					import 'package:flutter_example_packages/packages/embedder_texture/model.dart'; | 
				
			||||||
 | 
					import 'package:flutter_example_packages/packages/embedder_texture/package.dart'; | 
				
			||||||
 | 
					import 'package:flutter_example_packages/widgets/base/export.dart'; | 
				
			||||||
 | 
					import 'package:flutter_example_packages/widgets/blocks/block_alert.dart'; | 
				
			||||||
 | 
					import 'package:flutter_example_packages/widgets/blocks/block_info_package.dart'; | 
				
			||||||
 | 
					import 'package:flutter_example_packages/widgets/blocks/block_item.dart'; | 
				
			||||||
 | 
					import 'package:flutter_example_packages/widgets/layouts/block_layout.dart'; | 
				
			||||||
 | 
					import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | 
				
			||||||
 | 
					import 'package:embedder_texture/embedder_texture.dart'; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class EmbedderTexturePage extends AppStatefulWidget { | 
				
			||||||
 | 
					  EmbedderTexturePage({ | 
				
			||||||
 | 
					    super.key, | 
				
			||||||
 | 
					  }); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final Package package = packageEmbedderTexture; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override | 
				
			||||||
 | 
					  State<EmbedderTexturePage> createState() => _EmbedderTexturePageState(); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _EmbedderTexturePageState extends AppState<EmbedderTexturePage> { | 
				
			||||||
 | 
					  @override | 
				
			||||||
 | 
					  Widget buildWide( | 
				
			||||||
 | 
					    BuildContext context, | 
				
			||||||
 | 
					    MediaQueryData media, | 
				
			||||||
 | 
					    AppLocalizations l10n, | 
				
			||||||
 | 
					  ) { | 
				
			||||||
 | 
					    final width = MediaQuery.of(context).size.width; | 
				
			||||||
 | 
					    final height = MediaQuery.of(context).size.height; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return BlockLayout<EmbedderTextureModel>( | 
				
			||||||
 | 
					      model: getIt<EmbedderTextureModel>(), | 
				
			||||||
 | 
					      title: widget.package.key, | 
				
			||||||
 | 
					      builder: (context, child, model) { | 
				
			||||||
 | 
					        return Padding( | 
				
			||||||
 | 
					          padding: const EdgeInsets.all(20), | 
				
			||||||
 | 
					          child: Center( | 
				
			||||||
 | 
					            child: EmbedderTexture( | 
				
			||||||
 | 
					              width: width, | 
				
			||||||
 | 
					              height: height, | 
				
			||||||
 | 
					            ), | 
				
			||||||
 | 
					          ), | 
				
			||||||
 | 
					        ); | 
				
			||||||
 | 
					      }, | 
				
			||||||
 | 
					    ); | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,139 @@ | 
				
			|||||||
 | 
					# Project-level configuration. | 
				
			||||||
 | 
					cmake_minimum_required(VERSION 3.10) | 
				
			||||||
 | 
					project(runner LANGUAGES CXX) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The name of the executable created for the application. Change this to change | 
				
			||||||
 | 
					# the on-disk name of your application. | 
				
			||||||
 | 
					set(BINARY_NAME "flutter_example_packages") | 
				
			||||||
 | 
					# The unique GTK application identifier for this application. See: | 
				
			||||||
 | 
					# https://wiki.gnome.org/HowDoI/ChooseApplicationID | 
				
			||||||
 | 
					set(APPLICATION_ID "ru.auroraos.flutter_example_packages") | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Explicitly opt in to modern CMake behaviors to avoid warnings with recent | 
				
			||||||
 | 
					# versions of CMake. | 
				
			||||||
 | 
					cmake_policy(SET CMP0063 NEW) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Load bundled libraries from the lib/ directory relative to the binary. | 
				
			||||||
 | 
					set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Root filesystem for cross-building. | 
				
			||||||
 | 
					if(FLUTTER_TARGET_PLATFORM_SYSROOT) | 
				
			||||||
 | 
					  set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) | 
				
			||||||
 | 
					  set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) | 
				
			||||||
 | 
					  set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | 
				
			||||||
 | 
					  set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) | 
				
			||||||
 | 
					  set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | 
				
			||||||
 | 
					  set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) | 
				
			||||||
 | 
					endif() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Define build configuration options. | 
				
			||||||
 | 
					if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) | 
				
			||||||
 | 
					  set(CMAKE_BUILD_TYPE "Debug" CACHE | 
				
			||||||
 | 
					    STRING "Flutter build mode" FORCE) | 
				
			||||||
 | 
					  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS | 
				
			||||||
 | 
					    "Debug" "Profile" "Release") | 
				
			||||||
 | 
					endif() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Compilation settings that should be applied to most targets. | 
				
			||||||
 | 
					# | 
				
			||||||
 | 
					# Be cautious about adding new options here, as plugins use this function by | 
				
			||||||
 | 
					# default. In most cases, you should add new options to specific targets instead | 
				
			||||||
 | 
					# of modifying this function. | 
				
			||||||
 | 
					function(APPLY_STANDARD_SETTINGS TARGET) | 
				
			||||||
 | 
					  target_compile_features(${TARGET} PUBLIC cxx_std_14) | 
				
			||||||
 | 
					#  target_compile_options(${TARGET} PRIVATE -Wall -Werror) | 
				
			||||||
 | 
					  target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>") | 
				
			||||||
 | 
					  target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>") | 
				
			||||||
 | 
					endfunction() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Flutter library and tool build rules. | 
				
			||||||
 | 
					set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") | 
				
			||||||
 | 
					add_subdirectory(${FLUTTER_MANAGED_DIR}) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# System-level dependencies. | 
				
			||||||
 | 
					find_package(PkgConfig REQUIRED) | 
				
			||||||
 | 
					pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Define the application target. To change its name, change BINARY_NAME above, | 
				
			||||||
 | 
					# not the value here, or `flutter run` will no longer work. | 
				
			||||||
 | 
					# | 
				
			||||||
 | 
					# Any new source files that you add to the application should be added here. | 
				
			||||||
 | 
					add_executable(${BINARY_NAME} | 
				
			||||||
 | 
					  "main.cc" | 
				
			||||||
 | 
					  "my_application.cc" | 
				
			||||||
 | 
					  "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" | 
				
			||||||
 | 
					) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Apply the standard set of build settings. This can be removed for applications | 
				
			||||||
 | 
					# that need different build settings. | 
				
			||||||
 | 
					apply_standard_settings(${BINARY_NAME}) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add dependency libraries. Add any application-specific dependencies here. | 
				
			||||||
 | 
					target_link_libraries(${BINARY_NAME} PRIVATE flutter) | 
				
			||||||
 | 
					target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Run the Flutter tool portions of the build. This must not be removed. | 
				
			||||||
 | 
					add_dependencies(${BINARY_NAME} flutter_assemble) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Only the install-generated bundle's copy of the executable will launch | 
				
			||||||
 | 
					# correctly, since the resources must in the right relative locations. To avoid | 
				
			||||||
 | 
					# people trying to run the unbundled copy, put it in a subdirectory instead of | 
				
			||||||
 | 
					# the default top-level location. | 
				
			||||||
 | 
					set_target_properties(${BINARY_NAME} | 
				
			||||||
 | 
					  PROPERTIES | 
				
			||||||
 | 
					  RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" | 
				
			||||||
 | 
					) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Generated plugin build rules, which manage building the plugins and adding | 
				
			||||||
 | 
					# them to the application. | 
				
			||||||
 | 
					include(flutter/generated_plugins.cmake) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === Installation === | 
				
			||||||
 | 
					# By default, "installing" just makes a relocatable bundle in the build | 
				
			||||||
 | 
					# directory. | 
				
			||||||
 | 
					set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") | 
				
			||||||
 | 
					if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) | 
				
			||||||
 | 
					  set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) | 
				
			||||||
 | 
					endif() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Start with a clean build bundle directory every time. | 
				
			||||||
 | 
					install(CODE " | 
				
			||||||
 | 
					  file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") | 
				
			||||||
 | 
					  " COMPONENT Runtime) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") | 
				
			||||||
 | 
					set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" | 
				
			||||||
 | 
					  COMPONENT Runtime) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" | 
				
			||||||
 | 
					  COMPONENT Runtime) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | 
				
			||||||
 | 
					  COMPONENT Runtime) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) | 
				
			||||||
 | 
					  install(FILES "${bundled_library}" | 
				
			||||||
 | 
					    DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | 
				
			||||||
 | 
					    COMPONENT Runtime) | 
				
			||||||
 | 
					endforeach(bundled_library) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Fully re-copy the assets directory on each build to avoid having stale files | 
				
			||||||
 | 
					# from a previous install. | 
				
			||||||
 | 
					set(FLUTTER_ASSET_DIR_NAME "flutter_assets") | 
				
			||||||
 | 
					install(CODE " | 
				
			||||||
 | 
					  file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") | 
				
			||||||
 | 
					  " COMPONENT Runtime) | 
				
			||||||
 | 
					install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" | 
				
			||||||
 | 
					  DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Install the AOT library on non-Debug builds only. | 
				
			||||||
 | 
					if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") | 
				
			||||||
 | 
					  install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | 
				
			||||||
 | 
					    COMPONENT Runtime) | 
				
			||||||
 | 
					endif() | 
				
			||||||
@ -0,0 +1,88 @@ | 
				
			|||||||
 | 
					# This file controls Flutter-level build steps. It should not be edited. | 
				
			||||||
 | 
					cmake_minimum_required(VERSION 3.10) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Configuration provided via flutter tool. | 
				
			||||||
 | 
					include(${EPHEMERAL_DIR}/generated_config.cmake) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# TODO: Move the rest of this into files in ephemeral. See | 
				
			||||||
 | 
					# https://github.com/flutter/flutter/issues/57146. | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Serves the same purpose as list(TRANSFORM ... PREPEND ...), | 
				
			||||||
 | 
					# which isn't available in 3.10. | 
				
			||||||
 | 
					function(list_prepend LIST_NAME PREFIX) | 
				
			||||||
 | 
					    set(NEW_LIST "") | 
				
			||||||
 | 
					    foreach(element ${${LIST_NAME}}) | 
				
			||||||
 | 
					        list(APPEND NEW_LIST "${PREFIX}${element}") | 
				
			||||||
 | 
					    endforeach(element) | 
				
			||||||
 | 
					    set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) | 
				
			||||||
 | 
					endfunction() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === Flutter Library === | 
				
			||||||
 | 
					# System-level dependencies. | 
				
			||||||
 | 
					find_package(PkgConfig REQUIRED) | 
				
			||||||
 | 
					pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) | 
				
			||||||
 | 
					pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) | 
				
			||||||
 | 
					pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Published to parent scope for install step. | 
				
			||||||
 | 
					set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) | 
				
			||||||
 | 
					set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) | 
				
			||||||
 | 
					set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) | 
				
			||||||
 | 
					set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					list(APPEND FLUTTER_LIBRARY_HEADERS | 
				
			||||||
 | 
					  "fl_basic_message_channel.h" | 
				
			||||||
 | 
					  "fl_binary_codec.h" | 
				
			||||||
 | 
					  "fl_binary_messenger.h" | 
				
			||||||
 | 
					  "fl_dart_project.h" | 
				
			||||||
 | 
					  "fl_engine.h" | 
				
			||||||
 | 
					  "fl_json_message_codec.h" | 
				
			||||||
 | 
					  "fl_json_method_codec.h" | 
				
			||||||
 | 
					  "fl_message_codec.h" | 
				
			||||||
 | 
					  "fl_method_call.h" | 
				
			||||||
 | 
					  "fl_method_channel.h" | 
				
			||||||
 | 
					  "fl_method_codec.h" | 
				
			||||||
 | 
					  "fl_method_response.h" | 
				
			||||||
 | 
					  "fl_plugin_registrar.h" | 
				
			||||||
 | 
					  "fl_plugin_registry.h" | 
				
			||||||
 | 
					  "fl_standard_message_codec.h" | 
				
			||||||
 | 
					  "fl_standard_method_codec.h" | 
				
			||||||
 | 
					  "fl_string_codec.h" | 
				
			||||||
 | 
					  "fl_value.h" | 
				
			||||||
 | 
					  "fl_view.h" | 
				
			||||||
 | 
					  "flutter_linux.h" | 
				
			||||||
 | 
					) | 
				
			||||||
 | 
					list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") | 
				
			||||||
 | 
					add_library(flutter INTERFACE) | 
				
			||||||
 | 
					target_include_directories(flutter INTERFACE | 
				
			||||||
 | 
					  "${EPHEMERAL_DIR}" | 
				
			||||||
 | 
					) | 
				
			||||||
 | 
					target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") | 
				
			||||||
 | 
					target_link_libraries(flutter INTERFACE | 
				
			||||||
 | 
					  PkgConfig::GTK | 
				
			||||||
 | 
					  PkgConfig::GLIB | 
				
			||||||
 | 
					  PkgConfig::GIO | 
				
			||||||
 | 
					) | 
				
			||||||
 | 
					add_dependencies(flutter flutter_assemble) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# === Flutter tool backend === | 
				
			||||||
 | 
					# _phony_ is a non-existent file to force this command to run every time, | 
				
			||||||
 | 
					# since currently there's no way to get a full input/output list from the | 
				
			||||||
 | 
					# flutter tool. | 
				
			||||||
 | 
					add_custom_command( | 
				
			||||||
 | 
					  OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} | 
				
			||||||
 | 
					    ${CMAKE_CURRENT_BINARY_DIR}/_phony_ | 
				
			||||||
 | 
					  COMMAND ${CMAKE_COMMAND} -E env | 
				
			||||||
 | 
					    ${FLUTTER_TOOL_ENVIRONMENT} | 
				
			||||||
 | 
					    "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" | 
				
			||||||
 | 
					      ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} | 
				
			||||||
 | 
					  VERBATIM | 
				
			||||||
 | 
					) | 
				
			||||||
 | 
					add_custom_target(flutter_assemble DEPENDS | 
				
			||||||
 | 
					  "${FLUTTER_LIBRARY}" | 
				
			||||||
 | 
					  ${FLUTTER_LIBRARY_HEADERS} | 
				
			||||||
 | 
					) | 
				
			||||||
@ -0,0 +1,19 @@ | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					//  Generated file. Do not edit.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// clang-format off
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "generated_plugin_registrant.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <embedder_texture/embedder_texture_plugin.h> | 
				
			||||||
 | 
					#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void fl_register_plugins(FlPluginRegistry* registry) { | 
				
			||||||
 | 
					  g_autoptr(FlPluginRegistrar) embedder_texture_registrar = | 
				
			||||||
 | 
					      fl_plugin_registry_get_registrar_for_plugin(registry, "EmbedderTexturePlugin"); | 
				
			||||||
 | 
					  embedder_texture_plugin_register_with_registrar(embedder_texture_registrar); | 
				
			||||||
 | 
					  g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = | 
				
			||||||
 | 
					      fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); | 
				
			||||||
 | 
					  flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,15 @@ | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					//  Generated file. Do not edit.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// clang-format off
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GENERATED_PLUGIN_REGISTRANT_ | 
				
			||||||
 | 
					#define GENERATED_PLUGIN_REGISTRANT_ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <flutter_linux/flutter_linux.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Registers Flutter plugins.
 | 
				
			||||||
 | 
					void fl_register_plugins(FlPluginRegistry* registry); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif  // GENERATED_PLUGIN_REGISTRANT_
 | 
				
			||||||
@ -0,0 +1,25 @@ | 
				
			|||||||
 | 
					# | 
				
			||||||
 | 
					# Generated file, do not edit. | 
				
			||||||
 | 
					# | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					list(APPEND FLUTTER_PLUGIN_LIST | 
				
			||||||
 | 
					  embedder_texture | 
				
			||||||
 | 
					  flutter_secure_storage_linux | 
				
			||||||
 | 
					) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					list(APPEND FLUTTER_FFI_PLUGIN_LIST | 
				
			||||||
 | 
					) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(PLUGIN_BUNDLED_LIBRARIES) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					foreach(plugin ${FLUTTER_PLUGIN_LIST}) | 
				
			||||||
 | 
					  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) | 
				
			||||||
 | 
					  target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) | 
				
			||||||
 | 
					  list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>) | 
				
			||||||
 | 
					  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) | 
				
			||||||
 | 
					endforeach(plugin) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) | 
				
			||||||
 | 
					  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) | 
				
			||||||
 | 
					  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) | 
				
			||||||
 | 
					endforeach(ffi_plugin) | 
				
			||||||
@ -0,0 +1,6 @@ | 
				
			|||||||
 | 
					#include "my_application.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char** argv) { | 
				
			||||||
 | 
					  g_autoptr(MyApplication) app = my_application_new(); | 
				
			||||||
 | 
					  return g_application_run(G_APPLICATION(app), argc, argv); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,104 @@ | 
				
			|||||||
 | 
					#include "my_application.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <flutter_linux/flutter_linux.h> | 
				
			||||||
 | 
					#ifdef GDK_WINDOWING_X11 | 
				
			||||||
 | 
					#include <gdk/gdkx.h> | 
				
			||||||
 | 
					#endif | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "flutter/generated_plugin_registrant.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct _MyApplication { | 
				
			||||||
 | 
					  GtkApplication parent_instance; | 
				
			||||||
 | 
					  char** dart_entrypoint_arguments; | 
				
			||||||
 | 
					}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Implements GApplication::activate.
 | 
				
			||||||
 | 
					static void my_application_activate(GApplication* application) { | 
				
			||||||
 | 
					  MyApplication* self = MY_APPLICATION(application); | 
				
			||||||
 | 
					  GtkWindow* window = | 
				
			||||||
 | 
					      GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Use a header bar when running in GNOME as this is the common style used
 | 
				
			||||||
 | 
					  // by applications and is the setup most users will be using (e.g. Ubuntu
 | 
				
			||||||
 | 
					  // desktop).
 | 
				
			||||||
 | 
					  // If running on X and not using GNOME then just use a traditional title bar
 | 
				
			||||||
 | 
					  // in case the window manager does more exotic layout, e.g. tiling.
 | 
				
			||||||
 | 
					  // If running on Wayland assume the header bar will work (may need changing
 | 
				
			||||||
 | 
					  // if future cases occur).
 | 
				
			||||||
 | 
					  gboolean use_header_bar = TRUE; | 
				
			||||||
 | 
					#ifdef GDK_WINDOWING_X11 | 
				
			||||||
 | 
					  GdkScreen* screen = gtk_window_get_screen(window); | 
				
			||||||
 | 
					  if (GDK_IS_X11_SCREEN(screen)) { | 
				
			||||||
 | 
					    const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); | 
				
			||||||
 | 
					    if (g_strcmp0(wm_name, "GNOME Shell") != 0) { | 
				
			||||||
 | 
					      use_header_bar = FALSE; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					#endif | 
				
			||||||
 | 
					  if (use_header_bar) { | 
				
			||||||
 | 
					    GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); | 
				
			||||||
 | 
					    gtk_widget_show(GTK_WIDGET(header_bar)); | 
				
			||||||
 | 
					    gtk_header_bar_set_title(header_bar, "flutter_example_packages"); | 
				
			||||||
 | 
					    gtk_header_bar_set_show_close_button(header_bar, TRUE); | 
				
			||||||
 | 
					    gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); | 
				
			||||||
 | 
					  } else { | 
				
			||||||
 | 
					    gtk_window_set_title(window, "flutter_example_packages"); | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  gtk_window_set_default_size(window, 1280, 720); | 
				
			||||||
 | 
					  gtk_widget_show(GTK_WIDGET(window)); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  g_autoptr(FlDartProject) project = fl_dart_project_new(); | 
				
			||||||
 | 
					  fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  FlView* view = fl_view_new(project); | 
				
			||||||
 | 
					  gtk_widget_show(GTK_WIDGET(view)); | 
				
			||||||
 | 
					  gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fl_register_plugins(FL_PLUGIN_REGISTRY(view)); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  gtk_widget_grab_focus(GTK_WIDGET(view)); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Implements GApplication::local_command_line.
 | 
				
			||||||
 | 
					static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { | 
				
			||||||
 | 
					  MyApplication* self = MY_APPLICATION(application); | 
				
			||||||
 | 
					  // Strip out the first argument as it is the binary name.
 | 
				
			||||||
 | 
					  self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  g_autoptr(GError) error = nullptr; | 
				
			||||||
 | 
					  if (!g_application_register(application, nullptr, &error)) { | 
				
			||||||
 | 
					     g_warning("Failed to register: %s", error->message); | 
				
			||||||
 | 
					     *exit_status = 1; | 
				
			||||||
 | 
					     return TRUE; | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  g_application_activate(application); | 
				
			||||||
 | 
					  *exit_status = 0; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return TRUE; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Implements GObject::dispose.
 | 
				
			||||||
 | 
					static void my_application_dispose(GObject* object) { | 
				
			||||||
 | 
					  MyApplication* self = MY_APPLICATION(object); | 
				
			||||||
 | 
					  g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); | 
				
			||||||
 | 
					  G_OBJECT_CLASS(my_application_parent_class)->dispose(object); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void my_application_class_init(MyApplicationClass* klass) { | 
				
			||||||
 | 
					  G_APPLICATION_CLASS(klass)->activate = my_application_activate; | 
				
			||||||
 | 
					  G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; | 
				
			||||||
 | 
					  G_OBJECT_CLASS(klass)->dispose = my_application_dispose; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void my_application_init(MyApplication* self) {} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MyApplication* my_application_new() { | 
				
			||||||
 | 
					  return MY_APPLICATION(g_object_new(my_application_get_type(), | 
				
			||||||
 | 
					                                     "application-id", APPLICATION_ID, | 
				
			||||||
 | 
					                                     "flags", G_APPLICATION_NON_UNIQUE, | 
				
			||||||
 | 
					                                     nullptr)); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,18 @@ | 
				
			|||||||
 | 
					#ifndef FLUTTER_MY_APPLICATION_H_ | 
				
			||||||
 | 
					#define FLUTTER_MY_APPLICATION_H_ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gtk/gtk.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, | 
				
			||||||
 | 
					                     GtkApplication) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * my_application_new: | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * Creates a new Flutter-based application. | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * Returns: a new #MyApplication. | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					MyApplication* my_application_new(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif  // FLUTTER_MY_APPLICATION_H_
 | 
				
			||||||
@ -0,0 +1,30 @@ | 
				
			|||||||
 | 
					# 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/ | 
				
			||||||
 | 
					.packages | 
				
			||||||
 | 
					build/ | 
				
			||||||
@ -0,0 +1 @@ | 
				
			|||||||
 | 
					include: package:flutter_lints/flutter.yaml | 
				
			||||||
@ -0,0 +1,36 @@ | 
				
			|||||||
 | 
					# SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> | 
				
			||||||
 | 
					# SPDX-License-Identifier: BSD-3-Clause | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cmake_minimum_required(VERSION 3.10) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(PROJECT_NAME embedder_texture) | 
				
			||||||
 | 
					set(PLUGIN_NAME  embedder_texture_platform_plugin) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					project(${PROJECT_NAME} LANGUAGES CXX) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(CMAKE_CXX_STANDARD 17) | 
				
			||||||
 | 
					set(CMAKE_CXX_STANDARD_REQUIRED ON) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-psabi") | 
				
			||||||
 | 
					set(CMAKE_CXX_FLAGS_RELEASE "-O3") | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					find_package(PkgConfig REQUIRED) | 
				
			||||||
 | 
					find_package(Qt5 COMPONENTS Core Multimedia REQUIRED) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pkg_check_modules(FlutterEmbedder REQUIRED IMPORTED_TARGET flutter-embedder) | 
				
			||||||
 | 
					pkg_check_modules(GLES REQUIRED IMPORTED_TARGET glesv2) | 
				
			||||||
 | 
					pkg_check_modules(SC REQUIRED IMPORTED_TARGET streamcamera) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_library(${PLUGIN_NAME} SHARED | 
				
			||||||
 | 
					    embedder_texture_plugin.cpp | 
				
			||||||
 | 
					    camera_pixels_helper.cpp | 
				
			||||||
 | 
					    camera_egl_helper.cpp | 
				
			||||||
 | 
					    camera.cpp | 
				
			||||||
 | 
					) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) | 
				
			||||||
 | 
					target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::FlutterEmbedder PkgConfig::GLES PkgConfig::SC) | 
				
			||||||
 | 
					target_link_libraries(${PLUGIN_NAME} PUBLIC Qt5::Core Qt5::Multimedia) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_include_directories(${PLUGIN_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) | 
				
			||||||
 | 
					target_compile_definitions(${PLUGIN_NAME} PRIVATE PLUGIN_IMPL) | 
				
			||||||
@ -0,0 +1,114 @@ | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					#include <embedder_texture/camera.h> | 
				
			||||||
 | 
					#include <embedder_texture/camera_egl_helper.h> | 
				
			||||||
 | 
					#include <embedder_texture/camera_pixels_helper.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Camera::Camera(TextureRegistrar *plugin) | 
				
			||||||
 | 
					    : m_plugin(plugin) | 
				
			||||||
 | 
					    , m_manager(StreamCameraManager()) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    CameraEGLHelper::EGLInit(); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Camera::InitializeCamera(int cameraID) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    if (m_cameraId != cameraID && m_manager->getNumberOfCameras()) { | 
				
			||||||
 | 
					        Aurora::StreamCamera::CameraInfo info; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (m_manager->getCameraInfo(cameraID, info)) { | 
				
			||||||
 | 
					            m_cameraId = cameraID; | 
				
			||||||
 | 
					            m_camera = m_manager->openCamera(info.id); | 
				
			||||||
 | 
					            m_camera->setListener(this); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Aurora::StreamCamera::CameraCapability Camera::StartCapture() | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    if (m_camera) { | 
				
			||||||
 | 
					        Aurora::StreamCamera::CameraInfo info; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (m_camera->getInfo(info)) { | 
				
			||||||
 | 
					            std::vector<Aurora::StreamCamera::CameraCapability> caps; | 
				
			||||||
 | 
					            if (m_manager->queryCapabilities(info.id, caps)) { | 
				
			||||||
 | 
					                for(Aurora::StreamCamera::CameraCapability cap : caps) { | 
				
			||||||
 | 
					                    if (m_widthTexture + m_heightTexture < cap.width + cap.height) { | 
				
			||||||
 | 
					                        m_camera->startCapture(cap); | 
				
			||||||
 | 
					                        return cap; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                } | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					    return Aurora::StreamCamera::CameraCapability{}; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Camera::StopCapture() | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    if (m_camera) { | 
				
			||||||
 | 
					        m_cameraId = -1; | 
				
			||||||
 | 
					        m_buffer = nullptr; | 
				
			||||||
 | 
					        m_camera->stopCapture(); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::map<Encodable, Encodable> Camera::Register(int cameraID, int width, int height) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    m_widthTexture = width; | 
				
			||||||
 | 
					    m_heightTexture = height; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_textureId = m_plugin->RegisterTexture( | 
				
			||||||
 | 
					        [this](size_t width, size_t height) { return this->m_buffer; }); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    InitializeCamera(cameraID); | 
				
			||||||
 | 
					    auto cab = StartCapture(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return std::map<Encodable, Encodable>{ | 
				
			||||||
 | 
					        {"textureId", m_textureId}, | 
				
			||||||
 | 
					        {"width", cab.width}, | 
				
			||||||
 | 
					        {"height", cab.height}, | 
				
			||||||
 | 
					    }; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Camera::Unregister() | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    StopCapture(); | 
				
			||||||
 | 
					    m_plugin->UnregisterTexture(m_textureId); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Camera::onCameraFrame(std::shared_ptr<Aurora::StreamCamera::GraphicBuffer> buffer) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    if (buffer->handleType == Aurora::StreamCamera::HandleType::EGL) { | 
				
			||||||
 | 
					        // @todo Not tested. The device needs to be completed.
 | 
				
			||||||
 | 
					        auto eglImage = CameraEGLHelper::EGLCreateImage(buffer); | 
				
			||||||
 | 
					        this->m_buffer = new TextureVariant(FlutterEGLImage{ | 
				
			||||||
 | 
					            eglImage, | 
				
			||||||
 | 
					            buffer->width, | 
				
			||||||
 | 
					            buffer->height, | 
				
			||||||
 | 
					        }); | 
				
			||||||
 | 
					    } else { | 
				
			||||||
 | 
					        auto pixels = CameraPixelsHelper::YUVtoARGB(buffer->mapYCbCr()); | 
				
			||||||
 | 
					        this->m_buffer = new TextureVariant(FlutterPixelBuffer{ | 
				
			||||||
 | 
					            pixels, | 
				
			||||||
 | 
					            buffer->width, | 
				
			||||||
 | 
					            buffer->height, | 
				
			||||||
 | 
					        }); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_plugin->MarkTextureAvailable(m_textureId); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Camera::onCameraError(const std::string &errorDescription) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    this->Unregister(); | 
				
			||||||
 | 
					    std::cout << errorDescription << std::endl; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Camera::onCameraParameterChanged(Aurora::StreamCamera::CameraParameter parameter, | 
				
			||||||
 | 
					                                      const std::string &value) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    std::cout << "onCameraParameterChanged" << std::endl; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,42 @@ | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					#include <embedder_texture/camera_egl_helper.h> | 
				
			||||||
 | 
					#include <flutter/platform-methods.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <GLES2/gl2.h> | 
				
			||||||
 | 
					#include <GLES2/gl2ext.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; | 
				
			||||||
 | 
					static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CameraEGLHelper::EGLInit() | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    eglCreateImageKHR = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>( | 
				
			||||||
 | 
					        eglGetProcAddress("eglCreateImageKHR")); | 
				
			||||||
 | 
					    eglDestroyImageKHR = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>( | 
				
			||||||
 | 
					        eglGetProcAddress("eglDestroyImageKHR")); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EGLImageKHR CameraEGLHelper::EGLCreateImage( | 
				
			||||||
 | 
					    std::shared_ptr<Aurora::StreamCamera::GraphicBuffer> buffer) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    auto display = PlatformMethods::GetEGLDisplay(); | 
				
			||||||
 | 
					    auto context = PlatformMethods::GetEGLContext(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const void *handle = buffer->handle; | 
				
			||||||
 | 
					    GLint eglImgAttrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE}; | 
				
			||||||
 | 
					    return eglCreateImageKHR(display, | 
				
			||||||
 | 
					                             context, | 
				
			||||||
 | 
					                             EGL_NATIVE_BUFFER_ANDROID, | 
				
			||||||
 | 
					                             (EGLClientBuffer) handle, | 
				
			||||||
 | 
					                             eglImgAttrs); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CameraEGLHelper::EGLDestroyImage(EGLImageKHR image) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    auto display = PlatformMethods::GetEGLDisplay(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    eglDestroyImageKHR(display, image); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,106 @@ | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					#include <embedder_texture/camera_helper.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; | 
				
			||||||
 | 
					static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CameraHelper::EGLInit() | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    eglCreateImageKHR = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>( | 
				
			||||||
 | 
					        eglGetProcAddress("eglCreateImageKHR")); | 
				
			||||||
 | 
					    eglDestroyImageKHR = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>( | 
				
			||||||
 | 
					        eglGetProcAddress("eglDestroyImageKHR")); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EGLImageKHR CameraHelper::EGLCreateImage( | 
				
			||||||
 | 
					    std::shared_ptr<const Aurora::StreamCamera::YCbCrFrame> frame) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    auto eglDisplay = PlatformMethods::GetEGLDisplay(); | 
				
			||||||
 | 
					    auto eglContext = PlatformMethods::GetEGLContext(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const void *handle = buffer->handle; | 
				
			||||||
 | 
					    GLint eglImgAttrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE}; | 
				
			||||||
 | 
					    return s_eglCreateImageKHR(eglDisplay, | 
				
			||||||
 | 
					                               eglContext, | 
				
			||||||
 | 
					                               EGL_NATIVE_BUFFER_ANDROID, | 
				
			||||||
 | 
					                               (EGLClientBuffer) handle, | 
				
			||||||
 | 
					                               eglImgAttrs); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CameraHelper::EGLDestroyImage(EGLImageKHR eglImage, EGLDisplay eglDisplay) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    return eglDestroyImageKHR(eglDisplay, eglImage); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t *CameraHelper::YUVtoARGB(std::shared_ptr<const Aurora::StreamCamera::YCbCrFrame> frame) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    QSize size(frame->width, frame->height); | 
				
			||||||
 | 
					    QImage *image = new QImage(size, QImage::Format_ARGB32); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    planarYuv420ToArgb(frame->y, | 
				
			||||||
 | 
					                       frame->cb, | 
				
			||||||
 | 
					                       frame->cr, | 
				
			||||||
 | 
					                       frame->yStride, | 
				
			||||||
 | 
					                       frame->cStride, | 
				
			||||||
 | 
					                       frame->cStride, | 
				
			||||||
 | 
					                       frame->chromaStep, | 
				
			||||||
 | 
					                       reinterpret_cast<quint32 *>(image->bits()), | 
				
			||||||
 | 
					                       frame->width, | 
				
			||||||
 | 
					                       frame->height); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return static_cast<uint8_t *>(image->bits()); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					quint32 CameraHelper::yuvToArgb(qint32 y, qint32 rv, qint32 guv, qint32 bu, qint32 a = 255) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    qint32 yy = (y - 16) * 298; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (a << 24) | qBound(0, (yy + rv) >> 8, 255) << 16 | qBound(0, (yy - guv) >> 8, 255) << 8 | 
				
			||||||
 | 
					           | qBound(0, (yy + bu) >> 8, 255); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CameraHelper::planarYuv420ToArgb(const uchar *y, | 
				
			||||||
 | 
					                                      const uchar *u, | 
				
			||||||
 | 
					                                      const uchar *v, | 
				
			||||||
 | 
					                                      qint32 yStride, | 
				
			||||||
 | 
					                                      qint32 uStride, | 
				
			||||||
 | 
					                                      qint32 vStride, | 
				
			||||||
 | 
					                                      qint32 uvPixelStride, | 
				
			||||||
 | 
					                                      quint32 *rgb, | 
				
			||||||
 | 
					                                      qint32 width, | 
				
			||||||
 | 
					                                      qint32 height) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    quint32 *rgb0 = rgb; | 
				
			||||||
 | 
					    quint32 *rgb1 = rgb + width; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (qint32 j = 0; j < height; j += 2) { | 
				
			||||||
 | 
					        const uchar *lineY0 = y; | 
				
			||||||
 | 
					        const uchar *lineY1 = y + yStride; | 
				
			||||||
 | 
					        const uchar *lineU = u; | 
				
			||||||
 | 
					        const uchar *lineV = v; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (qint32 i = 0; i < width; i += 2) { | 
				
			||||||
 | 
					            const qint32 uu = *lineU - 128; | 
				
			||||||
 | 
					            const qint32 vv = *lineV - 128; | 
				
			||||||
 | 
					            const qint32 rv = 409 * vv + 128; | 
				
			||||||
 | 
					            const qint32 guv = 100 * uu + 208 * vv + 128; | 
				
			||||||
 | 
					            const qint32 bu = 516 * uu + 128; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            lineU += uvPixelStride; | 
				
			||||||
 | 
					            lineV += uvPixelStride; | 
				
			||||||
 | 
					            *rgb0++ = yuvToArgb(*lineY0++, rv, guv, bu); | 
				
			||||||
 | 
					            *rgb0++ = yuvToArgb(*lineY0++, rv, guv, bu); | 
				
			||||||
 | 
					            *rgb1++ = yuvToArgb(*lineY1++, rv, guv, bu); | 
				
			||||||
 | 
					            *rgb1++ = yuvToArgb(*lineY1++, rv, guv, bu); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        y += yStride << 1; | 
				
			||||||
 | 
					        u += uStride; | 
				
			||||||
 | 
					        v += vStride; | 
				
			||||||
 | 
					        rgb0 += width; | 
				
			||||||
 | 
					        rgb1 += width; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,77 @@ | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					#include <embedder_texture/camera_pixels_helper.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t *CameraPixelsHelper::YUVtoARGB(std::shared_ptr<const Aurora::StreamCamera::YCbCrFrame> frame) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    QSize size(frame->width, frame->height); | 
				
			||||||
 | 
					    QImage *image = new QImage(size, QImage::Format_ARGB32); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    planarYuv420ToArgb(frame->y, | 
				
			||||||
 | 
					                       frame->cr, | 
				
			||||||
 | 
					                       frame->cb, | 
				
			||||||
 | 
					                       frame->yStride, | 
				
			||||||
 | 
					                       frame->cStride, | 
				
			||||||
 | 
					                       frame->cStride, | 
				
			||||||
 | 
					                       frame->chromaStep, | 
				
			||||||
 | 
					                       reinterpret_cast<quint32 *>(image->bits()), | 
				
			||||||
 | 
					                       frame->width, | 
				
			||||||
 | 
					                       frame->height); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return static_cast<uint8_t *>(image->bits()); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					quint32 CameraPixelsHelper::yuvToArgb(qint32 y, qint32 rv, qint32 guv, qint32 bu, qint32 a = 255) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    qint32 yy = (y - 16) * 298; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (a << 24) | 
				
			||||||
 | 
					           | qBound(0, (yy + rv) >> 8, 255) << 16 | 
				
			||||||
 | 
					           | qBound(0, (yy - guv) >> 8, 255) << 8 | 
				
			||||||
 | 
					           | qBound(0, (yy + bu) >> 8, 255); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CameraPixelsHelper::planarYuv420ToArgb(const uchar *y, | 
				
			||||||
 | 
					                                            const uchar *u, | 
				
			||||||
 | 
					                                            const uchar *v, | 
				
			||||||
 | 
					                                            qint32 yStride, | 
				
			||||||
 | 
					                                            qint32 uStride, | 
				
			||||||
 | 
					                                            qint32 vStride, | 
				
			||||||
 | 
					                                            qint32 uvPixelStride, | 
				
			||||||
 | 
					                                            quint32 *rgb, | 
				
			||||||
 | 
					                                            qint32 width, | 
				
			||||||
 | 
					                                            qint32 height) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    quint32 *rgb0 = rgb; | 
				
			||||||
 | 
					    quint32 *rgb1 = rgb + width; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (qint32 j = 0; j < height; j += 2) { | 
				
			||||||
 | 
					        const uchar *lineY0 = y; | 
				
			||||||
 | 
					        const uchar *lineY1 = y + yStride; | 
				
			||||||
 | 
					        const uchar *lineU = u; | 
				
			||||||
 | 
					        const uchar *lineV = v; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (qint32 i = 0; i < width; i += 2) { | 
				
			||||||
 | 
					            const qint32 uu = *lineU - 128; | 
				
			||||||
 | 
					            const qint32 vv = *lineV - 128; | 
				
			||||||
 | 
					            const qint32 rv = 409 * vv + 128; | 
				
			||||||
 | 
					            const qint32 guv = 100 * uu + 208 * vv + 128; | 
				
			||||||
 | 
					            const qint32 bu = 516 * uu + 128; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            lineU += uvPixelStride; | 
				
			||||||
 | 
					            lineV += uvPixelStride; | 
				
			||||||
 | 
					            *rgb0++ = yuvToArgb(*lineY0++, rv, guv, bu); | 
				
			||||||
 | 
					            *rgb0++ = yuvToArgb(*lineY0++, rv, guv, bu); | 
				
			||||||
 | 
					            *rgb1++ = yuvToArgb(*lineY1++, rv, guv, bu); | 
				
			||||||
 | 
					            *rgb1++ = yuvToArgb(*lineY1++, rv, guv, bu); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        y += yStride << 1; | 
				
			||||||
 | 
					        u += uStride; | 
				
			||||||
 | 
					        v += vStride; | 
				
			||||||
 | 
					        rgb0 += width; | 
				
			||||||
 | 
					        rgb1 += width; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,87 @@ | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					#include <embedder_texture/embedder_texture_plugin.h> | 
				
			||||||
 | 
					#include <flutter/method-channel.h> | 
				
			||||||
 | 
					#include <flutter/platform-data.h> | 
				
			||||||
 | 
					#include <flutter/platform-events.h> | 
				
			||||||
 | 
					#include <flutter/platform-methods.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EmbedderTexturePlugin::EmbedderTexturePlugin() | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    PlatformEvents::SubscribeOrientationChanged([this](DisplayRotation orientation) { | 
				
			||||||
 | 
					        if (this->m_isEnableOrientationChanged) { | 
				
			||||||
 | 
					            EventChannel("embedder_texture_orientation", MethodCodecType::Standard) | 
				
			||||||
 | 
					                .SendEvent(static_cast<int>(orientation)); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					    }); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void EmbedderTexturePlugin::RegisterWithRegistrar(PluginRegistrar ®istrar) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    TextureRegistrar *plugin = registrar.GetRegisterTexture(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_camera = new Camera(plugin); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    registrar.RegisterMethodChannel("embedder_texture", | 
				
			||||||
 | 
					                                    MethodCodecType::Standard, | 
				
			||||||
 | 
					                                    [this](const MethodCall &call) { this->onMethodCall(call); }); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    registrar.RegisterEventChannel( | 
				
			||||||
 | 
					        "embedder_texture_orientation", | 
				
			||||||
 | 
					        MethodCodecType::Standard, | 
				
			||||||
 | 
					        [this](const Encodable &) { | 
				
			||||||
 | 
					            this->m_isEnableOrientationChanged = true; | 
				
			||||||
 | 
					            return EventResponse(); | 
				
			||||||
 | 
					        }, | 
				
			||||||
 | 
					        [this](const Encodable &) { | 
				
			||||||
 | 
					            this->m_isEnableOrientationChanged = false; | 
				
			||||||
 | 
					            return EventResponse(); | 
				
			||||||
 | 
					        }); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void EmbedderTexturePlugin::onMethodCall(const MethodCall &call) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    const auto &method = call.GetMethod(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (method == "create") { | 
				
			||||||
 | 
					        onCreate(call); | 
				
			||||||
 | 
					        return; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (method == "remove") { | 
				
			||||||
 | 
					        onRemove(call); | 
				
			||||||
 | 
					        return; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unimplemented(call); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void EmbedderTexturePlugin::onCreate(const MethodCall &call) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    auto cameraId = 0; | 
				
			||||||
 | 
					    auto width = call.GetArgument<Encodable::Int>("width"); | 
				
			||||||
 | 
					    auto height = call.GetArgument<Encodable::Int>("height"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto result = m_camera->Register(cameraId, width, height); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result["orientation"] = static_cast<int>(PlatformMethods::GetOrientation()); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    call.SendSuccessResponse(result); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void EmbedderTexturePlugin::onRemove(const MethodCall &call) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    auto textureId = call.GetArgument<Encodable::Int>("textureId"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_camera->Unregister(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    call.SendSuccessResponse(true); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void EmbedderTexturePlugin::unimplemented(const MethodCall &call) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    call.SendSuccessResponse(nullptr); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,47 @@ | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					#ifndef CAMERA_BUFFER_H | 
				
			||||||
 | 
					#define CAMERA_BUFFER_H | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <flutter/plugin-interface.h> | 
				
			||||||
 | 
					#include <streamcamera/streamcamera.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QImage> | 
				
			||||||
 | 
					#include <QtCore> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Camera : public Aurora::StreamCamera::CameraListener | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					public: | 
				
			||||||
 | 
					    Camera(TextureRegistrar *plugin); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void onCameraError(const std::string &errorDescription) override; | 
				
			||||||
 | 
					    void onCameraFrame(std::shared_ptr<Aurora::StreamCamera::GraphicBuffer> buffer) override; | 
				
			||||||
 | 
					    void onCameraParameterChanged(Aurora::StreamCamera::CameraParameter, | 
				
			||||||
 | 
					                                  const std::string &value) override; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::map<Encodable, Encodable> Register(int cameraID, int width, int height); | 
				
			||||||
 | 
					    void Unregister(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private: | 
				
			||||||
 | 
					    void InitializeCamera(int cameraID); | 
				
			||||||
 | 
					    Aurora::StreamCamera::CameraCapability StartCapture(); | 
				
			||||||
 | 
					    void StopCapture(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private: | 
				
			||||||
 | 
					    TextureRegistrar *m_plugin; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Aurora::StreamCamera::CameraManager *m_manager; | 
				
			||||||
 | 
					    std::shared_ptr<Aurora::StreamCamera::Camera> m_camera; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int m_cameraId = -1; | 
				
			||||||
 | 
					    int64_t m_textureId; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int m_widthTexture; | 
				
			||||||
 | 
					    int m_heightTexture; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TextureVariant *m_buffer; | 
				
			||||||
 | 
					}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* CAMERA_BUFFER_H */ | 
				
			||||||
@ -0,0 +1,21 @@ | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					#ifndef CAMERA_EGL_HELPER_H | 
				
			||||||
 | 
					#define CAMERA_EGL_HELPER_H | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <streamcamera/streamcamera.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <EGL/egl.h> | 
				
			||||||
 | 
					#include <EGL/eglext.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CameraEGLHelper | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					public: | 
				
			||||||
 | 
					    static void EGLInit(); | 
				
			||||||
 | 
					    static EGLImageKHR EGLCreateImage(std::shared_ptr<Aurora::StreamCamera::GraphicBuffer> buffer); | 
				
			||||||
 | 
					    static void EGLDestroyImage(EGLImageKHR image); | 
				
			||||||
 | 
					}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* CAMERA_EGL_HELPER_H */ | 
				
			||||||
@ -0,0 +1,33 @@ | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					#ifndef CAMERA_PIXELS_HELPER_H | 
				
			||||||
 | 
					#define CAMERA_PIXELS_HELPER_H | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <flutter/plugin-interface.h> | 
				
			||||||
 | 
					#include <streamcamera/streamcamera.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QImage> | 
				
			||||||
 | 
					#include <QtCore> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CameraPixelsHelper | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					public: | 
				
			||||||
 | 
					    static uint8_t *YUVtoARGB(std::shared_ptr<const Aurora::StreamCamera::YCbCrFrame> frame); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private: | 
				
			||||||
 | 
					    static quint32 yuvToArgb(qint32 y, qint32 rv, qint32 guv, qint32 bu, qint32 a); | 
				
			||||||
 | 
					    static void planarYuv420ToArgb(const uchar *y, | 
				
			||||||
 | 
					                                   const uchar *u, | 
				
			||||||
 | 
					                                   const uchar *v, | 
				
			||||||
 | 
					                                   qint32 yStride, | 
				
			||||||
 | 
					                                   qint32 uStride, | 
				
			||||||
 | 
					                                   qint32 vStride, | 
				
			||||||
 | 
					                                   qint32 uvPixelStride, | 
				
			||||||
 | 
					                                   quint32 *rgb, | 
				
			||||||
 | 
					                                   qint32 width, | 
				
			||||||
 | 
					                                   qint32 height); | 
				
			||||||
 | 
					}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* CAMERA_PIXELS_HELPER_H */ | 
				
			||||||
@ -0,0 +1,35 @@ | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					#ifndef EMBEDDER_TEXTURE_PLUGIN_H | 
				
			||||||
 | 
					#define EMBEDDER_TEXTURE_PLUGIN_H | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <flutter/plugin-interface.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <embedder_texture/camera.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef PLUGIN_IMPL | 
				
			||||||
 | 
					#define PLUGIN_EXPORT __attribute__((visibility("default"))) | 
				
			||||||
 | 
					#else | 
				
			||||||
 | 
					#define PLUGIN_EXPORT | 
				
			||||||
 | 
					#endif | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PLUGIN_EXPORT EmbedderTexturePlugin final : public PluginInterface | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					public: | 
				
			||||||
 | 
					    EmbedderTexturePlugin(); | 
				
			||||||
 | 
					    void RegisterWithRegistrar(PluginRegistrar ®istrar) override; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private: | 
				
			||||||
 | 
					    void onMethodCall(const MethodCall &call); | 
				
			||||||
 | 
					    void onCreate(const MethodCall &call); | 
				
			||||||
 | 
					    void onRemove(const MethodCall &call); | 
				
			||||||
 | 
					    void unimplemented(const MethodCall &call); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private: | 
				
			||||||
 | 
					    Camera *m_camera; | 
				
			||||||
 | 
					    bool m_isEnableOrientationChanged = false; | 
				
			||||||
 | 
					}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* EMBEDDER_TEXTURE_PLUGIN_H */ | 
				
			||||||
@ -0,0 +1,162 @@ | 
				
			|||||||
 | 
					import 'package:flutter/material.dart'; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'embedder_texture_platform_interface.dart'; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum OrientationEvent { | 
				
			||||||
 | 
					  undefined, | 
				
			||||||
 | 
					  portrait, | 
				
			||||||
 | 
					  landscape, | 
				
			||||||
 | 
					  portraitFlipped, | 
				
			||||||
 | 
					  landscapeFlipped, | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class EmbedderTexture extends StatefulWidget { | 
				
			||||||
 | 
					  const EmbedderTexture({ | 
				
			||||||
 | 
					    super.key, | 
				
			||||||
 | 
					    required this.width, | 
				
			||||||
 | 
					    required this.height, | 
				
			||||||
 | 
					  }); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final double width; | 
				
			||||||
 | 
					  final double height; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override | 
				
			||||||
 | 
					  State<EmbedderTexture> createState() => _EmbedderTextureState(); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _EmbedderTextureState extends State<EmbedderTexture> { | 
				
			||||||
 | 
					  int _textureID = 0; | 
				
			||||||
 | 
					  int _cameraWidth = 0; | 
				
			||||||
 | 
					  int _cameraHeight = 0; | 
				
			||||||
 | 
					  OrientationEvent _orientation = OrientationEvent.undefined; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override | 
				
			||||||
 | 
					  initState() { | 
				
			||||||
 | 
					    super.initState(); | 
				
			||||||
 | 
					    EmbedderTexturePlatform.instance | 
				
			||||||
 | 
					        .create(widget.width, widget.height) | 
				
			||||||
 | 
					        .then((data) => setState(() { | 
				
			||||||
 | 
					              if (mounted) { | 
				
			||||||
 | 
					                _textureID = data['textureId']!; | 
				
			||||||
 | 
					                _cameraWidth = data['width']!; | 
				
			||||||
 | 
					                _cameraHeight = data['height']!; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                switch (data['orientation']!) { | 
				
			||||||
 | 
					                  case 0: | 
				
			||||||
 | 
					                    _orientation = OrientationEvent.portrait; | 
				
			||||||
 | 
					                    break; | 
				
			||||||
 | 
					                  case 90: | 
				
			||||||
 | 
					                    _orientation = OrientationEvent.landscape; | 
				
			||||||
 | 
					                    break; | 
				
			||||||
 | 
					                  case 180: | 
				
			||||||
 | 
					                    _orientation = OrientationEvent.portraitFlipped; | 
				
			||||||
 | 
					                    break; | 
				
			||||||
 | 
					                  case 270: | 
				
			||||||
 | 
					                    _orientation = OrientationEvent.landscapeFlipped; | 
				
			||||||
 | 
					                    break; | 
				
			||||||
 | 
					                  default: | 
				
			||||||
 | 
					                    _orientation = OrientationEvent.undefined; | 
				
			||||||
 | 
					                } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                debugPrint(data.toString()); | 
				
			||||||
 | 
					              } | 
				
			||||||
 | 
					            })); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    EmbedderTexturePlatform.instance.onChangeOrientation().listen((event) { | 
				
			||||||
 | 
					      setState(() { | 
				
			||||||
 | 
					        if (mounted) { | 
				
			||||||
 | 
					          _orientation = event; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					      }); | 
				
			||||||
 | 
					    }); | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override | 
				
			||||||
 | 
					  void dispose() { | 
				
			||||||
 | 
					    super.dispose(); | 
				
			||||||
 | 
					    EmbedderTexturePlatform.instance.remove(_textureID); | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // @override | 
				
			||||||
 | 
					  // Widget build(BuildContext context) { | 
				
			||||||
 | 
					  //   if (_textureID != 0) { | 
				
			||||||
 | 
					  //     double w = 0; | 
				
			||||||
 | 
					  //     double h = 0; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  //     if (MediaQuery.of(context).orientation == Orientation.portrait) { | 
				
			||||||
 | 
					  //       w = _cameraWidth * widget.height / (widget.width - 40); | 
				
			||||||
 | 
					  //       h = widget.width - 40; | 
				
			||||||
 | 
					  //     } else { | 
				
			||||||
 | 
					  //       w = _cameraHeight.toDouble(); | 
				
			||||||
 | 
					  //       h = widget.height - 40 - 56; | 
				
			||||||
 | 
					  //     } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  //     return Container( | 
				
			||||||
 | 
					  //       color: Colors.black, | 
				
			||||||
 | 
					  //       width: widget.width, | 
				
			||||||
 | 
					  //       height: widget.height, | 
				
			||||||
 | 
					  //       child: RotationTransition( | 
				
			||||||
 | 
					  //         turns: AlwaysStoppedAnimation( | 
				
			||||||
 | 
					  //           _orientation == OrientationEvent.portrait ? 90 / 360 : 0, | 
				
			||||||
 | 
					  //         ), | 
				
			||||||
 | 
					  //         child: SizedBox( | 
				
			||||||
 | 
					  //           width: w, | 
				
			||||||
 | 
					  //           height: h, | 
				
			||||||
 | 
					  //           child: Texture(textureId: _textureID), | 
				
			||||||
 | 
					  //         ), | 
				
			||||||
 | 
					  //       ), | 
				
			||||||
 | 
					  //     ); | 
				
			||||||
 | 
					  //   } | 
				
			||||||
 | 
					  //   return const SizedBox.shrink(); | 
				
			||||||
 | 
					  // } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override | 
				
			||||||
 | 
					  Widget build(BuildContext context) { | 
				
			||||||
 | 
					    if (_textureID != 0) { | 
				
			||||||
 | 
					      double w = 0; | 
				
			||||||
 | 
					      double h = 0; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (_orientation == OrientationEvent.portrait || | 
				
			||||||
 | 
					          _orientation == OrientationEvent.portraitFlipped) { | 
				
			||||||
 | 
					        w = _cameraWidth * widget.height / (widget.width - 40); | 
				
			||||||
 | 
					        h = widget.width - 40; | 
				
			||||||
 | 
					      } else { | 
				
			||||||
 | 
					        w = _cameraHeight.toDouble(); | 
				
			||||||
 | 
					        h = widget.height - 40 - 56; | 
				
			||||||
 | 
					      } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      AlwaysStoppedAnimation<double>? turns; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      switch (_orientation) { | 
				
			||||||
 | 
					        case OrientationEvent.portrait: | 
				
			||||||
 | 
					          turns = const AlwaysStoppedAnimation(90 / 360); | 
				
			||||||
 | 
					          break; | 
				
			||||||
 | 
					        case OrientationEvent.portraitFlipped: | 
				
			||||||
 | 
					          turns = const AlwaysStoppedAnimation(270 / 360); | 
				
			||||||
 | 
					          break; | 
				
			||||||
 | 
					        case OrientationEvent.landscapeFlipped: | 
				
			||||||
 | 
					          turns = const AlwaysStoppedAnimation(180 / 360); | 
				
			||||||
 | 
					          break; | 
				
			||||||
 | 
					        default: | 
				
			||||||
 | 
					          turns = const AlwaysStoppedAnimation(0); | 
				
			||||||
 | 
					      } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return Container( | 
				
			||||||
 | 
					        color: Colors.black, | 
				
			||||||
 | 
					        width: widget.width, | 
				
			||||||
 | 
					        height: widget.height, | 
				
			||||||
 | 
					        child: Center( | 
				
			||||||
 | 
					          child: RotationTransition( | 
				
			||||||
 | 
					            turns: turns, | 
				
			||||||
 | 
					            child: SizedBox( | 
				
			||||||
 | 
					              width: w, | 
				
			||||||
 | 
					              height: h, | 
				
			||||||
 | 
					              child: Texture(textureId: _textureID), | 
				
			||||||
 | 
					            ), | 
				
			||||||
 | 
					          ), | 
				
			||||||
 | 
					        ), | 
				
			||||||
 | 
					      ); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					    return const SizedBox.shrink(); | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,54 @@ | 
				
			|||||||
 | 
					import 'package:embedder_texture/embedder_texture.dart'; | 
				
			||||||
 | 
					import 'package:flutter/foundation.dart'; | 
				
			||||||
 | 
					import 'package:flutter/services.dart'; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'embedder_texture_platform_interface.dart'; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// An implementation of [LinuxOpenglPlatform] that uses method channels. | 
				
			||||||
 | 
					class MethodChannelEmbedderTexture extends EmbedderTexturePlatform { | 
				
			||||||
 | 
					  /// The method channel used to interact with the native platform. | 
				
			||||||
 | 
					  @visibleForTesting | 
				
			||||||
 | 
					  final methodChannel = const MethodChannel('embedder_texture'); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override | 
				
			||||||
 | 
					  Future<Map<dynamic, dynamic>> create(double width, double height) async { | 
				
			||||||
 | 
					    final data = | 
				
			||||||
 | 
					        await methodChannel.invokeMethod<Map<dynamic, dynamic>?>('create', { | 
				
			||||||
 | 
					      'width': width.round(), | 
				
			||||||
 | 
					      'height': height.round(), | 
				
			||||||
 | 
					    }); | 
				
			||||||
 | 
					    return data ?? {}; | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override | 
				
			||||||
 | 
					  Future<bool> remove(int textureId) async { | 
				
			||||||
 | 
					    return await methodChannel.invokeMethod<bool>('remove', { | 
				
			||||||
 | 
					          'textureId': textureId, | 
				
			||||||
 | 
					        }) ?? | 
				
			||||||
 | 
					        false; | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override | 
				
			||||||
 | 
					  Stream<OrientationEvent> onChangeOrientation() async* { | 
				
			||||||
 | 
					    await for (final orientation | 
				
			||||||
 | 
					        in const EventChannel('embedder_texture_orientation') | 
				
			||||||
 | 
					            .receiveBroadcastStream()) { | 
				
			||||||
 | 
					      switch (orientation) { | 
				
			||||||
 | 
					        case 0: | 
				
			||||||
 | 
					          yield OrientationEvent.portrait; | 
				
			||||||
 | 
					          break; | 
				
			||||||
 | 
					        case 90: | 
				
			||||||
 | 
					          yield OrientationEvent.landscape; | 
				
			||||||
 | 
					          break; | 
				
			||||||
 | 
					        case 180: | 
				
			||||||
 | 
					          yield OrientationEvent.portraitFlipped; | 
				
			||||||
 | 
					          break; | 
				
			||||||
 | 
					        case 270: | 
				
			||||||
 | 
					          yield OrientationEvent.landscapeFlipped; | 
				
			||||||
 | 
					          break; | 
				
			||||||
 | 
					        default: | 
				
			||||||
 | 
					          yield OrientationEvent.undefined; | 
				
			||||||
 | 
					      } | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,38 @@ | 
				
			|||||||
 | 
					import 'package:embedder_texture/embedder_texture.dart'; | 
				
			||||||
 | 
					import 'package:plugin_platform_interface/plugin_platform_interface.dart'; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'embedder_texture_method_channel.dart'; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class EmbedderTexturePlatform extends PlatformInterface { | 
				
			||||||
 | 
					  /// Constructs a LinuxOpenglPlatform. | 
				
			||||||
 | 
					  EmbedderTexturePlatform() : super(token: _token); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static final Object _token = Object(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static EmbedderTexturePlatform _instance = MethodChannelEmbedderTexture(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// The default instance of [LinuxOpenglPlatform] to use. | 
				
			||||||
 | 
					  /// | 
				
			||||||
 | 
					  /// Defaults to [MethodChannelLinuxOpengl]. | 
				
			||||||
 | 
					  static EmbedderTexturePlatform get instance => _instance; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Platform-specific implementations should set this with their own | 
				
			||||||
 | 
					  /// platform-specific class that extends [LinuxOpenglPlatform] when | 
				
			||||||
 | 
					  /// they register themselves. | 
				
			||||||
 | 
					  static set instance(EmbedderTexturePlatform instance) { | 
				
			||||||
 | 
					    PlatformInterface.verifyToken(instance, _token); | 
				
			||||||
 | 
					    _instance = instance; | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Stream<OrientationEvent> onChangeOrientation() { | 
				
			||||||
 | 
					    throw UnimplementedError('onChangeOrientation() has not been implemented.'); | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<Map<dynamic, dynamic>> create(double width, double height) { | 
				
			||||||
 | 
					    throw UnimplementedError('create() has not been implemented.'); | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<bool> remove(int textureId) { | 
				
			||||||
 | 
					    throw UnimplementedError('remove() has not been implemented.'); | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,24 @@ | 
				
			|||||||
 | 
					cmake_minimum_required(VERSION 3.10) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(PROJECT_NAME "embedder_texture") | 
				
			||||||
 | 
					project(${PROJECT_NAME} LANGUAGES CXX) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(PLUGIN_NAME "embedder_texture_plugin") | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					list(APPEND PLUGIN_SOURCES | 
				
			||||||
 | 
					  "fl_my_texture_gl.cc" | 
				
			||||||
 | 
					  "embedder_texture_plugin.cc" | 
				
			||||||
 | 
					) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_library(${PLUGIN_NAME} SHARED | 
				
			||||||
 | 
					  ${PLUGIN_SOURCES} | 
				
			||||||
 | 
					) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					apply_standard_settings(${PLUGIN_NAME}) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) | 
				
			||||||
 | 
					target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_include_directories(${PLUGIN_NAME} INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include") | 
				
			||||||
 | 
					target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) | 
				
			||||||
 | 
					target_link_libraries(${PLUGIN_NAME} PUBLIC GL) | 
				
			||||||
@ -0,0 +1,173 @@ | 
				
			|||||||
 | 
					#include "include/embedder_texture/embedder_texture_plugin.h" | 
				
			||||||
 | 
					#include "include/fl_my_texture_gl.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <flutter_linux/flutter_linux.h> | 
				
			||||||
 | 
					#include <flutter_linux/fl_view.h> | 
				
			||||||
 | 
					#include <GLES2/gl2.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "embedder_texture_plugin_private.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EMBEDDER_TEXTURE_PLUGIN(obj)                                     \ | 
				
			||||||
 | 
					  (G_TYPE_CHECK_INSTANCE_CAST((obj), embedder_texture_plugin_get_type(), \
 | 
				
			||||||
 | 
					                              LinuxOpenglPlugin)) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct _LinuxOpenglPlugin | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					  GObject parent_instance; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  unsigned int width = 0; | 
				
			||||||
 | 
					  unsigned int height = 0; | 
				
			||||||
 | 
					  unsigned int texture_id = 0; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  FlTexture *texture = nullptr; | 
				
			||||||
 | 
					  FlTextureRegistrar *texture_registrar = nullptr; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  FlMyTextureGL *myTexture = nullptr; | 
				
			||||||
 | 
					  FlView *fl_view = nullptr; | 
				
			||||||
 | 
					}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_DEFINE_TYPE(LinuxOpenglPlugin, embedder_texture_plugin, g_object_get_type()) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Called when a method call is received from Flutter.
 | 
				
			||||||
 | 
					static void embedder_texture_plugin_handle_method_call( | 
				
			||||||
 | 
					    LinuxOpenglPlugin *self, | 
				
			||||||
 | 
					    FlMethodCall *method_call) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  g_autoptr(FlMethodResponse) response = nullptr; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const gchar *method = fl_method_call_get_name(method_call); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (strcmp(method, "create") == 0) | 
				
			||||||
 | 
					  { | 
				
			||||||
 | 
					    response = create(self, method_call); | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					  else if (strcmp(method, "remove") == 0) | 
				
			||||||
 | 
					  { | 
				
			||||||
 | 
					    response = remove(self, method_call); | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					  else | 
				
			||||||
 | 
					  { | 
				
			||||||
 | 
					    response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new()); | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fl_method_call_respond(method_call, response, nullptr); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FlMethodResponse *create( | 
				
			||||||
 | 
					    LinuxOpenglPlugin *self, | 
				
			||||||
 | 
					    FlMethodCall *method_call) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    GError *error = NULL; | 
				
			||||||
 | 
					    FlValue *args = fl_method_call_get_args(method_call); | 
				
			||||||
 | 
					    FlValue *w = fl_value_lookup_string(args, "width"); | 
				
			||||||
 | 
					    FlValue *h = fl_value_lookup_string(args, "height"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (w != nullptr) | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        self->width = fl_value_get_float(w); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (h != nullptr) | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        self->height = fl_value_get_float(h); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (self->width != 0 && self->height != 0) | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        static GLfloat pixels[] = | 
				
			||||||
 | 
					            { | 
				
			||||||
 | 
					                1, 0, 0, | 
				
			||||||
 | 
					                0, 1, 0, | 
				
			||||||
 | 
					                0, 0, 1, | 
				
			||||||
 | 
					                1, 1, 1 | 
				
			||||||
 | 
					            }; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // create in open gl
 | 
				
			||||||
 | 
					        glGenTextures(1, &self->texture_id); | 
				
			||||||
 | 
					        glBindTexture(GL_TEXTURE_2D, self->texture_id); | 
				
			||||||
 | 
					        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 
				
			||||||
 | 
					        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 
				
			||||||
 | 
					        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 
				
			||||||
 | 
					        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // create
 | 
				
			||||||
 | 
					        self->myTexture = fl_my_texture_gl_new(GL_TEXTURE_2D, self->texture_id, self->width, self->height); | 
				
			||||||
 | 
					        self->texture = FL_TEXTURE(self->myTexture); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // reg
 | 
				
			||||||
 | 
					        fl_texture_registrar_register_texture(self->texture_registrar, self->texture); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // draw
 | 
				
			||||||
 | 
					        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_FLOAT, pixels); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // send id
 | 
				
			||||||
 | 
					        g_autoptr(FlValue) result = fl_value_new_int(reinterpret_cast<int64_t>(self->texture)); | 
				
			||||||
 | 
					        return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return FL_METHOD_RESPONSE(fl_method_error_response_new( | 
				
			||||||
 | 
					      "500", | 
				
			||||||
 | 
					      "Method create() called without passing width or height parameters!", | 
				
			||||||
 | 
					      nullptr)); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FlMethodResponse *remove( | 
				
			||||||
 | 
					    LinuxOpenglPlugin *self, | 
				
			||||||
 | 
					    FlMethodCall *method_call) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    FlValue *args = fl_method_call_get_args(method_call); | 
				
			||||||
 | 
					    FlValue *id = fl_value_lookup_string(args, "textureId"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (id != nullptr) | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        int textureId = fl_value_get_int(id); | 
				
			||||||
 | 
					        fl_texture_registrar_unregister_texture(self->texture_registrar, self->texture); | 
				
			||||||
 | 
					        g_autoptr(FlValue) result = fl_value_new_null(); | 
				
			||||||
 | 
					        return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return FL_METHOD_RESPONSE(fl_method_error_response_new( | 
				
			||||||
 | 
					      "500", | 
				
			||||||
 | 
					      "Method remove() called without passing textureId parameters!", | 
				
			||||||
 | 
					      nullptr)); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void embedder_texture_plugin_dispose(GObject *object) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					  G_OBJECT_CLASS(embedder_texture_plugin_parent_class)->dispose(object); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void embedder_texture_plugin_class_init(LinuxOpenglPluginClass *klass) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					  G_OBJECT_CLASS(klass)->dispose = embedder_texture_plugin_dispose; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void embedder_texture_plugin_init(LinuxOpenglPlugin *self) {} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void method_call_cb(FlMethodChannel *channel, FlMethodCall *method_call, | 
				
			||||||
 | 
					                           gpointer user_data) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					  LinuxOpenglPlugin *plugin = EMBEDDER_TEXTURE_PLUGIN(user_data); | 
				
			||||||
 | 
					  embedder_texture_plugin_handle_method_call(plugin, method_call); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void embedder_texture_plugin_register_with_registrar(FlPluginRegistrar *registrar) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					  LinuxOpenglPlugin *plugin = EMBEDDER_TEXTURE_PLUGIN( | 
				
			||||||
 | 
					      g_object_new(embedder_texture_plugin_get_type(), nullptr)); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  plugin->fl_view = fl_plugin_registrar_get_view(registrar); | 
				
			||||||
 | 
					  plugin->texture_registrar = fl_plugin_registrar_get_texture_registrar(registrar); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); | 
				
			||||||
 | 
					  g_autoptr(FlMethodChannel) channel = | 
				
			||||||
 | 
					      fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar), | 
				
			||||||
 | 
					                            "embedder_texture", | 
				
			||||||
 | 
					                            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,7 @@ | 
				
			|||||||
 | 
					#include <flutter_linux/flutter_linux.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "include/embedder_texture/embedder_texture_plugin.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FlMethodResponse *create(LinuxOpenglPlugin *self, FlMethodCall *method_call); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FlMethodResponse *remove(LinuxOpenglPlugin *self, FlMethodCall *method_call); | 
				
			||||||
@ -0,0 +1,44 @@ | 
				
			|||||||
 | 
					#include "include/fl_my_texture_gl.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_DEFINE_TYPE(FlMyTextureGL, | 
				
			||||||
 | 
					              fl_my_texture_gl, | 
				
			||||||
 | 
					              fl_texture_gl_get_type()) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static gboolean fl_my_texture_gl_populate(FlTextureGL *texture, | 
				
			||||||
 | 
					                                          uint32_t *target, | 
				
			||||||
 | 
					                                          uint32_t *name, | 
				
			||||||
 | 
					                                          uint32_t *width, | 
				
			||||||
 | 
					                                          uint32_t *height, | 
				
			||||||
 | 
					                                          GError **error) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					  FlMyTextureGL* f = (FlMyTextureGL*) texture; | 
				
			||||||
 | 
					  *target = f->target; | 
				
			||||||
 | 
					  *name = f->name; | 
				
			||||||
 | 
					  *width = f->width; | 
				
			||||||
 | 
					  *height = f->height; | 
				
			||||||
 | 
					  return true; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FlMyTextureGL *fl_my_texture_gl_new(uint32_t target, | 
				
			||||||
 | 
					                                    uint32_t name, | 
				
			||||||
 | 
					                                    uint32_t width, | 
				
			||||||
 | 
					                                    uint32_t height) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					  auto r = FL_MY_TEXTURE_GL(g_object_new(fl_my_texture_gl_get_type(), nullptr)); | 
				
			||||||
 | 
					  r->target = target; | 
				
			||||||
 | 
					  r->name = name; | 
				
			||||||
 | 
					  r->width = width; | 
				
			||||||
 | 
					  r->height = height; | 
				
			||||||
 | 
					  return r; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fl_my_texture_gl_class_init( | 
				
			||||||
 | 
					    FlMyTextureGLClass *klass) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					  FL_TEXTURE_GL_CLASS(klass)->populate = | 
				
			||||||
 | 
					      fl_my_texture_gl_populate; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fl_my_texture_gl_init(FlMyTextureGL *self) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,26 @@ | 
				
			|||||||
 | 
					#ifndef FLUTTER_PLUGIN_EMBEDDER_TEXTURE_PLUGIN_H_ | 
				
			||||||
 | 
					#define FLUTTER_PLUGIN_EMBEDDER_TEXTURE_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 _LinuxOpenglPlugin LinuxOpenglPlugin; | 
				
			||||||
 | 
					typedef struct { | 
				
			||||||
 | 
					  GObjectClass parent_class; | 
				
			||||||
 | 
					} LinuxOpenglPluginClass; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FLUTTER_PLUGIN_EXPORT GType embedder_texture_plugin_get_type(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FLUTTER_PLUGIN_EXPORT void embedder_texture_plugin_register_with_registrar( | 
				
			||||||
 | 
					    FlPluginRegistrar* registrar); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_END_DECLS | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif  // FLUTTER_PLUGIN_EMBEDDER_TEXTURE_PLUGIN_H_
 | 
				
			||||||
@ -0,0 +1,28 @@ | 
				
			|||||||
 | 
					#ifndef FLUTTER_MY_TEXTURE_H | 
				
			||||||
 | 
					#define FLUTTER_MY_TEXTURE_H | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gtk/gtk.h> | 
				
			||||||
 | 
					#include <glib-object.h> | 
				
			||||||
 | 
					#include "embedder_texture/embedder_texture_plugin.h" | 
				
			||||||
 | 
					#include <flutter_linux/flutter_linux.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					G_DECLARE_FINAL_TYPE(FlMyTextureGL, | 
				
			||||||
 | 
					                     fl_my_texture_gl, | 
				
			||||||
 | 
					                     FL, | 
				
			||||||
 | 
					                     MY_TEXTURE_GL, | 
				
			||||||
 | 
					                     FlTextureGL) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct _FlMyTextureGL | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    FlTextureGL parent_instance; | 
				
			||||||
 | 
					    uint32_t target; | 
				
			||||||
 | 
					    uint32_t name; | 
				
			||||||
 | 
					    uint32_t width; | 
				
			||||||
 | 
					    uint32_t height; | 
				
			||||||
 | 
					}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FlMyTextureGL *fl_my_texture_gl_new(uint32_t target, | 
				
			||||||
 | 
					                                    uint32_t name, | 
				
			||||||
 | 
					                                    uint32_t width, | 
				
			||||||
 | 
					                                    uint32_t height); | 
				
			||||||
 | 
					#endif // FLUTTER_MY_TEXTURE_H
 | 
				
			||||||
@ -0,0 +1,25 @@ | 
				
			|||||||
 | 
					name: embedder_texture | 
				
			||||||
 | 
					description: Example create texture. | 
				
			||||||
 | 
					version: 0.0.1 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					environment: | 
				
			||||||
 | 
					  sdk: '>=3.0.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 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					flutter: | 
				
			||||||
 | 
					  plugin: | 
				
			||||||
 | 
					    platforms: | 
				
			||||||
 | 
					      linux: | 
				
			||||||
 | 
					        pluginClass: EmbedderTexturePlugin | 
				
			||||||
 | 
					      aurora: | 
				
			||||||
 | 
					        pluginClass: EmbedderTexturePlugin | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue