diff --git a/flutter/flutter/CHANGELOG.md b/flutter/flutter/CHANGELOG.md index 1b1603a..31f1289 100644 --- a/flutter/flutter/CHANGELOG.md +++ b/flutter/flutter/CHANGELOG.md @@ -1,8 +1,8 @@ ## 4.5.1 -- Bugfix release +- Feature release based on native v4.5.1 ## 4.5.1-LTS -- Bugfix LTS release +- Feature release based on native v4.5.1.LTS ## 4.5.0 - Initial release diff --git a/flutter/flutter/android/build.gradle b/flutter/flutter/android/build.gradle index 8575b34..0a033dc 100644 --- a/flutter/flutter/android/build.gradle +++ b/flutter/flutter/android/build.gradle @@ -43,6 +43,6 @@ repositories { dependencies { implementation 'androidx.annotation:annotation:1.2.0' - implementation 'com.arthenica:ffmpeg-kit-https:4.5.1' + implementation 'com.arthenica:ffmpeg-kit-https:4.5.1-1' } diff --git a/flutter/flutter/android/src/main/java/com/arthenica/ffmpegkit/flutter/FFmpegKitFlutterPlugin.java b/flutter/flutter/android/src/main/java/com/arthenica/ffmpegkit/flutter/FFmpegKitFlutterPlugin.java index fce186f..3d227bb 100644 --- a/flutter/flutter/android/src/main/java/com/arthenica/ffmpegkit/flutter/FFmpegKitFlutterPlugin.java +++ b/flutter/flutter/android/src/main/java/com/arthenica/ffmpegkit/flutter/FFmpegKitFlutterPlugin.java @@ -359,6 +359,13 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met resultHandler.errorAsync(result, "INVALID_ARGUMENTS", "Invalid arguments array."); } break; + case "getMediaInformation": + if (sessionId != null) { + getMediaInformation(sessionId, result); + } else { + resultHandler.errorAsync(result, "INVALID_SESSION", "Invalid session id."); + } + break; case "mediaInformationJsonParserFrom": if (ffprobeJsonOutput != null) { mediaInformationJsonParserFrom(ffprobeJsonOutput, result); @@ -876,6 +883,21 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met resultHandler.successAsync(result, toMap(session)); } + protected void getMediaInformation(@NonNull final Integer sessionId, @NonNull final Result result) { + final Session session = FFmpegKitConfig.getSession(sessionId.longValue()); + if (session == null) { + resultHandler.errorAsync(result, "SESSION_NOT_FOUND", "Session not found."); + } else { + if (session.isMediaInformation()) { + final MediaInformationSession mediaInformationSession = (MediaInformationSession) session; + final MediaInformation mediaInformation = mediaInformationSession.getMediaInformation(); + resultHandler.successAsync(result, toMap(mediaInformation)); + } else { + resultHandler.errorAsync(result, "NOT_MEDIA_INFORMATION_SESSION", "A session is found but it does not have the correct type."); + } + } + } + // MediaInformationJsonParser protected void mediaInformationJsonParserFrom(@NonNull final String ffprobeJsonOutput, @NonNull final Result result) { @@ -1332,19 +1354,17 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met sessionMap.put(KEY_SESSION_START_TIME, toLong(session.getStartTime())); sessionMap.put(KEY_SESSION_COMMAND, session.getCommand()); - if (session.isFFprobe()) { - if (session.isMediaInformation()) { - final MediaInformationSession mediaInformationSession = (MediaInformationSession) session; - final MediaInformation mediaInformation = mediaInformationSession.getMediaInformation(); - if (mediaInformation != null) { - sessionMap.put(KEY_SESSION_MEDIA_INFORMATION, toMap(mediaInformation)); - } - sessionMap.put(KEY_SESSION_TYPE, SESSION_TYPE_MEDIA_INFORMATION); - } else { - sessionMap.put(KEY_SESSION_TYPE, SESSION_TYPE_FFPROBE); - } - } else { + if (session.isFFmpeg()) { sessionMap.put(KEY_SESSION_TYPE, SESSION_TYPE_FFMPEG); + } else if (session.isFFprobe()) { + sessionMap.put(KEY_SESSION_TYPE, SESSION_TYPE_FFPROBE); + } else if (session.isMediaInformation()) { + final MediaInformationSession mediaInformationSession = (MediaInformationSession) session; + final MediaInformation mediaInformation = mediaInformationSession.getMediaInformation(); + if (mediaInformation != null) { + sessionMap.put(KEY_SESSION_MEDIA_INFORMATION, toMap(mediaInformation)); + } + sessionMap.put(KEY_SESSION_TYPE, SESSION_TYPE_MEDIA_INFORMATION); } return sessionMap; @@ -1432,18 +1452,20 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met } protected static Map toMap(final MediaInformation mediaInformation) { - Map map = new HashMap<>(); - if (mediaInformation != null) { + Map map = new HashMap<>(); + if (mediaInformation.getAllProperties() != null) { JSONObject allProperties = mediaInformation.getAllProperties(); if (allProperties != null) { map = toMap(allProperties); } } - } - return map; + return map; + } else { + return null; + } } protected static Map toMap(final JSONObject jsonObject) { diff --git a/flutter/flutter/ios/Classes/FFmpegKitFlutterPlugin.m b/flutter/flutter/ios/Classes/FFmpegKitFlutterPlugin.m index 965c799..c7b5f8a 100644 --- a/flutter/flutter/ios/Classes/FFmpegKitFlutterPlugin.m +++ b/flutter/flutter/ios/Classes/FFmpegKitFlutterPlugin.m @@ -232,6 +232,12 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; } else { result([FlutterError errorWithCode:@"INVALID_ARGUMENTS" message:@"Invalid arguments array." details:nil]); } + } else if ([@"getMediaInformation" isEqualToString:call.method]) { + if (sessionId != nil) { + [self getMediaInformation:sessionId result:result]; + } else { + result([FlutterError errorWithCode:@"INVALID_SESSION" message:@"Invalid session id." details:nil]); + } } else if ([@"mediaInformationJsonParserFrom" isEqualToString:call.method]) { if (ffprobeJsonOutput != nil) { [self mediaInformationJsonParserFrom:ffprobeJsonOutput result:result]; @@ -609,6 +615,20 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; result([FFmpegKitFlutterPlugin toSessionDictionary:session]); } +- (void)getMediaInformation:(NSNumber*)sessionId result:(FlutterResult)result { + AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:[sessionId longValue]]; + if (session == nil) { + result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); + } else { + if ([session isMediaInformation]) { + MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session; + result([FFmpegKitFlutterPlugin toMediaInformationDictionary:[mediaInformationSession getMediaInformation]]); + } else { + result([FlutterError errorWithCode:@"NOT_MEDIA_INFORMATION_SESSION" message:@"A session is found but it does not have the correct type." details:nil]); + } + } +} + // MediaInformationJsonParser - (void)mediaInformationJsonParserFrom:(NSString*)ffprobeJsonOutput result:(FlutterResult)result { @@ -1061,16 +1081,14 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; dictionary[KEY_SESSION_START_TIME] = [NSNumber numberWithLong:[[session getStartTime] timeIntervalSince1970]*1000]; dictionary[KEY_SESSION_COMMAND] = [session getCommand]; - if ([session isFFprobe]) { - if ([session isMediaInformation]) { - MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session; - dictionary[KEY_SESSION_MEDIA_INFORMATION] = [FFmpegKitFlutterPlugin toMediaInformationDictionary:[mediaInformationSession getMediaInformation]]; - dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_MEDIA_INFORMATION]; - } else { - dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFPROBE]; - } - } else { + if ([session isFFmpeg]) { dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFMPEG]; + } else if ([session isFFprobe]) { + dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFPROBE]; + } else if ([session isMediaInformation]) { + MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session; + dictionary[KEY_SESSION_MEDIA_INFORMATION] = [FFmpegKitFlutterPlugin toMediaInformationDictionary:[mediaInformationSession getMediaInformation]]; + dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_MEDIA_INFORMATION]; } return dictionary; diff --git a/flutter/flutter/lib/ffmpeg_kit.dart b/flutter/flutter/lib/ffmpeg_kit.dart index 18dce96..88d3d29 100644 --- a/flutter/flutter/lib/ffmpeg_kit.dart +++ b/flutter/flutter/lib/ffmpeg_kit.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 Taner Sener + * Copyright (c) 2019-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -34,21 +34,14 @@ class FFmpegKit { /// Synchronously executes FFmpeg command provided. Space character is used /// to split command into arguments. You can use single or double quote /// characters to specify arguments inside your command. - static Future execute(String command, - [FFmpegSessionCompleteCallback? completeCallback = null, - LogCallback? logCallback = null, - StatisticsCallback? statisticsCallback = null]) async => - FFmpegKit.executeWithArguments(FFmpegKitConfig.parseArguments(command), - completeCallback, logCallback, statisticsCallback); + static Future execute(String command) async => + FFmpegKit.executeWithArguments(FFmpegKitConfig.parseArguments(command)); /// Synchronously executes FFmpeg with arguments provided. static Future executeWithArguments( - List commandArguments, - [FFmpegSessionCompleteCallback? completeCallback = null, - LogCallback? logCallback = null, - StatisticsCallback? statisticsCallback = null]) async { - final session = await FFmpegSession.create(commandArguments, - completeCallback, logCallback, statisticsCallback, null); + List commandArguments) async { + final session = + await FFmpegSession.create(commandArguments, null, null, null, null); await FFmpegKitConfig.ffmpegExecute(session); diff --git a/flutter/flutter/lib/ffmpeg_kit_config.dart b/flutter/flutter/lib/ffmpeg_kit_config.dart index d9abc76..bf57480 100644 --- a/flutter/flutter/lib/ffmpeg_kit_config.dart +++ b/flutter/flutter/lib/ffmpeg_kit_config.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 Taner Sener + * Copyright (c) 2019-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -366,6 +366,55 @@ class FFmpegKitConfig { } } + /// Converts the given Structured Access Framework Uri ("content:…") into + /// an input url that can be used in FFmpeg and FFprobe commands. + /// + /// Note that this method is Android only. It will fail if called on other + /// platforms. It also requires API Level ≥ 19. On older API levels it + /// returns an empty url. + static Future getSafParameterForRead(String uriString) async { + try { + await init(); + return _platform.ffmpegKitConfigGetSafParameter(uriString, "r"); + } on PlatformException catch (e, stack) { + print("Plugin getSafParameterForRead error: ${e.message}"); + return Future.error("getSafParameterForRead failed.", stack); + } + } + + /// Converts the given Structured Access Framework Uri ("content:…") into + /// an output url that can be used in FFmpeg and FFprobe commands. + /// + /// Note that this method is Android only. It will fail if called on other + /// platforms. It also requires API Level ≥ 19. On older API levels it + /// returns an empty url. + static Future getSafParameterForWrite(String uriString) async { + try { + await init(); + return _platform.ffmpegKitConfigGetSafParameter(uriString, "w"); + } on PlatformException catch (e, stack) { + print("Plugin getSafParameterForWrite error: ${e.message}"); + return Future.error("getSafParameterForWrite failed.", stack); + } + } + + /// Converts the given Structured Access Framework Uri into an saf protocol + /// url opened with the given open mode. + /// + /// Note that this method is Android only. It will fail if called on other + /// platforms. It also requires API Level ≥ 19. On older API levels it + /// returns an empty url. + static Future getSafParameter( + String uriString, String openMode) async { + try { + await init(); + return _platform.ffmpegKitConfigGetSafParameter(uriString, openMode); + } on PlatformException catch (e, stack) { + print("Plugin getSafParameter error: ${e.message}"); + return Future.error("getSafParameter failed.", stack); + } + } + /// Returns the session history size. static Future getSessionHistorySize() async { try { @@ -763,53 +812,4 @@ class FFmpegKitConfig { return Future.error("selectDocumentForWrite failed.", stack); } } - - /// Converts the given Structured Access Framework Uri ("content:…") into - /// an input url that can be used in FFmpeg and FFprobe commands. - /// - /// Note that this method is Android only. It will fail if called on other - /// platforms. It also requires API Level ≥ 19. On older API levels it - /// returns an empty url. - static Future getSafParameterForRead(String uriString) async { - try { - await init(); - return _platform.ffmpegKitConfigGetSafParameter(uriString, "r"); - } on PlatformException catch (e, stack) { - print("Plugin getSafParameterForRead error: ${e.message}"); - return Future.error("getSafParameterForRead failed.", stack); - } - } - - /// Converts the given Structured Access Framework Uri ("content:…") into - /// an output url that can be used in FFmpeg and FFprobe commands. - /// - /// Note that this method is Android only. It will fail if called on other - /// platforms. It also requires API Level ≥ 19. On older API levels it - /// returns an empty url. - static Future getSafParameterForWrite(String uriString) async { - try { - await init(); - return _platform.ffmpegKitConfigGetSafParameter(uriString, "w"); - } on PlatformException catch (e, stack) { - print("Plugin getSafParameterForWrite error: ${e.message}"); - return Future.error("getSafParameterForWrite failed.", stack); - } - } - - /// Converts the given Structured Access Framework Uri into an saf protocol - /// url opened with the given open mode. - /// - /// Note that this method is Android only. It will fail if called on other - /// platforms. It also requires API Level ≥ 19. On older API levels it - /// returns an empty url. - static Future getSafParameter( - String uriString, String openMode) async { - try { - await init(); - return _platform.ffmpegKitConfigGetSafParameter(uriString, openMode); - } on PlatformException catch (e, stack) { - print("Plugin getSafParameter error: ${e.message}"); - return Future.error("getSafParameter failed.", stack); - } - } } diff --git a/flutter/flutter/lib/ffprobe_kit.dart b/flutter/flutter/lib/ffprobe_kit.dart index 7822755..49165a2 100644 --- a/flutter/flutter/lib/ffprobe_kit.dart +++ b/flutter/flutter/lib/ffprobe_kit.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 Taner Sener + * Copyright (c) 2019-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -35,19 +35,14 @@ class FFprobeKit { /// Synchronously executes FFprobe command provided. Space character is used /// to split command into arguments. You can use single or double quote /// characters to specify arguments inside your command. - static Future execute(String command, - [FFprobeSessionCompleteCallback? completeCallback = null, - LogCallback? logCallback = null]) async => - FFprobeKit.executeWithArguments(FFmpegKitConfig.parseArguments(command), - completeCallback, logCallback); + static Future execute(String command) async => + FFprobeKit.executeWithArguments(FFmpegKitConfig.parseArguments(command)); /// Synchronously executes FFprobe with arguments provided. static Future executeWithArguments( - List commandArguments, - [FFprobeSessionCompleteCallback? completeCallback = null, - LogCallback? logCallback = null]) async { - final session = await FFprobeSession.create( - commandArguments, completeCallback, logCallback, null); + List commandArguments) async { + final session = + await FFprobeSession.create(commandArguments, null, null, null); await FFmpegKitConfig.ffprobeExecute(session); @@ -85,9 +80,7 @@ class FFprobeKit { /// Extracts media information for the file specified with path. static Future getMediaInformation(String path, - [MediaInformationSessionCompleteCallback? completeCallback = null, - LogCallback? logCallback = null, - int? waitTimeout = null]) async { + [int? waitTimeout = null]) async { final commandArguments = [ "-v", "error", @@ -101,7 +94,7 @@ class FFprobeKit { path ]; return FFprobeKit.getMediaInformationFromCommandArguments( - commandArguments, completeCallback, logCallback, waitTimeout); + commandArguments, waitTimeout); } /// Extracts media information using the command provided. The command @@ -109,28 +102,28 @@ class FFprobeKit { /// successfully extract media information from it. static Future getMediaInformationFromCommand( String command, - [MediaInformationSessionCompleteCallback? completeCallback = null, - LogCallback? logCallback = null, - int? waitTimeout = null]) async => + [int? waitTimeout = null]) async => FFprobeKit.getMediaInformationFromCommandArguments( - FFmpegKitConfig.parseArguments(command), - completeCallback, - logCallback, - waitTimeout); + FFmpegKitConfig.parseArguments(command), waitTimeout); /// Extracts media information using the command arguments provided. The /// command passed to this method must generate the output in JSON format in /// order to successfully extract media information from it. static Future getMediaInformationFromCommandArguments(List commandArguments, - [MediaInformationSessionCompleteCallback? completeCallback = null, - LogCallback? logCallback = null, - int? waitTimeout = null]) async { - final session = await MediaInformationSession.create( - commandArguments, completeCallback, logCallback); + [int? waitTimeout = null]) async { + final session = + await MediaInformationSession.create(commandArguments, null, null); await FFmpegKitConfig.getMediaInformationExecute(session, waitTimeout); + final mediaInformation = await _platform + .mediaInformationSessionGetMediaInformation(session.getSessionId()) + .then(FFmpegKitFactory.mapToNullableMediaInformation); + if (mediaInformation != null) { + session.setMediaInformation(mediaInformation); + } + return session; } @@ -193,6 +186,13 @@ class FFprobeKit { await FFmpegKitConfig.asyncGetMediaInformationExecute(session, waitTimeout); + final mediaInformation = await _platform + .mediaInformationSessionGetMediaInformation(session.getSessionId()) + .then(FFmpegKitFactory.mapToNullableMediaInformation); + if (mediaInformation != null) { + session.setMediaInformation(mediaInformation); + } + return session; } diff --git a/flutter/flutter/lib/src/ffmpeg_kit_factory.dart b/flutter/flutter/lib/src/ffmpeg_kit_factory.dart index 6140c53..bb4529d 100644 --- a/flutter/flutter/lib/src/ffmpeg_kit_factory.dart +++ b/flutter/flutter/lib/src/ffmpeg_kit_factory.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 Taner Sener + * Copyright (c) 2019-2022 Taner Sener * * This file is part of FFmpegKit. * @@ -24,6 +24,7 @@ import '../ffprobe_session_complete_callback.dart'; import '../log.dart'; import '../log_callback.dart'; import '../log_redirection_strategy.dart'; +import '../media_information.dart'; import '../media_information_session.dart'; import '../media_information_session_complete_callback.dart'; import '../session.dart'; @@ -90,7 +91,16 @@ class FFmpegKitFactory { } } - static String getVersion() => "4.5.0"; + static MediaInformation? mapToNullableMediaInformation( + Map? mediaInformationMap) { + if (mediaInformationMap != null) { + return new MediaInformation(mediaInformationMap); + } else { + return null; + } + } + + static String getVersion() => "4.5.1"; static LogRedirectionStrategy? getLogRedirectionStrategy(int? sessionId) => logRedirectionStrategyMap[sessionId]; diff --git a/flutter/flutter/macos/Classes/FFmpegKitFlutterPlugin.m b/flutter/flutter/macos/Classes/FFmpegKitFlutterPlugin.m index 1618616..f9f557e 100644 --- a/flutter/flutter/macos/Classes/FFmpegKitFlutterPlugin.m +++ b/flutter/flutter/macos/Classes/FFmpegKitFlutterPlugin.m @@ -57,7 +57,7 @@ static int const SESSION_TYPE_MEDIA_INFORMATION = 3; // EVENTS static NSString *const EVENT_LOG_CALLBACK_EVENT = @"FFmpegKitLogCallbackEvent"; static NSString *const EVENT_STATISTICS_CALLBACK_EVENT = @"FFmpegKitStatisticsCallbackEvent"; -static NSString *const EVENT_EXECUTE_CALLBACK_EVENT = @"FFmpegKitCompleteCallbackEvent"; +static NSString *const EVENT_COMPLETE_CALLBACK_EVENT = @"FFmpegKitCompleteCallbackEvent"; // ARGUMENT NAMES static NSString *const ARGUMENT_SESSION_ID = @"sessionId"; @@ -110,9 +110,19 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; } - (void)registerGlobalCallbacks { - [FFmpegKitConfig enableExecuteCallback:^(id session){ + [FFmpegKitConfig enableFFmpegSessionCompleteCallback:^(FFmpegSession* session){ NSDictionary *dictionary = [FFmpegKitFlutterPlugin toSessionDictionary:session]; - self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_EXECUTE_CALLBACK_EVENT withDictionary:dictionary]); + self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); + }]; + + [FFmpegKitConfig enableFFprobeSessionCompleteCallback:^(FFprobeSession* session){ + NSDictionary *dictionary = [FFmpegKitFlutterPlugin toSessionDictionary:session]; + self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); + }]; + + [FFmpegKitConfig enableMediaInformationSessionCompleteCallback:^(MediaInformationSession* session){ + NSDictionary *dictionary = [FFmpegKitFlutterPlugin toSessionDictionary:session]; + self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]); }]; [FFmpegKitConfig enableLogCallback: ^(Log* log){ @@ -222,6 +232,12 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; } else { result([FlutterError errorWithCode:@"INVALID_ARGUMENTS" message:@"Invalid arguments array." details:nil]); } + } else if ([@"getMediaInformation" isEqualToString:call.method]) { + if (sessionId != nil) { + [self getMediaInformation:sessionId result:result]; + } else { + result([FlutterError errorWithCode:@"INVALID_SESSION" message:@"Invalid session id." details:nil]); + } } else if ([@"mediaInformationJsonParserFrom" isEqualToString:call.method]) { if (ffprobeJsonOutput != nil) { [self mediaInformationJsonParserFrom:ffprobeJsonOutput result:result]; @@ -419,6 +435,8 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; [self getFFmpegSessions:result]; } else if ([@"getFFprobeSessions" isEqualToString:call.method]) { [self getFFprobeSessions:result]; + } else if ([@"getMediaInformationSessions" isEqualToString:call.method]) { + [self getMediaInformationSessions:result]; } else if ([@"getPackageName" isEqualToString:call.method]) { [self getPackageName:result]; } else if ([@"getExternalLibraries" isEqualToString:call.method]) { @@ -545,7 +563,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; // FFmpegSession - (void)ffmpegSession:(NSArray*)arguments result:(FlutterResult)result { - FFmpegSession* session = [[FFmpegSession alloc] init:arguments withExecuteCallback:nil withLogCallback:nil withStatisticsCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; + FFmpegSession* session = [[FFmpegSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil withStatisticsCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; result([FFmpegKitFlutterPlugin toSessionDictionary:session]); } @@ -554,7 +572,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; if (session == nil) { result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); } else { - if ([session isMemberOfClass:[FFmpegSession class]]) { + if ([session isFFmpeg]) { int timeout; if ([FFmpegKitFlutterPlugin isValidPositiveNumber:waitTimeout]) { timeout = [waitTimeout intValue]; @@ -574,7 +592,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; if (session == nil) { result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); } else { - if ([session isMemberOfClass:[FFmpegSession class]]) { + if ([session isFFmpeg]) { NSArray* statistics = [(FFmpegSession*)session getStatistics]; result([FFmpegKitFlutterPlugin toStatisticsArray:statistics]); } else { @@ -586,17 +604,31 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; // FFprobeSession - (void)ffprobeSession:(NSArray*)arguments result:(FlutterResult)result { - FFprobeSession* session = [[FFprobeSession alloc] init:arguments withExecuteCallback:nil withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; + FFprobeSession* session = [[FFprobeSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; result([FFmpegKitFlutterPlugin toSessionDictionary:session]); } // MediaInformationSession - (void)mediaInformationSession:(NSArray*)arguments result:(FlutterResult)result { - MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withExecuteCallback:nil withLogCallback:nil]; + MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil]; result([FFmpegKitFlutterPlugin toSessionDictionary:session]); } +- (void)getMediaInformation:(NSNumber*)sessionId result:(FlutterResult)result { + AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:[sessionId longValue]]; + if (session == nil) { + result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); + } else { + if ([session isMediaInformation]) { + MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session; + result([FFmpegKitFlutterPlugin toMediaInformationDictionary:[mediaInformationSession getMediaInformation]]); + } else { + result([FlutterError errorWithCode:@"NOT_MEDIA_INFORMATION_SESSION" message:@"A session is found but it does not have the correct type." details:nil]); + } + } +} + // MediaInformationJsonParser - (void)mediaInformationJsonParserFrom:(NSString*)ffprobeJsonOutput result:(FlutterResult)result { @@ -733,7 +765,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; if (session == nil) { result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); } else { - if ([session isMemberOfClass:[FFmpegSession class]]) { + if ([session isFFmpeg]) { dispatch_async(asyncDispatchQueue, ^{ [FFmpegKitConfig ffmpegExecute:(FFmpegSession*)session]; result(nil); @@ -749,7 +781,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; if (session == nil) { result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); } else { - if ([session isMemberOfClass:[FFprobeSession class]]) { + if ([session isFFprobe]) { dispatch_async(asyncDispatchQueue, ^{ [FFmpegKitConfig ffprobeExecute:(FFprobeSession*)session]; result(nil); @@ -765,7 +797,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; if (session == nil) { result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); } else { - if ([session isMemberOfClass:[MediaInformationSession class]]) { + if ([session isMediaInformation]) { int timeout; if ([FFmpegKitFlutterPlugin isValidPositiveNumber:waitTimeout]) { timeout = [waitTimeout intValue]; @@ -787,7 +819,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; if (session == nil) { result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); } else { - if ([session isMemberOfClass:[FFmpegSession class]]) { + if ([session isFFmpeg]) { [FFmpegKitConfig asyncFFmpegExecute:(FFmpegSession*)session]; result(nil); } else { @@ -801,7 +833,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; if (session == nil) { result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); } else { - if ([session isMemberOfClass:[FFprobeSession class]]) { + if ([session isFFprobe]) { [FFmpegKitConfig asyncFFprobeExecute:(FFprobeSession*)session]; result(nil); } else { @@ -815,7 +847,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; if (session == nil) { result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); } else { - if ([session isMemberOfClass:[MediaInformationSession class]]) { + if ([session isMediaInformation]) { int timeout; if ([FFmpegKitFlutterPlugin isValidPositiveNumber:waitTimeout]) { timeout = [waitTimeout intValue]; @@ -1007,7 +1039,11 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; // FFprobeKit - (void)getFFprobeSessions:(FlutterResult)result { - result([FFmpegKitFlutterPlugin toSessionArray:[FFprobeKit listSessions]]); + result([FFmpegKitFlutterPlugin toSessionArray:[FFprobeKit listFFprobeSessions]]); +} + +- (void)getMediaInformationSessions:(FlutterResult)result { + result([FFmpegKitFlutterPlugin toSessionArray:[FFprobeKit listMediaInformationSessions]]); } // Packages @@ -1045,16 +1081,14 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit; dictionary[KEY_SESSION_START_TIME] = [NSNumber numberWithLong:[[session getStartTime] timeIntervalSince1970]*1000]; dictionary[KEY_SESSION_COMMAND] = [session getCommand]; - if ([session isFFprobe]) { - if ([(AbstractSession*)session isMemberOfClass:[MediaInformationSession class]]) { - MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session; - dictionary[KEY_SESSION_MEDIA_INFORMATION] = [FFmpegKitFlutterPlugin toMediaInformationDictionary:[mediaInformationSession getMediaInformation]]; - dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_MEDIA_INFORMATION]; - } else { - dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFPROBE]; - } - } else { + if ([session isFFmpeg]) { dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFMPEG]; + } else if ([session isFFprobe]) { + dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFPROBE]; + } else if ([session isMediaInformation]) { + MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session; + dictionary[KEY_SESSION_MEDIA_INFORMATION] = [FFmpegKitFlutterPlugin toMediaInformationDictionary:[mediaInformationSession getMediaInformation]]; + dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_MEDIA_INFORMATION]; } return dictionary; diff --git a/flutter/flutter/pubspec.yaml b/flutter/flutter/pubspec.yaml index 7ada2a1..39e5d01 100644 --- a/flutter/flutter/pubspec.yaml +++ b/flutter/flutter/pubspec.yaml @@ -21,7 +21,7 @@ flutter: pluginClass: FFmpegKitFlutterPlugin dependencies: - ffmpeg_kit_flutter_platform_interface: ^0.1.1 + ffmpeg_kit_flutter_platform_interface: ^0.2.0 flutter: sdk: flutter diff --git a/flutter/flutter_platform_interface/CHANGELOG.md b/flutter/flutter_platform_interface/CHANGELOG.md index 83b74a2..979c3b1 100644 --- a/flutter/flutter_platform_interface/CHANGELOG.md +++ b/flutter/flutter_platform_interface/CHANGELOG.md @@ -1,2 +1,8 @@ +## 0.2.0 +- Implements execute methods +- Merges existing getSafParameter methods into a single method with a new openMode parameter +- Adds list media information sessions methods to FFprobeKit +- Adds getMediaInformation method + ## 0.1.0 - Initial release diff --git a/flutter/flutter_platform_interface/lib/ffmpeg_kit_flutter_platform_interface.dart b/flutter/flutter_platform_interface/lib/ffmpeg_kit_flutter_platform_interface.dart index 6a36146..779dcff 100644 --- a/flutter/flutter_platform_interface/lib/ffmpeg_kit_flutter_platform_interface.dart +++ b/flutter/flutter_platform_interface/lib/ffmpeg_kit_flutter_platform_interface.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Taner Sener + * Copyright (c) 2021-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -382,6 +382,12 @@ abstract class FFmpegKitPlatform extends PlatformInterface { 'mediaInformationJsonParserFromWithError() has not been implemented!'); } + Future?> mediaInformationSessionGetMediaInformation( + int? sessionId) async { + throw UnimplementedError('mediaInformationSessionGetMediaInformation() ' + 'has not been implemented!'); + } + Future getPackageName() async { throw UnimplementedError('getPackageName() has not been implemented!'); } diff --git a/flutter/flutter_platform_interface/lib/method_channel_ffmpeg_kit_flutter.dart b/flutter/flutter_platform_interface/lib/method_channel_ffmpeg_kit_flutter.dart index 32a4a6d..59dbbc7 100644 --- a/flutter/flutter_platform_interface/lib/method_channel_ffmpeg_kit_flutter.dart +++ b/flutter/flutter_platform_interface/lib/method_channel_ffmpeg_kit_flutter.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Taner Sener + * Copyright (c) 2021-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -99,13 +99,14 @@ class MethodChannelFFmpegKit extends FFmpegKitPlatform { int? sessionId) async => _channel.invokeMethod( 'abstractSessionThereAreAsynchronousMessagesInTransmit', - {'sessionId': sessionId}).then((value) => value ?? false); + {'sessionId': sessionId}).then((bool? value) => value ?? false); // ArchDetect @override - Future archDetectGetArch() async => - _channel.invokeMethod('getArch').then((value) => value ?? ""); + Future archDetectGetArch() async => _channel + .invokeMethod('getArch') + .then((String? value) => value ?? ""); // FFmpegKit @@ -180,14 +181,12 @@ class MethodChannelFFmpegKit extends FFmpegKitPlatform { _channel.invokeMethod('ignoreSignal', {'signal': signal}); @override - Future ffmpegKitConfigFFmpegExecute(int? sessionId) async => - _channel.invokeMethod( - 'ffmpegSessionExecute', {'sessionId': sessionId}); + Future ffmpegKitConfigFFmpegExecute(int? sessionId) async => _channel + .invokeMethod('ffmpegSessionExecute', {'sessionId': sessionId}); @override - Future ffmpegKitConfigFFprobeExecute(int? sessionId) async => - _channel.invokeMethod( - 'ffprobeSessionExecute', {'sessionId': sessionId}); + Future ffmpegKitConfigFFprobeExecute(int? sessionId) async => _channel + .invokeMethod('ffprobeSessionExecute', {'sessionId': sessionId}); @override Future ffmpegKitConfigGetMediaInformationExecute( @@ -351,6 +350,14 @@ class MethodChannelFFmpegKit extends FFmpegKitPlatform { 'mediaInformationJsonParserFromWithError', {'ffprobeJsonOutput': ffprobeJsonOutput}); + // MediaInformationSession + + @override + Future?> mediaInformationSessionGetMediaInformation( + int? sessionId) async => + _channel.invokeMethod>( + 'getMediaInformation(', {'sessionId': sessionId}); + @override Future getPackageName() async => _channel.invokeMethod('getPackageName'); diff --git a/flutter/flutter_platform_interface/pubspec.yaml b/flutter/flutter_platform_interface/pubspec.yaml index aadfaf1..a60b334 100644 --- a/flutter/flutter_platform_interface/pubspec.yaml +++ b/flutter/flutter_platform_interface/pubspec.yaml @@ -5,7 +5,7 @@ issue_tracker: https://github.com/tanersener/ffmpeg-kit/issues homepage: https://github.com/tanersener/ffmpeg-kit # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 0.1.0 +version: 0.2.0 environment: sdk: ">=2.12.0 <3.0.0"