Skip to content

Commit

Permalink
Added a "Import Media File" button
Browse files Browse the repository at this point in the history
- Experimenting with adding a "Import Media File" button. Currently working, but merging now, just so I have a reference point.
  • Loading branch information
latenitefilms committed Jul 13, 2023
1 parent 6381e8a commit b69759d
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 55 deletions.
8 changes: 7 additions & 1 deletion Source/Frameworks/gyroflow/inc/gyroflow.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,10 @@ const char* processFrame(
void *command_queue
);

uint32_t trashCache();
uint32_t trashCache(
void
);

const char* importMediaFile(
const char* media_file_path
);
64 changes: 62 additions & 2 deletions Source/Frameworks/gyroflow/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//---------------------------------------------------------
// Local name bindings:
//---------------------------------------------------------
use gyroflow_core::{StabilizationManager, stabilization::*};
use gyroflow_core::{StabilizationManager, stabilization::*, telemetry_parser::util::VideoMetadata};
use gyroflow_core::gpu::{ BufferDescription, BufferSource, Buffers };

use once_cell::sync::OnceCell; // Provides two new cell-like types, unsync::OnceCell and sync::OnceCell
Expand Down Expand Up @@ -48,6 +48,66 @@ pub extern "C" fn trashCache() -> u32 {
cache.len() as u32
}

//---------------------------------------------------------
// The "Import Media File" function that gets triggered
// from Objective-C Land:
//---------------------------------------------------------
#[no_mangle]
pub extern "C" fn importMediaFile(
media_file_path: *const c_char,
) -> *const c_char {
//---------------------------------------------------------
// Convert the file path to a `&str`:
//---------------------------------------------------------
let media_file_path_pointer = unsafe { CStr::from_ptr(media_file_path) };
let media_file_path_string = media_file_path_pointer.to_string_lossy();

log::info!("[Gyroflow Toolbox Rust] media_file_path_string: {:?}", media_file_path_string);

let mut stab = StabilizationManager::default();
{
//---------------------------------------------------------
// Find first lens profile database with loaded profiles:
//---------------------------------------------------------
let lock = MANAGER_CACHE.lock().unwrap();
for (_, v) in lock.iter() {
if v.lens_profile_db.read().loaded {
stab.lens_profile_db = v.lens_profile_db.clone();
break;
}
}
}

// Load video file. For simplicity, I'm passing None as metadata. You can change it as per your need.
match stab.load_video_file(&media_file_path_string, None) {
Ok(_) => {
log::info!("[Gyroflow Toolbox Rust] Video file loaded successfully");
},
Err(e) => {
log::error!("[Gyroflow Toolbox Rust] An error occured: {:?}", e);
}
}

// Export Gyroflow data
let gyroflow_data: String;
match stab.export_gyroflow_data(false, false, "{}") {
Ok(data) => {
gyroflow_data = data;
log::info!("[Gyroflow Toolbox Rust] Gyroflow data exported successfully");
},
Err(e) => {
log::error!("[Gyroflow Toolbox Rust] An error occured: {:?}", e);
gyroflow_data = "FAIL".to_string();
}
}

//---------------------------------------------------------
// Return Gyroflow Project data as string:
//---------------------------------------------------------
let result = CString::new(gyroflow_data).unwrap();
return result.into_raw()
}

//---------------------------------------------------------
// The "Process Frame" function that gets triggered from
// Objective-C Land:
Expand Down Expand Up @@ -297,7 +357,7 @@ pub extern "C" fn processFrame(
manager.process_pixels::<RGBAf>(timestamp, &mut buffers)
},
_ => {
log::error!("[Gyroflow Toolbox] Unsupported pixel format: {:?}", pixel_format_string);
log::error!("[Gyroflow Toolbox Rust] Unsupported pixel format: {:?}", pixel_format_string);
let result = CString::new("FAIL").unwrap();
return result.into_raw()
}
Expand Down
1 change: 1 addition & 0 deletions Source/Gyroflow/Plugin/GyroflowConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ enum {
kCB_LaunchGyroflow = 20,
kCB_LoadLastGyroflowProject = 25,
kCB_ImportGyroflowProject = 30,
kCB_ImportMediaFile = 35,
kCB_LoadedGyroflowProject = 40,
kCB_ReloadGyroflowProject = 50,

Expand Down
1 change: 1 addition & 0 deletions Source/Gyroflow/Plugin/GyroflowPlugIn.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
//---------------------------------------------------------
NSView* launchGyroflowView;
NSView* importGyroflowProjectView;
NSView* importMediaFileView;
NSView* reloadGyroflowProjectView;
NSView* loadLastGyroflowProjectView;
NSView* dropZoneView;
Expand Down
153 changes: 130 additions & 23 deletions Source/Gyroflow/Plugin/GyroflowPlugIn.m
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ - (NSView*)createViewForParameterID:(UInt32)parameterID
buttonTitle:@"Import Gyroflow Project"];
importGyroflowProjectView = view;
return view;
} else if (parameterID == kCB_ImportMediaFile) {
NSView* view = [[CustomButtonView alloc] initWithAPIManager:_apiManager
parentPlugin:self
buttonID:kCB_ImportMediaFile
buttonTitle:@"Import Media File"];
importMediaFileView = view;
return view;
} else if (parameterID == kCB_ReloadGyroflowProject) {
NSView* view = [[CustomButtonView alloc] initWithAPIManager:_apiManager
parentPlugin:self
Expand All @@ -177,14 +184,14 @@ - (NSView*)createViewForParameterID:(UInt32)parameterID
NSView* view = [[CustomButtonView alloc] initWithAPIManager:_apiManager
parentPlugin:self
buttonID:kCB_LoadLastGyroflowProject
buttonTitle:@"Import Last Saved Project"];
buttonTitle:@"Import Last Gyroflow Project"];
loadLastGyroflowProjectView = view;
return view;
} else if (parameterID == kCB_DropZone) {
NSView* view = [[CustomDropZoneView alloc] initWithAPIManager:_apiManager
parentPlugin:self
buttonID:kCB_DropZone
buttonTitle:@"Drop Zone"];
buttonTitle:@"Import Dropped Clip"];
dropZoneView = view;
return view;
} else {
Expand Down Expand Up @@ -230,23 +237,6 @@ - (BOOL)addParametersWithError:(NSError**)error
}
return NO;
}

//---------------------------------------------------------
// ADD PARAMETER: Drop Zone
//---------------------------------------------------------
if (![paramAPI addCustomParameterWithName:@"Drop Zone"
parameterID:kCB_DropZone
defaultValue:@0
parameterFlags:kFxParameterFlag_CUSTOM_UI | kFxParameterFlag_NOT_ANIMATABLE])
{
if (error != NULL) {
NSDictionary* userInfo = @{NSLocalizedDescriptionKey : @"[Gyroflow Toolbox Renderer] Unable to add parameter: kCB_DropZone"};
*error = [NSError errorWithDomain:FxPlugErrorDomain
code:kFxError_InvalidParameter
userInfo:userInfo];
}
return NO;
}

//---------------------------------------------------------
// ADD PARAMETER: 'Loaded Gyroflow Project' Text Box
Expand Down Expand Up @@ -283,9 +273,9 @@ - (BOOL)addParametersWithError:(NSError**)error
}

//---------------------------------------------------------
// ADD PARAMETER: 'Import Last Saved Project' Button
// ADD PARAMETER: 'Import Last Gyroflow Project' Button
//---------------------------------------------------------
if (![paramAPI addCustomParameterWithName:@"Import Last Saved Project"
if (![paramAPI addCustomParameterWithName:@"Import Last Gyroflow Project"
parameterID:kCB_LoadLastGyroflowProject
defaultValue:@0
parameterFlags:kFxParameterFlag_CUSTOM_UI | kFxParameterFlag_NOT_ANIMATABLE])
Expand All @@ -299,6 +289,40 @@ - (BOOL)addParametersWithError:(NSError**)error
return NO;
}

//---------------------------------------------------------
// ADD PARAMETER: 'Import Media File' Button
//---------------------------------------------------------
if (![paramAPI addCustomParameterWithName:@"Import Media File"
parameterID:kCB_ImportMediaFile
defaultValue:@0
parameterFlags:kFxParameterFlag_CUSTOM_UI | kFxParameterFlag_NOT_ANIMATABLE])
{
if (error != NULL) {
NSDictionary* userInfo = @{NSLocalizedDescriptionKey : @"[Gyroflow Toolbox Renderer] Unable to add parameter: kCB_ImportMediaFile"};
*error = [NSError errorWithDomain:FxPlugErrorDomain
code:kFxError_InvalidParameter
userInfo:userInfo];
}
return NO;
}

//---------------------------------------------------------
// ADD PARAMETER: Import Dropped Clip
//---------------------------------------------------------
if (![paramAPI addCustomParameterWithName:@"Import Dropped Clip"
parameterID:kCB_DropZone
defaultValue:@0
parameterFlags:kFxParameterFlag_CUSTOM_UI | kFxParameterFlag_NOT_ANIMATABLE])
{
if (error != NULL) {
NSDictionary* userInfo = @{NSLocalizedDescriptionKey : @"[Gyroflow Toolbox Renderer] Unable to add parameter: kCB_DropZone"};
*error = [NSError errorWithDomain:FxPlugErrorDomain
code:kFxError_InvalidParameter
userInfo:userInfo];
}
return NO;
}

//---------------------------------------------------------
// ADD PARAMETER: 'Open in Gyroflow' Button
//---------------------------------------------------------
Expand Down Expand Up @@ -643,7 +667,7 @@ - (BOOL)addParametersWithError:(NSError**)error
if (![paramAPI addStringParameterWithName:@"Unique Identifier"
parameterID:kCB_UniqueIdentifier
defaultValue:@""
parameterFlags:kFxParameterFlag_DISABLED])
parameterFlags:kFxParameterFlag_HIDDEN | kFxParameterFlag_NOT_ANIMATABLE])
{
if (error != NULL) {
NSDictionary* userInfo = @{NSLocalizedDescriptionKey : @"[Gyroflow Toolbox Renderer] Unable to add parameter: kCB_UniqueIdentifier"};
Expand Down Expand Up @@ -1211,9 +1235,92 @@ - (void)customButtonViewPressed:(UInt32)buttonID
[self buttonImportGyroflowProject];
} else if (buttonID == kCB_ReloadGyroflowProject) {
[self buttonReloadGyroflowProject];
} else if (buttonID == kCB_ImportMediaFile) {
[self buttonImportMediaFile];
}
}

//---------------------------------------------------------
// BUTTON: 'Launch Gyroflow'
//---------------------------------------------------------
- (void)buttonImportMediaFile {
NSLog(@"[Gyroflow Toolbox Renderer] Import Media File!");

//---------------------------------------------------------
// Setup an NSOpenPanel:
//---------------------------------------------------------
NSOpenPanel* panel = [NSOpenPanel openPanel];
[panel setCanChooseDirectories:NO];
[panel setCanCreateDirectories:YES];
[panel setCanChooseFiles:YES];
[panel setAllowsMultipleSelection:NO];
//[panel setDirectoryURL:optionalURL];

//---------------------------------------------------------
// Limit the file type to .gyroflow files:
//---------------------------------------------------------
UTType *mxf = [UTType typeWithFilenameExtension:@"mxf"];
UTType *braw = [UTType typeWithFilenameExtension:@"braw"];
UTType *mpFour = [UTType typeWithFilenameExtension:@"mp4"];

NSArray *allowedContentTypes = [NSArray arrayWithObjects:mxf, braw, mpFour, nil];
[panel setAllowedContentTypes:allowedContentTypes];

//---------------------------------------------------------
// Open the panel:
//---------------------------------------------------------
NSModalResponse result = [panel runModal];
if (result != NSModalResponseOK) {
return;
}

//---------------------------------------------------------
// Start accessing security scoped resource:
//---------------------------------------------------------
NSURL *url = [panel URL];
BOOL startedOK = [url startAccessingSecurityScopedResource];
if (startedOK == NO) {
[self showAlertWithMessage:@"An error has occurred." info:@"Failed to startAccessingSecurityScopedResource. This shouldn't happen."];
return;
}

NSString *path = [url path];

NSLog(@"[Gyroflow Toolbox Renderer] Import Media File Path: %@", path);

const char* importResult = importMediaFile([path UTF8String]);
NSString *resultString = [NSString stringWithUTF8String: importResult];
NSLog(@"[Gyroflow Toolbox Renderer] resultString: %@", resultString);


if (resultString == nil || [resultString isEqualToString:@"FAIL"]) {
[self showAlertWithMessage:@"An error has occurred" info:@"Failed to generate a Gyroflow Project from the Media File."];
return;
}

//---------------------------------------------------------
// Create a temporary file in the temporary directory to
// save our Gyroflow Project:
//---------------------------------------------------------
NSString *randomFilename = [[NSUUID UUID] UUIDString];
NSURL *tempDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
NSURL *tempFileURL = [NSURL fileURLWithPath:[tempDirURL.path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", randomFilename]]];
NSString *tempFilePath = [tempFileURL path];

NSError *error = nil;
[resultString writeToFile:tempFilePath
atomically:YES
encoding:NSUTF8StringEncoding
error:&error];

if (error) {
NSString *errorMessage = [NSString stringWithFormat:@"Failed to write the temporary Gyroflow project to disk due to:\n\n%@", error.localizedDescription];
[self showAlertWithMessage:@"An error has occurred" info:errorMessage];
}

[self importGyroflowProjectWithOptionalURL:[NSURL fileURLWithPath:tempFilePath]];
}

//---------------------------------------------------------
// BUTTON: 'Launch Gyroflow'
//---------------------------------------------------------
Expand Down Expand Up @@ -1381,7 +1488,7 @@ - (void)buttonReloadGyroflowProject {

//---------------------------------------------------------
// Trash all the caches in Rust land:
//---------------------------------------------------------
//---------------------------------------------------------
uint32_t cacheSize = trashCache();
NSLog(@"[Gyroflow Toolbox Renderer]: Rust MANAGER_CACHE size after trashing (should be zero): %u", cacheSize);

Expand Down
Loading

0 comments on commit b69759d

Please sign in to comment.