From 5dcfc7239a54f42980b8595a7114cf8eb21e2213 Mon Sep 17 00:00:00 2001 From: "Alexander \"PapaTutuWawa" Date: Fri, 8 Sep 2023 21:41:10 +0200 Subject: [PATCH] feat: Move over the media API --- .../moxxy/moxxy_native/MoxxyNativePlugin.kt | 4 + .../moxxy_native/contacts/ContactsApi.kt | 117 +++++------ .../contacts/ContactsImplementation.kt | 6 +- .../org/moxxy/moxxy_native/media/MediaApi.kt | 79 +++++++ .../moxxy_native/media/MediaImplementation.kt | 45 ++++ .../moxxy_native/platform/PlatformApi.kt | 196 +++++++++--------- .../platform/PlatformImplementation.kt | 2 +- lib/moxxy_native.dart | 1 + lib/pigeon/media.g.dart | 47 +++++ pigeon/media.dart | 16 ++ 10 files changed, 353 insertions(+), 160 deletions(-) create mode 100644 android/src/main/kotlin/org/moxxy/moxxy_native/media/MediaApi.kt create mode 100644 android/src/main/kotlin/org/moxxy/moxxy_native/media/MediaImplementation.kt create mode 100644 lib/pigeon/media.g.dart create mode 100644 pigeon/media.dart diff --git a/android/src/main/kotlin/org/moxxy/moxxy_native/MoxxyNativePlugin.kt b/android/src/main/kotlin/org/moxxy/moxxy_native/MoxxyNativePlugin.kt index 058d361..42f0cdb 100644 --- a/android/src/main/kotlin/org/moxxy/moxxy_native/MoxxyNativePlugin.kt +++ b/android/src/main/kotlin/org/moxxy/moxxy_native/MoxxyNativePlugin.kt @@ -17,6 +17,8 @@ import org.moxxy.moxxy_native.contacts.ContactsImplementation import org.moxxy.moxxy_native.contacts.MoxxyContactsApi import org.moxxy.moxxy_native.cryptography.CryptographyImplementation import org.moxxy.moxxy_native.cryptography.MoxxyCryptographyApi +import org.moxxy.moxxy_native.media.MediaImplementation +import org.moxxy.moxxy_native.media.MoxxyMediaApi import org.moxxy.moxxy_native.notifications.MessagingNotification import org.moxxy.moxxy_native.notifications.MoxxyNotificationsApi import org.moxxy.moxxy_native.notifications.NotificationChannel @@ -65,6 +67,7 @@ class MoxxyNativePlugin : FlutterPlugin, ActivityAware, MoxxyPickerApi, MoxxyNot private val cryptographyImplementation = CryptographyImplementation() private lateinit var contactsImplementation: ContactsImplementation private lateinit var platformImplementation: PlatformImplementation + private val mediaImplementation = MediaImplementation() override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { context = flutterPluginBinding.applicationContext @@ -77,6 +80,7 @@ class MoxxyNativePlugin : FlutterPlugin, ActivityAware, MoxxyPickerApi, MoxxyNot MoxxyCryptographyApi.setUp(flutterPluginBinding.binaryMessenger, cryptographyImplementation) MoxxyContactsApi.setUp(flutterPluginBinding.binaryMessenger, contactsImplementation) MoxxyPlatformApi.setUp(flutterPluginBinding.binaryMessenger, platformImplementation) + MoxxyMediaApi.setUp(flutterPluginBinding.binaryMessenger, mediaImplementation) // Register the picker handler pickerListener = PickerResultListener(context!!) diff --git a/android/src/main/kotlin/org/moxxy/moxxy_native/contacts/ContactsApi.kt b/android/src/main/kotlin/org/moxxy/moxxy_native/contacts/ContactsApi.kt index 5236e9c..3a9a33c 100644 --- a/android/src/main/kotlin/org/moxxy/moxxy_native/contacts/ContactsApi.kt +++ b/android/src/main/kotlin/org/moxxy/moxxy_native/contacts/ContactsApi.kt @@ -8,27 +8,25 @@ import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MessageCodec import io.flutter.plugin.common.StandardMessageCodec -import java.io.ByteArrayOutputStream -import java.nio.ByteBuffer private fun wrapResult(result: Any?): List { - return listOf(result) + return listOf(result) } private fun wrapError(exception: Throwable): List { - if (exception is FlutterError) { - return listOf( - exception.code, - exception.message, - exception.details - ) - } else { - return listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) - } + if (exception is FlutterError) { + return listOf( + exception.code, + exception.message, + exception.details, + ) + } else { + return listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception), + ) + } } /** @@ -37,58 +35,61 @@ private fun wrapError(exception: Throwable): List { * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null, ) : Throwable() /** The type of icon to use when no avatar path is provided. */ enum class FallbackIconType(val raw: Int) { - NONE(0), - PERSON(1), - NOTES(2); + NONE(0), + PERSON(1), + NOTES(2), + ; - companion object { - fun ofRaw(raw: Int): FallbackIconType? { - return values().firstOrNull { it.raw == raw } + companion object { + fun ofRaw(raw: Int): FallbackIconType? { + return values().firstOrNull { it.raw == raw } + } } - } } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface MoxxyContactsApi { - fun recordSentMessage(name: String, jid: String, avatarPath: String?, fallbackIcon: FallbackIconType) + fun recordSentMessage(name: String, jid: String, avatarPath: String?, fallbackIcon: FallbackIconType) - companion object { - /** The codec used by MoxxyContactsApi. */ - val codec: MessageCodec by lazy { - StandardMessageCodec() - } - /** Sets up an instance of `MoxxyContactsApi` to handle messages through the `binaryMessenger`. */ - @Suppress("UNCHECKED_CAST") - fun setUp(binaryMessenger: BinaryMessenger, api: MoxxyContactsApi?) { - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyContactsApi.recordSentMessage", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val nameArg = args[0] as String - val jidArg = args[1] as String - val avatarPathArg = args[2] as String? - val fallbackIconArg = FallbackIconType.ofRaw(args[3] as Int)!! - var wrapped: List - try { - api.recordSentMessage(nameArg, jidArg, avatarPathArg, fallbackIconArg) - wrapped = listOf(null) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) + companion object { + /** The codec used by MoxxyContactsApi. */ + val codec: MessageCodec by lazy { + StandardMessageCodec() + } + + /** Sets up an instance of `MoxxyContactsApi` to handle messages through the `binaryMessenger`. */ + @Suppress("UNCHECKED_CAST") + fun setUp(binaryMessenger: BinaryMessenger, api: MoxxyContactsApi?) { + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyContactsApi.recordSentMessage", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val nameArg = args[0] as String + val jidArg = args[1] as String + val avatarPathArg = args[2] as String? + val fallbackIconArg = FallbackIconType.ofRaw(args[3] as Int)!! + var wrapped: List + try { + api.recordSentMessage(nameArg, jidArg, avatarPathArg, fallbackIconArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } } - } } - } } diff --git a/android/src/main/kotlin/org/moxxy/moxxy_native/contacts/ContactsImplementation.kt b/android/src/main/kotlin/org/moxxy/moxxy_native/contacts/ContactsImplementation.kt index 3390624..4782a82 100644 --- a/android/src/main/kotlin/org/moxxy/moxxy_native/contacts/ContactsImplementation.kt +++ b/android/src/main/kotlin/org/moxxy/moxxy_native/contacts/ContactsImplementation.kt @@ -17,7 +17,7 @@ class ContactsImplementation(private val context: Context) : MoxxyContactsApi { name: String, jid: String, avatarPath: String?, - fallbackIcon: FallbackIconType + fallbackIcon: FallbackIconType, ) { val pkgName = context.packageName val intent = Intent(context, Class.forName("$pkgName.MainActivity")).apply { @@ -49,7 +49,7 @@ class ContactsImplementation(private val context: Context) : MoxxyContactsApi { shortcutBuilder.setIcon(icon) personBuilder.setIcon(icon) } else { - val resourceId = when(fallbackIcon) { + val resourceId = when (fallbackIcon) { FallbackIconType.NONE, FallbackIconType.PERSON -> R.mipmap.person FallbackIconType.NOTES -> R.mipmap.notes } @@ -64,4 +64,4 @@ class ContactsImplementation(private val context: Context) : MoxxyContactsApi { listOf(shortcutBuilder.build()), ) } -} \ No newline at end of file +} diff --git a/android/src/main/kotlin/org/moxxy/moxxy_native/media/MediaApi.kt b/android/src/main/kotlin/org/moxxy/moxxy_native/media/MediaApi.kt new file mode 100644 index 0000000..de35877 --- /dev/null +++ b/android/src/main/kotlin/org/moxxy/moxxy_native/media/MediaApi.kt @@ -0,0 +1,79 @@ +// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +package org.moxxy.moxxy_native.media + +import android.util.Log +import io.flutter.plugin.common.BasicMessageChannel +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMessageCodec + +private fun wrapResult(result: Any?): List { + return listOf(result) +} + +private fun wrapError(exception: Throwable): List { + if (exception is FlutterError) { + return listOf( + exception.code, + exception.message, + exception.details, + ) + } else { + return listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception), + ) + } +} + +/** + * Error class for passing custom error details to Flutter via a thrown PlatformException. + * @property code The error code. + * @property message The error message. + * @property details The error details. Must be a datatype supported by the api codec. + */ +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null, +) : Throwable() + +/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ +interface MoxxyMediaApi { + fun generateVideoThumbnail(src: String, dest: String, maxWidth: Long): Boolean + + companion object { + /** The codec used by MoxxyMediaApi. */ + val codec: MessageCodec by lazy { + StandardMessageCodec() + } + + /** Sets up an instance of `MoxxyMediaApi` to handle messages through the `binaryMessenger`. */ + @Suppress("UNCHECKED_CAST") + fun setUp(binaryMessenger: BinaryMessenger, api: MoxxyMediaApi?) { + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyMediaApi.generateVideoThumbnail", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val srcArg = args[0] as String + val destArg = args[1] as String + val maxWidthArg = args[2].let { if (it is Int) it.toLong() else it as Long } + var wrapped: List + try { + wrapped = listOf(api.generateVideoThumbnail(srcArg, destArg, maxWidthArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } +} diff --git a/android/src/main/kotlin/org/moxxy/moxxy_native/media/MediaImplementation.kt b/android/src/main/kotlin/org/moxxy/moxxy_native/media/MediaImplementation.kt new file mode 100644 index 0000000..c566f5a --- /dev/null +++ b/android/src/main/kotlin/org/moxxy/moxxy_native/media/MediaImplementation.kt @@ -0,0 +1,45 @@ +package org.moxxy.moxxy_native.media + +import android.graphics.Bitmap +import android.media.MediaMetadataRetriever +import android.util.Log +import org.moxxy.moxxy_native.TAG +import java.io.FileOutputStream + +class MediaImplementation : MoxxyMediaApi { + override fun generateVideoThumbnail(src: String, dest: String, maxWidth: Long): Boolean { + try { + // Get a frame as a thumbnail + val mmr = MediaMetadataRetriever().apply { + setDataSource(src) + } + val unscaledThumbnail = mmr.getFrameAtTime(0) ?: return false + + // Scale down the thumbnail while keeping the aspect ratio + val scalingFactor = maxWidth.toDouble() / unscaledThumbnail.width + Log.d(TAG, "Scaling to $maxWidth from ${unscaledThumbnail.width} with scalingFactor $scalingFactor") + val thumbnail = Bitmap.createScaledBitmap( + unscaledThumbnail, + (unscaledThumbnail.width * scalingFactor).toInt(), + (unscaledThumbnail.height * scalingFactor).toInt(), + false, + ) + + // Write it to the destination file + val fileOutputStream = FileOutputStream(dest) + thumbnail.compress(Bitmap.CompressFormat.JPEG, 75, fileOutputStream) + + // Clean up + fileOutputStream.apply { + flush() + close() + } + + // Success + return true + } catch (ex: Exception) { + Log.e(TAG, "Failed to create thumbnail for $src: ${ex.message}") + return false + } + } +} diff --git a/android/src/main/kotlin/org/moxxy/moxxy_native/platform/PlatformApi.kt b/android/src/main/kotlin/org/moxxy/moxxy_native/platform/PlatformApi.kt index d4528d5..8f74a73 100644 --- a/android/src/main/kotlin/org/moxxy/moxxy_native/platform/PlatformApi.kt +++ b/android/src/main/kotlin/org/moxxy/moxxy_native/platform/PlatformApi.kt @@ -8,27 +8,25 @@ import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MessageCodec import io.flutter.plugin.common.StandardMessageCodec -import java.io.ByteArrayOutputStream -import java.nio.ByteBuffer private fun wrapResult(result: Any?): List { - return listOf(result) + return listOf(result) } private fun wrapError(exception: Throwable): List { - if (exception is FlutterError) { - return listOf( - exception.code, - exception.message, - exception.details - ) - } else { - return listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) - } + if (exception is FlutterError) { + return listOf( + exception.code, + exception.message, + exception.details, + ) + } else { + return listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception), + ) + } } /** @@ -37,91 +35,93 @@ private fun wrapError(exception: Throwable): List { * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null, ) : Throwable() + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface MoxxyPlatformApi { - fun getPersistentDataPath(): String - fun getCacheDataPath(): String - fun openBatteryOptimisationSettings() - fun isIgnoringBatteryOptimizations(): Boolean + fun getPersistentDataPath(): String + fun getCacheDataPath(): String + fun openBatteryOptimisationSettings() + fun isIgnoringBatteryOptimizations(): Boolean - companion object { - /** The codec used by MoxxyPlatformApi. */ - val codec: MessageCodec by lazy { - StandardMessageCodec() + companion object { + /** The codec used by MoxxyPlatformApi. */ + val codec: MessageCodec by lazy { + StandardMessageCodec() + } + + /** Sets up an instance of `MoxxyPlatformApi` to handle messages through the `binaryMessenger`. */ + @Suppress("UNCHECKED_CAST") + fun setUp(binaryMessenger: BinaryMessenger, api: MoxxyPlatformApi?) { + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyPlatformApi.getPersistentDataPath", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.getPersistentDataPath()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyPlatformApi.getCacheDataPath", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.getCacheDataPath()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyPlatformApi.openBatteryOptimisationSettings", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + api.openBatteryOptimisationSettings() + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyPlatformApi.isIgnoringBatteryOptimizations", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.isIgnoringBatteryOptimizations()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } } - /** Sets up an instance of `MoxxyPlatformApi` to handle messages through the `binaryMessenger`. */ - @Suppress("UNCHECKED_CAST") - fun setUp(binaryMessenger: BinaryMessenger, api: MoxxyPlatformApi?) { - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyPlatformApi.getPersistentDataPath", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - var wrapped: List - try { - wrapped = listOf(api.getPersistentDataPath()) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyPlatformApi.getCacheDataPath", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - var wrapped: List - try { - wrapped = listOf(api.getCacheDataPath()) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyPlatformApi.openBatteryOptimisationSettings", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - var wrapped: List - try { - api.openBatteryOptimisationSettings() - wrapped = listOf(null) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyPlatformApi.isIgnoringBatteryOptimizations", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - var wrapped: List - try { - wrapped = listOf(api.isIgnoringBatteryOptimizations()) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - } - } } diff --git a/android/src/main/kotlin/org/moxxy/moxxy_native/platform/PlatformImplementation.kt b/android/src/main/kotlin/org/moxxy/moxxy_native/platform/PlatformImplementation.kt index 63478bc..66d27df 100644 --- a/android/src/main/kotlin/org/moxxy/moxxy_native/platform/PlatformImplementation.kt +++ b/android/src/main/kotlin/org/moxxy/moxxy_native/platform/PlatformImplementation.kt @@ -27,4 +27,4 @@ class PlatformImplementation(private val context: Context) : MoxxyPlatformApi { val pm = context.getSystemService(PowerManager::class.java) return pm.isIgnoringBatteryOptimizations(context.packageName) } -} \ No newline at end of file +} diff --git a/lib/moxxy_native.dart b/lib/moxxy_native.dart index e27987f..9e985da 100644 --- a/lib/moxxy_native.dart +++ b/lib/moxxy_native.dart @@ -1,5 +1,6 @@ export 'pigeon/contacts.g.dart'; export 'pigeon/cryptography.g.dart'; +export 'pigeon/media.g.dart'; export 'pigeon/notifications.g.dart'; export 'pigeon/picker.g.dart'; export 'pigeon/platform.g.dart'; diff --git a/lib/pigeon/media.g.dart b/lib/pigeon/media.g.dart new file mode 100644 index 0000000..6031faa --- /dev/null +++ b/lib/pigeon/media.g.dart @@ -0,0 +1,47 @@ +// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +class MoxxyMediaApi { + /// Constructor for [MoxxyMediaApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + MoxxyMediaApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = StandardMessageCodec(); + + Future generateVideoThumbnail(String arg_src, String arg_dest, int arg_maxWidth) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.moxxy_native.MoxxyMediaApi.generateVideoThumbnail', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_src, arg_dest, arg_maxWidth]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as bool?)!; + } + } +} diff --git a/pigeon/media.dart b/pigeon/media.dart new file mode 100644 index 0000000..994db5e --- /dev/null +++ b/pigeon/media.dart @@ -0,0 +1,16 @@ +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/pigeon/media.g.dart', + kotlinOut: 'android/src/main/kotlin/org/moxxy/moxxy_native/media/MediaApi.kt', + kotlinOptions: KotlinOptions( + package: 'org.moxxy.moxxy_native.media', + ), + ), +) + +@HostApi() +abstract class MoxxyMediaApi { + bool generateVideoThumbnail(String src, String dest, int maxWidth); +}