2024-12-14 18:15:22 +00:00
# pragma once
# include <JuceHeader.h>
# include "../components/EffectComponent.h"
# include "../components/SvgButton.h"
# include "../LookAndFeel.h"
# include "../components/SwitchButton.h"
2024-12-15 19:23:31 +00:00
# define VERSION_HINT 2
class RecordingParameters {
2024-12-14 18:15:22 +00:00
public :
2024-12-15 19:23:31 +00:00
RecordingParameters ( ) {
qualityParameter . disableLfo ( ) ;
qualityParameter . disableSidechain ( ) ;
2025-01-26 21:02:01 +00:00
resolution . disableLfo ( ) ;
resolution . disableSidechain ( ) ;
frameRate . disableLfo ( ) ;
frameRate . disableSidechain ( ) ;
2024-12-15 19:23:31 +00:00
}
2025-01-04 14:35:10 +00:00
private :
# if SOSCI_FEATURES
const bool sosciFeatures = true ;
# else
const bool sosciFeatures = false ;
# endif
public :
2024-12-15 19:23:31 +00:00
EffectParameter qualityParameter = EffectParameter (
2025-01-06 11:17:42 +00:00
" Video Quality " ,
2025-01-08 11:28:28 +00:00
" Controls the quality of the recording video. 0 is the worst possible quality, and 1 is almost lossless. " ,
2024-12-15 19:23:31 +00:00
" brightness " ,
VERSION_HINT , 0.7 , 0.0 , 1.0
2024-12-14 18:15:22 +00:00
) ;
2025-01-08 11:28:28 +00:00
BooleanParameter losslessVideo = BooleanParameter ( " Lossless Video " , " losslessVideo " , VERSION_HINT , false , " Record video in a lossless format. WARNING: This is not supported by all media players. " ) ;
2024-12-15 19:23:31 +00:00
Effect qualityEffect = Effect ( & qualityParameter ) ;
2024-12-14 18:15:22 +00:00
2024-12-15 19:23:31 +00:00
BooleanParameter recordAudio = BooleanParameter ( " Record Audio " , " recordAudio " , VERSION_HINT , true , " Record audio along with the video. " ) ;
2025-01-04 14:35:10 +00:00
BooleanParameter recordVideo = BooleanParameter ( " Record Video " , " recordVideo " , VERSION_HINT , sosciFeatures , " Record video output of the visualiser. " ) ;
2025-01-26 21:02:01 +00:00
EffectParameter resolution = EffectParameter (
" Resolution " ,
" The resolution of the recorded video. This only changes when not recording. " ,
" resolution " ,
VERSION_HINT , 1024 , 128 , 2048 , 1.0
) ;
Effect resolutionEffect = Effect ( & resolution ) ;
EffectParameter frameRate = EffectParameter (
" Frame Rate " ,
" The frame rate of the recorded video. This only changes when not recording. " ,
" frameRate " ,
VERSION_HINT , 60.0 , 10 , 240 , 0.01
) ;
Effect frameRateEffect = Effect ( & frameRate ) ;
2024-12-14 18:15:22 +00:00
2024-12-15 19:23:31 +00:00
juce : : String compressionPreset = " fast " ;
void save ( juce : : XmlElement * xml ) {
auto settingsXml = xml - > createNewChildElement ( " recordingSettings " ) ;
2025-01-08 11:28:28 +00:00
losslessVideo . save ( settingsXml - > createNewChildElement ( " losslessVideo " ) ) ;
2024-12-15 19:23:31 +00:00
recordAudio . save ( settingsXml - > createNewChildElement ( " recordAudio " ) ) ;
recordVideo . save ( settingsXml - > createNewChildElement ( " recordVideo " ) ) ;
settingsXml - > setAttribute ( " compressionPreset " , compressionPreset ) ;
2025-01-12 20:39:20 +00:00
settingsXml - > setAttribute ( " customSharedTextureServerName " , customSharedTextureServerName ) ;
2024-12-15 19:23:31 +00:00
auto qualityXml = settingsXml - > createNewChildElement ( " quality " ) ;
qualityEffect . save ( qualityXml ) ;
2025-01-26 21:02:01 +00:00
auto resolutionXml = settingsXml - > createNewChildElement ( " resolution " ) ;
resolutionEffect . save ( resolutionXml ) ;
auto frameRateXml = settingsXml - > createNewChildElement ( " frameRate " ) ;
frameRateEffect . save ( frameRateXml ) ;
2024-12-14 18:15:22 +00:00
}
2024-12-15 19:23:31 +00:00
// opt to not change any values if not found
void load ( juce : : XmlElement * xml ) {
if ( auto * settingsXml = xml - > getChildByName ( " recordingSettings " ) ) {
2025-01-08 11:28:28 +00:00
if ( auto * losslessVideoXml = settingsXml - > getChildByName ( " losslessVideo " ) ) {
losslessVideo . load ( losslessVideoXml ) ;
}
2024-12-15 19:23:31 +00:00
if ( auto * recordAudioXml = settingsXml - > getChildByName ( " recordAudio " ) ) {
recordAudio . load ( recordAudioXml ) ;
}
if ( auto * recordVideoXml = settingsXml - > getChildByName ( " recordVideo " ) ) {
recordVideo . load ( recordVideoXml ) ;
}
if ( settingsXml - > hasAttribute ( " compressionPreset " ) ) {
compressionPreset = settingsXml - > getStringAttribute ( " compressionPreset " ) ;
}
2025-01-12 20:39:20 +00:00
if ( settingsXml - > hasAttribute ( " customSharedTextureServerName " ) ) {
customSharedTextureServerName = settingsXml - > getStringAttribute ( " customSharedTextureServerName " ) ;
}
2024-12-15 19:23:31 +00:00
if ( auto * qualityXml = settingsXml - > getChildByName ( " quality " ) ) {
qualityEffect . load ( qualityXml ) ;
}
2025-01-26 21:02:01 +00:00
if ( auto * resolutionXml = settingsXml - > getChildByName ( " resolution " ) ) {
resolutionEffect . load ( resolutionXml ) ;
}
if ( auto * frameRateXml = settingsXml - > getChildByName ( " frameRate " ) ) {
frameRateEffect . load ( frameRateXml ) ;
}
2024-12-15 19:23:31 +00:00
}
2024-12-14 18:15:22 +00:00
}
2024-12-15 19:23:31 +00:00
juce : : StringArray compressionPresets = { " ultrafast " , " superfast " , " veryfast " , " faster " , " fast " , " medium " , " slow " , " slower " , " veryslow " } ;
2025-01-12 20:39:20 +00:00
juce : : String customSharedTextureServerName = " " ;
2024-12-15 19:23:31 +00:00
} ;
2024-12-14 18:15:22 +00:00
2024-12-15 19:23:31 +00:00
class RecordingSettings : public juce : : Component {
public :
RecordingSettings ( RecordingParameters & ) ;
~ RecordingSettings ( ) ;
void resized ( ) override ;
2025-01-06 18:27:23 +00:00
int getCRF ( ) {
2025-01-08 11:28:28 +00:00
if ( parameters . losslessVideo . getBoolValue ( ) ) {
return 0 ;
}
2025-01-06 18:27:23 +00:00
double quality = juce : : jlimit ( 0.0 , 1.0 , parameters . qualityEffect . getValue ( ) ) ;
2025-01-08 11:28:28 +00:00
// mapping to 1-51 for ffmpeg's crf value (ignoring 0 as this is lossless and
// not supported by all media players)
return 50 * ( 1.0 - quality ) + 1 ;
2025-01-06 18:27:23 +00:00
}
2025-01-19 20:43:28 +00:00
int getVideoToolboxQuality ( ) {
if ( parameters . losslessVideo . getBoolValue ( ) ) {
return 100 ;
}
double quality = juce : : jlimit ( 0.0 , 1.0 , parameters . qualityEffect . getValue ( ) ) ;
return 100 * quality ;
}
2025-01-06 18:27:23 +00:00
bool recordingVideo ( ) {
return parameters . recordVideo . getBoolValue ( ) ;
}
bool recordingAudio ( ) {
return parameters . recordAudio . getBoolValue ( ) ;
}
juce : : String getCompressionPreset ( ) {
return parameters . compressionPreset ;
}
2025-01-12 20:39:20 +00:00
juce : : String getCustomSharedTextureServerName ( ) {
if ( parameters . customSharedTextureServerName . isEmpty ( ) ) {
return " osci-render - " + juce : : String ( juce : : Time : : getCurrentTime ( ) . toMilliseconds ( ) ) ;
}
return parameters . customSharedTextureServerName ;
}
2025-01-26 21:02:01 +00:00
int getResolution ( ) {
return parameters . resolution . getValueUnnormalised ( ) ;
}
double getFrameRate ( ) {
return parameters . frameRate . getValueUnnormalised ( ) ;
}
2025-01-06 18:27:23 +00:00
2024-12-15 19:23:31 +00:00
RecordingParameters & parameters ;
2024-12-14 18:15:22 +00:00
private :
2024-12-15 19:23:31 +00:00
EffectComponent quality { parameters . qualityEffect } ;
2025-01-26 21:02:01 +00:00
EffectComponent resolution { parameters . resolutionEffect } ;
EffectComponent frameRate { parameters . frameRateEffect } ;
2024-12-14 18:15:22 +00:00
2025-01-08 11:28:28 +00:00
jux : : SwitchButton losslessVideo { & parameters . losslessVideo } ;
2024-12-15 19:23:31 +00:00
jux : : SwitchButton recordAudio { & parameters . recordAudio } ;
jux : : SwitchButton recordVideo { & parameters . recordVideo } ;
2025-01-04 14:35:10 +00:00
# if !SOSCI_FEATURES
juce : : TextEditor recordVideoWarning { " recordVideoWarning " } ;
juce : : HyperlinkButton sosciLink { " Purchase here " , juce : : URL ( " https://osci-render.com/sosci " ) } ;
# endif
2024-12-15 19:23:31 +00:00
juce : : Label compressionPresetLabel { " Compression Speed " , " Compression Speed " } ;
juce : : ComboBox compressionPreset ;
2025-01-12 20:39:20 +00:00
juce : : Label customSharedTextureOutputLabel { " Custom Syphon/Spout Name " , " Custom Syphon/Spout Name " } ;
juce : : TextEditor customSharedTextureOutputEditor { " customSharedTextureOutputEditor " } ;
2024-12-15 19:23:31 +00:00
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR ( RecordingSettings )
2024-12-14 18:15:22 +00:00
} ;