--- /dev/null
+<?xml version="1.0"?>
+<PLUGIN TITLE=Compressor>
+<KEYFRAME TITLE=loud><COMPRESSOR TRIGGER=0 REACTION_LEN=-1.0000000000000014e-01 DECAY_LEN=9.9999999999999367e-02 SMOOTHING_ONLY=0 INPUT=2>
+<LEVEL X=-4.9852631578947367e+01 Y=0>
+</KEYFRAME>
+<KEYFRAME TITLE=soft><COMPRESSOR TRIGGER=0 REACTION_LEN=-1.0000000000000014e-01 DECAY_LEN=4.9999999999999982e+00 SMOOTHING_ONLY=0 INPUT=2>
+<LEVEL X=-4.9852631578947367e+01 Y=0>
+</KEYFRAME>
+<KEYFRAME TITLE=voice><COMPRESSOR TRIGGER=0 REACTION_LEN=-1.0000000000000001e-01 DECAY_LEN=1.0000000000000001e-01 SMOOTHING_ONLY=0 INPUT=2>
+<LEVEL X=-3.0484210526315792e+01 Y=-80>
+<LEVEL X=-1.9873684210526321e+01 Y=0>
+</KEYFRAME>
+<KEYFRAME TITLE="live audio"><COMPRESSOR TRIGGER=0 REACTION_LEN=1.0000000000000001e-01 DECAY_LEN=1.0000000000000001e-01 SMOOTHING_ONLY=0 INPUT=2>
+<LEVEL X=-4.9852631578947367e+01 Y=0>
+</KEYFRAME>
+</PLUGIN>
+<PLUGIN TITLE=Lens>
+<KEYFRAME TITLE="15mm full frame stretch"><LENS FOCAL_LENGTH0=5.999998e-01 FOCAL_LENGTH1=6.000000e-01 FOCAL_LENGTH2=6.000000e-01 FOCAL_LENGTH3=6.000000e-01 ASPECT=1 RADIUS=1.020000e+00 MODE=3 CENTER_X=50 CENTER_Y=50 DRAW_GUIDES=0></KEYFRAME>
+<KEYFRAME TITLE="15mm 1.6x stretch"><LENS FOCAL_LENGTH0=3.699997e-01 FOCAL_LENGTH1=3.700000e-01 FOCAL_LENGTH2=3.700000e-01 FOCAL_LENGTH3=3.700000e-01 ASPECT=1 RADIUS=8.500000e-01 MODE=3 CENTER_X=50 CENTER_Y=50 DRAW_GUIDES=0></KEYFRAME>
+<KEYFRAME TITLE="15mm full frame hemi"><LENS FOCAL_LENGTH0=5.999998e-01 FOCAL_LENGTH1=6.000000e-01 FOCAL_LENGTH2=6.000000e-01 FOCAL_LENGTH3=6.000000e-01 ASPECT=1.200000e+00 RADIUS=1.020000e+00 MODE=3 CENTER_X=50 CENTER_Y=50 DRAW_GUIDES=0></KEYFRAME>
+<KEYFRAME TITLE="15mm 1920x1080"><LENS FOCAL_LENGTH0=5.799997e-01 FOCAL_LENGTH1=5.800000e-01 FOCAL_LENGTH2=5.800000e-01 FOCAL_LENGTH3=5.800000e-01 ASPECT=1 RADIUS=9.400000e-01 MODE=3 CENTER_X=50 CENTER_Y=50 DRAW_GUIDES=0></KEYFRAME>
+<KEYFRAME TITLE="15mm 1.6x video"><LENS FOCAL_LENGTH0=3.699998e-01 FOCAL_LENGTH1=3.700001e-01 FOCAL_LENGTH2=3.700001e-01 FOCAL_LENGTH3=3.700001e-01 ASPECT=1 RADIUS=8.400001e-01 MODE=3 CENTER_X=50 CENTER_Y=50 DRAW_GUIDES=0></KEYFRAME>
+<KEYFRAME TITLE=gopro><LENS FOCAL_LENGTH0=4.999998e-01 FOCAL_LENGTH1=5.000001e-01 FOCAL_LENGTH2=5.000001e-01 FOCAL_LENGTH3=5.000001e-01 ASPECT=1 RADIUS=1.200000e+00 MODE=3 CENTER_X=50 CENTER_Y=50 DRAW_GUIDES=0></KEYFRAME>
+<KEYFRAME TITLE="gopro hemi"><LENS FOCAL_LENGTH0=4.999998e-01 FOCAL_LENGTH1=5.000001e-01 FOCAL_LENGTH2=5.000001e-01 FOCAL_LENGTH3=5.000001e-01 ASPECT=1.330000e+00 RADIUS=7.300000e-01 MODE=3 CENTER_X=50 CENTER_Y=50 DRAW_GUIDES=0></KEYFRAME>
+<KEYFRAME TITLE=gopro2.7k><LENS FOCAL_LENGTH0=4.399988e-01 FOCAL_LENGTH1=4.400000e-01 FOCAL_LENGTH2=4.400000e-01 FOCAL_LENGTH3=4.400000e-01 ASPECT=1 RADIUS=8.500000e-01 MODE=3 CENTER_X=50 CENTER_Y=50 DRAW_GUIDES=0></KEYFRAME>
+<KEYFRAME TITLE="gopro 4k"><LENS FOCAL_LENGTH0=4.999998e-01 FOCAL_LENGTH1=5.000001e-01 FOCAL_LENGTH2=5.000001e-01 FOCAL_LENGTH3=5.000001e-01 ASPECT=1 RADIUS=8.700000e-01 MODE=3 CENTER_X=50 CENTER_Y=50 DRAW_GUIDES=0></KEYFRAME>
+</PLUGIN>
+<PLUGIN TITLE=Spectrogram>
+<KEYFRAME TITLE=sissel><SPECTROGRAM LEVEL=1.4901161193847656e-08 NORMALIZE=0 WINDOW_SIZE=4096 XZOOM=1 MODE=0 HISTORY_SIZE=4 W=750 H=656>
+</KEYFRAME>
+</PLUGIN>
+<PLUGIN TITLE=Downsample>
+<KEYFRAME TITLE="UV 2x2"><DOWNSAMPLE HORIZONTAL=2 VERTICAL=2 HORIZONTAL_X=0 VERTICAL_Y=0 R=0 G=1 B=1 A=0></KEYFRAME>
+</PLUGIN>
+<PLUGIN TITLE=Scale>
+<KEYFRAME TITLE="d-1 to gootube"><SCALE WIDTH=4.400000e-01 HEIGHT=5.000000e-01></KEYFRAME>
+<KEYFRAME TITLE="640x480 to d-1"><SCALE WIDTH=1.100000e+00 HEIGHT=1></KEYFRAME>
+<KEYFRAME TITLE="fix D-1 on gootube"><SCALE WIDTH=1 HEIGHT=1.125100e+00></KEYFRAME>
+</PLUGIN>
+<PLUGIN TITLE=Motion>
+<KEYFRAME TITLE=coptercam><MOTION BLOCK_COUNT=1 GLOBAL_POSITIONS=256 ROTATE_POSITIONS=4 GLOBAL_BLOCK_W=45 GLOBAL_BLOCK_H=52 ROTATION_BLOCK_W=33 ROTATION_BLOCK_H=32 BLOCK_X=50 BLOCK_Y=50 GLOBAL_RANGE_W=39 GLOBAL_RANGE_H=47 ROTATION_RANGE=10 ROTATION_CENTER=0 MAGNITUDE=50 RETURN_SPEED=3 MODE1=1 GLOBAL=1 ROTATE=1 MODE2=5 DRAW_VECTORS=0 MODE3=11 TRACK_FRAME=0 BOTTOM_IS_MASTER=1 HORIZONTAL_ONLY=0 VERTICAL_ONLY=0></KEYFRAME>
+<KEYFRAME TITLE=running><MOTION BLOCK_COUNT=1 GLOBAL_POSITIONS=1024 ROTATE_POSITIONS=4 GLOBAL_BLOCK_W=34 GLOBAL_BLOCK_H=46 BLOCK_X=50 BLOCK_Y=50 GLOBAL_RANGE_W=100 GLOBAL_RANGE_H=100 ROTATION_RANGE=5 ROTATION_CENTER=0 MAGNITUDE=50 RETURN_SPEED=10 ROTATE_MAGNITUDE=15 ROTATE_RETURN_SPEED=10 ACTION_TYPE=3 GLOBAL=1 ROTATE=1 TRACKING_TYPE=1 DRAW_VECTORS=1 TRACKING_OBJECT=2 TRACK_FRAME=0 BOTTOM_IS_MASTER=1 HORIZONTAL_ONLY=0 VERTICAL_ONLY=0></KEYFRAME>
+</PLUGIN>
+<PLUGIN TITLE=Reverb>
+<KEYFRAME TITLE=loud><REVERB LEVELINIT=0 DELAY_INIT=20 REF_LEVEL1=-1.7999996185302734e+01 REF_LEVEL2=-3.8000030517578125e+01 REF_TOTAL=124 REF_LENGTH=1059 LOWPASS1=24539 LOWPASS2=24539>
+</KEYFRAME>
+<KEYFRAME TITLE=long><REVERB LEVELINIT=0 DELAY_INIT=20 REF_LEVEL1=-16 REF_LEVEL2=-3.8000030517578125e+01 REF_TOTAL=137 REF_LENGTH=3034 LOWPASS1=24539 LOWPASS2=24539>
+</KEYFRAME>
+<KEYFRAME TITLE=piano><REVERB LEVELINIT=0 DELAY_INIT=90 REF_LEVEL1=-28 REF_LEVEL2=-40 REF_TOTAL=163 REF_LENGTH=600 LOWPASS1=24539 LOWPASS2=4425>
+</KEYFRAME>
+</PLUGIN>
+<PLUGIN TITLE="Interpolate Video">
+<KEYFRAME TITLE="10fps analog"><INTERPOLATEVIDEO INPUT_RATE=10 USE_KEYFRAMES=0 OPTIC_FLOW=1 DRAW_VECTORS=0 SEARCH_RADIUS=16 MACROBLOCK_SIZE=32></KEYFRAME>
+<KEYFRAME TITLE=iss><INTERPOLATEVIDEO INPUT_RATE=1 USE_KEYFRAMES=0 OPTIC_FLOW=1 DRAW_VECTORS=1 SEARCH_RADIUS=111 MACROBLOCK_SIZE=101></KEYFRAME>
+<KEYFRAME TITLE=hd><INTERPOLATEVIDEO INPUT_RATE=2.3976023976023978e+01 USE_KEYFRAMES=0 OPTIC_FLOW=1 DRAW_VECTORS=0 SEARCH_RADIUS=40 MACROBLOCK_SIZE=50></KEYFRAME>
+<KEYFRAME TITLE=weather><INTERPOLATEVIDEO INPUT_RATE=5 USE_KEYFRAMES=0 OPTIC_FLOW=1 DRAW_VECTORS=0 SEARCH_RADIUS=32 MACROBLOCK_SIZE=60></KEYFRAME>
+</PLUGIN>
+<PLUGIN TITLE="Chroma key (HSV)">
+<KEYFRAME TITLE=blue><CHROMAKEY_HSV RED=0 GREEN=1.137255e-01 BLUE=1 MIN_BRIGHTNESS=0 MAX_BRIGHTNESS=100 SATURATION=0 MIN_SATURATION=20 TOLERANCE=30 IN_SLOPE=0 OUT_SLOPE=0 ALPHA_OFFSET=0 SPILL_THRESHOLD=0 SPILL_AMOUNT=0 SHOW_MASK=0></KEYFRAME>
+<KEYFRAME TITLE=pink><CHROMAKEY_HSV RED=1 GREEN=0 BLUE=8.313726e-01 MIN_BRIGHTNESS=0 MAX_BRIGHTNESS=100 SATURATION=0 MIN_SATURATION=20 TOLERANCE=20 IN_SLOPE=0 OUT_SLOPE=0 ALPHA_OFFSET=0 SPILL_THRESHOLD=0 SPILL_AMOUNT=0 SHOW_MASK=0></KEYFRAME>
+<KEYFRAME TITLE=cyan><CHROMAKEY_HSV RED=0 GREEN=9.647059e-01 BLUE=1 MIN_BRIGHTNESS=0 MAX_BRIGHTNESS=100 SATURATION=0 MIN_SATURATION=1.850000e+01 TOLERANCE=30 IN_SLOPE=0 OUT_SLOPE=0 ALPHA_OFFSET=0 SPILL_THRESHOLD=0 SPILL_AMOUNT=0 SHOW_MASK=0></KEYFRAME>
+<KEYFRAME TITLE=red><CHROMAKEY_HSV RED=1 GREEN=0 BLUE=9.137255e-01 MIN_BRIGHTNESS=11 MAX_BRIGHTNESS=100 SATURATION=0 MIN_SATURATION=20 TOLERANCE=20 IN_SLOPE=0 OUT_SLOPE=0 ALPHA_OFFSET=0 SPILL_THRESHOLD=0 SPILL_AMOUNT=0 SHOW_MASK=0></KEYFRAME>
+</PLUGIN>
+<PLUGIN TITLE=Histogram>
+<KEYFRAME TITLE=cr2><HISTOGRAM AUTOMATIC=0 THRESHOLD=9.990000e-01 PLOT=1 SPLIT=0 W=440 H=579 PARADE=0 MODE=3 LOW_OUTPUT_0=0 HIGH_OUTPUT_0=1 LOW_INPUT_0=0 HIGH_INPUT_0=1 GAMMA_0=1 LOW_OUTPUT_1=0 HIGH_OUTPUT_1=1 LOW_INPUT_1=0 HIGH_INPUT_1=1 GAMMA_1=1 LOW_OUTPUT_2=0 HIGH_OUTPUT_2=1 LOW_INPUT_2=0 HIGH_INPUT_2=1 GAMMA_2=1 LOW_OUTPUT_3=0 HIGH_OUTPUT_3=1 LOW_INPUT_3=0 HIGH_INPUT_3=5.548077e-01 GAMMA_3=2>
+</KEYFRAME>
+</PLUGIN>
+<PLUGIN TITLE="EQ Parametric">
+<KEYFRAME TITLE=ultrarunner><PARAMETRICEQ WETNESS=0 WINDOW_SIZE=4096>
+<BAND NUMBER=0 FREQ=2095 QUALITY=7.700000e-01 MAGNITUDE=5.800000e+00 MODE=3>
+<BAND NUMBER=1 FREQ=440 QUALITY=1 MAGNITUDE=0 MODE=0>
+<BAND NUMBER=2 FREQ=440 QUALITY=1 MAGNITUDE=0 MODE=0>
+</KEYFRAME>
+</PLUGIN>
+<PLUGIN TITLE=ReframeRT>
+<KEYFRAME TITLE=dave><REFRAMERT SCALE=2 DENOM=1 STRETCH=1></KEYFRAME>
+</PLUGIN>
+<PLUGIN TITLE="Sphere Cam">
+<KEYFRAME TITLE="gear360 4k"><SPHERECAM ENABLED_0=1 FOV_0=192 CENTER_X_0=2.520000e+01 CENTER_Y_0=5.179997e+01 ROTATE_X_0=100 ROTATE_Y_0=50 ROTATE_Z_0=0 ENABLED_1=1 FOV_1=1.917000e+02 CENTER_X_1=7.499998e+01 CENTER_Y_1=5.079998e+01 ROTATE_X_1=5.019999e+01 ROTATE_Y_1=4.940001e+01 ROTATE_Z_1=8.000001e-01 FEATHER=1 DRAW_GUIDES=0 MODE=1></KEYFRAME>
+<KEYFRAME TITLE="gear360 7k"><SPHERECAM ENABLED_0=1 FOV_0=194 CENTER_X_0=2.520000e+01 CENTER_Y_0=5.149998e+01 ROTATE_X_0=50 ROTATE_Y_0=50 ROTATE_Z_0=0 ENABLED_1=1 FOV_1=1.946000e+02 CENTER_X_1=7.499999e+01 CENTER_Y_1=5.129996e+01 ROTATE_X_1=0 ROTATE_Y_1=4.980000e+01 ROTATE_Z_1=1 FEATHER=1 DRAW_GUIDES=0 MODE=1></KEYFRAME>
+<KEYFRAME TITLE="gear360 sideways 4k"><SPHERECAM ENABLED_0=1 FOV_0=192 CENTER_X_0=2.530000e+01 CENTER_Y_0=5.129998e+01 ROTATE_X_0=100 ROTATE_Y_0=50 ROTATE_Z_0=90 ENABLED_1=1 FOV_1=1.917000e+02 CENTER_X_1=7.499998e+01 CENTER_Y_1=5.109998e+01 ROTATE_X_1=5.019999e+01 ROTATE_Y_1=4.980000e+01 ROTATE_Z_1=-8.889997e+01 FEATHER=1 DRAW_GUIDES=0 MODE=1></KEYFRAME>
+<KEYFRAME TITLE="gear360 sideways, 7k"><SPHERECAM ENABLED_0=1 FOV_0=194 CENTER_X_0=2.520000e+01 CENTER_Y_0=5.139998e+01 ROTATE_X_0=50 ROTATE_Y_0=50 ROTATE_Z_0=90 ENABLED_1=1 FOV_1=1.946000e+02 CENTER_X_1=7.499999e+01 CENTER_Y_1=5.079997e+01 ROTATE_X_1=0 ROTATE_Y_1=4.990000e+01 ROTATE_Z_1=-8.900002e+01 FEATHER=1 DRAW_GUIDES=0 MODE=1></KEYFRAME>
+</PLUGIN>
# install to bin
binstall: install-recursive
- cp -a COPYING README models ffmpeg msg info tips bin/.
+ cp -a COPYING README models Cinelerra_factory ffmpeg msg info tips bin/.
sed -e 's/\<cin\>/$(WANT_CIN)/g' < image/cin.desktop \
> "bin/applications/$(WANT_CIN).desktop"
cp -a image/cin.svg "bin/pixmaps/$(WANT_CIN)".svg
cd bin; $(inst_sh) "$(DESTDIR)$(WANT_CINLIB_DIR)" \
bdwrite cutads hveg2enc mpeg2enc mplex mplexlo
cd bin; $(inst_sh) "$(DESTDIR)$(datadir)/$(WANT_CIN)" \
- COPYING README models ffmpeg msg info tips doc
+ COPYING README models Cinelerra_factory ffmpeg msg info tips doc
cd bin/locale; $(inst_sh) "$(DESTDIR)$(localedir)" .
cd bin/plugins; $(inst_sh) "$(DESTDIR)$(WANT_PLUGIN_DIR)" .
cd bin/ladspa; $(inst_sh) "$(DESTDIR)$(WANT_LADSPA_DIR)" .
install:
for dir in $(SUBDIRS); do $(MAKE) -C $$dir install; done
- cp -a COPYING README models ffmpeg msg info tips bin/.
+ cp -a COPYING README models Cinelerra_factory ffmpeg msg info tips bin/.
for d in picon*; do cp -a $$d/. bin/plugins/$$d/.; done
rebuild:
$(OBJDIR)/channel.o \
$(OBJDIR)/channelpicker.o \
$(OBJDIR)/chantables.o \
- $(OBJDIR)/cicolors.o \
$(OBJDIR)/clipedit.o \
$(OBJDIR)/clippopup.o \
$(OBJDIR)/colorpicker.o \
$(OBJDIR)/pluginvclient.o \
$(OBJDIR)/preferences.o \
$(OBJDIR)/preferencesthread.o \
+ $(OBJDIR)/presets.o \
$(OBJDIR)/probeprefs.o \
$(OBJDIR)/proxy.o \
$(OBJDIR)/question.o \
#include "aautomation.h"
#include "atrack.inc"
-#include "colors.h"
+#include "bccolors.h"
#include "edl.h"
#include "edlsession.h"
#include "floatauto.h"
#include "adeviceprefs.h"
#include "audioalsa.h"
#include "audiodevice.inc"
+#include "bcsignals.h"
#include "bitspopup.h"
#include "edl.h"
#include "language.h"
+#include "mwindow.h"
#include "playbackconfig.h"
#include "preferences.h"
#include "preferencesthread.h"
#include "recordconfig.h"
+#include "theme.h"
#include <string.h>
-#define DEVICE_H 50
+//#define DEVICE_H 50
ADevicePrefs::ADevicePrefs(int x, int y, PreferencesWindow *pwindow, PreferencesDialog *dialog,
AudioOutConfig *out_config, AudioInConfig *in_config, int mode)
int ADevicePrefs::get_h(int recording)
{
- return !recording ? DEVICE_H + 30 : DEVICE_H;
+ int margin = pwindow->mwindow->theme->widget_border;
+ int result = BC_Title::calculate_h(dialog, "X", MEDIUMFONT) + margin +
+ BC_TextBox::calculate_h(dialog, MEDIUMFONT, 1, 1);
+ if( !recording ) {
+ result += BC_CheckBox::calculate_h(dialog) + margin;
+ }
+
+ return result;
}
int ADevicePrefs::delete_objects()
{
char *output_char = 0;
int *output_int = 0;
+ int margin = pwindow->mwindow->theme->widget_border;
int y1 = y;
BC_Resources *resources = BC_WindowBase::get_resources();
break;
}
dialog->add_subwindow(oss_enable[i] = new OSSEnable(x1, y1 + 20, output_int));
- x1 += oss_enable[i]->get_w() + 5;
+ x1 += oss_enable[i]->get_w() + margin;
#endif
switch(mode) {
case MODEPLAY:
dialog->add_subwindow(path_title);
}
- oss_path[i] = new ADeviceTextBox(x1, y1 + 20, output_char);
+ oss_path[i] = new ADeviceTextBox(
+ x1, y1 + path_title->get_h() + margin, output_char);
dialog->add_subwindow(oss_path[i]);
-
- x1 += oss_path[i]->get_w() + 5;
+ x1 += oss_path[i]->get_w() + margin;
if(i == 0) {
switch(mode) {
case MODEPLAY:
bits_title = new BC_Title(x1, y, _("Bits:"),
MEDIUMFONT, resources->text_default);
dialog->add_subwindow(bits_title);
- oss_bits = new BitsPopup(dialog, x1, y1 + 20, output_int,
- 0, 0, 0, 0, 1);
+ oss_bits = new BitsPopup(dialog,
+ x1, y1 + bits_title->get_h() + margin,
+ output_int, 0, 0, 0, 0, 1);
oss_bits->create_objects();
}
- x1 += oss_bits->get_w() + 5;
- y1 += DEVICE_H;
-break; // apparently, 'i' must be zero
+ x1 += oss_bits->get_w() + margin;
+// y1 += DEVICE_H;
+ break;
}
return 0;
#ifdef HAVE_ALSA
char *output_char = 0;
int *output_int = 0;
- int y1 = y;
+ int margin = pwindow->mwindow->theme->widget_border;
BC_Resources *resources = BC_WindowBase::get_resources();
- int x1 = x + menu->get_w() + 5;
+ int x1 = x + menu->get_w() + margin;
+ int y1 = y;
ArrayList<char*> *alsa_titles = new ArrayList<char*>;
alsa_titles->set_array_delete();
AudioALSA::list_devices(alsa_titles, 0, mode);
-
alsa_drivers = new ArrayList<BC_ListBoxItem*>;
for(int i = 0; i < alsa_titles->total; i++)
alsa_drivers->append(new BC_ListBoxItem(alsa_titles->values[i]));
path_title = new BC_Title(x1, y, _("Device:"),
MEDIUMFONT, resources->text_default);
dialog->add_subwindow(path_title);
- alsa_device = new ALSADevice(dialog, x1, y1 + 20, output_char, alsa_drivers);
+ y1 += path_title->get_h() + margin;
+ alsa_device = new ALSADevice(dialog,
+ x1, y1, output_char, alsa_drivers);
alsa_device->create_objects();
int x2 = x1;
bits_title = new BC_Title(x1, y, _("Bits:"),
MEDIUMFONT, resources->text_default);
dialog->add_subwindow(bits_title);
- alsa_bits = new BitsPopup(dialog, x1, y1 + 20, output_int, 0, 0, 0, 0, 1);
+ y1 = y + bits_title->get_h() + margin;
+ alsa_bits = new BitsPopup(dialog,
+ x1, y1, output_int, 0, 0, 0, 0, 1);
alsa_bits->create_objects();
- y1 += alsa_bits->get_h() + 20 + 5;
+ y1 += alsa_bits->get_h();
x1 = x2;
if(mode == MODEPLAY) {
void ADriverMenu::create_objects()
{
+#ifdef HAVE_ALSA
+ add_item(new ADriverItem(this, AUDIO_ALSA_TITLE, AUDIO_ALSA));
+#endif
+
#ifdef HAVE_OSS
add_item(new ADriverItem(this, AUDIO_OSS_TITLE, AUDIO_OSS));
add_item(new ADriverItem(this, AUDIO_OSS_ENVY24_TITLE, AUDIO_OSS_ENVY24));
#endif
-#ifdef HAVE_ALSA
- add_item(new ADriverItem(this, AUDIO_ALSA_TITLE, AUDIO_ALSA));
-#endif
-
#ifdef HAVE_ESOUND
if(!do_input) add_item(new ADriverItem(this, AUDIO_ESOUND_TITLE, AUDIO_ESOUND));
#endif
~ADevicePrefs();
void reset();
- static int get_h(int recording = 0);
+// static int get_h(int recording = 0);
+ int get_h(int recording = 0);
int update(AudioOutConfig *out_config);
// creation - set if this is the first initialize of the object
// to prevent file format from being overwritten
tiff_cmodel = 0;
tiff_compression = 0;
+ mov_sphere = 0;
+ jpeg_sphere = 0;
use_header = 1;
id = EDL::next_id();
tiff_cmodel = asset->tiff_cmodel;
tiff_compression = asset->tiff_compression;
+
+
+ mov_sphere = asset->mov_sphere;
+ jpeg_sphere = asset->jpeg_sphere;
}
int64_t Asset::get_index_offset(int channel)
interlace_fixmethod == asset.interlace_fixmethod &&
width == asset.width &&
height == asset.height &&
- !strcmp(vcodec, asset.vcodec));
+ !strcmp(vcodec, asset.vcodec) &&
+ mov_sphere == asset.mov_sphere &&
+ jpeg_sphere == asset.jpeg_sphere);
if(result && format == FILE_FFMPEG)
result = !strcmp(ff_video_options, asset.ff_video_options) &&
ff_video_bitrate == asset.ff_video_bitrate &&
file->tag.get_property("VCODEC", vcodec);
video_length = file->tag.get_property("VIDEO_LENGTH", (int64_t)0);
+ mov_sphere = file->tag.get_property("MOV_SPHERE", 0);
+ jpeg_sphere = file->tag.get_property("JPEG_SPHERE", 0);
single_frame = file->tag.get_property("SINGLE_FRAME", (int64_t)0);
interlace_autofixoption = file->tag.get_property("INTERLACE_AUTOFIX",0);
file->tag.set_property("VCODEC", vcodec);
file->tag.set_property("VIDEO_LENGTH", video_length);
+ file->tag.set_property("MOV_SPHERE", mov_sphere);
+ file->tag.set_property("JPEG_SPHERE", jpeg_sphere);
file->tag.set_property("SINGLE_FRAME", single_frame);
file->tag.set_property("INTERLACE_AUTOFIX", interlace_autofixoption);
tiff_cmodel = GET_DEFAULT("TIFF_CMODEL", tiff_cmodel);
tiff_compression = GET_DEFAULT("TIFF_COMPRESSION", tiff_compression);
+ mov_sphere = GET_DEFAULT("MOV_SPHERE", mov_sphere);
+ jpeg_sphere = GET_DEFAULT("JPEG_SPHERE", jpeg_sphere);
boundaries();
}
UPDATE_DEFAULT("EXR_COMPRESSION", exr_compression);
UPDATE_DEFAULT("TIFF_CMODEL", tiff_cmodel);
UPDATE_DEFAULT("TIFF_COMPRESSION", tiff_compression);
+
+
+
+ UPDATE_DEFAULT("MOV_SPHERE", mov_sphere);
+ UPDATE_DEFAULT("JPEG_SPHERE", jpeg_sphere);
}
+
+
+
if(do_bits)
{
UPDATE_DEFAULT("BITS", bits);
video_data, layers, program, frame_rate, width, height,
vcodec, aspect_ratio,string);
fprintf(fp," video_length %jd repeat %d\n", video_length, single_frame);
+ printf(" mov_sphere=%d jpeg_sphere=%d\n", mov_sphere, jpeg_sphere);
return 0;
}
char vcodec[BCTEXTLEN];
// Length in frames
+// -1 means a still photo
int64_t video_length;
int ac3_bitrate;
+// Insert tag for spherical playback
+ int mov_sphere, jpeg_sphere;
+
// Image file sequences. Background rendering doesn't want to write a
// sequence header but instead wants to start the sequence numbering at a certain
// number. This ensures deletion of all the frames which aren't being used.
int AssetPopupInfo::handle_event()
{
int cur_x, cur_y;
- popup->gui->get_abs_cursor_xy(cur_x, cur_y, 0);
-
- if( mwindow->session->drag_assets->total ) {
- mwindow->awindow->asset_edit->edit_asset(
+ popup->gui->get_abs_cursor_xy(cur_x, cur_y);
+ if( mwindow->session->drag_assets->size() ) {
+ AssetEdit *asset_edit = mwindow->awindow->get_asset_editor();
+ asset_edit->edit_asset(
mwindow->session->drag_assets->values[0], cur_x, cur_y);
}
- else
- if( mwindow->session->drag_clips->total ) {
+ else if( mwindow->session->drag_clips->size() ) {
popup->gui->awindow->clip_edit->edit_clip(
mwindow->session->drag_clips->values[0], cur_x, cur_y);
}
return 0;
}
+void ATrack::deglitch(double position,
+ int edit_labels, int edit_plugins, int edit_autos)
+{
+ int64_t samples = to_units(position, 0);
+ edits->deglitch(samples);
+ if( edit_plugins ) {
+ for(int i = 0; i < plugin_set.size(); i++) {
+ plugin_set.get(i)->deglitch(samples);
+ }
+ }
+}
+
int modify_handles(int64_t oldposition, int64_t newposition, int currentend);
+ void deglitch(double position,
+ int edit_labels,
+ int edit_plugins,
+ int edit_autos);
int64_t length();
// int get_dimensions(double &view_start,
AudioConfig::AudioConfig()
{
+ audio_in_driver = AUDIO_ALSA;
+ afirewire_in_port = 0;
+ afirewire_in_channel = 63;
+ strcpy(oss_in_device, "/dev/dsp");
+ oss_in_channels = 2;
+ oss_in_bits = 16;
+ strcpy(esound_in_server, "");
+ esound_in_port = 0;
+
+ audio_out_driver = AUDIO_ALSA;
+ strpcy(oss_out_device, "/dev/dsp");
+ oss_out_channels = 2;
+ oss_out_bits = 16;
+ strpcy(esound_out_server, "");
+ esound_out_port = 0;
+
+ audio_duplex_driver = AUDIO_ALSA;
+ strcpy(oss_duplex_device, "/dev/dsp");
+ oss_duplex_channels = 2;
+ oss_duplex_bits = 16;
+ strcpy(esound_duplex_server, "");
+ esound_duplex_port = 0;
}
AudioConfig::~AudioConfig()
int AudioConfig::load_defaults(BC_Hash *defaults)
{
- audio_in_driver = defaults->get("AUDIOINDRIVER", AUDIO_OSS);
+ audio_in_driver = defaults->get("AUDIOINDRIVER", AUDIO_ALSA);
afirewire_in_port = defaults->get("AFIREWIRE_IN_PORT", 0);
afirewire_in_channel = defaults->get("AFIREWIRE_IN_CHANNEL", 63);
sprintf(oss_in_device, "/dev/dsp");
defaults->get("ESOUND_IN_SERVER", esound_in_server);
esound_in_port = defaults->get("ESOUND_IN_PORT", 0);
- audio_out_driver = defaults->get("AUDIO_OUT_DRIVER", AUDIO_OSS);
- audio_duplex_driver = defaults->get("AUDIO_DUPLEX_DRIVER", AUDIO_OSS);
+ audio_out_driver = defaults->get("AUDIO_OUT_DRIVER", AUDIO_ALSA);
+ audio_duplex_driver = defaults->get("AUDIO_DUPLEX_DRIVER", AUDIO_ALSA);
sprintf(oss_out_device, "/dev/dsp");
defaults->get("OSS_OUT_DEVICE", oss_out_device);
oss_out_channels = defaults->get("OUT_CHANNELS", 2);
defaults->get("ESOUND_OUT_SERVER", esound_out_server);
esound_out_port = defaults->get("ESOUND_OUT_PORT", 0);
- audio_duplex_driver = defaults->get("AUDIO_DUPLEX_DRIVER", AUDIO_OSS);
+ audio_duplex_driver = defaults->get("AUDIO_DUPLEX_DRIVER", AUDIO_ALSA);
sprintf(oss_duplex_device, "/dev/dsp");
defaults->get("OSS_DUPLEX_DEVICE", oss_duplex_device);
oss_duplex_channels = defaults->get("DUPLEX_CHANNELS", 2);
#include "autos.h"
#include "atrack.inc"
#include "bcsignals.h"
-#include "colors.h"
+#include "bccolors.h"
#include "edl.h"
#include "edlsession.h"
#include "filexml.h"
this->mwindow = mwindow;
current_folder[0] = 0;
asset_remove = 0;
- asset_edit = 0;
clip_edit = 0;
label_edit = 0;
}
gui->unlock_window();
}
Thread::join();
+ asset_editors.remove_all_objects();
delete asset_remove;
- delete asset_edit;
delete label_edit;
delete clip_edit;
delete effect_tip;
gui->create_objects();
gui->async_update_assets();
asset_remove = new AssetRemoveThread(mwindow);
- asset_edit = new AssetEdit(mwindow);
clip_edit = new ClipEdit(mwindow, this, 0);
label_edit = new LabelEdit(mwindow, this, 0);
effect_tip = new EffectTipDialog(mwindow, this);
}
+AssetEdit *AWindow::get_asset_editor()
+{
+ AssetEdit *asset_edit = 0;
+ for( int i=0; !asset_edit && i<asset_editors.size(); ++i ) {
+ AssetEdit *thread = asset_editors[i];
+ if( !thread->running() ) asset_edit = thread;
+ }
+ if( !asset_edit ) {
+ asset_edit = new AssetEdit(mwindow);
+ asset_editors.append(asset_edit);
+ }
+ return asset_edit;
+}
+
+
void AWindow::run()
{
gui->run_window();
#ifndef AWINDOW_H
#define AWINDOW_H
+#include "arraylist.h"
#include "assetedit.inc"
#include "assetremove.inc"
#include "awindowgui.inc"
void run();
void create_objects();
+ AssetEdit *get_asset_editor();
int load_defaults(BC_Hash *defaults);
int save_defaults(BC_Hash *defaults);
AWindowGUI *gui;
MWindow *mwindow;
- AssetEdit *asset_edit;
+ ArrayList<AssetEdit*> asset_editors;
AssetRemoveThread *asset_remove;
ClipEdit *clip_edit;
LabelEdit *label_edit;
return 1;
}
-AWindowInfo::AWindowInfo(MWindow *mwindow, AWindowGUI *gui, int x, int y)
- : BC_Button(x, y, mwindow->theme->infoasset_data)
-{
- this->mwindow = mwindow;
- this->gui = gui;
- set_tooltip(_("Edit information on asset"));
-}
-
-int AWindowInfo::handle_event()
-{
- int cur_x, cur_y;
- gui->get_abs_cursor_xy(cur_x, cur_y, 0);
- gui->awindow->asset_edit->edit_asset(gui->selected_asset(), cur_x, cur_y);
- return 1;
-}
+// AWindowInfo::AWindowInfo(MWindow *mwindow, AWindowGUI *gui, int x, int y)
+// : BC_Button(x, y, mwindow->theme->infoasset_data)
+// {
+// this->mwindow = mwindow;
+// this->gui = gui;
+// set_tooltip(_("Edit information on asset"));
+// }
+//
+// int AWindowInfo::handle_event()
+// {
+// int cur_x, cur_y;
+// gui->get_abs_cursor_xy(cur_x, cur_y, 0);
+// gui->awindow->asset_edit->edit_asset(gui->selected_asset(), cur_x, cur_y);
+// return 1;
+// }
AWindowRedrawIndex::AWindowRedrawIndex(MWindow *mwindow, AWindowGUI *gui, int x, int y)
: BC_Button(x, y, mwindow->theme->redrawindex_data)
return 1;
}
-
oldest = current;
}
if( oldest && oldest->position >= 0 ) {
+ result = oldest->get_size();
del_item(oldest);
- result = 1;
}
lock->unlock();
return result;
// Called when done with the item returned by get_.
// Ignore if item was 0.
void unlock();
-// delete oldest member, returns 1 if item deleted or 0 if none found
+// Delete oldest item.
+// Return number of bytes freed if successful. Return 0 if nothing to delete.
int delete_oldest();
// Calculate current size of cache in bytes
int64_t get_memory_usage();
/*
* CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
float &canvas_x1, float &canvas_y1, float &canvas_x2, float &canvas_y2,
int canvas_w, int canvas_h)
{
-// printf("Canvas::get_transfers %d %d\n", canvas_w,
-// canvas_h);
+//printf("Canvas::get_transfers %d canvas_w=%d canvas_h=%d\n",
+// __LINE__, canvas_w, canvas_h);
// automatic canvas size detection
if(canvas_w < 0) canvas_w = get_canvas()->get_w();
if(canvas_h < 0) canvas_h = get_canvas()->get_h();
{
out_h = (int)(out_w / edl->get_aspect_ratio() + 0.5);
canvas_y1 = canvas_h / 2 - out_h / 2;
+// printf("Canvas::get_transfers %d canvas_h=%d out_h=%f canvas_y1=%f\n",
+// __LINE__,
+// canvas_h,
+// out_h,
+// canvas_y1);
}
canvas_x2 = canvas_x1 + out_w;
canvas_y2 = canvas_y1 + out_h;
canvas_y1 = MAX(0, canvas_y1);
canvas_x2 = MAX(canvas_x1, canvas_x2);
canvas_y2 = MAX(canvas_y1, canvas_y2);
-// printf("Canvas::get_transfers 2 %f,%f %f,%f -> %f,%f %f,%f\n",
+// printf("Canvas::get_transfers %d %f,%f %f,%f -> %f,%f %f,%f\n",
+// __LINE__,
// output_x1,
// output_y1,
// output_x2,
if( refresh_frame &&
(refresh_frame->get_w() != device->out_w ||
- refresh_frame->get_h() != device->out_h ||
- refresh_frame->get_color_model() != best_color_model) ) {
+ refresh_frame->get_h() != device->out_h ) ) {
+// x11 direct render uses BC_BGR8888, use tranfer_from to remap
delete refresh_frame; refresh_frame = 0;
}
get_canvas()->lock_window(" Canvas::output_refresh");
}
else
- refresh_frame->copy_from(output_frame);
+ refresh_frame->transfer_from(output_frame);
}
}
ChannelScan::ChannelScan(MWindow *mwindow)
- : BC_MenuItem(_("Scan..."), _("Shift-S"), 'S')
+ : BC_MenuItem(_("Scan..."), _("Ctrl-Alt-s"), 's')
{
- set_shift();
+ set_ctrl();
+ set_alt();
this->mwindow = mwindow;
}
popup->gui->get_abs_cursor_xy(cur_x, cur_y, 0);
if( mwindow->session->drag_assets->total ) {
- mwindow->awindow->asset_edit->edit_asset(
+ AssetEdit *asset_edit = mwindow->awindow->get_asset_editor();
+ asset_edit->edit_asset(
mwindow->session->drag_assets->values[0], cur_x, cur_y);
}
else
#include "bcbutton.h"
#include "bccapture.h"
+#include "bccolors.h"
#include "bcdisplayinfo.h"
#include "colorpicker.h"
#include "condition.h"
#include "language.h"
#include "mutex.h"
#include "mwindow.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "vframe.h"
#include <string.h>
if(mwindow->session->drag_assets->total)
{
mwindow->gui->lock_window("CWindowGUI::drag_stop 1");
- mwindow->clear(0);
+ mwindow->clear(0, 1);
mwindow->load_assets(mwindow->session->drag_assets,
mwindow->edl->local_session->get_selectionstart(),
LOADMODE_PASTE,
if(mwindow->session->drag_clips->total)
{
mwindow->gui->lock_window("CWindowGUI::drag_stop 2");
- mwindow->clear(0);
+ mwindow->clear(0, 1);
mwindow->paste_edls(mwindow->session->drag_clips,
LOADMODE_PASTE,
mwindow->session->track_highlighted,
float blue = (float)*row++ / max; \
if(do_yuv) \
{ \
- mwindow->edl->local_session->red += red + V_TO_R * (blue - 0.5); \
- mwindow->edl->local_session->green += red + U_TO_G * (green - 0.5) + V_TO_G * (blue - 0.5); \
- mwindow->edl->local_session->blue += red + U_TO_B * (green - 0.5); \
+ float r = red + V_TO_R * (blue - 0.5); \
+ float g = red + U_TO_G * (green - 0.5) + V_TO_G * (blue - 0.5); \
+ float b = red + U_TO_B * (green - 0.5); \
+ mwindow->edl->local_session->red += r; \
+ mwindow->edl->local_session->green += g; \
+ mwindow->edl->local_session->blue += b; \
+ if(r > mwindow->edl->local_session->red_max) mwindow->edl->local_session->red_max = r; \
+ if(g > mwindow->edl->local_session->green_max) mwindow->edl->local_session->green_max = g; \
+ if(b > mwindow->edl->local_session->blue_max) mwindow->edl->local_session->blue_max = b; \
} \
else \
{ \
mwindow->edl->local_session->red += red; \
mwindow->edl->local_session->green += green; \
mwindow->edl->local_session->blue += blue; \
+ if(red > mwindow->edl->local_session->red_max) mwindow->edl->local_session->red_max = red; \
+ if(green > mwindow->edl->local_session->green_max) mwindow->edl->local_session->green_max = green; \
+ if(blue > mwindow->edl->local_session->blue_max) mwindow->edl->local_session->blue_max = blue; \
} \
}
mwindow->edl->local_session->red = 0;
mwindow->edl->local_session->green = 0;
mwindow->edl->local_session->blue = 0;
+ mwindow->edl->local_session->red_max = 0;
+ mwindow->edl->local_session->green_max = 0;
+ mwindow->edl->local_session->blue_max = 0;
for(int i = row1; i < row2; i++)
{
for(int j = column1; j < column2; j++)
-
/*
* CINELERRA
- * Copyright (C) 2008-2014 Adam Williams <broadcast at earthling dot net>
+ * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <stdint.h>
#include "automation.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "clip.h"
#include "condition.h"
#include "cpanel.h"
CWindowEyedropGUI::CWindowEyedropGUI(MWindow *mwindow, CWindowTool *thread)
- : CWindowToolGUI(mwindow, thread, _(PROGRAM_NAME ": Color"), 220, 250)
+ : CWindowToolGUI(mwindow, thread, _(PROGRAM_NAME ": Color"), 220, 290)
{
}
y = title6->get_y() + this->v->get_h() + 2*margin;
add_subwindow(sample = new BC_SubWindow(x, y, 50, 50));
+ y += sample->get_h() + margin;
+ add_subwindow(use_max = new CWindowEyedropCheckBox(mwindow, this, x, y));
update();
unlock_window();
}
radius->update((int64_t)mwindow->edl->session->eyedrop_radius);
- float r = mwindow->edl->local_session->red;
- float g = mwindow->edl->local_session->green;
- float b = mwindow->edl->local_session->blue;
- red->update(r);
- green->update(g);
- blue->update(b);
+ LocalSession *local_session = mwindow->edl->local_session;
+ int use_max = local_session->use_max;
+ float r = use_max ? local_session->red_max : local_session->red;
+ float g = use_max ? local_session->green_max : local_session->green;
+ float b = use_max ? local_session->blue_max : local_session->blue;
+ this->red->update(r);
+ this->green->update(g);
+ this->blue->update(b);
+
int rx = 255*r + 0.5; bclamp(rx,0,255);
int gx = 255*g + 0.5; bclamp(gx,0,255);
int bx = 255*b + 0.5; bclamp(bx,0,255);
char rgb_text[BCSTRLEN];
sprintf(rgb_text, "#%02x%02x%02x", rx, gx, bx);
rgb_hex->update(rgb_text);
-
+
float y, u, v;
- YUV::rgb_to_yuv_f(mwindow->edl->local_session->red,
- mwindow->edl->local_session->green,
- mwindow->edl->local_session->blue,
- y, u, v);
+ YUV::rgb_to_yuv_f(r, g, b, y, u, v);
this->y->update(y);
this->u->update(u); u += 0.5;
this->v->update(v); v += 0.5;
+
int yx = 255*y + 0.5; bclamp(yx,0,255);
int ux = 255*u + 0.5; bclamp(ux,0,255);
int vx = 255*v + 0.5; bclamp(vx,0,255);
}
+CWindowEyedropCheckBox::CWindowEyedropCheckBox(MWindow *mwindow,
+ CWindowEyedropGUI *gui, int x, int y)
+ : BC_CheckBox(x, y, mwindow->edl->local_session->use_max, _("Use maximum"))
+{
+ this->mwindow = mwindow;
+ this->gui = gui;
+}
+
+int CWindowEyedropCheckBox::handle_event()
+{
+ mwindow->edl->local_session->use_max = get_value();
+
+ gui->update();
+ return 1;
+}
+
+
CWindowCameraGUI::CWindowCameraGUI(MWindow *mwindow, CWindowTool *thread)
: CWindowToolGUI(mwindow,
thread,
};
-
+class CWindowEyedropCheckBox;
class CWindowEyedropGUI : public CWindowToolGUI
{
public:
BC_Title *current;
CWindowCoord *radius;
+ CWindowEyedropCheckBox *use_max;
BC_Title *red, *green, *blue, *y, *u, *v;
BC_Title *rgb_hex, *yuv_hex;
BC_SubWindow *sample;
};
+class CWindowEyedropCheckBox : public BC_CheckBox
+{
+public:
+ CWindowEyedropCheckBox(MWindow *mwindow,
+ CWindowEyedropGUI *gui,
+ int x,
+ int y);
+
+ int handle_event();
+ MWindow *mwindow;
+ CWindowEyedropGUI *gui;
+};
+
+
class CWindowCameraGUI : public CWindowToolGUI
{
next->startproject += cut_length;
next->startsource += cut_length;
next->length -= cut_length;
-//printf("Edit::shift_end_out 2 %d\n", cut_length);
+//printf("Edit::shift_end_out %d cut_length=%d\n", __LINE__, cut_length);
}
else
{
+//printf("Edit::shift_end_out %d cut_length=%d next->length=%d\n", __LINE__, cut_length, next->length);
cut_length = next->length;
+ next->startproject += next->length;
+ next->startsource += next->length;
next->length = 0;
length += cut_length;
+//track->dump();
}
}
else
/*
* CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
else
{
// move end of edit out
-//printf("Edits::modify_handle 6\n");
+//printf("Edits::modify_handle %d edit_mode=%d\n", __LINE__, edit_mode);
current_edit->shift_end_out(edit_mode,
track->to_units(newposition, 0),
track->to_units(oldposition, 0),
track->shift_effects(position, length, edit_autos);
}
+// only used for audio but also used for plugins which inherit from Edits
+void Edits::deglitch(int64_t position)
+{
+// range from the splice junk appears
+ int64_t threshold = (int64_t)((double)edl->session->sample_rate /
+ edl->session->frame_rate) / 2;
+ Edit *current = 0;
+
+// the last edit before the splice
+ Edit *edit1 = 0;
+ if(first)
+ {
+ for(current = first; current; current = NEXT)
+ {
+ if(current->startproject + current->length >= position - threshold)
+ {
+ edit1 = current;
+ break;
+ }
+ }
+
+// ignore if it ends after the splice
+ if(current && current->startproject + current->length >= position)
+ {
+ edit1 = 0;
+ }
+ }
+
+// the first edit after the splice
+ Edit *edit2 = 0;
+ if(last)
+ {
+ for(current = last; current; current = PREVIOUS)
+ {
+ if(current->startproject < position + threshold)
+ {
+ edit2 = current;
+ break;
+ }
+ }
+
+ // ignore if it starts before the splice
+ if(current && current->startproject < position)
+ {
+ edit2 = 0;
+ }
+ }
+
+
+
+
+// printf("Edits::deglitch %d position=%ld edit1=%p edit2=%p\n", __LINE__,
+// position,
+// edit1,
+// edit2);
+// delete junk between the edits
+ if(edit1 != edit2)
+ {
+ if(edit1 != 0)
+ {
+// end the starting edit later
+ current = edit1->next;
+ while(current != 0 &&
+ current != edit2 &&
+ current->startproject < position)
+ {
+ Edit* next = NEXT;
+
+ edit1->length += current->length;
+ remove(current);
+
+ current = next;
+ }
+ }
+
+ if(edit2 != 0)
+ {
+// start the ending edit earlier
+ current = edit2->previous;
+ while(current != 0 &&
+ current != edit1 &&
+ current->startproject >= position)
+ {
+ Edit *previous = PREVIOUS;
+
+ int64_t length = current->length;
+//printf("Edits::deglitch %d length=%ld\n", __LINE__, length);
+ if(!edit2->silence() &&
+ length > edit2->startsource)
+ {
+ length = edit2->startsource;
+ }
+
+ // shift edit2 by using material from its source
+ edit2->startproject -= length;
+ edit2->startsource -= length;
+ // assume enough is at the end
+ edit2->length += length;
+
+ // shift edit2 & its source earlier by remainder
+ if(length < current->length)
+ {
+ int64_t remainder = current->length - length;
+ edit2->startproject -= remainder;
+ // assume enough is at the end
+ edit2->length += remainder;
+ }
+
+ remove(current);
+
+
+ current = previous;
+ }
+ }
+ }
+
+}
+
+
+
+
int edit_plugins,
int edit_autos,
Edits *trim_edits);
+ void deglitch(int64_t position);
virtual int optimize();
virtual int clone_derived(Edit* new_edit, Edit* old_edit) { return 0; }
}
}
+void EDL::deglitch(double position)
+{
+ if( !session->cursor_on_frames ) return;
+ Track *current_track = tracks->first;
+ for( ; current_track; current_track=current_track->next ) {
+ if( !current_track->record ) continue;
+ if( current_track->data_type != TRACK_AUDIO ) continue;
+ ATrack *atrack = (ATrack*)current_track;
+ atrack->deglitch(position,
+ session->labels_follow_edits,
+ session->plugins_follow_edits,
+ session->autos_follow_edits);
+ }
+}
-int EDL::clear(double start,
- double end,
- int clear_labels,
- int clear_plugins,
- int edit_autos)
+int EDL::clear(double start, double end,
+ int clear_labels, int clear_plugins, int edit_autos)
{
if(start == end)
{
int clear_labels,
int clear_plugins,
int edit_autos);
+ void deglitch(double position);
// Insert the asset at a point in the EDL
void insert_asset(Asset *asset,
EDL *nested_edl,
#define EDIT_HANDLE_MODES 3
// Behavior for the edit handles based on mouse button
-#define MOVE_ALL_EDITS 0
-#define MOVE_ONE_EDIT 1
-#define MOVE_NO_EDITS 2
+#define MOVE_ALL_EDITS 0 // default for left button
+#define MOVE_ONE_EDIT 1 // default for middle button
+#define MOVE_NO_EDITS 2 // default for right button
#define MOVE_EDITS_DISABLED 3
// AWindow folders
record_write_length = 131072;
record_realtime_toc = 1;
- safe_regions = 0;
+ safe_regions = 0;
sample_rate = 48000;
- scrub_speed = 2.;
- show_assets = 1;
- show_titles = 1;
+ scrub_speed = 2.;
+ show_assets = 1;
+ show_titles = 1;
test_playback_edits = 1;
time_format = TIME_HMSF;
- nudge_format = 1;
- tool_window = 0;
+ nudge_format = 1;
+ tool_window = 0;
for(int i = 0; i < MAXCHANNELS; i++) {
vchannel_x[i] = 64*i;
vchannel_y[i] = 0;
aconfig_in = new AudioInConfig;
vconfig_in = new VideoInConfig;
recording_format = new Asset;
- video_every_frame = 0;
- video_asynchronous = 0;
+ video_every_frame = 0;
+// video_asynchronous = 0;
video_tracks = 1;
video_write_length = 30;
- view_follows_playback = 1;
- vwindow_meter = 0;
- vwindow_zoom = 1.;
+ view_follows_playback = 1;
+ vwindow_meter = 0;
+ vwindow_zoom = 1.;
playback_config = new PlaybackConfig;
}
return ((playback_preload != ptr->playback_preload) ||
(interpolation_type != ptr->interpolation_type) ||
(video_every_frame != ptr->video_every_frame) ||
- (video_asynchronous != ptr->video_asynchronous) ||
+// (video_asynchronous != ptr->video_asynchronous) ||
(real_time_playback != ptr->real_time_playback) ||
(playback_software_position != ptr->playback_software_position) ||
(test_playback_edits != ptr->test_playback_edits) ||
(decode_subtitles != ptr->decode_subtitles) ||
(subtitle_number != ptr->subtitle_number) ||
(interpolate_raw != ptr->interpolate_raw) ||
- (white_balance_raw != ptr->white_balance_raw));
+ (white_balance_raw != ptr->white_balance_raw) ||
+ (proxy_scale != ptr->proxy_scale) ||
+ (proxy_use_scaler != ptr->proxy_use_scaler));
}
void EDLSession::equivalent_output(EDLSession *session, double *result)
}
video_channels = defaults->get("VCHANNELS", video_channels);
video_every_frame = defaults->get("VIDEO_EVERY_FRAME", 0);
- video_asynchronous = defaults->get("VIDEO_ASYNCHRONOUS", 0);
+// video_asynchronous = defaults->get("VIDEO_ASYNCHRONOUS", 0);
video_tracks = defaults->get("VTRACKS", video_tracks);
video_write_length = defaults->get("VIDEO_WRITE_LENGTH", 30);
view_follows_playback = defaults->get("VIEW_FOLLOWS_PLAYBACK", 1);
defaults->update("SAFE_REGIONS", safe_regions);
defaults->update("SAMPLERATE", sample_rate);
defaults->update("SCRUB_SPEED", scrub_speed);
- defaults->update("SI_USEDURATION",si_useduration);
+ defaults->update("SI_USEDURATION",si_useduration);
defaults->update("SI_DURATION",si_duration);
defaults->update("SHOW_ASSETS", show_assets);
defaults->update("SHOW_TITLES", show_titles);
}
defaults->update("VCHANNELS", video_channels);
defaults->update("VIDEO_EVERY_FRAME", video_every_frame);
- defaults->update("VIDEO_ASYNCHRONOUS", video_asynchronous);
+// defaults->update("VIDEO_ASYNCHRONOUS", video_asynchronous);
defaults->update("VTRACKS", video_tracks);
defaults->update("VIDEO_WRITE_LENGTH", video_write_length);
defaults->update("VIEW_FOLLOWS_PLAYBACK", view_follows_playback);
file->tag.set_property("COLORMODEL", string);
ilacemode_to_xmltext(string, interlace_mode);
file->tag.set_property("INTERLACE_MODE",string);
- file->tag.set_property("CHANNELS", video_channels);
+ file->tag.set_property("CHANNELS", video_channels);
for(int i = 0; i < video_channels; i++)
{
sprintf(string, "VCHANNEL_X_%d", i);
video_channels = session->video_channels;
*vconfig_in = *session->vconfig_in;
video_every_frame = session->video_every_frame;
- video_asynchronous = session->video_asynchronous;
+// video_asynchronous = session->video_asynchronous;
video_tracks = session->video_tracks;
video_write_length = session->video_write_length;
view_follows_playback = session->view_follows_playback;
// play every frame
int video_every_frame;
// decode video asynchronously
- int video_asynchronous;
+// int video_asynchronous;
int video_tracks;
// number of frames to write to disk at a time during video recording.
int video_write_length;
if( decoder->capabilities & AV_CODEC_CAP_DR1 )
avctx->flags |= CODEC_FLAG_EMU_EDGE;
avcodec_parameters_to_context(avctx, st->codecpar);
+ if( !av_dict_get(copts, "threads", NULL, 0) )
+ avctx->thread_count = ffmpeg->ff_cpus();
ret = avcodec_open2(avctx, decoder, &copts);
}
if( ret >= 0 ) {
av_dict_set(&sopts, "cin_bitrate", 0, 0);
av_dict_set(&sopts, "cin_quality", 0, 0);
+ if( !av_dict_get(sopts, "threads", NULL, 0) )
+ ctx->thread_count = ff_cpus();
ret = avcodec_open2(ctx, codec, &sopts);
if( ret >= 0 ) {
ret = avcodec_parameters_from_context(st->codecpar, ctx);
}
if( ret >= 0 ) {
avcodec_parameters_to_context(avctx, st->codecpar);
+ if( !av_dict_get(copts, "threads", NULL, 0) )
+ avctx->thread_count = ff_cpus();
ret = avcodec_open2(avctx, decoder, &copts);
}
av_dict_free(&copts);
#include "samples.h"
#include "vframe.h"
+//static int temp_debug = 0;
//suppress noref warning
void *vorbis0_ov_callbacks[] = {
&OV_CALLBACKS_DEFAULT, &OV_CALLBACKS_NOCLOSE,
format_completion->unlock();
}
- if( temp_frame ) delete temp_frame;
-
+ if( temp_frame ) {
+//printf("File::~File %d temp_debug=%d\n", __LINE__, --temp_debug);
+ delete temp_frame;
+ }
close_file(0);
this->white_balance_raw = value;
}
-
void File::set_cache_frames(int value)
{
// caching only done locally
int File::delete_oldest()
{
-// caching only done locally
+// return the number of bytes freed
return frame_cache->delete_oldest();
}
this->wr = wr;
file = 0;
- if( debug ) printf("File::open_file %d\n", __LINE__);
-
if( debug ) printf("File::open_file %p %d\n", this, __LINE__);
switch( this->asset->format ) {
const int debug = 0;
//printf("File::read_frame pos=%jd cache=%d 1frame=%d\n",
// current_frame, use_cache, asset->single_frame);
- if( debug ) PRINT_TRACE
-
-//printf("File::read_frame %d\n", __LINE__);
-
if( video_thread && !is_thread ) return video_thread->read_frame(frame);
-
-//printf("File::read_frame %d\n", __LINE__);
- if( debug ) PRINT_TRACE
if( !file ) return 1;
if( debug ) PRINT_TRACE
int result = 0;
int advance_position = 1;
int cache_active = use_cache || asset->single_frame ? 1 : 0;
int64_t cache_position = !asset->single_frame ? current_frame : -1;
+
// Test cache
if( cache_active && frame_cache->get_frame(frame, cache_position,
current_layer, asset->frame_rate) ) {
// Need temp
else if( frame->get_color_model() != BC_COMPRESSED &&
(supported_colormodel != frame->get_color_model() ||
- frame->get_w() != asset->width ||
- frame->get_h() != asset->height) ) {
+ (!file->can_scale_input() &&
+ (frame->get_w() != asset->width ||
+ frame->get_h() != asset->height))) ) {
// printf("File::read_frame %d\n", __LINE__);
// Can't advance position here because it needs to be added to cache
}
}
-// printf("File::read_frame %d\n", __LINE__);
if( !temp_frame ) {
- temp_frame = new VFrame(0,
- -1,
- asset->width,
- asset->height,
- supported_colormodel,
- -1);
+ temp_frame = new VFrame(asset->width, asset->height, supported_colormodel);
}
// printf("File::read_frame %d\n", __LINE__);
return 0;
}
-int File::can_copy_from(Asset *asset,
- int64_t position,
- int output_w,
- int output_h)
+int File::can_copy_from(Asset *asset, int64_t position, int output_w, int output_h)
{
if( asset && file ) {
return asset->width == output_w &&
// to delete the file object. Otherwise we'd delete just the cached frames
// while the list of open files grew.
void set_cache_frames(int value);
-// Delete frame cache. Return 0 if successful. Return 1 if
-// nothing to delete.
+// Delete oldest frame from cache.
+// Return number of bytes freed if successful.
+// Return 0 if nothing to delete.
int purge_cache();
// Delete oldest frame from cache. Return 0 if successful. Return 1 if
// nothing to delete.
virtual int colormodel_supported(int colormodel) { return BC_RGB888; }
// This file can copy compressed frames directly from the asset
virtual int can_copy_from(Asset *asset, int64_t position) { return 0; }
+ virtual int can_scale_input() { return 0; }
virtual int get_render_strategy(ArrayList<int>* render_strategies) { return VRENDER_VPIXEL; }
// Manages an audio history buffer
int FileFFMPEG::get_best_colormodel(Asset *asset, int driver)
{
switch(driver) {
- case PLAYBACK_X11:
- return BC_RGB888;
- case PLAYBACK_X11_XV:
- case PLAYBACK_ASYNCHRONOUS:
- return BC_YUV888;
- case PLAYBACK_X11_GL:
- return BC_YUV888;
- case PLAYBACK_DV1394:
- case PLAYBACK_FIREWIRE:
- return BC_YUV422P;
- case VIDEO4LINUX2:
- return BC_RGB888;
- case VIDEO4LINUX2JPEG:
- return BC_COMPRESSED;
- case CAPTURE_DVB:
- case VIDEO4LINUX2MPEG:
- return BC_YUV422P;
- case CAPTURE_JPEG_WEBCAM:
- return BC_COMPRESSED;
- case CAPTURE_YUYV_WEBCAM:
- return BC_YUV422;
- case CAPTURE_FIREWIRE:
- case CAPTURE_IEC61883:
- return BC_YUV422P;
+// the direct X11 color model requires scaling in the codec
+ case PLAYBACK_X11: return BC_BGR8888;
+// case PLAYBACK_X11: return BC_RGB888;
+ case PLAYBACK_X11_GL: return BC_RGB888;
}
- return BC_RGB888;
+ return BC_YUV420P;
}
int FileFFMPEG::can_render(const char *fformat, const char *type)
int write_frames(VFrame ***frames,int len);
int read_samples(double *buffer,int64_t len);
int read_frame(VFrame *frame);
+ int can_scale_input() { return 1; }
int64_t get_memory_usage(void);
int colormodel_supported(int colormodel);
static int get_best_colormodel(Asset *asset, int driver);
frame->get_color_model(),
1);
+// insert spherical tag
+ if(asset->jpeg_sphere)
+ {
+ const char *sphere_tag =
+ "http://ns.adobe.com/xap/1.0/\x00<?xpacket begin='\xef\xbb\xbf' id='W5M0MpCehiHzreSzNTczkc9d'?>\n"
+ "<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::Cinelerra'>\n"
+ "<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>\n"
+ "\n"
+ " <rdf:Description rdf:about=''\n"
+ " xmlns:GPano='http://ns.google.com/photos/1.0/panorama/'>\n"
+ " <GPano:ProjectionType>equirectangular</GPano:ProjectionType>\n"
+ " </rdf:Description>\n"
+ "</rdf:RDF>\n"
+ "</x:xmpmeta>\n"
+ "<?xpacket end='w'?>";
+
+// calculate length by skipping the \x00 byte
+ int skip = 32;
+ int tag_len = strlen(sphere_tag + skip) + skip;
+ int tag_len2 = tag_len + 2;
+ int tag_len3 = tag_len + 4;
+
+ data->allocate_compressed_data(
+ mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor) + tag_len3);
+ data->set_compressed_size(
+ mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor) + tag_len3);
+
+ int jfif_size = 0x14;
+ uint8_t *ptr = data->get_data();
+ memcpy(ptr,
+ mjpeg_output_buffer((mjpeg_t*)jpeg_unit->compressor),
+ jfif_size);
+ ptr += jfif_size;
+ *ptr++ = 0xff;
+ *ptr++ = 0xe1;
+ *ptr++ = (tag_len2 >> 8) & 0xff;
+ *ptr++ = tag_len2 & 0xff;
+ memcpy(ptr,
+ sphere_tag,
+ tag_len);
+ ptr += tag_len;
+ memcpy(ptr,
+ mjpeg_output_buffer((mjpeg_t*)jpeg_unit->compressor) + jfif_size,
+ mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor) - jfif_size);
+ }
+ else
+ {
+ data->allocate_compressed_data(mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor));
+ data->set_compressed_size(mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor));
+ memcpy(data->get_data(),
+ mjpeg_output_buffer((mjpeg_t*)jpeg_unit->compressor),
+ mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor));
+ }
data->allocate_compressed_data(mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor));
data->set_compressed_size(mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor));
memcpy(data->get_data(),
parent_window->get_abs_cursor_x(1),
parent_window->get_abs_cursor_y(1),
400,
- 100)
+ 200)
{
this->parent_window = parent_window;
this->asset = asset;
int x = 10, y = 10;
lock_window("JPEGConfigVideo::create_objects");
add_subwindow(new BC_Title(x, y, _("Quality:")));
- add_subwindow(new BC_ISlider(x + 80,
- y,
- 0,
- 200,
- 200,
- 0,
- 100,
- asset->jpeg_quality,
- 0,
- 0,
+ BC_ISlider *slider;
+ add_subwindow(slider = new BC_ISlider(x + 80, y,
+ 0, 200, 200, 0, 100, asset->jpeg_quality, 0, 0,
&asset->jpeg_quality));
+ y += slider->get_h() + 10;
+ add_subwindow(new BC_CheckBox(x, y,
+ &asset->jpeg_sphere, _("Tag for spherical playback")));
add_subwindow(new BC_OKButton(this));
show_window(1);
FILE *in;
-// Fix path for VFS
+// Fix path for VFS. Not used anymore.
if(!strncmp(asset->path, RENDERFARM_FS_PREFIX, strlen(RENDERFARM_FS_PREFIX)))
sprintf(string, "%s%s", RENDERFARM_FS_PREFIX, path);
else
switch(driver)
{
case PLAYBACK_X11:
- return BC_RGB888;
+// return BC_RGB888;
+// the direct X11 color model requires scaling in the codec
+ return BC_BGR8888;
case PLAYBACK_X11_XV:
case PLAYBACK_ASYNCHRONOUS:
return zmpeg3_cmdl(asset->vmpeg_cmodel) > 0 ?
static const char *zmpeg3_cmdl_name(int cmdl);
// This file can copy frames directly from the asset
int can_copy_from(Asset *asset, int64_t position);
+ int can_scale_input() { return 1; }
private:
void to_streamchannel(int channel, int &stream_out, int &channel_out);
int x = init_x;
int y = init_y;
int ylev = init_y;
+ int margin = mwindow->theme->widget_border;
this->locked_compressor = locked_compressor;
this->recording = recording;
x = init_x;
window->add_subwindow(format_title = new BC_Title(x, y, _("File Format:")));
- x += 90;
+ x += format_title->get_w() + margin;
window->add_subwindow(format_text = new BC_TextBox(x, y, 160, 1,
File::formattostr(asset->format)));
- x += format_text->get_w();
+ x += format_text->get_w() + margin;
//printf("FormatTools::create_objects %d %p\n", __LINE__, window);
window->add_subwindow(format_button = new FormatFormat(x, y, this));
format_button->create_objects();
format_ffmpeg->create_objects();
x = init_x;
y += format_button->get_h() + 10;
- if(do_audio)
- {
- window->add_subwindow(audio_title = new BC_Title(x, y, _("Audio:"), LARGEFONT, BC_WindowBase::get_resources()->audiovideo_color));
- x += 80;
+ if( do_audio ) {
+ window->add_subwindow(audio_title = new BC_Title(x, y, _("Audio:"), LARGEFONT,
+ BC_WindowBase::get_resources()->audiovideo_color));
+ x += audio_title->get_w() + margin;
window->add_subwindow(aparams_button = new FormatAParams(mwindow, this, x, y));
- x += aparams_button->get_w() + 10;
- if(prompt_audio)
- {
+ x += aparams_button->get_w() + margin;
+ if(prompt_audio) {
window->add_subwindow(audio_switch = new FormatAudio(x, y, this, asset->audio_data));
}
x = init_x;
}
//printf("FormatTools::create_objects 7\n");
- if(do_video)
- {
- if(horizontal_layout && do_audio){
+ if( do_video ) {
+ if( horizontal_layout && do_audio ) {
x += 370;
y = ylev;
}
//printf("FormatTools::create_objects 8\n");
- window->add_subwindow(video_title = new BC_Title(x, y, _("Video:"), LARGEFONT, BC_WindowBase::get_resources()->audiovideo_color));
- x += 80;
- if(prompt_video_compression)
- {
+ window->add_subwindow(video_title = new BC_Title(x, y, _("Video:"), LARGEFONT,
+ BC_WindowBase::get_resources()->audiovideo_color));
+ x += video_title->get_w() + margin;
+ if(prompt_video_compression) {
window->add_subwindow(vparams_button = new FormatVParams(mwindow, this, x, y));
- x += vparams_button->get_w() + 10;
+ x += vparams_button->get_w() + margin;
}
//printf("FormatTools::create_objects 9\n");
- if(prompt_video)
- {
+ if(prompt_video) {
window->add_subwindow(video_switch = new FormatVideo(x, y, this, asset->video_data));
y += video_switch->get_h();
}
- else
- {
+ else {
y += vparams_button->get_h();
}
}
void KeyFrame::update_parameter(BC_Hash *params,
- const char *text,
- char *extra)
+ const char *text, const char *extra)
{
FileXML output;
FileXML input;
// extra text in a newly allocated string
void get_contents(BC_Hash *ptr, char **text, char **extra);
// Update a single parameter or the anonymous text depending on which argument is nonzero
- void update_parameter(BC_Hash *params,
- const char *text,
- char *extra);
+ void update_parameter(BC_Hash *params, const char *text, const char *extra);
private:
char data[MESSAGESIZE];
/*
* CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
- *
+ * Copyright (C) 2017 Adam Williams <broadcast at earthling dot net>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
+ *
*/
#include "bchash.h"
#include "bcsignals.h"
#include "edl.h"
+#include "file.h"
+#include "filesystem.h"
#include "keyframe.h"
#include "keyframes.h"
#include "keyframegui.h"
#include "mwindow.h"
#include "mwindowgui.h"
#include "plugin.h"
+#include "preferences.h"
+#include "presets.h"
#include "theme.h"
#include "trackcanvas.h"
#include "tracks.h"
keyframe = 0;
keyframe_data = new ArrayList<BC_ListBoxItem*>[KEYFRAME_COLUMNS];
plugin_title[0] = 0;
+ is_factory = 0;
+ preset_text[0] = 0;
window_title[0] = 0;
- column_titles[0] = (char*)_("Parameter");
- column_titles[1] = (char*)_("Value");
+ column_titles[0] = (char*)"Parameter";
+ column_titles[1] = (char*)"Value";
column_width[0] = 0;
column_width[1] = 0;
+ presets_data = new ArrayList<BC_ListBoxItem*>;
+ presets_db = new PresetsDB;
}
KeyFrameThread::~KeyFrameThread()
{
- close_window();
- for(int i = 0; i < KEYFRAME_COLUMNS; i++)
+ for( int i=0; i<KEYFRAME_COLUMNS; ++i )
keyframe_data[i].remove_all_objects();
delete [] keyframe_data;
+ presets_data->remove_all_objects();
+ delete presets_data;
+ is_factories.remove_all();
+ preset_titles.remove_all_objects();
}
+#ifdef EDIT_KEYFRAME
void KeyFrameThread::update_values()
{
// Get the current selection before deleting the tables
int selection = -1;
- for(int i = 0; i < keyframe_data[0].size(); i++) {
- if(keyframe_data[0].get(i)->get_selected()) {
+ for( int i=0; i<keyframe_data[0].size(); ++i ) {
+ if( keyframe_data[0].get(i)->get_selected() ) {
selection = i;
break;
}
}
- for(int i = 0; i < KEYFRAME_COLUMNS; i++)
+ for( int i=0; i<KEYFRAME_COLUMNS; ++i )
keyframe_data[i].remove_all_objects();
// Must lock main window to read keyframe
mwindow->gui->lock_window("KeyFrameThread::update_values");
- if(!plugin || !mwindow->edl->tracks->plugin_exists(plugin)) {
+ if( !plugin || !mwindow->edl->tracks->plugin_exists(plugin) ) {
mwindow->gui->unlock_window();
return;
}
KeyFrame *keyframe = 0;
- if(this->keyframe && plugin->keyframe_exists(this->keyframe)) {
+ if( this->keyframe && plugin->keyframe_exists(this->keyframe) ) {
// If user edited a specific keyframe, use it.
keyframe = this->keyframe;
}
- else if(plugin->track) {
+ else
+ if( plugin->track ) {
// Use currently highlighted keyframe
keyframe = plugin->get_prev_keyframe(
plugin->track->to_units(
PLAY_FORWARD);
}
- if(keyframe) {
+ if( keyframe ) {
BC_Hash hash;
- char *text = 0, *extra = 0;
- keyframe->get_contents(&hash, &text, &extra);
-
- for(int i = 0; i < hash.size(); i++)
- {
+ char *text = 0, *data = 0;
+ keyframe->get_contents(&hash, &text, &data);
+
+ for( int i=0; i<hash.size(); ++i ) {
keyframe_data[0].append(new BC_ListBoxItem(hash.get_key(i)));
keyframe_data[1].append(new BC_ListBoxItem(hash.get_value(i)));
}
- keyframe_data[0].append(new BC_ListBoxItem((char*)_("TEXT")));
- keyframe_data[1].append(new BC_ListBoxItem(text ? text : ""));
-
+ keyframe_data[0].append(new BC_ListBoxItem((char*)"TEXT"));
+ keyframe_data[1].append(new BC_ListBoxItem(text));
+ keyframe_data[0].append(new BC_ListBoxItem((char*)"DATA"));
+ keyframe_data[1].append(new BC_ListBoxItem(data));
+
delete [] text;
- delete [] extra;
+ delete [] data;
}
column_width[0] = mwindow->session->keyframedialog_column1;
column_width[1] = mwindow->session->keyframedialog_column2;
- if(selection >= 0 && selection < keyframe_data[0].size()) {
- for(int i = 0; i < KEYFRAME_COLUMNS; i++)
+ if( selection >= 0 && selection < keyframe_data[0].size() ) {
+ for( int i=0; i<KEYFRAME_COLUMNS; ++i )
keyframe_data[i].get(selection)->set_selected(1);
}
mwindow->gui->unlock_window();
}
+#endif
void KeyFrameThread::start_window(Plugin *plugin, KeyFrame *keyframe)
{
- if(!BC_DialogThread::is_running()) {
- if(!mwindow->edl->tracks->plugin_exists(plugin)) return;
+ if( !BC_DialogThread::is_running() ) {
+ if( !mwindow->edl->tracks->plugin_exists(plugin) ) return;
this->keyframe = keyframe;
this->plugin = plugin;
plugin->calculate_title(plugin_title, 0);
- sprintf(window_title, _(PROGRAM_NAME ": %s Keyframe"), plugin_title);
+ sprintf(window_title, PROGRAM_NAME ": %s Keyframe", plugin_title);
+
+// Load all the presets from disk
+ char path[BCTEXTLEN];
+ FileSystem fs;
+// system wide presets
+ sprintf(path, "%s/%s", File::get_cindat_path(), FACTORY_FILE);
+ fs.complete_path(path);
+ presets_db->load_from_file(path, 1, 1);
+// user presets
+ sprintf(path, "%s/%s", File::get_config_path(), PRESETS_FILE);
+ fs.complete_path(path);
+ presets_db->load_from_file(path, 0, 0);
+
+ calculate_preset_list();
+
+#ifdef EDIT_KEYFRAME
update_values();
+#endif
mwindow->gui->unlock_window();
BC_DialogThread::start();
mwindow->gui->lock_window("KeyFrameThread::start_window");
BC_Window* KeyFrameThread::new_gui()
{
mwindow->gui->lock_window("KeyFrameThread::new_gui");
-
- int x = mwindow->gui->get_abs_cursor_x(0) -
+
+ int x = mwindow->gui->get_abs_cursor_x(0) -
mwindow->session->plugindialog_w / 2;
- int y = mwindow->gui->get_abs_cursor_y(0) -
+ int y = mwindow->gui->get_abs_cursor_y(0) -
mwindow->session->plugindialog_h / 2;
- KeyFrameWindow *window = new KeyFrameWindow(mwindow,
- this, x, y, window_title);
- window->create_objects();
+ KeyFrameWindow *window = new KeyFrameWindow(mwindow,
+ this,
+ x,
+ y,
+ window_title);
+ window->create_objects();
+
+
mwindow->gui->unlock_window();
+
return window;
}
void KeyFrameThread::handle_done_event(int result)
{
- if( !result )
- apply_value();
+// Apply the preset
+ if( !result ) {
+ apply_preset(preset_text, is_factory);
+ }
}
void KeyFrameThread::handle_close_event(int result)
keyframe = 0;
}
+void KeyFrameThread::close_window()
+{
+ lock_window("KeyFrameThread::close_window");
+ if( get_gui() ) {
+ get_gui()->lock_window("KeyFrameThread::close_window");
+ get_gui()->set_done(1);
+ get_gui()->unlock_window();
+ }
+ unlock_window();
+}
+
+
+
+void KeyFrameThread::calculate_preset_list()
+{
+ presets_data->remove_all_objects();
+ is_factories.remove_all();
+ preset_titles.remove_all_objects();
+ int total_presets = presets_db->get_total_presets(plugin_title, 0);
+
+// sort the list
+ presets_db->sort(plugin_title);
+
+ for( int i=0; i<total_presets; ++i ) {
+ char text[BCTEXTLEN];
+ char *orig_title = presets_db->get_preset_title( plugin_title, i);
+ if( !orig_title ) continue;
+ int is_factory = presets_db->get_is_factory(plugin_title, i);
+ sprintf(text, "%s%s", is_factory ? "*" : "", orig_title);
+ presets_data->append(new BC_ListBoxItem(text));
+
+ preset_titles.append(strdup(orig_title));
+ is_factories.append(is_factory);
+ }
+}
+
void KeyFrameThread::update_gui(int update_value_text)
{
- if(BC_DialogThread::is_running()) {
+#ifdef EDIT_KEYFRAME
+ if( BC_DialogThread::is_running() ) {
mwindow->gui->lock_window("KeyFrameThread::update_gui");
update_values();
mwindow->gui->unlock_window();
lock_window("KeyFrameThread::update_gui");
KeyFrameWindow *window = (KeyFrameWindow*)get_gui();
- if(window) {
+ if( window ) {
window->lock_window("KeyFrameThread::update_gui");
window->keyframe_list->update(keyframe_data,
- (const char **)column_titles,
+ column_titles,
column_width,
KEYFRAME_COLUMNS,
window->keyframe_list->get_xposition(),
window->keyframe_list->get_yposition(),
window->keyframe_list->get_highlighted_item());
- if( update_value_text ) {
- int selection_number = window->keyframe_list->get_selection_number(0, 0);
- if( selection_number >= 0 && selection_number < keyframe_data[1].size()) {
- char *edit_value = keyframe_data[1].get(selection_number)->get_text();
- window->value_text->update(edit_value);
- }
+ if( update_value_text &&
+ window->keyframe_list->get_selection_number(0, 0) >= 0 &&
+ window->keyframe_list->get_selection_number(0, 0) < keyframe_data[1].size() ) {
+ window->value_text->update(
+ keyframe_data[1].get(window->keyframe_list->get_selection_number(0, 0))->get_text());
}
window->unlock_window();
}
unlock_window();
}
+#endif
+}
+
+void KeyFrameThread::save_preset(const char *title, int is_factory)
+{
+ get_gui()->unlock_window();
+ mwindow->gui->lock_window("KeyFrameThread::save_preset");
+
+// Test EDL for plugin existence
+ if( !mwindow->edl->tracks->plugin_exists(plugin) ) {
+ mwindow->gui->unlock_window();
+ get_gui()->lock_window("KeyFrameThread::save_preset 2");
+ return;
+ }
+
+// Get current plugin keyframe
+ EDL *edl = mwindow->edl;
+ Track *track = plugin->track;
+ KeyFrame *keyframe = plugin->get_prev_keyframe(
+ track->to_units(edl->local_session->get_selectionstart(1), 0),
+ PLAY_FORWARD);
+
+// Send to database
+ presets_db->save_preset(plugin_title, title, keyframe->get_data());
+
+ mwindow->gui->unlock_window();
+ get_gui()->lock_window("KeyFrameThread::save_preset 2");
+
+// Update list
+ calculate_preset_list();
+ ((KeyFrameWindow*)get_gui())->preset_list->update(presets_data,
+ 0, 0, 1);
+}
+
+void KeyFrameThread::delete_preset(const char *title, int is_factory)
+{
+ get_gui()->unlock_window();
+ mwindow->gui->lock_window("KeyFrameThread::save_preset");
+
+// Test EDL for plugin existence
+ if( !mwindow->edl->tracks->plugin_exists(plugin) ) {
+ mwindow->gui->unlock_window();
+ get_gui()->lock_window("KeyFrameThread::delete_preset 1");
+ return;
+ }
+
+ presets_db->delete_preset(plugin_title, title, is_factory);
+
+ mwindow->gui->unlock_window();
+ get_gui()->lock_window("KeyFrameThread::delete_preset 2");
+
+// Update list
+ calculate_preset_list();
+ ((KeyFrameWindow*)get_gui())->preset_list->update(presets_data,
+ 0, 0, 1);
}
+
+void KeyFrameThread::apply_preset(const char *title, int is_factory)
+{
+ if( presets_db->preset_exists(plugin_title, title, is_factory) ) {
+ get_gui()->unlock_window();
+ mwindow->gui->lock_window("KeyFrameThread::apply_preset");
+
+// Test EDL for plugin existence
+ if( !mwindow->edl->tracks->plugin_exists(plugin) ) {
+ mwindow->gui->unlock_window();
+ get_gui()->lock_window("KeyFrameThread::apply_preset 1");
+ return;
+ }
+
+ mwindow->undo->update_undo_before();
+
+#ifdef USE_KEYFRAME_SPANNING
+ KeyFrame keyframe;
+ presets_db->load_preset(plugin_title, title, &keyframe, is_factory);
+ plugin->keyframes->update_parameter(&keyframe);
+#else
+ KeyFrame *keyframe = plugin->get_keyframe();
+ presets_db->load_preset(plugin_title, title, keyframe, is_factory);
+#endif
+ mwindow->save_backup();
+ mwindow->undo->update_undo_after(_("apply preset"), LOAD_AUTOMATION);
+
+ mwindow->update_plugin_guis(0);
+ mwindow->gui->draw_overlays(1);
+ mwindow->sync_parameters(CHANGE_PARAMS);
+
+
+ update_gui(1);
+ mwindow->gui->unlock_window();
+ get_gui()->lock_window("KeyFrameThread::apply_preset");
+ }
+}
+
+#ifdef EDIT_KEYFRAME
void KeyFrameThread::apply_value()
{
- const char *text = 0;
- BC_Hash hash;
+ const char *text = 0, *data = 0;
+ BC_Hash *hash = 0;
KeyFrameWindow *window = (KeyFrameWindow*)get_gui();
int selection = window->keyframe_list->get_selection_number(0, 0);
//printf("KeyFrameThread::apply_value %d %d\n", __LINE__, selection);
- if(selection < 0) return;
-
- if(selection == keyframe_data[0].size() - 1)
+ if( selection < 0 ) return;
+
+ if( selection == keyframe_data[0].size() - 2 )
text = window->value_text->get_text();
+ else if( selection == keyframe_data[0].size() - 1 )
+ data = window->value_text->get_text();
else {
- char *key = keyframe_data[0].get(selection)->get_text();
+ const char *key = keyframe_data[0].get(selection)->get_text();
const char *value = window->value_text->get_text();
- hash.update(key, value);
+ hash = new BC_Hash();
+ hash->update(key, value);
}
get_gui()->unlock_window();
mwindow->gui->lock_window("KeyFrameThread::apply_value");
- if(plugin && mwindow->edl->tracks->plugin_exists(plugin)) {
+ if( plugin && mwindow->edl->tracks->plugin_exists(plugin) ) {
mwindow->undo->update_undo_before();
- if(mwindow->session->keyframedialog_all) {
+ if( mwindow->session->keyframedialog_all ) {
// Search for all keyframes in selection but don't create a new one.
Track *track = plugin->track;
int64_t start = track->to_units(mwindow->edl->local_session->get_selectionstart(0), 0);
int64_t end = track->to_units(mwindow->edl->local_session->get_selectionend(0), 0);
int got_it = 0;
- for(KeyFrame *current = (KeyFrame*)plugin->keyframes->last;
- current;
- current = (KeyFrame*)PREVIOUS) {
+ KeyFrame *current = (KeyFrame*)plugin->keyframes->last;
+ for( ; current; current=(KeyFrame*)PREVIOUS ) {
got_it = 1;
- if(current && current->position < end) {
- current->update_parameter(&hash, text, 0);
+ if( current && current->position < end ) {
+ current->update_parameter(hash, text, data);
// Stop at beginning of range
- if(current->position <= start) break;
+ if( current->position <= start ) break;
}
}
- if(!got_it) {
- KeyFrame* keyframe = (KeyFrame*)plugin->keyframes->default_auto;
- keyframe->update_parameter(&hash, text, 0);
+ if( !got_it ) {
+ current = (KeyFrame*)plugin->keyframes->default_auto;
+ current->update_parameter(hash, text, data);
}
}
else {
// Create new keyframe if enabled
KeyFrame *keyframe = plugin->get_keyframe();
- keyframe->update_parameter(&hash, text, 0);
+ keyframe->update_parameter(hash, text, data);
}
}
else {
}
mwindow->save_backup();
- mwindow->undo->update_undo_after(_("edit keyframe"), LOAD_AUTOMATION);
+ mwindow->undo->update_undo_after(_("edit keyframe"), LOAD_AUTOMATION);
mwindow->update_plugin_guis(0);
mwindow->gui->draw_overlays(1);
mwindow->sync_parameters(CHANGE_PARAMS);
-
-
-
mwindow->gui->unlock_window();
update_gui(0);
get_gui()->lock_window("KeyFrameThread::apply_value");
+ delete hash;
}
+#endif
+
KeyFrameWindow::KeyFrameWindow(MWindow *mwindow,
- KeyFrameThread *thread, int x, int y, char *title_string)
- : BC_Window(title_string, x, y,
- mwindow->session->keyframedialog_w,
- mwindow->session->keyframedialog_h,
- 320, 240, 1, 0, 1)
+ KeyFrameThread *thread,
+ int x,
+ int y,
+ char *title_string)
+ : BC_Window(title_string,
+ x,
+ y,
+ mwindow->session->keyframedialog_w,
+ mwindow->session->keyframedialog_h,
+ 320,
+ 240,
+ 1,
+ 0,
+ 1)
{
this->mwindow = mwindow;
this->thread = thread;
thread->column_width[1] = mwindow->session->keyframedialog_column2;
lock_window("KeyFrameWindow::create_objects");
+#ifdef EDIT_KEYFRAME
+
+
add_subwindow(title1 = new BC_Title(theme->keyframe_list_x,
- theme->keyframe_list_y -
- BC_Title::calculate_h(this, (char*)"Py", LARGEFONT) -
+ theme->keyframe_list_y -
+ BC_Title::calculate_h(this, (char*)"Py", LARGEFONT) -
theme->widget_border,
- _("Keyframe parameters:"), LARGEFONT));
+ _("Keyframe parameters:"),
+ LARGEFONT));
add_subwindow(keyframe_list = new KeyFrameList(thread,
- this, theme->keyframe_list_x, theme->keyframe_list_y,
- theme->keyframe_list_w, theme->keyframe_list_h));
+ this,
+ theme->keyframe_list_x,
+ theme->keyframe_list_y,
+ theme->keyframe_list_w,
+ theme->keyframe_list_h));
+// add_subwindow(title2 = new BC_Title(theme->keyframe_text_x,
+// theme->keyframe_text_y - BC_Title::calculate_h(this, "P") - theme->widget_border,
+// _("Global Text:")));
+// add_subwindow(keyframe_text = new KeyFrameText(thread,
+// this,
+// theme->keyframe_text_x,
+// theme->keyframe_text_y,
+// theme->keyframe_text_w));
add_subwindow(title3 = new BC_Title(theme->keyframe_value_x,
theme->keyframe_value_y - BC_Title::calculate_h(this, (char*)"P") - theme->widget_border,
_("Edit value:")));
add_subwindow(value_text = new KeyFrameValue(thread,
- this, theme->keyframe_value_x, theme->keyframe_value_y, theme->keyframe_value_w));
+ this,
+ theme->keyframe_value_x,
+ theme->keyframe_value_y,
+ theme->keyframe_value_w));
add_subwindow(all_toggle = new KeyFrameAll(thread,
- this, theme->keyframe_all_x, theme->keyframe_all_y));
+ this,
+ theme->keyframe_all_x,
+ theme->keyframe_all_y));
+
+#endif
+
- add_subwindow(new KeyFrameParamsOK(thread, this));
+
+ add_subwindow(title4 = new BC_Title(theme->presets_list_x,
+ theme->presets_list_y -
+ BC_Title::calculate_h(this, (char*)"Py", LARGEFONT) -
+ theme->widget_border,
+ _("Presets:"),
+ LARGEFONT));
+ add_subwindow(preset_list = new KeyFramePresetsList(thread,
+ this,
+ theme->presets_list_x,
+ theme->presets_list_y,
+ theme->presets_list_w,
+ theme->presets_list_h));
+ add_subwindow(title5 = new BC_Title(theme->presets_text_x,
+ theme->presets_text_y - BC_Title::calculate_h(this, (char*)"P") - theme->widget_border,
+ _("Preset title:")));
+ add_subwindow(preset_text = new KeyFramePresetsText(thread,
+ this,
+ theme->presets_text_x,
+ theme->presets_text_y,
+ theme->presets_text_w));
+ add_subwindow(delete_preset = new KeyFramePresetsDelete(thread,
+ this,
+ theme->presets_delete_x,
+ theme->presets_delete_y));
+ add_subwindow(save_preset = new KeyFramePresetsSave(thread,
+ this,
+ theme->presets_save_x,
+ theme->presets_save_y));
+ add_subwindow(apply_preset = new KeyFramePresetsApply(thread,
+ this,
+ theme->presets_apply_x,
+ theme->presets_apply_y));
+
+
+
+
+ add_subwindow(new KeyFramePresetsOK(thread, this));
add_subwindow(new BC_CancelButton(this));
show_window();
unlock_window();
}
+// called when going in & out of a factory preset
+void KeyFrameWindow::update_editing()
+{
+ if( thread->is_factory ) {
+ delete_preset->disable();
+ save_preset->disable();
+ }
+ else {
+ delete_preset->enable();
+ save_preset->enable();
+ }
+}
+
+
+
int KeyFrameWindow::resize_event(int w, int h)
{
Theme *theme = mwindow->theme;
mwindow->session->keyframedialog_h = h;
theme->get_keyframedialog_sizes(this);
+#ifdef EDIT_KEYFRAME
+
title1->reposition_window(theme->keyframe_list_x,
theme->keyframe_list_y - BC_Title::calculate_h(this, (char*)"P") - theme->widget_border);
+// title2->reposition_window(theme->keyframe_text_x,
+// theme->keyframe_text_y - BC_Title::calculate_h(this, (char*)"P") - theme->widget_border);
title3->reposition_window(theme->keyframe_value_x,
theme->keyframe_value_y - BC_Title::calculate_h(this, (char*)"P") - theme->widget_border);
- keyframe_list->reposition_window(theme->keyframe_list_x, theme->keyframe_list_y,
- theme->keyframe_list_w, theme->keyframe_list_h);
- value_text->reposition_window(theme->keyframe_value_x, theme->keyframe_value_y,
+ keyframe_list->reposition_window(theme->keyframe_list_x,
+ theme->keyframe_list_y,
+ theme->keyframe_list_w,
+ theme->keyframe_list_h);
+// text->reposition_window(theme->keyframe_text_x,
+// theme->keyframe_text_y,
+// theme->keyframe_text_w);
+ value_text->reposition_window(theme->keyframe_value_x,
+ theme->keyframe_value_y,
theme->keyframe_value_w);
- all_toggle->reposition_window(theme->keyframe_all_x, theme->keyframe_all_y);
+ all_toggle->reposition_window(theme->keyframe_all_x,
+ theme->keyframe_all_y);
+
+#endif // EDIT_KEYFRAME
+
+
+
+
+ title4->reposition_window(theme->presets_list_x,
+ theme->presets_list_y - BC_Title::calculate_h(this, (char*)"P") - theme->widget_border);
+ title5->reposition_window(theme->presets_text_x,
+ theme->presets_text_y - BC_Title::calculate_h(this, (char*)"P") - theme->widget_border);
+ preset_list->reposition_window(theme->presets_list_x,
+ theme->presets_list_y,
+ theme->presets_list_w,
+ theme->presets_list_h);
+ preset_text->reposition_window(theme->presets_text_x,
+ theme->presets_text_y,
+ theme->presets_text_w);
+ delete_preset->reposition_window(theme->presets_delete_x,
+ theme->presets_delete_y);
+ save_preset->reposition_window(theme->presets_save_x,
+ theme->presets_save_y);
+ apply_preset->reposition_window(theme->presets_apply_x,
+ theme->presets_apply_y);
return 0;
}
+
+
+
+#ifdef EDIT_KEYFRAME
+
+
KeyFrameList::KeyFrameList(KeyFrameThread *thread,
- KeyFrameWindow *window, int x, int y, int w, int h)
- : BC_ListBox(x, y, w, h, LISTBOX_TEXT,
- thread->keyframe_data, (const char **)thread->column_titles,
- thread->column_width, KEYFRAME_COLUMNS)
+ KeyFrameWindow *window,
+ int x,
+ int y,
+ int w,
+ int h)
+ : BC_ListBox(x,
+ y,
+ w,
+ h,
+ LISTBOX_TEXT,
+ thread->keyframe_data,
+ thread->column_titles,
+ thread->column_width,
+ KEYFRAME_COLUMNS)
{
this->thread = thread;
this->window = window;
}
+
+
+// KeyFrameText::KeyFrameText(KeyFrameThread *thread,
+// KeyFrameWindow *window,
+// int x,
+// int y,
+// int w)
+// : BC_TextBox(x,
+// y,
+// w,
+// 1,
+// "")
+// {
+// this->thread = thread;
+// this->window = window;
+// }
+//
+// int KeyFrameText::handle_event()
+// {
+// return 0;
+// }
+
+
+
KeyFrameValue::KeyFrameValue(KeyFrameThread *thread,
- KeyFrameWindow *window, int x, int y, int w)
- : BC_TextBox(x, y, w, 1, "")
+ KeyFrameWindow *window,
+ int x,
+ int y,
+ int w)
+ : BC_TextBox(x,
+ y,
+ w,
+ 1,
+ (char*)"")
{
this->thread = thread;
this->window = window;
int KeyFrameValue::handle_event()
{
- thread->update_values();
+ thread->apply_value();
return 0;
}
+
+
+
KeyFrameAll::KeyFrameAll(KeyFrameThread *thread,
- KeyFrameWindow *window, int x, int y)
- : BC_CheckBox(x, y, thread->mwindow->session->keyframedialog_all,
+ KeyFrameWindow *window,
+ int x,
+ int y)
+ : BC_CheckBox(x,
+ y,
+ thread->mwindow->session->keyframedialog_all,
_("Apply to all selected keyframes"))
{
this->thread = thread;
return 1;
}
-KeyFrameParamsOK::KeyFrameParamsOK(KeyFrameThread *thread, KeyFrameWindow *window)
+#endif // EDIT_KEYFRAME
+
+
+
+
+
+
+
+
+
+
+KeyFramePresetsList::KeyFramePresetsList(KeyFrameThread *thread,
+ KeyFrameWindow *window,
+ int x,
+ int y,
+ int w,
+ int h)
+ : BC_ListBox(x,
+ y,
+ w,
+ h,
+ LISTBOX_TEXT,
+ thread->presets_data)
+{
+ this->thread = thread;
+ this->window = window;
+}
+
+int KeyFramePresetsList::selection_changed()
+{
+ int number = get_selection_number(0, 0);
+ if( number >= 0 ) {
+ strcpy(thread->preset_text, thread->preset_titles.get(number));
+ thread->is_factory = thread->is_factories.get(number);
+// show title without factory symbol in the textbox
+ window->preset_text->update(
+ thread->presets_data->get(number)->get_text());
+ window->update_editing();
+ }
+
+ return 0;
+}
+
+int KeyFramePresetsList::handle_event()
+{
+ thread->apply_preset(thread->preset_text, thread->is_factory);
+ window->set_done(0);
+ return 0;
+}
+
+
+KeyFramePresetsText::KeyFramePresetsText(KeyFrameThread *thread,
+ KeyFrameWindow *window, int x, int y, int w)
+ : BC_TextBox(x, y, w, 1, thread->preset_text)
+{
+ this->thread = thread;
+ this->window = window;
+}
+
+// user entered a title
+int KeyFramePresetsText::handle_event()
+{
+ strcpy(thread->preset_text, get_text());
+// once changed, it's now not a factory preset
+ thread->is_factory = 0;
+ window->update_editing();
+ return 0;
+}
+
+
+KeyFramePresetsDelete::KeyFramePresetsDelete(KeyFrameThread *thread,
+ KeyFrameWindow *window,
+ int x,
+ int y)
+ : BC_GenericButton(x, y, _("Delete"))
+{
+ this->thread = thread;
+ this->window = window;
+}
+
+int KeyFramePresetsDelete::handle_event()
+{
+ if( !thread->is_factory ) {
+ thread->delete_preset(thread->preset_text, thread->is_factory);
+ }
+ return 1;
+}
+
+
+KeyFramePresetsSave::KeyFramePresetsSave(KeyFrameThread *thread,
+ KeyFrameWindow *window,
+ int x,
+ int y)
+: BC_GenericButton(x, y, _("Save"))
+{
+ this->thread = thread;
+ this->window = window;
+}
+
+int KeyFramePresetsSave::handle_event()
+{
+ if( !thread->is_factory ) {
+ thread->save_preset(thread->preset_text, thread->is_factory);
+ }
+ return 1;
+}
+
+
+
+
+
+
+
+
+KeyFramePresetsApply::KeyFramePresetsApply(KeyFrameThread *thread,
+ KeyFrameWindow *window,
+ int x,
+ int y)
+ : BC_GenericButton(x, y, _("Apply"))
+{
+ this->thread = thread;
+ this->window = window;
+}
+
+int KeyFramePresetsApply::handle_event()
+{
+ thread->apply_preset(thread->preset_text, thread->is_factory);
+ return 1;
+}
+
+
+KeyFramePresetsOK::KeyFramePresetsOK(KeyFrameThread *thread,
+ KeyFrameWindow *window)
: BC_OKButton(window)
{
this->thread = thread;
this->window = window;
}
-int KeyFrameParamsOK::keypress_event()
+int KeyFramePresetsOK::keypress_event()
{
if( get_keypress() == RETURN ) {
- thread->apply_value();
- return 1;
+// Apply the preset
+ if( thread->presets_db->preset_exists(thread->plugin_title,
+ thread->preset_text, thread->is_factory) ) {
+ window->set_done(0);
+ return 1;
+ }
+ else {
+ if( !thread->is_factory ) {
+ thread->save_preset(thread->preset_text, thread->is_factory);
+ return 1;
+ }
+ }
}
return 0;
}
/*
* CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
- *
+ * Copyright (C) 2017 Adam Williams <broadcast at earthling dot net>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
+ *
*/
#ifndef KEYFRAMEGUI_H
#include "bcdialog.h"
#include "guicast.h"
+#include "presets.inc"
class KeyFrameWindow;
+
+
#define KEYFRAME_COLUMNS 2
// Enable editing of detailed keyframe parameters.
+#define EDIT_KEYFRAME
+
class KeyFrameThread : public BC_DialogThread
{
public:
void handle_close_event(int result);
void update_values();
void save_value(char *value);
+ void save_preset(const char *title, int is_factory);
+ void delete_preset(const char *title, int is_factory);
+ void apply_preset(const char *title, int is_factory);
void apply_value();
+ void calculate_preset_list();
void update_gui(int update_value_text = 1);
+ void close_window();
ArrayList<BC_ListBoxItem*> *keyframe_data;
Plugin *plugin;
MWindow *mwindow;
char window_title[BCTEXTLEN];
char plugin_title[BCTEXTLEN];
- char *column_titles[KEYFRAME_COLUMNS];
+
+// the currently selected preset is a factory preset
+ int is_factory;
+// title of the currently selected preset from the DB
+ char preset_text[BCTEXTLEN];
+
+ const char *column_titles[KEYFRAME_COLUMNS];
int column_width[KEYFRAME_COLUMNS];
+// list of preset text to display
+ ArrayList<BC_ListBoxItem*> *presets_data;
+// flag for each preset shown
+ ArrayList<int> is_factories;
+// title of each preset shown
+ ArrayList<char*> preset_titles;
+ PresetsDB *presets_db;
};
+#ifdef EDIT_KEYFRAME
+
+
class KeyFrameList : public BC_ListBox
{
public:
KeyFrameList(KeyFrameThread *thread,
- KeyFrameWindow *window, int x, int y, int w, int h);
+ KeyFrameWindow *window,
+ int x,
+ int y,
+ int w,
+ int h);
int selection_changed();
int handle_event();
int column_resize_event();
KeyFrameThread *thread;
KeyFrameWindow *window;
};
+#endif
-class KeyFrameParamList : public BC_ListBox
+class KeyFramePresetsList : public BC_ListBox
{
public:
- KeyFrameParamList(KeyFrameThread *thread,
- KeyFrameWindow *window, int x, int y, int w, int h);
+ KeyFramePresetsList(KeyFrameThread *thread,
+ KeyFrameWindow *window,
+ int x,
+ int y,
+ int w,
+ int h);
int selection_changed();
int handle_event();
KeyFrameThread *thread;
KeyFrameWindow *window;
};
+class KeyFramePresetsText : public BC_TextBox
+{
+public:
+ KeyFramePresetsText(KeyFrameThread *thread,
+ KeyFrameWindow *window,
+ int x,
+ int y,
+ int w);
+ int handle_event();
+ KeyFrameThread *thread;
+ KeyFrameWindow *window;
+};
+
+
+class KeyFramePresetsDelete : public BC_GenericButton
+{
+public:
+ KeyFramePresetsDelete(KeyFrameThread *thread,
+ KeyFrameWindow *window,
+ int x,
+ int y);
+ int handle_event();
+ KeyFrameThread *thread;
+ KeyFrameWindow *window;
+};
+
+class KeyFramePresetsSave : public BC_GenericButton
+{
+public:
+ KeyFramePresetsSave(KeyFrameThread *thread,
+ KeyFrameWindow *window,
+ int x,
+ int y);
+ int handle_event();
+ KeyFrameThread *thread;
+ KeyFrameWindow *window;
+};
+
+class KeyFramePresetsApply : public BC_GenericButton
+{
+public:
+ KeyFramePresetsApply(KeyFrameThread *thread,
+ KeyFrameWindow *window,
+ int x,
+ int y);
+ int handle_event();
+ KeyFrameThread *thread;
+ KeyFrameWindow *window;
+};
+
+/*
+ * class KeyFrameText : public BC_TextBox
+ * {
+ * public:
+ * KeyFrameText(KeyFrameThread *thread,
+ * KeyFrameWindow *window,
+ * int x,
+ * int y,
+ * int w);
+ * int handle_event();
+ * KeyFrameThread *thread;
+ * KeyFrameWindow *window;
+ * };
+ */
+
+#ifdef EDIT_KEYFRAME
+
+
class KeyFrameValue : public BC_TextBox
{
public:
KeyFrameValue(KeyFrameThread *thread,
- KeyFrameWindow *window, int x, int y, int w);
+ KeyFrameWindow *window,
+ int x,
+ int y,
+ int w);
int handle_event();
KeyFrameThread *thread;
KeyFrameWindow *window;
{
public:
KeyFrameAll(KeyFrameThread *thread,
- KeyFrameWindow *window, int x, int y);
+ KeyFrameWindow *window,
+ int x,
+ int y);
int handle_event();
KeyFrameThread *thread;
KeyFrameWindow *window;
};
-class KeyFrameParamsOK : public BC_OKButton
+#endif
+
+
+class KeyFramePresetsOK : public BC_OKButton
{
public:
- KeyFrameParamsOK(KeyFrameThread *thread,
+ KeyFramePresetsOK(KeyFrameThread *thread,
KeyFrameWindow *window);
int keypress_event();
KeyFrameThread *thread;
KeyFrameWindow *window;
};
+
+
class KeyFrameWindow : public BC_Window
{
public:
KeyFrameWindow(MWindow *mwindow,
- KeyFrameThread *thread, int x, int y, char *title);
+ KeyFrameThread *thread,
+ int x,
+ int y,
+ char *title);
void create_objects();
int resize_event(int w, int h);
+ void update_editing();
+
+#ifdef EDIT_KEYFRAME
// List of parameters, values, & whether the parameter is defined by the current keyframe.
KeyFrameList *keyframe_list;
// Value text of the current parameter
KeyFrameValue *value_text;
KeyFrameAll *all_toggle;
- BC_Title *title1, *title3;
+#endif
+
+ KeyFramePresetsList *preset_list;
+ KeyFramePresetsText *preset_text;
+ KeyFramePresetsDelete *delete_preset;
+ KeyFramePresetsSave *save_preset;
+ KeyFramePresetsApply *apply_preset;
+
+#ifdef EDIT_KEYFRAME
+
+ BC_Title *title1;
+// BC_Title *title2;
+ BC_Title *title3;
+#endif
+
+ BC_Title *title4;
+ BC_Title *title5;
MWindow *mwindow;
KeyFrameThread *thread;
};
+
+
+
#endif
+
+
+
+
+
floatauto_type = FloatAuto::SMOOTH;
red = green = blue = 0;
+ red_max = green_max = blue_max = 0;
+ use_max = 0;
}
LocalSession::~LocalSession()
preview_end = that->preview_end;
red = that->red;
green = that->green;
+ blue = that->blue;
+ red_max = that->red_max;
+ green_max = that->green_max;
+ blue_max = that->blue_max;
+ use_max = that->use_max;
for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
automation_mins[i] = that->automation_mins[i];
automation_maxs[i] = that->automation_maxs[i];
}
floatauto_type = that->floatauto_type;
-
- blue = that->blue;
}
void LocalSession::save_xml(FileXML *file, double start)
file->tag.set_property("RED", red);
file->tag.set_property("GREEN", green);
file->tag.set_property("BLUE", blue);
+ file->tag.set_property("RED_MAX", red_max);
+ file->tag.set_property("GREEN_MAX", green_max);
+ file->tag.set_property("BLUE_MAX", blue_max);
+ file->tag.set_property("USE_MAX", use_max);
for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
if (!Automation::autogrouptypes_fixedrange[i]) {
red = that->red;
green = that->green;
blue = that->blue;
+ red_max = that->red_max;
+ green_max = that->green_max;
+ blue_max = that->blue_max;
}
red = file->tag.get_property("RED", red);
green = file->tag.get_property("GREEN", green);
blue = file->tag.get_property("BLUE", blue);
-
+ red_max = file->tag.get_property("RED_MAX", red_max);
+ green_max = file->tag.get_property("GREEN_MAX", green_max);
+ blue_max = file->tag.get_property("BLUE_MAX", blue_max);
+ use_max = file->tag.get_property("USE_MAX", use_max);
for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
if (!Automation::autogrouptypes_fixedrange[i]) {
red = defaults->get("RED", 0.0);
green = defaults->get("GREEN", 0.0);
blue = defaults->get("BLUE", 0.0);
+ red_max = defaults->get("RED_MAX", 0.0);
+ green_max = defaults->get("GREEN_MAX", 0.0);
+ blue_max = defaults->get("BLUE_MAX", 0.0);
+ use_max = defaults->get("USE_MAX", 0);
for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
if (!Automation::autogrouptypes_fixedrange[i]) {
defaults->update("RED", red);
defaults->update("GREEN", green);
defaults->update("BLUE", blue);
+ defaults->update("RED_MAX", red_max);
+ defaults->update("GREEN_MAX", green_max);
+ defaults->update("BLUE_MAX", blue_max);
+ defaults->update("USE_MAX", use_max);
for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
if (!Automation::autogrouptypes_fixedrange[i]) {
// Eye dropper
float red, green, blue;
+ float red_max, green_max, blue_max;
+ int use_max;
private:
// The reason why selection ranges and inpoints have to be separate:
// The selection position has to change to set new in points.
/*
* CINELERRA
- * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
+ * Copyright (C) 1997-2017 Adam Williams <broadcast at earthling dot net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "theme.h"
MainClock::MainClock(MWindow *mwindow, int x, int y, int w)
- : BC_Title(x, y, "", MEDIUM_7SEGMENT, BLACK, 0, w)
+ : BC_Title(x, y, "", CLOCKFONT, //MEDIUM_7SEGMENT,
+ mwindow->theme->clock_fg_color, 0, w)
{
this->mwindow = mwindow;
position_offset = 0;
mwindow->undo->update_undo_before("", 0);
if(load_mode == LOADMODE_PASTE)
- mwindow->clear(0);
+ mwindow->clear(0, 1);
mwindow->load_assets(&assets, -1, load_mode, 0, 0,
mwindow->edl->session->labels_follow_edits,
// Clears active region in EDL.
// If clear_handle, edit boundaries are cleared if the range is 0.
// Called by paste, record, menueffects, render, and CWindow drop.
- void clear(int clear_handle);
+ void clear(int clear_handle, int deglitch);
void clear_labels();
int clear_labels(double start, double end);
void concatenate_tracks();
#define DEFAULT_THEME "UnFlat"
#define DEFAULT_PICON "cinfinity"
#define CONFIG_FILE "Cinelerra_rc"
+// user presets
#define PRESETS_FILE "Cinelerra_presets"
+// factory presets
+#define FACTORY_FILE "Cinelerra_factory"
#define PICTURE_FILE "Cinelerra_picture"
#define PLUGIN_FILE "Cinelerra_plugins"
#define LADSPA_FILE "ladspa_plugins."
void MWindow::clear_entry()
{
undo->update_undo_before();
- clear(1);
+ clear(1, 1);
edl->optimize();
save_backup();
send_command(CURRENT_FRAME, CHANGE_EDL, edl, 1);
}
-void MWindow::clear(int clear_handle)
+void MWindow::clear(int clear_handle, int deglitch)
{
double start = edl->local_session->get_selectionstart();
double end = edl->local_session->get_selectionend();
edl->session->plugins_follow_edits,
edl->session->autos_follow_edits);
}
+
+// always needed by paste operations
+ if(deglitch)
+ {
+ edl->deglitch(start);
+ }
}
void MWindow::set_automation_mode(int mode)
edl->session->labels_follow_edits,
edl->session->plugins_follow_edits,
edl->session->autos_follow_edits);
+ edl->deglitch(start);
edl->optimize();
if( (session->drag_handle == 1 && edit_mode != MOVE_NO_EDITS) ||
(session->drag_handle == 0 && edit_mode == MOVE_ONE_EDIT) ) {
+//printf("MWindow::finish_modify_handles %d\n", __LINE__);
edl->local_session->set_selectionstart(session->drag_position);
edl->local_session->set_selectionend(session->drag_position);
+ edl->deglitch(session->drag_position);
}
else
if( edit_mode != MOVE_NO_EDITS ) {
+//printf("MWindow::finish_modify_handles %d\n", __LINE__);
edl->local_session->set_selectionstart(session->drag_start);
edl->local_session->set_selectionend(session->drag_start);
+ edl->deglitch(session->drag_start);
}
+// clamp the selection to 0
if( edl->local_session->get_selectionstart(1) < 0 ) {
edl->local_session->set_selectionstart(0);
edl->local_session->set_selectionend(0);
edl->paste_silence(start, end, 0,
edl->session->plugins_follow_edits,
edl->session->autos_follow_edits);
+ edl->deglitch(start);
+ edl->deglitch(end);
+
+
save_backup();
undo->update_undo_after(_("mute"), LOAD_EDITS);
int edit_plugins,
int edit_autos)
{
- clear(0);
+ clear(0, 1);
// Want to insert with assets shared with the master EDL.
insert(start, file,
gui->from_clipboard(string, len, BC_PRIMARY_SELECTION);
FileXML file;
file.read_from_string(string);
- clear(0);
+ clear(0, 1);
insert(start, &file,
edl->session->labels_follow_edits,
edl->session->labels_follow_edits,
edl->session->plugins_follow_edits,
edl->session->autos_follow_edits);
+ edl->deglitch(start);
+ edl->deglitch(end);
edl->optimize();
save_backup();
undo->update_undo_after(_("silence"), LOAD_EDITS | LOAD_TIMEBAR);
edl->session->labels_follow_edits,
edl->session->plugins_follow_edits,
edl->session->autos_follow_edits);
+ edl->deglitch(0);
+ edl->deglitch(edl->local_session->get_selectionend() -
+ edl->local_session->get_selectionstart());
+
save_backup();
undo->update_undo_after(_("trim selection"), LOAD_EDITS | LOAD_TIMEBAR);
void New::create_new_edl()
{
- if(!new_edl)
- {
+ if( !new_edl ) {
new_edl = new EDL;
new_edl->create_objects();
new_edl->load_defaults(mwindow->defaults);
int New::create_new_project()
{
mwindow->cwindow->playback_engine->que->send_command(STOP,
- CHANGE_NONE,
- 0,
- 0);
+ CHANGE_NONE, 0, 0);
- for(int i = 0; i < mwindow->vwindows.size(); i++)
- {
+ for( int i=0; i<mwindow->vwindows.size(); ++i ) {
VWindow *vwindow = mwindow->vwindows.get(i);
if( !vwindow->is_running() ) continue;
vwindow->playback_engine->que->send_command(STOP, CHANGE_NONE, 0, 0);
mwindow->gui->lock_window();
mwindow->reset_caches();
-
-
memcpy(new_edl->session->achannel_positions,
&mwindow->preferences->channel_positions[
MAXCHANNELS * (new_edl->session->audio_channels - 1)],
close_window();
}
-
-
BC_Window* NewThread::new_gui()
{
mwindow->edl->save_defaults(mwindow->defaults);
return nwindow;
}
-
-
void NewThread::handle_close_event(int result)
{
-
if( !new_project->new_edl ) return;
new_project->new_edl->save_defaults(mwindow->defaults);
mwindow->defaults->save();
- if(result)
- {
+ if( result ) {
// Aborted
if( !new_project->new_edl->Garbage::remove_user() )
new_project->new_edl = 0;
}
- else
- {
+ else {
new_project->create_new_project();
}
}
-
-
int NewThread::load_defaults()
{
auto_aspect = mwindow->defaults->get("AUTOASPECT", 0);
int NewThread::update_aspect()
{
- if(auto_aspect)
- {
+ if( auto_aspect ) {
char string[BCTEXTLEN];
mwindow->create_aspect_ratio(new_project->new_edl->session->aspect_w,
new_project->new_edl->session->aspect_h,
}
-
-
NewWindow::NewWindow(MWindow *mwindow, NewThread *new_thread, int x, int y)
: BC_Window(_(PROGRAM_NAME ": New Project"), x, y, WIDTH, HEIGHT,
-1, -1, 0, 0, 1)
NewWindow::~NewWindow()
{
lock_window("NewWindow::~NewWindow");
- if(format_presets) delete format_presets;
+ if( format_presets ) delete format_presets;
unlock_window();
}
x = format_presets->x;
y = format_presets->y;
-
-
y += 40;
y1 = y;
add_subwindow(new BC_Title(x, y, _("Audio"), LARGEFONT));
add_subwindow(aspect_h_text = new NewAspectH(this, "", x1, y));
x1 += aspect_h_text->get_w();
add_subwindow(new AspectPulldown(mwindow,
- aspect_w_text,
- aspect_h_text,
- x1,
- y));
+ aspect_w_text, aspect_h_text, x1, y));
x1 = aspect_w_text->get_x();
y += aspect_w_text->get_h() + 5;
}
-
-
-
-
-
NewPresets::NewPresets(MWindow *mwindow, NewWindow *gui, int x, int y)
: FormatPresets(mwindow, gui, 0, x, y)
{
}
-
NewATracks::NewATracks(NewWindow *nwindow, const char *text, int x, int y)
: BC_TextBox(x, y, 90, 1, text)
{
return 1;
}
+
NewAChannels::NewAChannels(NewWindow *nwindow, const char *text, int x, int y)
: BC_TextBox(x, y, 90, 1, text)
{
return 1;
}
+
NewAChannelsTumbler::NewAChannelsTumbler(NewWindow *nwindow, int x, int y)
: BC_Tumbler(x, y)
{
return 1;
}
+
SampleRatePulldown::SampleRatePulldown(MWindow *mwindow, BC_TextBox *output, int x, int y)
- : BC_ListBox(x,
- y,
- 100,
- 200,
- LISTBOX_TEXT,
- &mwindow->theme->sample_rates,
- 0,
- 0,
- 1,
- 0,
- 1)
+ : BC_ListBox(x, y, 100, 200, LISTBOX_TEXT,
+ &mwindow->theme->sample_rates, 0, 0, 1, 0, 1)
{
this->mwindow = mwindow;
this->output = output;
}
-
-
-
-
-
-
-
-
-
-
-
-
-
NewVTracks::NewVTracks(NewWindow *nwindow, const char *text, int x, int y)
: BC_TextBox(x, y, 90, 1, text)
{
return 1;
}
+
NewVTracksTumbler::NewVTracksTumbler(NewWindow *nwindow, int x, int y)
: BC_Tumbler(x, y)
{
return 1;
}
+
NewVChannels::NewVChannels(NewWindow *nwindow, const char *text, int x, int y)
: BC_TextBox(x, y, 90, 1, text)
{
return 1;
}
+
NewVChannelsTumbler::NewVChannelsTumbler(NewWindow *nwindow, int x, int y)
: BC_Tumbler(x, y)
{
return 1;
}
+
NewFrameRate::NewFrameRate(NewWindow *nwindow, const char *text, int x, int y)
: BC_TextBox(x, y, 90, 1, text)
{
return 1;
}
+
FrameRatePulldown::FrameRatePulldown(MWindow *mwindow,
- BC_TextBox *output,
- int x,
- int y)
- : BC_ListBox(x,
- y,
- 100,
- 200,
- LISTBOX_TEXT,
- &mwindow->theme->frame_rates,
- 0,
- 0,
- 1,
- 0,
- 1)
+ BC_TextBox *output, int x, int y)
+ : BC_ListBox(x, y, 150, 250, LISTBOX_TEXT,
+ &mwindow->theme->frame_rates, 0, 0, 1, 0, 1)
{
this->mwindow = mwindow;
this->output = output;
}
FrameSizePulldown::FrameSizePulldown(Theme *theme,
- BC_TextBox *output_w,
- BC_TextBox *output_h,
- int x,
- int y)
- : BC_ListBox(x,
- y,
- 100,
- 250,
- LISTBOX_TEXT,
- &theme->frame_sizes,
- 0,
- 0,
- 1,
- 0,
- 1)
+ BC_TextBox *output_w, BC_TextBox *output_h, int x, int y)
+ : BC_ListBox(x, y, 150, 250, LISTBOX_TEXT,
+ &theme->frame_sizes, 0, 0, 1, 0, 1)
{
this->theme = theme;
this->output_w = output_w;
this->output_h = output_h;
}
+
int FrameSizePulldown::handle_event()
{
char *text = get_selection(0, 0)->get_text();
strcpy(string, text);
ptr = strrchr(string, 'x');
- if(ptr)
- {
+ if( ptr ) {
ptr++;
h = atol(ptr);
return 1;
}
+
NewOutputW::NewOutputW(NewWindow *nwindow, int x, int y)
: BC_TextBox(x, y, 70, 1, nwindow->new_edl->session->output_w)
{
return 1;
}
+
NewOutputH::NewOutputH(NewWindow *nwindow, int x, int y)
: BC_TextBox(x, y, 70, 1, nwindow->new_edl->session->output_h)
{
return 1;
}
+
NewAspectW::NewAspectW(NewWindow *nwindow, const char *text, int x, int y)
: BC_TextBox(x, y, 70, 1, text)
{
return 1;
}
+
NewAspectH::NewAspectH(NewWindow *nwindow, const char *text, int x, int y)
: BC_TextBox(x, y, 70, 1, text)
{
return 1;
}
+
AspectPulldown::AspectPulldown(MWindow *mwindow,
- BC_TextBox *output_w,
- BC_TextBox *output_h,
- int x,
- int y)
- : BC_ListBox(x,
- y,
- 100,
- 200,
- LISTBOX_TEXT,
- &mwindow->theme->aspect_ratios,
- 0,
- 0,
- 1,
- 0,
- 1)
+ BC_TextBox *output_w, BC_TextBox *output_h, int x, int y)
+ : BC_ListBox(x, y, 100, 200, LISTBOX_TEXT,
+ &mwindow->theme->aspect_ratios, 0, 0, 1, 0, 1)
{
this->mwindow = mwindow;
this->output_w = output_w;
this->output_h = output_h;
}
+
int AspectPulldown::handle_event()
{
char *text = get_selection(0, 0)->get_text();
strcpy(string, text);
ptr = strrchr(string, ':');
- if(ptr)
- {
+ if( ptr ) {
ptr++;
h = atof(ptr);
return 1;
}
+
ColormodelItem::ColormodelItem(const char *text, int value)
: BC_ListBoxItem(text)
{
}
ColormodelPulldown::ColormodelPulldown(MWindow *mwindow,
- BC_TextBox *output_text,
- int *output_value,
- int x,
- int y)
- : BC_ListBox(x,
- y,
- 200,
- 150,
- LISTBOX_TEXT,
- (ArrayList<BC_ListBoxItem*>*)&mwindow->colormodels,
- 0,
- 0,
- 1,
- 0,
- 1)
+ BC_TextBox *output_text, int *output_value, int x, int y)
+ : BC_ListBox(x, y, 200, 150, LISTBOX_TEXT,
+ (ArrayList<BC_ListBoxItem*>*)&mwindow->colormodels, 0, 0, 1, 0, 1)
{
this->mwindow = mwindow;
this->output_text = output_text;
const char* ColormodelPulldown::colormodel_to_text()
{
- for(int i = 0; i < mwindow->colormodels.total; i++)
- if(mwindow->colormodels.values[i]->value == *output_value)
+ for( int i=0; i<mwindow->colormodels.total; ++i )
+ if( mwindow->colormodels.values[i]->value == *output_value )
return mwindow->colormodels.values[i]->get_text();
return _("Unknown");
}
}
-
-
-
-
-
-
NewSwapExtents::NewSwapExtents(MWindow *mwindow, NewWindow *gui, int x, int y)
: BC_Button(x, y, mwindow->theme->get_image_set("swap_extents"))
{
return 1;
}
-
-
-
strncpy(asset->path, package->path, sizeof(asset->path));
file = new File;
-
file->set_processors(preferences->processors);
-
-//printf("PackageRenderer::create_output %d\n", __LINE__);
- result = file->open_file(preferences,
- asset,
- 0,
- 1);
-//printf("PackageRenderer::create_output %d %d\n", __LINE__, result);
+ result = file->open_file(preferences, asset, 0, 1);
if(result && mwindow)
{
direct_frame_copying = 0;
-//printf("PackageRenderer::create_engine %d\n", __LINE__);
+//printf("PackageRenderer::create_engine %d video_write_length=%d\n", __LINE__, video_write_length);
+// starting frames are corrupted if video_write_length > 2. Work around it, for now.
+ if(video_write_length > 2)
+ {
+ video_write_length = 2;
+ }
file->start_video_thread(video_write_length,
command->get_edl()->session->color_model,
preferences->processors > 1 ? 2 : 1,
VFrame *preview_output;
video_device->new_output_buffer(&preview_output,
- command->get_edl()->session->color_model);
+ command->get_edl()->session->color_model,
+ command->get_edl());
preview_output->copy_from(video_output_ptr);
video_device->write_buffer(preview_output,
//printf("Render::direct_frame_copy 2\n");
if(!package->use_brender)
+ {
error |= ((VEdit*)playable_edit)->read_frame(compressed_output,
video_position,
PLAY_FORWARD,
1,
0,
0);
-
+//printf("Render::direct_frame_copy %d %d\n", __LINE__, compressed_output->get_compressed_size());
+ }
+
if(!error && video_preroll > 0)
{
VideoOutConfig::VideoOutConfig()
{
- driver = PLAYBACK_X11_XV;
+ driver = PLAYBACK_X11;
x11_host[0] = 0;
x11_use_fields = USE_NO_FIELDS;
contrast = 32768;
whiteness = 32768;
out_channel = -1;
+ use_direct_x11 = 1;
}
VideoOutConfig::~VideoOutConfig()
return (driver == that.driver) &&
!strcmp(x11_host, that.x11_host) &&
(x11_use_fields == that.x11_use_fields) &&
+ (use_direct_x11 == that.use_direct_x11) &&
(brightness == that.brightness) &&
(hue == that.hue) &&
(color == that.color) &&
this->driver = src->driver;
strcpy(this->x11_host, src->x11_host);
this->x11_use_fields = src->x11_use_fields;
+ this->use_direct_x11 = src->use_direct_x11;
firewire_channel = src->firewire_channel;
firewire_port = src->firewire_port;
int driver;
int out_channel;
+ int use_direct_x11;
// X11 options
char x11_host[BCTEXTLEN];
x = mwindow->theme->preferencesoptions_x;
y = mwindow->theme->preferencesoptions_y;
- //int margin = mwindow->theme->widget_border;
+ int margin = mwindow->theme->widget_border;
// Audio
- add_subwindow(new BC_Title(x,
- y,
- _("Audio Out"),
- LARGEFONT));
-
-
- y += get_text_height(LARGEFONT) + 5;
-
-
BC_Title *title1, *title2;
+ add_subwindow(title1 = new BC_Title(x, y, _("Audio Out"), LARGEFONT));
+ y += title1->get_h() + margin;
add_subwindow(title2 = new BC_Title(x, y, _("Playback buffer samples:"), MEDIUMFONT));
- x2 = MAX(title2->get_w(), title2->get_w()) + 10;
+ x2 = title2->get_x() + title2->get_w() + margin;
SET_TRACE
sprintf(string, "%d", playback_config->aconfig->fragment_size);
PlaybackModuleFragment *menu;
- add_subwindow(menu = new PlaybackModuleFragment(x2,
- y,
- pwindow,
- this,
- string));
+ add_subwindow(menu = new PlaybackModuleFragment(x2, y, pwindow, this, string));
menu->add_item(new BC_MenuItem("1024"));
menu->add_item(new BC_MenuItem("2048"));
menu->add_item(new BC_MenuItem("4096"));
// Video
- y += audio_device->get_h();
+ y += audio_device->get_h(0) + margin;
SET_TRACE
- add_subwindow(new BC_Bar(5, y, get_w() - 10));
+ add_subwindow(new BC_Bar(x, y, get_w() - x * 2));
y += 5;
SET_TRACE
- add_subwindow(new BC_Title(x, y, _("Video Out"), LARGEFONT));
- y += 30;
+ add_subwindow(title1 = new BC_Title(x, y, _("Video Out"), LARGEFONT));
+ y += title1->get_h() + margin;
SET_TRACE
add_subwindow(window = new VideoEveryFrame(pwindow, this, x, y));
-
- add_subwindow(new BC_Title(x + 200, y + 5, _("Framerate achieved:")));
- add_subwindow(framerate_title = new BC_Title(x + 350, y + 5, "--", MEDIUMFONT, RED));
+ int x1 = x + window->get_w() + 30;
+ const char *txt = _("Framerate achieved:");
+ int y1 = y + (window->get_h() - BC_Title::calculate_h(this, txt)) / 2;
+ add_subwindow(title1 = new BC_Title(x1, y1, txt));
+ x1 += title1->get_w() + margin;
+ add_subwindow(framerate_title = new BC_Title(x1, y1, _("--"), MEDIUMFONT, RED));
draw_framerate(0);
- y += window->get_h() + 5;
+ y += window->get_h() + 2*margin;
- add_subwindow(asynchronous = new VideoAsynchronous(pwindow, x, y));
- y += asynchronous->get_h() + 10;
+// add_subwindow(asynchronous = new VideoAsynchronous(pwindow, x, y));
+// y += asynchronous->get_h() + 10;
SET_TRACE
add_subwindow(title1 = new BC_Title(x, y, _("Scaling equation: Enlarge / Reduce ")));
add_subwindow(title1 = new BC_Title(x, y, _("DVD Subtitle to display:")));
PlaybackSubtitleNumber *subtitle_number;
- subtitle_number = new PlaybackSubtitleNumber(x + title1->get_w() + 10,
- y,
- pwindow,
- this);
+ x1 = x + title1->get_w() + margin;
+ subtitle_number = new PlaybackSubtitleNumber(x1, y, pwindow, this);
subtitle_number->create_objects();
x2 = x + title1->get_w() + 10 + subtitle_number->get_w() + 30;
PlaybackSubtitle *subtitle_toggle;
+ x1 += subtitle_number->get_w() + margin;
add_subwindow(subtitle_toggle = new PlaybackSubtitle(x2, y, pwindow, this));
y += subtitle_toggle->get_h();
add_subwindow(interpolate_raw = new PlaybackInterpolateRaw( x, y,
pwindow, this));
- y += interpolate_raw->get_h();
+ y += interpolate_raw->get_h() + margin;
- add_subwindow(white_balance_raw = new PlaybackWhiteBalanceRaw( x, y,
+ add_subwindow(white_balance_raw = new PlaybackWhiteBalanceRaw(x, y,
pwindow, this));
- y += white_balance_raw->get_h() + 10;
- if(!pwindow->thread->edl->session->interpolate_raw)
- white_balance_raw->disable();
+ if(!pwindow->thread->edl->session->interpolate_raw)
+ white_balance_raw->disable();
+ y += white_balance_raw->get_h() + margin;
- y += white_balance_raw->get_h() + 5;
add_subwindow(vdevice_title = new BC_Title(x, y, _("Video Driver:")));
- video_device = new VDevicePrefs(x + vdevice_title->get_w() + 10, y,
- pwindow, this, playback_config->vconfig, 0, MODEPLAY);
+ y += vdevice_title->get_h() + margin;
+ video_device = new VDevicePrefs(x, y, pwindow, this,
+ playback_config->vconfig, 0, MODEPLAY);
video_device->initialize(0);
}
int PlaybackInterpolateRaw::handle_event()
{
pwindow->thread->edl->session->interpolate_raw = get_value();
- if(!pwindow->thread->edl->session->interpolate_raw) {
+ if( !pwindow->thread->edl->session->interpolate_raw ) {
playback->white_balance_raw->update(0, 0);
playback->white_balance_raw->disable();
}
return 1;
}
-
PlaybackWhiteBalanceRaw::PlaybackWhiteBalanceRaw( int x, int y,
PreferencesWindow *pwindow, PlaybackPrefs *playback)
: BC_CheckBox(x,
return 1;
}
-
-VideoAsynchronous::VideoAsynchronous(PreferencesWindow *pwindow, int x, int y)
- : BC_CheckBox(x, y,
- pwindow->thread->edl->session->video_every_frame &&
- pwindow->thread->edl->session->video_asynchronous,
- _("Decode frames asynchronously"))
-{
- this->pwindow = pwindow;
- if(!pwindow->thread->edl->session->video_every_frame)
- disable();
-}
-
-int VideoAsynchronous::handle_event()
-{
- pwindow->thread->edl->session->video_asynchronous = get_value();
- return 1;
-}
+// VideoAsynchronous::VideoAsynchronous(PreferencesWindow *pwindow, int x, int y)
+// : BC_CheckBox(x, y,
+// pwindow->thread->edl->session->video_every_frame &&
+// pwindow->thread->edl->session->video_asynchronous,
+// _("Decode frames asynchronously"))
+// {
+// this->pwindow = pwindow;
+// if(!pwindow->thread->edl->session->video_every_frame)
+// disable();
+// }
+//
+// int VideoAsynchronous::handle_event()
+// {
+// pwindow->thread->edl->session->video_asynchronous = get_value();
+// return 1;
+// }
VideoEveryFrame::VideoEveryFrame(PreferencesWindow *pwindow,
int VideoEveryFrame::handle_event()
{
pwindow->thread->edl->session->video_every_frame = get_value();
- if(!pwindow->thread->edl->session->video_every_frame) {
- playback_prefs->asynchronous->update(0, 0);
- playback_prefs->asynchronous->disable();
- }
- else {
- playback_prefs->asynchronous->update(pwindow->thread->edl->session->video_asynchronous, 0);
- playback_prefs->asynchronous->enable();
- }
+// if(!pwindow->thread->edl->session->video_every_frame) {
+// playback_prefs->asynchronous->update(0, 0);
+// playback_prefs->asynchronous->disable();
+// }
+// else {
+// playback_prefs->asynchronous->update(pwindow->thread->edl->session->video_asynchronous, 0);
+// playback_prefs->asynchronous->enable();
+// }
return 1;
}
class PlaybackSoftwareTimer;
class PlaybackRealTime;
class PlaybackMap51_2;
-class VideoAsynchronous;
+//class VideoAsynchronous;
class VideoEveryFrame;
class PlaybackPreload;
class PlaybackInterpolateRaw;
BC_Title *framerate_title;
PlaybackInterpolateRaw *interpolate_raw;
PlaybackWhiteBalanceRaw *white_balance_raw;
- VideoAsynchronous *asynchronous;
+// VideoAsynchronous *asynchronous;
BC_Title *vdevice_title;
PlaybackAudioOffset *audio_offset;
PreferencesWindow *pwindow;
};
+// class VideoAsynchronous : public BC_CheckBox
+// {
+// public:
+// VideoAsynchronous(PreferencesWindow *pwindow, int x, int y);
+// int handle_event();
+// PreferencesWindow *pwindow;
+// };
+
class PlaybackMap51_2 : public BC_CheckBox
{
public:
PlaybackPrefs *playback_prefs;
};
-class VideoAsynchronous : public BC_CheckBox
-{
-public:
- VideoAsynchronous(PreferencesWindow *pwindow, int x, int y);
- int handle_event();
- PreferencesWindow *pwindow;
-};
-
class VideoEveryFrame : public BC_CheckBox
{
public:
float PluginClient::get_red()
{
- if(server->mwindow)
- return server->mwindow->edl->local_session->red;
- else
- if(server->edl)
- return server->edl->local_session->red;
- else
- return 0;
+ EDL *edl = server->mwindow ? server->mwindow->edl : server->edl;
+ return !edl ? 0 : edl->local_session->use_max ?
+ edl->local_session->red_max :
+ edl->local_session->red;
}
float PluginClient::get_green()
{
- if(server->mwindow)
- return server->mwindow->edl->local_session->green;
- else
- if(server->edl)
- return server->edl->local_session->green;
- else
- return 0;
+ EDL *edl = server->mwindow ? server->mwindow->edl : server->edl;
+ return !edl ? 0 : edl->local_session->use_max ?
+ edl->local_session->green_max :
+ edl->local_session->green;
}
float PluginClient::get_blue()
{
- if(server->mwindow)
- return server->mwindow->edl->local_session->blue;
- else
- if(server->edl)
- return server->edl->local_session->blue;
- else
- return 0;
+ EDL *edl = server->mwindow ? server->mwindow->edl : server->edl;
+ return !edl ? 0 : edl->local_session->use_max ?
+ edl->local_session->blue_max :
+ edl->local_session->blue;
}
-
int64_t PluginClient::get_source_position()
{
return source_position;
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "bcsignals.h"
+#include "bcwindowbase.inc"
+#include "file.h"
+#include "filesystem.h"
+#include "filexml.h"
+#include "keyframe.h"
+#include "messages.inc"
+#include "mwindow.h"
+#include "pluginserver.h"
+#include "preferences.inc"
+#include "presets.h"
+
+#include <errno.h>
+#include <string.h>
+
+PresetsDB::PresetsDB()
+{
+}
+
+void PresetsDB::clear()
+{
+ plugins.remove_all_objects();
+}
+
+void PresetsDB::load_from_file(char *path, int is_factory, int clear_it)
+{
+ if( clear_it ) clear();
+ FileXML file;
+
+ file.read_from_file(path);
+ load_common(&file, is_factory);
+}
+
+void PresetsDB::load_from_string(char *string, int is_factory, int clear_it)
+{
+ if( clear_it ) clear();
+
+ FileXML file;
+ file.read_from_string(string);
+ load_common(&file, is_factory);
+}
+
+
+
+void PresetsDB::load_common(FileXML *file, int is_factory)
+{
+ int result = 0;
+ char string[BCTEXTLEN];
+
+ do {
+ result = file->read_tag();
+ if( ! result ) {
+ if( file->tag.title_is("PLUGIN") ) {
+ PresetsDBPlugin *plugin = 0;
+ sprintf(string, "Unknown");
+ const char *title = file->tag.get_property("TITLE", string);
+
+// Search for existing plugin
+ for( int i=0; i<plugins.size(); ++i ) {
+ if( !strcasecmp(plugins[i]->title, title) ) {
+ plugin = plugins[i];
+ break;
+ }
+ }
+
+// Create new plugin
+ if( !plugin ) {
+ plugin = new PresetsDBPlugin(title);
+ plugins.append(plugin);
+ }
+
+ plugin->load(file, is_factory);
+ }
+ }
+ } while(!result);
+}
+
+
+void PresetsDB::save()
+{
+ FileXML file;
+ for( int i=0; i<plugins.size(); ++i ) {
+ PresetsDBPlugin *plugin = plugins[i];
+ if( plugin->get_total_presets(1) > 0 ) {
+ plugin->save(&file);
+ }
+ }
+ file.terminate_string();
+
+ char path[BCTEXTLEN];
+ sprintf(path, "%s/%s", File::get_config_path(), PRESETS_FILE);
+ FileSystem fs;
+ fs.complete_path(path);
+ file.write_to_file(path);
+}
+
+
+int PresetsDB::get_total_presets(char *plugin_title, int user_only)
+{
+ for( int i=0; i<plugins.size(); ++i ) {
+ PresetsDBPlugin *plugin = plugins[i];
+ if( !strcasecmp(plugin->title, plugin_title) ) {
+ return plugin->get_total_presets(user_only);
+ }
+ }
+
+ return 0;
+}
+
+
+// move factory presets to the start, followed by sorted preset titles
+void PresetsDB::sort(char *plugin_title)
+{
+ PresetsDBPlugin *plugin = 0;
+ for( int i=0; !plugin && i<plugins.size(); ++i ) {
+ if( !strcasecmp(plugins[i]->title, plugin_title) )
+ plugin = plugins[i];
+ }
+
+ if( plugin ) {
+ int done = 0;
+ int total_presets = plugin->get_total_presets(0);
+ while( !done ) {
+ done = 1;
+ for( int i=0; i<total_presets-1; ++i ) {
+ PresetsDBKeyframe *keyframe1 = plugin->keyframes[i];
+ PresetsDBKeyframe *keyframe2 = plugin->keyframes[i+1];
+
+ if( (keyframe2->is_factory && !keyframe1->is_factory) ||
+ (keyframe2->is_factory == keyframe1->is_factory &&
+ strcmp(keyframe2->title, keyframe1->title) < 0) ) {
+ plugin->keyframes.set(i, keyframe2);
+ plugin->keyframes.set(i + 1, keyframe1);
+ done = 0;
+ }
+ }
+ }
+ }
+}
+
+
+char* PresetsDB::get_preset_title(char *plugin_title, int number)
+{
+ for( int i=0; i<plugins.size(); ++i ) {
+ PresetsDBPlugin *plugin = plugins[i];
+ if( !strcasecmp(plugin->title, plugin_title) ) {
+ if( number < plugin->keyframes.size() )
+ return plugin->keyframes[number]->title;
+ printf("PresetsDB::get_preset_title %d buffer overrun\n", __LINE__);
+ break;
+ }
+ }
+ return 0;
+}
+
+
+int PresetsDB::get_is_factory(char *plugin_title, int number)
+{
+ for( int i=0; i<plugins.size(); ++i ) {
+ PresetsDBPlugin *plugin = plugins[i];
+ if( !strcasecmp(plugin->title, plugin_title) ) {
+ if( number < plugin->keyframes.size() )
+ return plugin->keyframes[number]->is_factory;
+ printf("PresetsDB::get_preset_title %d buffer overrun\n", __LINE__);
+ break;
+ }
+ }
+ return 0;
+}
+
+
+char* PresetsDB::get_preset_data(char *plugin_title, int number)
+{
+ for( int i=0; i<plugins.size(); ++i ) {
+ PresetsDBPlugin *plugin = plugins[i];
+ if( !strcasecmp(plugin->title, plugin_title) ) {
+ if( number < plugin->keyframes.size() )
+ return plugin->keyframes[number]->data;
+ printf("PresetsDB::get_preset_data %d buffer overrun\n", __LINE__);
+ break;
+ }
+ }
+ return 0;
+}
+
+PresetsDBPlugin* PresetsDB::get_plugin(const char *plugin_title)
+{
+ for( int i=0; i<plugins.size(); ++i ) {
+ PresetsDBPlugin *plugin = plugins[i];
+ if( !strcasecmp(plugin->title, plugin_title) )
+ return plugin;
+ }
+ return 0;
+}
+
+PresetsDBPlugin* PresetsDB::new_plugin(const char *plugin_title)
+{
+ PresetsDBPlugin *result = new PresetsDBPlugin(plugin_title);
+ plugins.append(result);
+ return result;
+}
+
+
+void PresetsDB::save_preset(const char *plugin_title,
+ const char *preset_title,
+ char *data)
+{
+ PresetsDBPlugin *plugin = get_plugin(plugin_title);
+ if( !plugin ) plugin = new_plugin(plugin_title);
+ PresetsDBKeyframe *keyframe = plugin->get_keyframe(preset_title, 0);
+ if( !keyframe ) keyframe = plugin->new_keyframe(preset_title);
+ keyframe->set_data(data);
+ save();
+
+}
+
+
+void PresetsDB::delete_preset(const char *plugin_title,
+ const char *preset_title,
+ int is_factory)
+{
+ PresetsDBPlugin *plugin = get_plugin(plugin_title);
+ if( plugin ) {
+ plugin->delete_keyframe(preset_title);
+ }
+ save();
+}
+
+void PresetsDB::load_preset(const char *plugin_title,
+ const char *preset_title,
+ KeyFrame *keyframe,
+ int is_factory)
+{
+ PresetsDBPlugin *plugin = get_plugin(plugin_title);
+ if( plugin ) {
+ plugin->load_preset(preset_title, keyframe, is_factory);
+ }
+}
+
+int PresetsDB::preset_exists(const char *plugin_title,
+ const char *preset_title,
+ int is_factory)
+{
+ PresetsDBPlugin *plugin = get_plugin(plugin_title);
+ if( plugin ) {
+ return plugin->preset_exists(preset_title, is_factory);
+ }
+ return 0;
+}
+
+
+
+
+PresetsDBKeyframe::PresetsDBKeyframe(const char *title, int is_factory)
+{
+ this->title = strdup(title);
+ data = 0;
+ this->is_factory = is_factory;
+}
+
+PresetsDBKeyframe::~PresetsDBKeyframe()
+{
+ delete [] title;
+ delete [] data;
+}
+
+void PresetsDBKeyframe::set_data(char *data)
+{
+ delete [] this->data;
+ this->data = new char[strlen(data) + 1];
+ strcpy(this->data, data);
+}
+
+
+PresetsDBPlugin::PresetsDBPlugin(const char *title)
+{
+ this->title = strdup(title);
+}
+
+PresetsDBPlugin::~PresetsDBPlugin()
+{
+ keyframes.remove_all_objects();
+ delete [] title;
+}
+
+int PresetsDBPlugin::get_total_presets(int user_only)
+{
+ if( !user_only )
+ return keyframes.size();
+ int result = 0;
+ for( int j=0; j<keyframes.size(); ++j )
+ if( !keyframes[j]->is_factory ) ++result;
+ return result;
+}
+
+void PresetsDBPlugin::load(FileXML *file, int is_factory)
+{
+ int result = 0;
+ char string[BCTEXTLEN];
+
+ do {
+ result = file->read_tag();
+ if( !result ) {
+ if( file->tag.title_is("/PLUGIN") ) break;
+ else
+ if( file->tag.title_is("KEYFRAME") ) {
+ sprintf(string, "Unknown");
+ const char *keyframe_title = file->tag.get_property("TITLE", string);
+ PresetsDBKeyframe *keyframe = new PresetsDBKeyframe(keyframe_title, is_factory);
+
+ char data[MESSAGESIZE];
+ file->read_text_until("/KEYFRAME", data, MESSAGESIZE);
+ keyframe->set_data(data);
+ keyframes.append(keyframe);
+
+ }
+ }
+ } while(!result);
+}
+
+void PresetsDBPlugin::save(FileXML *file)
+{
+ file->tag.set_title("PLUGIN");
+ file->tag.set_property("TITLE", title);
+ file->append_tag();
+ file->append_newline();
+
+ for( int j=0; j<keyframes.size(); ++j ) {
+ PresetsDBKeyframe *keyframe = keyframes[j];
+
+ if( !keyframe->is_factory ) {
+ file->tag.set_title("KEYFRAME");
+ file->tag.set_property("TITLE", keyframe->title);
+ file->append_tag();
+ file->append_text(keyframe->data);
+ file->tag.set_title("/KEYFRAME");
+ file->append_tag();
+ file->append_newline();
+ }
+ }
+
+ file->tag.set_title("/PLUGIN");
+ file->append_tag();
+ file->append_newline();
+}
+
+PresetsDBKeyframe* PresetsDBPlugin::get_keyframe(const char *title,
+ int is_factory)
+{
+ for( int i=0; i<keyframes.size(); ++i ) {
+ PresetsDBKeyframe *keyframe = keyframes[i];
+ if( !strcasecmp(keyframe->title, title) &&
+ keyframe->is_factory == is_factory )
+ return keyframe;
+ }
+ return 0;
+}
+
+void PresetsDBPlugin::delete_keyframe(const char *title)
+{
+ for( int i=0; i<keyframes.size(); ++i ) {
+ PresetsDBKeyframe *keyframe = keyframes[i];
+ if( !strcasecmp(keyframe->title, title) && !keyframe->is_factory )
+ keyframes.remove_object_number(i);
+ return;
+ }
+}
+
+
+PresetsDBKeyframe* PresetsDBPlugin::new_keyframe(const char *title)
+{
+ PresetsDBKeyframe *keyframe = new PresetsDBKeyframe(title, 0);
+ keyframes.append(keyframe);
+ return keyframe;
+}
+
+void PresetsDBPlugin::load_preset(const char *preset_title,
+ KeyFrame *keyframe,
+ int is_factory)
+{
+ PresetsDBKeyframe *src = get_keyframe(preset_title, is_factory);
+ if( src ) {
+ keyframe->set_data(src->data);
+// Save as the plugin's default, Need the path
+//printf("PresetsDBPlugin::load_preset %d %s\n", __LINE__, title);
+ PluginServer *server = MWindow::scan_plugindb(title, -1);
+ if( server ) {
+ char path[BCTEXTLEN];
+ server->get_defaults_path(path);
+ FileSystem fs;
+ fs.complete_path(path);
+
+ FILE *fd = fopen(path, "w");
+ if( fd ) {
+ if( !fwrite(src->data, strlen(src->data), 1, fd) ) {
+ fprintf(stderr, "PresetsDBPlugin::load_preset %d \"%s\": %s\n",
+ __LINE__,
+ path,
+ strerror(errno));
+ }
+
+ fclose(fd);
+ }
+ else {
+ fprintf(stderr, "PresetsDBPlugin::load_preset %d \"%s\": %s\n",
+ __LINE__, path, strerror(errno));
+ }
+ }
+ }
+}
+
+int PresetsDBPlugin::preset_exists(const char *preset_title, int is_factory)
+{
+ PresetsDBKeyframe *src = get_keyframe(preset_title, is_factory);
+ return src ? 1 : 0;
+}
+
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef PRESETS_H
+#define PRESETS_H
+
+
+#include "arraylist.h"
+#include "filexml.inc"
+#include "keyframe.inc"
+
+
+// Front end for a DB of presets for all plugins
+
+// A single preset
+class PresetsDBKeyframe
+{
+public:
+ PresetsDBKeyframe(const char *title, int is_factory);
+ ~PresetsDBKeyframe();
+
+ void set_data(char *data);
+
+ char *title;
+ char *data;
+// is a factory preset
+ int is_factory;
+};
+
+// Presets for a single plugin
+class PresetsDBPlugin
+{
+public:
+ PresetsDBPlugin(const char *title);
+ ~PresetsDBPlugin();
+
+
+ void load(FileXML *file, int is_factory);
+ void save(FileXML *file);
+
+// Get a preset by name
+ PresetsDBKeyframe* get_keyframe(const char *title, int is_factory);
+// Create a new keyframe
+ PresetsDBKeyframe* new_keyframe(const char *title);
+ void delete_keyframe(const char *title);
+// Load a preset into the keyframe
+ void load_preset(const char *preset_title,
+ KeyFrame *keyframe,
+ int is_factory);
+ int preset_exists(const char *preset_title, int is_factory);
+ int get_total_presets(int user_only);
+
+ ArrayList<PresetsDBKeyframe*> keyframes;
+ char *title;
+};
+
+class PresetsDB
+{
+public:
+ PresetsDB();
+
+// Load the database from the file.
+ void load_from_file(char *path, int is_factory, int clear_it);
+// load the database from a string
+ void load_from_string(char *string, int is_factory, int clear_it);
+ void load_common(FileXML *file, int is_factory);
+
+// Save the database to the file.
+ void save();
+ void sort(char *plugin_title);
+
+// Get the total number of presets for a plugin
+ int get_total_presets(char *plugin_title, int user_only);
+// Get the title of a preset
+ char* get_preset_title(char *plugin_title, int number);
+ int get_is_factory(char *plugin_title, int number);
+// Get the data for a preset
+ char* get_preset_data(char *plugin_title, int number);
+// Get a pluginDB by name
+ PresetsDBPlugin* get_plugin(const char *plugin_title);
+// Create a pluginDB
+ PresetsDBPlugin* new_plugin(const char *plugin_title);
+ void save_preset(const char *plugin_title,
+ const char *preset_title,
+ char *data);
+ void delete_preset(const char *plugin_title,
+ const char *preset_title,
+ int is_factory);
+// Load a preset into the keyframe
+ void load_preset(const char *plugin_title,
+ const char *preset_title,
+ KeyFrame *keyframe,
+ int is_factory);
+ int preset_exists(const char *plugin_title,
+ const char *preset_title,
+ int is_factory);
+
+private:
+// Remove all plugin data
+ void clear();
+
+ ArrayList<PresetsDBPlugin*> plugins;
+};
+
+
+
+#endif
+
+
+
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef PRESETS_INC
+#define PRESETS_INC
+
+
+class PresetsDB;
+
+#endif
+
+
+
+
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#if 0
+
+
+
+
+#include "edl.h"
+#include "keyframe.h"
+#include "keys.h"
+#include "language.h"
+#include "localsession.h"
+#include "mainsession.h"
+#include "mainundo.h"
+#include "mwindow.h"
+#include "mwindowgui.h"
+#include "plugin.h"
+#include "presets.h"
+#include "presetsgui.h"
+#include "theme.h"
+#include "trackcanvas.h"
+#include "tracks.h"
+
+
+
+
+
+
+
+
+
+
+
+PresetsThread::PresetsThread(MWindow *mwindow)
+ : BC_DialogThread()
+{
+ this->mwindow = mwindow;
+ plugin = 0;
+ data = new ArrayList<BC_ListBoxItem*>;
+ presets_db = new PresetsDB;
+ plugin_title[0] = 0;
+ window_title[0] = 0;
+}
+
+PresetsThread::~PresetsThread()
+{
+ delete data;
+}
+
+void PresetsThread::calculate_list()
+{
+ data->remove_all_objects();
+ int total_presets = presets_db->get_total_presets(plugin_title);
+ for(int i = 0; i < total_presets; i++)
+ {
+ data->append(new BC_ListBoxItem(presets_db->get_preset_title(
+ plugin_title,
+ i)));
+ }
+}
+
+
+void PresetsThread::start_window(Plugin *plugin)
+{
+ if(!BC_DialogThread::is_running())
+ {
+ this->plugin = plugin;
+ plugin->calculate_title(plugin_title, 0);
+ sprintf(window_title, PROGRAM_NAME ": %s Presets", plugin_title);
+
+
+// Calculate database
+ presets_db->load();
+ calculate_list();
+
+
+ mwindow->gui->unlock_window();
+ BC_DialogThread::start();
+ mwindow->gui->lock_window("PresetsThread::start_window");
+ }
+}
+
+BC_Window* PresetsThread::new_gui()
+{
+ mwindow->gui->lock_window("PresetsThread::new_gui");
+ int x = mwindow->gui->get_abs_cursor_x(0) -
+ mwindow->session->plugindialog_w / 2;
+ int y = mwindow->gui->get_abs_cursor_y(0) -
+ mwindow->session->plugindialog_h / 2;
+
+ PresetsWindow *window = new PresetsWindow(mwindow,
+ this,
+ x,
+ y,
+ window_title);
+
+ window->create_objects();
+ mwindow->gui->unlock_window();
+ return window;
+}
+
+void PresetsThread::handle_done_event(int result)
+{
+// Apply the preset
+ if(!result)
+ {
+ char *title = ((PresetsWindow*)get_gui())->title_text->get_text();
+ apply_preset(title);
+ }
+}
+
+void PresetsThread::handle_close_event(int result)
+{
+}
+
+void PresetsThread::save_preset(char *title)
+{
+ get_gui()->unlock_window();
+ mwindow->gui->lock_window("PresetsThread::save_preset");
+
+// Test EDL for plugin existence
+ if(!mwindow->edl->tracks->plugin_exists(plugin))
+ {
+ mwindow->gui->unlock_window();
+ get_gui()->lock_window("PresetsThread::save_preset 2");
+ return;
+ }
+
+
+// Get current plugin keyframe
+ EDL *edl = mwindow->edl;
+ Track *track = plugin->track;
+ KeyFrame *keyframe = plugin->get_prev_keyframe(
+ track->to_units(edl->local_session->get_selectionstart(1), 0),
+ PLAY_FORWARD);
+
+// Send to database
+ presets_db->save_preset(plugin_title, title, keyframe->get_data());
+
+ mwindow->gui->unlock_window();
+ get_gui()->lock_window("PresetsThread::save_preset 2");
+
+
+// Update list
+ calculate_list();
+ ((PresetsWindow*)get_gui())->list->update(data,
+ 0,
+ 0,
+ 1);
+}
+
+void PresetsThread::delete_preset(char *title)
+{
+ get_gui()->unlock_window();
+ mwindow->gui->lock_window("PresetsThread::save_preset");
+
+// Test EDL for plugin existence
+ if(!mwindow->edl->tracks->plugin_exists(plugin))
+ {
+ mwindow->gui->unlock_window();
+ get_gui()->lock_window("PresetsThread::delete_preset 1");
+ return;
+ }
+
+ presets_db->delete_preset(plugin_title, title);
+
+ mwindow->gui->unlock_window();
+ get_gui()->lock_window("PresetsThread::delete_preset 2");
+
+
+// Update list
+ calculate_list();
+ ((PresetsWindow*)get_gui())->list->update(data,
+ 0,
+ 0,
+ 1);
+}
+
+
+void PresetsThread::apply_preset(char *title)
+{
+ if(presets_db->preset_exists(plugin_title, title))
+ {
+ get_gui()->unlock_window();
+ mwindow->gui->lock_window("PresetsThread::apply_preset");
+
+// Test EDL for plugin existence
+ if(!mwindow->edl->tracks->plugin_exists(plugin))
+ {
+ mwindow->gui->unlock_window();
+ get_gui()->lock_window("PresetsThread::delete_preset 1");
+ return;
+ }
+
+ mwindow->undo->update_undo_before();
+ KeyFrame *keyframe = plugin->get_keyframe();
+ presets_db->load_preset(plugin_title, title, keyframe);
+ mwindow->save_backup();
+ mwindow->undo->update_undo_after(_("apply preset"), LOAD_AUTOMATION);
+
+ mwindow->update_plugin_guis();
+ mwindow->gui->canvas->draw_overlays();
+ mwindow->gui->canvas->flash();
+ mwindow->sync_parameters(CHANGE_PARAMS);
+
+ mwindow->gui->unlock_window();
+ get_gui()->lock_window("PresetsThread::apply_preset");
+ }
+}
+
+
+
+
+
+PresetsList::PresetsList(PresetsThread *thread,
+ PresetsWindow *window,
+ int x,
+ int y,
+ int w,
+ int h)
+ : BC_ListBox(x,
+ y,
+ w,
+ h,
+ LISTBOX_TEXT,
+ thread->data)
+{
+ this->thread = thread;
+ this->window = window;
+}
+
+int PresetsList::selection_changed()
+{
+ window->title_text->update(
+ thread->data->get(get_selection_number(0, 0))->get_text());
+ return 0;
+}
+
+int PresetsList::handle_event()
+{
+ window->set_done(0);
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+PresetsText::PresetsText(PresetsThread *thread,
+ PresetsWindow *window,
+ int x,
+ int y,
+ int w)
+ : BC_TextBox(x,
+ y,
+ w,
+ 1,
+ "")
+{
+ this->thread = thread;
+ this->window = window;
+}
+
+int PresetsText::handle_event()
+{
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+PresetsDelete::PresetsDelete(PresetsThread *thread,
+ PresetsWindow *window,
+ int x,
+ int y)
+ : BC_GenericButton(x, y, _("Delete"))
+{
+ this->thread = thread;
+ this->window = window;
+}
+
+int PresetsDelete::handle_event()
+{
+ thread->delete_preset(window->title_text->get_text());
+ return 1;
+}
+
+
+
+
+
+
+
+PresetsSave::PresetsSave(PresetsThread *thread,
+ PresetsWindow *window,
+ int x,
+ int y)
+: BC_GenericButton(x, y, _("Save"))
+{
+ this->thread = thread;
+ this->window = window;
+}
+
+int PresetsSave::handle_event()
+{
+ thread->save_preset(window->title_text->get_text());
+ return 1;
+}
+
+
+
+
+
+
+
+
+PresetsApply::PresetsApply(PresetsThread *thread,
+ PresetsWindow *window,
+ int x,
+ int y)
+ : BC_GenericButton(x, y, _("Apply"))
+{
+ this->thread = thread;
+ this->window = window;
+}
+
+int PresetsApply::handle_event()
+{
+ thread->apply_preset(window->title_text->get_text());
+ return 1;
+}
+
+
+
+PresetsOK::PresetsOK(PresetsThread *thread,
+ PresetsWindow *window)
+ : BC_OKButton(window)
+{
+ this->thread = thread;
+ this->window = window;
+}
+
+int PresetsOK::keypress_event()
+{
+ if(get_keypress() == RETURN)
+ {
+printf("PresetsOK::keypress_event %d\n", __LINE__);
+ if(thread->presets_db->preset_exists(thread->plugin_title,
+ window->title_text->get_text()))
+ {
+printf("PresetsOK::keypress_event %d\n", __LINE__);
+ window->set_done(0);
+ return 1;
+ }
+ else
+ {
+printf("PresetsOK::keypress_event %d\n", __LINE__);
+ thread->save_preset(window->title_text->get_text());
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+PresetsWindow::PresetsWindow(MWindow *mwindow,
+ PresetsThread *thread,
+ int x,
+ int y,
+ char *title_string)
+ : BC_Window(title_string,
+ x,
+ y,
+ mwindow->session->presetdialog_w,
+ mwindow->session->presetdialog_h,
+ 320,
+ 240,
+ 1,
+ 0,
+ 1)
+{
+ this->mwindow = mwindow;
+ this->thread = thread;
+}
+
+void PresetsWindow::create_objects()
+{
+ Theme *theme = mwindow->theme;
+
+ lock_window("PresetsWindow::create_objects");
+ theme->get_presetdialog_sizes(this);
+
+ add_subwindow(title1 = new BC_Title(theme->presets_list_x,
+ theme->presets_list_y - BC_Title::calculate_h(this, "P") - theme->widget_border,
+ _("Saved presets:")));
+ add_subwindow(list = new PresetsList(thread,
+ this,
+ theme->presets_list_x,
+ theme->presets_list_y,
+ theme->presets_list_w,
+ theme->presets_list_h));
+ add_subwindow(title2 = new BC_Title(theme->presets_text_x,
+ theme->presets_text_y - BC_Title::calculate_h(this, "P") - theme->widget_border,
+ _("Preset title:")));
+ add_subwindow(title_text = new PresetsText(thread,
+ this,
+ theme->presets_text_x,
+ theme->presets_text_y,
+ theme->presets_text_w));
+ add_subwindow(delete_button = new PresetsDelete(thread,
+ this,
+ theme->presets_delete_x,
+ theme->presets_delete_y));
+ add_subwindow(save_button = new PresetsSave(thread,
+ this,
+ theme->presets_save_x,
+ theme->presets_save_y));
+ add_subwindow(apply_button = new PresetsApply(thread,
+ this,
+ theme->presets_apply_x,
+ theme->presets_apply_y));
+
+ add_subwindow(new PresetsOK(thread, this));
+ add_subwindow(new BC_CancelButton(this));
+
+ show_window();
+ unlock_window();
+}
+
+int PresetsWindow::resize_event(int w, int h)
+{
+ Theme *theme = mwindow->theme;
+ mwindow->session->presetdialog_w = w;
+ mwindow->session->presetdialog_h = h;
+ theme->get_presetdialog_sizes(this);
+
+ title1->reposition_window(theme->presets_list_x,
+ theme->presets_list_y - BC_Title::calculate_h(this, "P") - theme->widget_border);
+ title2->reposition_window(theme->presets_text_x,
+ theme->presets_text_y - BC_Title::calculate_h(this, "P") - theme->widget_border);
+ list->reposition_window(theme->presets_list_x,
+ theme->presets_list_y,
+ theme->presets_list_w,
+ theme->presets_list_h);
+ title_text->reposition_window(theme->presets_text_x,
+ theme->presets_text_y,
+ theme->presets_text_w);
+ delete_button->reposition_window(theme->presets_delete_x,
+ theme->presets_delete_y);
+ save_button->reposition_window(theme->presets_save_x,
+ theme->presets_save_y);
+ apply_button->reposition_window(theme->presets_apply_x,
+ theme->presets_apply_y);
+ return 0;
+}
+
+
+
+
+
+
+#endif
+
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef PRESETSGUI_H
+#define PRESETSGUI_H
+
+
+// Presets for effects & transitions
+#if 0
+
+#include "bcdialog.h"
+#include "guicast.h"
+#include "mwindow.inc"
+#include "plugin.inc"
+#include "presets.inc"
+
+class PresetsWindow;
+
+
+
+
+
+class PresetsThread : public BC_DialogThread
+{
+public:
+ PresetsThread(MWindow *mwindow);
+ ~PresetsThread();
+
+ void calculate_list();
+ void start_window(Plugin *plugin);
+ BC_Window* new_gui();
+ void handle_done_event(int result);
+ void handle_close_event(int result);
+ void save_preset(char *title);
+ void delete_preset(char *title);
+ void apply_preset(char *title);
+
+ char window_title[BCTEXTLEN];
+ char plugin_title[BCTEXTLEN];
+ MWindow *mwindow;
+ Plugin *plugin;
+ ArrayList<BC_ListBoxItem*> *data;
+ PresetsDB *presets_db;
+};
+
+class PresetsList : public BC_ListBox
+{
+public:
+ PresetsList(PresetsThread *thread,
+ PresetsWindow *window,
+ int x,
+ int y,
+ int w,
+ int h);
+ int selection_changed();
+ int handle_event();
+ PresetsThread *thread;
+ PresetsWindow *window;
+};
+
+class PresetsText : public BC_TextBox
+{
+public:
+ PresetsText(PresetsThread *thread,
+ PresetsWindow *window,
+ int x,
+ int y,
+ int w);
+ int handle_event();
+ PresetsThread *thread;
+ PresetsWindow *window;
+};
+
+
+class PresetsDelete : public BC_GenericButton
+{
+public:
+ PresetsDelete(PresetsThread *thread,
+ PresetsWindow *window,
+ int x,
+ int y);
+ int handle_event();
+ PresetsThread *thread;
+ PresetsWindow *window;
+};
+
+class PresetsSave : public BC_GenericButton
+{
+public:
+ PresetsSave(PresetsThread *thread,
+ PresetsWindow *window,
+ int x,
+ int y);
+ int handle_event();
+ PresetsThread *thread;
+ PresetsWindow *window;
+};
+
+class PresetsApply : public BC_GenericButton
+{
+public:
+ PresetsApply(PresetsThread *thread,
+ PresetsWindow *window,
+ int x,
+ int y);
+ int handle_event();
+ PresetsThread *thread;
+ PresetsWindow *window;
+};
+
+class PresetsOK : public BC_OKButton
+{
+public:
+ PresetsOK(PresetsThread *thread,
+ PresetsWindow *window);
+ int keypress_event();
+ PresetsThread *thread;
+ PresetsWindow *window;
+};
+
+
+class PresetsWindow : public BC_Window
+{
+public:
+ PresetsWindow(MWindow *mwindow,
+ PresetsThread *thread,
+ int x,
+ int y,
+ char *title_string);
+
+ void create_objects();
+ int resize_event(int w, int h);
+
+ PresetsList *list;
+ PresetsText *title_text;
+ PresetsDelete *delete_button;
+ PresetsSave *save_button;
+ PresetsApply *apply_button;
+ BC_Title *title1;
+ BC_Title *title2;
+ MWindow *mwindow;
+ PresetsThread *thread;
+};
+
+
+
+#endif
+
+#endif
+
+
+
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef PRESETSGUI_INC
+#define PRESETSGUI_INC
+
+
+class PresetsThread;
+class PresetsWindow;
+
+#endif
+
+
+
+
video_zoom = defaults->get("RECORD_VIDEO_Z", (float)1);
picture->load_defaults();
reverse_interlace = defaults->get("REVERSE_INTERLACE", 0);
+ do_cursor = defaults->get("RECORD_CURSOR", 0);
+ do_big_cursor = defaults->get("RECORD_BIG_CURSOR", 0);
for( int i=0; i<MAXCHANNELS; ++i ) {
sprintf(string, "RECORD_DCOFFSET_%d", i);
dc_offset[i] = defaults->get(string, 0);
defaults->update("RECORD_VIDEO_Z", video_zoom);
picture->save_defaults();
defaults->update("REVERSE_INTERLACE", reverse_interlace);
+ defaults->update("RECORD_CURSOR", do_cursor);
+ defaults->update("RECORD_BIG_CURSOR", do_big_cursor);
for( int i=0; i<MAXCHANNELS; ++i ) {
sprintf(string, "RECORD_DCOFFSET_%d", i);
defaults->update(string, dc_offset[i]);
mwindow->undo->update_undo_before();
// For pasting, clear the active region
if(load_mode == LOADMODE_PASTE)
- mwindow->clear(0);
+ mwindow->clear(0, 1);
int loadmode = load_mode == LOADMODE_RESOURCESONLY ?
LOADMODE_ASSETSONLY : load_mode;
mwindow->paste_edls(&new_edls, loadmode, 0, -1,
void Record::stop(int wait)
{
stop_operation();
- if( wait && running() )
+ if( record_gui )
record_gui->set_done(1);
- join();
+ if( wait )
+ join();
window_lock->lock("Record::stop");
delete record_thread; record_thread = 0;
delete record_monitor; record_monitor = 0;
master_channel->copy_usage(vdevice->channel);
picture->copy_usage(vdevice->picture);
vdevice->set_field_order(reverse_interlace);
+ vdevice->set_do_cursor(do_cursor, do_big_cursor);
vdevice->set_adevice(adevice);
if( adevice ) adevice->set_vdevice(vdevice);
set_dev_channel(get_current_channel());
record_gui->power_off->update(value);
}
-int Record::set_video_picture()
+void Record::set_video_picture()
{
if( default_asset->video_data && vdevice )
vdevice->set_picture(picture);
- return 0;
+}
+
+void Record::set_do_cursor()
+{
+ vdevice->set_do_cursor(do_cursor, do_big_cursor);
}
void Record::set_translation(int x, int y)
void set_play_gain(double gain);
void set_video_monitoring(int mode);
void stop_operation();
- int set_video_picture();
+ void set_video_picture();
+ void set_do_cursor();
// Set screencapture translation
void set_translation(int x, int y);
float video_zoom;
// Reverse the interlace in the video window display only
int reverse_interlace;
+// record the cursor for screencapture
+ int do_cursor;
+ int do_big_cursor;
// Color model for uncompressed device interface
int color_model;
// Picture quality and parameters the device supports
/*
* CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
RecordGUI::~RecordGUI()
{
-TRACE("RecordGUI::~RecordGUI 1");
delete status_thread;
delete batch_source;
delete batch_mode;
delete batch_start;
delete batch_duration;
delete load_mode;
-TRACE("RecordGUI::~RecordGUI 2");
}
return 1;
}
-
-
/*
* CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
mwindow->session->rwindow_fullscreen = 0;
if( !record->default_asset->video_data )
- min_w = MeterPanel::get_meters_width(
- mwindow->theme,
+ min_w = MeterPanel::get_meters_width(mwindow->theme,
record->default_asset->channels, 1);
-
-
-//SET_TRACE
window = new RecordMonitorGUI(mwindow, record, this, min_w);
-//SET_TRACE
window->create_objects();
-//SET_TRACE
if( record->default_asset->video_data ) {
// Configure the output for record monitoring
VideoOutConfig config;
-//SET_TRACE
device = new VideoDevice;
-//SET_TRACE
-
-
// Override default device for X11 drivers
if(mwindow->edl->session->playback_config->vconfig->driver ==
PLAYBACK_X11_XV) config.driver = PLAYBACK_X11_XV;
config.x11_use_fields = 0;
-
-//SET_TRACE
-
device->open_output(&config,
record->default_asset->frame_rate,
record->default_asset->width,
record->default_asset->height,
window->canvas, 0);
-//SET_TRACE
scope_thread = new RecordScopeThread(mwindow, this);
- if(mwindow->session->record_scope)
- {
+ if(mwindow->session->record_scope) {
scope_thread->start();
}
-
thread = new RecordMonitorThread(mwindow, record, this);
-//SET_TRACE
thread->start_playback();
-//SET_TRACE
}
-//SET_TRACE
Thread::start();
}
reverse_interlace = 0;
meters = 0;
canvas = 0;
+ cursor_toggle = 0;
+ big_cursor_toggle = 0;
current_operation = MONITOR_NONE;
signal_status = 0;
}
delete signal_status;
#endif
delete canvas;
- if( bitmap ) delete bitmap;
+ delete cursor_toggle;
+ delete big_cursor_toggle;
+ delete bitmap;
if( channel_picker ) delete channel_picker;
#ifdef HAVE_FIREWIRE
- if( avc1394transport_thread )
- delete avc1394transport_thread;
- if( avc ) {
- delete avc;
- }
- if( avc1394_transport ) {
- delete avc1394_transport;
- }
- if( avc1394transport_title )
- delete avc1394transport_title;
+ delete avc1394transport_thread;
+ delete avc;
+ delete avc1394_transport;
+ delete avc1394transport_title;
#endif
unlock_window();
}
driver == VIDEO4LINUX2MPEG ||
driver == CAPTURE_JPEG_WEBCAM ||
driver == CAPTURE_YUYV_WEBCAM);
+ int do_cursor = driver == SCREENCAPTURE;
int do_scopes = do_channel || driver == SCREENCAPTURE;
- int do_interlace = (driver == VIDEO4LINUX2JPEG);
+ int do_interlace = driver == VIDEO4LINUX2JPEG;
int background_done = 0;
int do_audio = record->default_asset->audio_data;
int do_video = record->default_asset->video_data;
x += reverse_interlace->get_w() + mwindow->theme->widget_border;
}
- if(do_scopes)
- {
+ if( do_scopes ) {
scope_toggle = new ScopeEnable(mwindow, thread, x, y);
add_subwindow(scope_toggle);
x += scope_toggle->get_w() + mwindow->theme->widget_border;
}
+ if( do_cursor ) {
+ add_subwindow(cursor_toggle = new DoCursor(record,
+ x,
+ y));
+ x += cursor_toggle->get_w() + mwindow->theme->widget_border;
+ add_subwindow(big_cursor_toggle = new DoBigCursor(record,
+ x,
+ y));
+ x += big_cursor_toggle->get_w() + mwindow->theme->widget_border;
+ }
+
add_subwindow(monitor_menu = new BC_PopupMenu(0, 0, 0, "", 0));
monitor_menu->add_item(new RecordMonitorFullsize(mwindow, this));
}
int RecordMonitorGUI::cursor_motion_event()
{
-//SET_TRACE
if( canvas && canvas->get_canvas() ) {
canvas->get_canvas()->unhide_cursor();
-//SET_TRACE
return canvas->cursor_motion_event();
}
return 0;
}
#endif
- if(channel_picker) channel_picker->reposition();
- if(reverse_interlace) reverse_interlace->reposition_window(reverse_interlace->get_x(),
- reverse_interlace->get_y());
- if(canvas && do_video)
- {
+
+ if( channel_picker ) {
+ channel_picker->reposition();
+ }
+ if( reverse_interlace ) {
+ reverse_interlace->reposition_window(
+ reverse_interlace->get_x(),
+ reverse_interlace->get_y());
+ }
+ if( cursor_toggle ) {
+ cursor_toggle->reposition_window(
+ cursor_toggle->get_x(),
+ cursor_toggle->get_y());
+ big_cursor_toggle->reposition_window(
+ big_cursor_toggle->get_x(),
+ big_cursor_toggle->get_y());
+ }
+
+ if( canvas && do_video ) {
canvas->reposition_window(0,
mwindow->theme->rmonitor_canvas_x,
mwindow->theme->rmonitor_canvas_y,
mwindow->theme->rmonitor_canvas_h);
}
- if(do_meters) {
+ if( do_meters ) {
meters->reposition_window(mwindow->theme->rmonitor_meter_x,
mwindow->theme->rmonitor_meter_y,
do_video ? -1 : mwindow->theme->rmonitor_meter_w,
mwindow->theme->rmonitor_meter_h);
meters->set_meters(record->default_asset->channels,1);
}
- else if(meters) {
+ else if( meters ) {
meters->set_meters(0,0);
}
return 0;
}
+
+DoCursor::DoCursor(Record *record, int x, int y)
+ : BC_CheckBox(x, y, record->do_cursor, _("Record cursor"))
+{
+ this->record = record;
+}
+
+DoCursor::~DoCursor()
+{
+}
+
+int DoCursor::handle_event()
+{
+ record->do_cursor = get_value();
+ return 0;
+}
+
+
+DoBigCursor::DoBigCursor(Record *record, int x, int y)
+ : BC_CheckBox(x, y, record->do_big_cursor, _("Big cursor"))
+{
+ this->record = record;
+}
+
+DoBigCursor::~DoBigCursor()
+{
+}
+
+int DoBigCursor::handle_event()
+{
+ record->do_big_cursor = get_value();
+ return 0;
+}
+
+
void RecordMonitorGUI::enable_signal_status(int enable)
{
#ifdef HAVE_DVB
void RecordMonitorThread::new_output_frame()
{
- record_monitor->device->new_output_buffer(&output_frame, output_colormodel);
+ record_monitor->device->new_output_buffer(&output_frame,
+ output_colormodel,
+ record->edl);
}
void RecordMonitorThread::
class ReverseInterlace;
class RecordMonitorCanvas;
+class DoCursor;
+class DoBigCursor;
class RecordMonitorGUI : public BC_Window
{
#endif
RecordChannelPicker *channel_picker;
ScopeEnable *scope_toggle;
+ DoCursor *cursor_toggle;
+ DoBigCursor *big_cursor_toggle;
ReverseInterlace *reverse_interlace;
int cursor_x_origin, cursor_y_origin;
int translate_x_origin, translate_y_origin;
Record *record;
};
+class DoCursor : public BC_CheckBox
+{
+public:
+ DoCursor(Record *record, int x, int y);
+ ~DoCursor();
+ int handle_event();
+ Record *record;
+};
+
+class DoBigCursor : public BC_CheckBox
+{
+public:
+ DoBigCursor(Record *record, int x, int y);
+ ~DoBigCursor();
+ int handle_event();
+ Record *record;
+};
+
class ReverseInterlace : public BC_CheckBox
{
public:
void RecordPrefs::create_objects()
{
- int x, y, x2;
+ int x, y, x1, x2;
char string[BCTEXTLEN];
BC_Resources *resources = BC_WindowBase::get_resources();
BC_Title *title;
+ BC_Title *title0, *title1, *title2, *title3;
+ BC_TextBox *textbox;
x = mwindow->theme->preferencesoptions_x;
y = mwindow->theme->preferencesoptions_y;
+ int margin = mwindow->theme->widget_border;
int x0 = x, y0 = y;
add_subwindow(title = new BC_Title(x, y, _("File Format:"),
LARGEFONT, resources->text_default));
- y += title->get_h() + 5;
+ y += title->get_h() + margin;
recording_format = new FormatTools(mwindow, this,
pwindow->thread->edl->session->recording_format);
add_subwindow(realtime_toc);
// Audio hardware
- add_subwindow(new BC_Bar(5, y, get_w() - 10));
- y += 5;
+ add_subwindow(new BC_Bar(x, y, get_w() - x * 2));
+ y += margin;
add_subwindow(title = new BC_Title(x, y,
_("Audio In"), LARGEFONT,
resources->text_default));
- y += title->get_h() + 5;
+ y += title->get_h() + margin;
add_subwindow(new BC_Title(x, y, _("Record Driver:"),
MEDIUMFONT, resources->text_default));
audio_in_device = new ADevicePrefs(x + 110, y, pwindow, this, 0,
pwindow->thread->edl->session->aconfig_in, MODERECORD);
audio_in_device->initialize(1);
- y += audio_in_device->get_h(1);
+ y += audio_in_device->get_h(1) + margin;
- BC_TextBox *textbox;
- BC_Title *title0, *title1, *title2, *title3;
int pad = RecordWriteLength::calculate_h(this,
MEDIUMFONT,
1,
add_subwindow(title1 = new BC_Title(x, y + pad, _("Samples to write to disk:")));
add_subwindow(title2 = new BC_Title(x, y + pad * 2, _("Sample rate for recording:")));
add_subwindow(title3 = new BC_Title(x, y + pad * 3, _("Channels to record:")));
- x2 = MAX(title0->get_w(), title1->get_w()) + mwindow->theme->widget_border;
- x2 = MAX(x2, title2->get_w() + mwindow->theme->widget_border);
- x2 = MAX(x2, title3->get_w() + mwindow->theme->widget_border);
+ x2 = MAX(title0->get_w(), title1->get_w()) + margin;
+ x2 = MAX(x2, title2->get_w() + margin);
+ x2 = MAX(x2, title3->get_w() + margin);
sprintf(string, "%ld", (long)pwindow->thread->edl->session->record_fragment_size);
// Video hardware
add_subwindow(new BC_Bar(5, y, get_w() - 10));
- y += 5;
+ y += margin;
- add_subwindow(new BC_Title(x, y, _("Video In"), LARGEFONT,
+ add_subwindow(title1 = new BC_Title(x, y, _("Video In"), LARGEFONT,
resources->text_default));
- y += 25;
+ y += title1->get_h() + margin;
- add_subwindow(new BC_Title(x, y, _("Record Driver:"), MEDIUMFONT,
+ add_subwindow(title1 = new BC_Title(x, y, _("Record Driver:"), MEDIUMFONT,
resources->text_default));
- video_in_device = new VDevicePrefs(x + 110, y, pwindow, this, 0,
- pwindow->thread->edl->session->vconfig_in, MODERECORD);
+ video_in_device = new VDevicePrefs(x + title1->get_w() + margin, y,
+ pwindow, this, 0, pwindow->thread->edl->session->vconfig_in, MODERECORD);
video_in_device->initialize(1);
+ y += video_in_device->get_h() + margin;
- y += 55;
+ add_subwindow(title1 = new BC_Title(x, y, _("Frames to record to disk at a time:")));
+ x1 = x + title1->get_w() + margin;
sprintf(string, "%d", pwindow->thread->edl->session->video_write_length);
- add_subwindow(textbox = new VideoWriteLength(pwindow, string, y));
- add_subwindow(new CaptureLengthTumbler(pwindow, textbox, textbox->get_x() + textbox->get_w(), y));
- add_subwindow(new BC_Title(x, y, _("Frames to record to disk at a time:")));
+ add_subwindow(textbox = new VideoWriteLength(pwindow, string, x1, y));
+ x1 += textbox->get_w() + margin;
+ add_subwindow(new CaptureLengthTumbler(pwindow, textbox, x1, y));
y += 27;
+
+ add_subwindow(title1 = new BC_Title(x, y, _("Frames to buffer in device:")));
+ x1 = x + title1->get_w() + margin;
sprintf(string, "%d", pwindow->thread->edl->session->vconfig_in->capture_length);
- add_subwindow(textbox = new VideoCaptureLength(pwindow, string, y));
- add_subwindow(new CaptureLengthTumbler(pwindow, textbox, textbox->get_x() + textbox->get_w(), y));
- add_subwindow(new BC_Title(x, y, _("Frames to buffer in device:")));
+ add_subwindow(textbox = new VideoCaptureLength(pwindow, string, x1, y));
+ x1 += textbox->get_w() + margin;
+ add_subwindow(new CaptureLengthTumbler(pwindow, textbox, x1, y));
y += 27;
- int x1 = x;
+ x1 = x;
add_subwindow(new BC_Title(x1, y, _("Positioning:")));
x1 += 100;
add_subwindow(textbox = new BC_TextBox(x1, y, 200, 1, ""));
y += 35;
BC_TextBox *w_text, *h_text;
- add_subwindow(new BC_Title(x, y, _("Size of captured frame:")));
- x += 170;
+ add_subwindow(title1 = new BC_Title(x, y, _("Size of captured frame:")));
+ x += title1->get_w() + margin;
add_subwindow(w_text = new RecordW(pwindow, x, y));
- x += w_text->get_w() + 2;
- add_subwindow(new BC_Title(x, y, "x"));
- x += 10;
+ x += w_text->get_w() + margin;
+ add_subwindow(title1 = new BC_Title(x, y, "x"));
+ x += title1->get_w() + margin;
add_subwindow(h_text = new RecordH(pwindow, x, y));
- x += h_text->get_w();
- add_subwindow(new FrameSizePulldown(mwindow->theme,
+ x += h_text->get_w() + margin;
+ FrameSizePulldown *tumbler;
+ add_subwindow(tumbler = new FrameSizePulldown(mwindow->theme,
w_text, h_text, x, y));
+ y += tumbler->get_h() + margin;
- y += 30;
- x = 5;
- add_subwindow(new BC_Title(x, y, _("Frame rate for recording:")));
- x += 180;
+ x = mwindow->theme->preferencesoptions_x;
+ add_subwindow(title1 = new BC_Title(x, y, _("Frame rate for recording:")));
+ x += title1->get_w() + margin;
add_subwindow(textbox = new RecordFrameRate(pwindow, x, y));
- x += 75;
+ x += textbox->get_w() + margin;
add_subwindow(new FrameRatePulldown(mwindow, textbox, x, y));
}
}
RecordFrameRate::RecordFrameRate(PreferencesWindow *pwindow, int x, int y)
- : BC_TextBox(x, y, 70, 1, pwindow->thread->edl->session->vconfig_in->in_framerate)
+ : BC_TextBox(x, y, 140, 1, pwindow->thread->edl->session->vconfig_in->in_framerate)
{
this->pwindow = pwindow;
}
-VideoWriteLength::VideoWriteLength(PreferencesWindow *pwindow, char *text, int y)
- : BC_TextBox(260, y, 100, 1, text)
+VideoWriteLength::VideoWriteLength(PreferencesWindow *pwindow, char *text, int x, int y)
+ : BC_TextBox(x, y, 100, 1, text)
{
this->pwindow = pwindow;
}
}
-VideoCaptureLength::VideoCaptureLength(PreferencesWindow *pwindow, char *text, int y)
- : BC_TextBox(260, y, 100, 1, text)
+VideoCaptureLength::VideoCaptureLength(PreferencesWindow *pwindow, char *text, int x, int y)
+ : BC_TextBox(x, y, 100, 1, text)
{
this->pwindow = pwindow;
}
class VideoWriteLength : public BC_TextBox
{
public:
- VideoWriteLength(PreferencesWindow *pwindow, char *text, int y);
+ VideoWriteLength(PreferencesWindow *pwindow, char *text, int x, int y);
int handle_event();
PreferencesWindow *pwindow;
};
class VideoCaptureLength : public BC_TextBox
{
public:
- VideoCaptureLength(PreferencesWindow *pwindow, char *text, int y);
+ VideoCaptureLength(PreferencesWindow *pwindow, char *text, int x, int y);
int handle_event();
PreferencesWindow *pwindow;
};
#include "bctheme.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "language.h"
#include "mainsession.h"
#include "mutex.h"
VideoDevice *vdevice = record->vdevice;
VFrame *capture_frame = get_buffer();
vdevice->set_field_order(record->reverse_interlace);
+ record->set_do_cursor();
// Capture a frame
grab_result = read_buffer(capture_frame);
if( done ) break;
/*
* CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
-#include "colors.h"
+#include "bccolors.h"
#include "mainsession.h"
#include "mwindow.h"
#include "mwindowgui.h"
ArrayList<Indexable*> *assets = render->packages->get_asset_list();
if(debug) printf("Render::render %d\n", __LINE__);
if(render->load_mode == LOADMODE_PASTE)
- mwindow->clear(0);
+ mwindow->clear(0, 1);
if(debug) printf("Render::render %d\n", __LINE__);
mwindow->load_assets(assets, -1, render->load_mode, 0, 0,
mwindow->edl->session->labels_follow_edits,
}
SaveAs::SaveAs(MWindow *mwindow)
- : BC_MenuItem(_("Save as..."), ""), Thread()
+ : BC_MenuItem(_("Save as..."), "Shift-S", 'S'), Thread()
{
this->mwindow = mwindow;
quit_now = 0;
*/
#include "bcsignals.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "clip.h"
#include "cursors.h"
#include "language.h"
#ifdef HAVE_DVB
#include "bctitle.h"
-#include "colors.h"
+#include "bccolors.h"
#include "devicedvbinput.h"
#include "fonts.h"
#include "signalstatus.h"
#include "bcwindow.h"
#include "bcsignals.h"
-#include "colors.h"
+#include "bccolors.h"
#include "fonts.h"
#include "thread.h"
#include "awindowgui.h"
#include "bcsignals.h"
#include "clip.h"
-#include "colors.h"
+#include "bccolors.h"
#include "cwindowgui.h"
#include "edl.h"
#include "edlsession.h"
play_h = 22;
title_h = 23;
clock_bg_color = BLACK;
+ clock_fg_color = GREEN;
assetedit_color = YELLOW;
const char *cp = getenv("BC_USE_COMMERCIALS");
use_commercials = !cp ? 0 : atoi(cp);
frame_sizes.append(new BC_ListBoxItem("128x96"));
frame_sizes.append(new BC_ListBoxItem("160x120"));
- frame_sizes.append(new BC_ListBoxItem("176x144"));
- frame_sizes.append(new BC_ListBoxItem("240x180"));
- frame_sizes.append(new BC_ListBoxItem("320x200"));
frame_sizes.append(new BC_ListBoxItem("320x240"));
- frame_sizes.append(new BC_ListBoxItem("352x288"));
frame_sizes.append(new BC_ListBoxItem("360x240"));
frame_sizes.append(new BC_ListBoxItem("400x300"));
- frame_sizes.append(new BC_ListBoxItem("424x318"));
- frame_sizes.append(new BC_ListBoxItem("512x384"));
- frame_sizes.append(new BC_ListBoxItem("640x350"));
+ frame_sizes.append(new BC_ListBoxItem("640x400"));
frame_sizes.append(new BC_ListBoxItem("640x480"));
- frame_sizes.append(new BC_ListBoxItem("704x576"));
frame_sizes.append(new BC_ListBoxItem("720x480"));
- frame_sizes.append(new BC_ListBoxItem("720x576"));
frame_sizes.append(new BC_ListBoxItem("800x600"));
- frame_sizes.append(new BC_ListBoxItem("852x480"));
- frame_sizes.append(new BC_ListBoxItem("852x480"));
- frame_sizes.append(new BC_ListBoxItem("960x540"));
- frame_sizes.append(new BC_ListBoxItem("960x1080"));
frame_sizes.append(new BC_ListBoxItem("1024x768"));
frame_sizes.append(new BC_ListBoxItem("1280x720"));
frame_sizes.append(new BC_ListBoxItem("1280x1024"));
- frame_sizes.append(new BC_ListBoxItem("1368x768"));
- frame_sizes.append(new BC_ListBoxItem("1408x1152"));
- frame_sizes.append(new BC_ListBoxItem("1600x1024"));
frame_sizes.append(new BC_ListBoxItem("1600x1200"));
frame_sizes.append(new BC_ListBoxItem("1920x1080"));
- frame_sizes.append(new BC_ListBoxItem("1920x1088"));
- frame_sizes.append(new BC_ListBoxItem("1920x1200"));
- frame_sizes.append(new BC_ListBoxItem("2048x1536"));
- frame_sizes.append(new BC_ListBoxItem("2560x1600"));
- frame_sizes.append(new BC_ListBoxItem("2560x2048"));
- frame_sizes.append(new BC_ListBoxItem("3200x2048"));
- frame_sizes.append(new BC_ListBoxItem("3840x2400"));
- frame_sizes.append(new BC_ListBoxItem("5120x4096"));
- frame_sizes.append(new BC_ListBoxItem("6400x4096"));
- frame_sizes.append(new BC_ListBoxItem("7680x4800"));
+ frame_sizes.append(new BC_ListBoxItem("3840x2160"));
+ frame_sizes.append(new BC_ListBoxItem("4096x1720"));
sample_rates.append(new BC_ListBoxItem("8000"));
sample_rates.append(new BC_ListBoxItem("16000"));
sample_rates.append(new BC_ListBoxItem("96000"));
sample_rates.append(new BC_ListBoxItem("192000"));
+ frame_rates.append(new BC_ListBoxItem("0.25"));
frame_rates.append(new BC_ListBoxItem("1"));
frame_rates.append(new BC_ListBoxItem("5"));
frame_rates.append(new BC_ListBoxItem("10"));
frame_rates.append(new BC_ListBoxItem("50"));
frame_rates.append(new BC_ListBoxItem("59.94"));
frame_rates.append(new BC_ListBoxItem("60"));
+ frame_rates.append(new BC_ListBoxItem("100"));
+ frame_rates.append(new BC_ListBoxItem("120"));
+ frame_rates.append(new BC_ListBoxItem("1000"));
char string[BCTEXTLEN];
for(int i = 1; i < 17; i++)
mbuttons_y = gui->menu_h() + 1;
mbuttons_w = gui->menu_w();
mbuttons_h = get_image("mbutton_bg")->get_h();
- mclock_x = 10;
- mclock_y = mbuttons_y - 1 + mbuttons_h + widget_border;
- mclock_w = get_image("clock_bg")->get_w() - 40;
+ mclock_x = window_border - 5;
+ mclock_y = mbuttons_y - 1 + mbuttons_h;
+ mclock_w = get_image("clock_bg")->get_w() - 20;
mclock_h = get_image("clock_bg")->get_h();
mtimebar_x = get_image("patchbay_bg")->get_w();
mtimebar_y = mbuttons_y - 1 + mbuttons_h;
void Theme::get_keyframedialog_sizes(KeyFrameWindow *gui)
{
- int x = widget_border;
- int y = window_border +
- BC_Title::calculate_h(gui, "P", LARGEFONT) +
+ int x = window_border;
+ int y = window_border +
+ BC_Title::calculate_h(gui, "P", LARGEFONT) +
+ widget_border;
+
+ presets_list_x = x;
+ presets_list_y = y;
+#ifdef EDIT_KEYFRAME
+ presets_list_w = mwindow->session->keyframedialog_w / 2 -
+ widget_border -
+ window_border;
+#else
+ presets_list_w = mwindow->session->keyframedialog_w -
+ presets_list_x -
+ window_border;
+#endif
+ presets_list_h = mwindow->session->keyframedialog_h -
+ BC_OKButton::calculate_h() -
+ presets_list_y -
+ widget_border -
+ widget_border -
+ BC_Title::calculate_h(gui, "P") -
+ widget_border -
+ BC_TextBox::calculate_h(gui,
+ MEDIUMFONT,
+ 1,
+ 1) -
+ widget_border -
+ (BC_GenericButton::calculate_h() + widget_border) * 3 -
+ window_border;
+ y += presets_list_h + widget_border + widget_border + BC_Title::calculate_h(gui, "P");
+ presets_text_x = x;
+ presets_text_y = y;
+ presets_text_w = presets_list_w;
+ y += BC_TextBox::calculate_h(gui,
+ MEDIUMFONT,
+ 1,
+ 1) + widget_border;
+
+ presets_delete_x = presets_text_x;
+ presets_delete_y = y;
+ y += BC_GenericButton::calculate_h() + widget_border;
+
+ presets_save_x = presets_text_x;
+ presets_save_y = y;
+ y += BC_GenericButton::calculate_h() + widget_border;
+
+ presets_apply_x = presets_text_x;
+ presets_apply_y = y;
+ y += BC_GenericButton::calculate_h();
+
+#ifdef EDIT_KEYFRAME
+ x = mwindow->session->keyframedialog_w / 2 + widget_border;
+ y = window_border +
+ BC_Title::calculate_h(gui, "P", LARGEFONT) +
widget_border;
keyframe_list_x = x;
keyframe_list_y = y;
- keyframe_list_w = mwindow->session->keyframedialog_w - widget_border * 2;
- keyframe_list_h = mwindow->session->keyframedialog_h - widget_border -
- widget_border - keyframe_list_y - BC_Title::calculate_h(gui, "P") -
- widget_border - BC_TextBox::calculate_h(gui, MEDIUMFONT, 1, 1) -
- widget_border - BC_Title::calculate_h(gui, "P") -
- widget_border - BC_OKButton::calculate_h() -
+ keyframe_list_w = mwindow->session->keyframedialog_w / 2 -
+ widget_border -
+ window_border;
+ keyframe_list_h = mwindow->session->keyframedialog_h -
+ keyframe_list_y -
+ widget_border -
+ widget_border -
+ BC_Title::calculate_h(gui, "P") -
+ widget_border -
+ BC_TextBox::calculate_h(gui,
+ MEDIUMFONT,
+ 1,
+ 1) -
+ widget_border -
+ BC_Title::calculate_h(gui, "P") -
+ widget_border -
+ BC_OKButton::calculate_h() -
window_border;
// keyframe_text_x = keyframe_list_x + keyframe_list_w + widget_border;
// keyframe_text_y = y;
// keyframe_text_w = mwindow->session->keyframedialog_w - keyframe_text_x - window_border;
-// y += BC_TextBox::calculate_h(gui,
-// MEDIUMFONT,
-// 1,
+// y += BC_TextBox::calculate_h(gui,
+// MEDIUMFONT,
+// 1,
// 1) + widget_border;
-//
+//
y += keyframe_list_h + BC_Title::calculate_h(gui, "P") + widget_border + widget_border;
keyframe_value_x = keyframe_list_x;
keyframe_value_y = y;
keyframe_value_w = keyframe_list_w;
- y += BC_TextBox::calculate_h(gui,
- MEDIUMFONT,
- 1,
+ y += BC_TextBox::calculate_h(gui,
+ MEDIUMFONT,
+ 1,
1) + widget_border;
keyframe_all_x = keyframe_value_x;
keyframe_all_y = y;
+
+#endif
+
}
int plugindialog_sharedattach_x, plugindialog_sharedattach_y;
int plugindialog_moduleattach_x, plugindialog_moduleattach_y;
+ int presets_list_x, presets_list_y, presets_list_w, presets_list_h;
+ int presets_text_x, presets_text_y, presets_text_w;
+ int presets_delete_x, presets_delete_y;
+ int presets_save_x, presets_save_y;
+ int presets_apply_x, presets_apply_y;
+
int keyframe_list_x, keyframe_list_y, keyframe_list_w, keyframe_list_h;
int keyframe_text_x, keyframe_text_y, keyframe_text_w, keyframe_text_h;
int keyframe_value_x, keyframe_value_y, keyframe_value_w, keyframe_value_h;
int window_border;
int widget_border;
int clock_bg_color;
+ int clock_fg_color;
int use_commercials;
// Bitmaps
}
-
-
-
-int Track::clear(double start,
- double end,
- int edit_edits,
- int edit_labels,
- int edit_plugins,
- int edit_autos,
- int convert_units,
- Edits *trim_edits)
+int Track::clear(double start, double end,
+ int edit_edits, int edit_labels, int edit_plugins,
+ int edit_autos, int convert_units, Edits *trim_edits)
{
// Edits::move_auto calls this routine after the units are converted to the track
// format.
#include "bcsignals.h"
#include "bctimer.h"
#include "clip.h"
-#include "colors.h"
+#include "bccolors.h"
#include "cplayback.h"
#include "cursors.h"
#include "cwindowgui.h"
int64_t track_x, track_y, track_w, track_h;
track_dimensions(track, track_x, track_y, track_w, track_h);
- if(button_press && get_buttonpress() == 3 &&
+ if(button_press && get_buttonpress() == RIGHT_BUTTON &&
cursor_y >= track_y && cursor_y < track_y + track_h) {
gui->edit_menu->update(track, 0);
gui->edit_menu->activate_menu();
end,
1, // edits
1, // labels
- clear_plugins,
+ clear_plugins, // edit_plugins
edit_autos,
- 1,
- 0);
+ 1, // convert_units
+ 0); // trim_edits
}
}
return 0;
*/
#include "clip.h"
-#include "colors.h"
+#include "bccolors.h"
#include "edl.h"
#include "edlsession.h"
#include "floatauto.h"
void VDevice1394::new_output_buffer(VFrame **output,
- int colormodel)
+ int colormodel,
+ EDL *edl)
{
if(user_frame)
{
void initialize();
int can_copy_from(Asset *asset, int output_w, int output_h);
// int stop_sharing();
- void new_output_buffer(VFrame **output, int colormodel);
+ void new_output_buffer(VFrame **output, int colormodel, EDL *edl);
void encrypt(unsigned char *output, unsigned char *data, int data_size);
private:
virtual int create_channeldb(ArrayList<Channel*> *channeldb) { return 1; };
virtual int read_buffer(VFrame *frame) { return 1; };
virtual int write_buffer(VFrame *output, EDL *edl) { return 1; };
- virtual void new_output_buffer(VFrame **output, int colormodel) {};
+ virtual void new_output_buffer(VFrame **output, int colormodel, EDL *edl) {};
virtual ArrayList<int>* get_render_strategies() { return 0; };
virtual int get_shared_data(unsigned char *data, long size) { return 0; };
virtual int stop_sharing() { return 0; };
#include "bcsignals.h"
#include "channeldb.h"
#include "channelpicker.h"
+#include "clip.h"
#include "edl.h"
#include "edlsession.h"
#include "formattools.h"
#include "preferencesthread.h"
#include "recordconfig.h"
#include "recordprefs.h"
+#include "theme.h"
#include <string.h>
firewire_path = 0;
fields_title = 0;
device_fields = 0;
+ use_direct_x11 = 0;
channel_picker = 0;
}
delete dvb_adapter_device;
delete follow_video_config;
delete dvb_adapter_title;
+ delete use_direct_x11;
delete port_title;
return 0;
}
+int VDevicePrefs::get_h()
+{
+ int margin = pwindow->mwindow->theme->widget_border;
+ return BC_Title::calculate_h(dialog, "X", MEDIUMFONT) + margin +
+ BC_TextBox::calculate_h(dialog, MEDIUMFONT, 1, 1);
+}
+
void VDevicePrefs::create_dvb_objs()
{
int x1 = x + menu->get_w() + 30;
char *output_char = &pwindow->thread->edl->session->vconfig_in->v4l2jpeg_in_device[0];
dialog->add_subwindow(device_title = new BC_Title(x1, y, _("Device path:"), MEDIUMFONT, resources->text_default));
dialog->add_subwindow(device_text = new VDeviceTextBox(x1, y + 20, output_char));
- x1 += max(device_title->get_w(),device_text->get_w()) + 5;
+ x1 += bmax(device_title->get_w(),device_text->get_w()) + 5;
int *output_int = &pwindow->thread->edl->session->vconfig_in->v4l2jpeg_in_fields;
fields_title = new BC_Title(x1, y, _("Fields:"), MEDIUMFONT, resources->text_default);
dialog->add_subwindow(fields_title);
{
char *output_char;
BC_Resources *resources = BC_WindowBase::get_resources();
- int x1 = x + menu->get_w() + 5;
output_char = out_config->x11_host;
const char *x11_display;
switch( pwindow->thread->current_dialog ) {
x11_display = _("Default B Display:"); break;
break;
}
- dialog->add_subwindow(device_title = new BC_Title(x1, y, x11_display,
+ int x1 = menu->get_x() + menu->get_w() + 10;
+ int y1 = menu->get_y();
+ if( driver == PLAYBACK_X11 ) y1 -= 10;
+ dialog->add_subwindow(device_title = new BC_Title(x1, y1+4, x11_display,
MEDIUMFONT, resources->text_default));
- dialog->add_subwindow(device_text = new VDeviceTextBox(x1, y + 20, output_char));
+ int x2 = x1 + device_title->get_w() + 10, dy = device_title->get_h();
+ dialog->add_subwindow(device_text = new VDeviceTextBox(x2, y1, output_char));
+ if( driver == PLAYBACK_X11 ) {
+ int y2 = device_text->get_h();
+ if( dy < y2 ) dy = y2;
+ y1 += dy + 5;
+ use_direct_x11 = new BC_CheckBox(x1, y1,
+ &out_config->use_direct_x11, _("use direct x11 render if possible"));
+ dialog->add_subwindow(use_direct_x11);
+ }
return 0;
}
int initialize(int creation /* = 0 */);
int delete_objects();
void reset_objects();
- static int max(int a,int b) { return a>b ? a : b; }
+ int get_h();
PreferencesWindow *pwindow;
PreferencesDialog *dialog;
BC_Title *device_title;
BC_Title *port_title;
BC_CheckBox *follow_video_config;
+ BC_CheckBox *use_direct_x11;
BC_Title *channel_title;
BC_Title *output_title;
BC_Title *syt_title;
/*
* CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
- *
+ * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
+ *
*/
#include "assets.h"
-#include "auto.h"
+#include "autos.h"
#include "bccapture.h"
+#include "bccmodels.h"
#include "bcsignals.h"
#include "canvas.h"
-#include "bccmodels.h"
#include "edl.h"
#include "edlsession.h"
-#include "maskautos.h"
+#include "file.h"
#include "maskauto.h"
+#include "maskautos.h"
#include "mwindow.h"
+#include "mwindowgui.h"
#include "playback3d.h"
#include "playbackconfig.h"
#include "preferences.h"
capture_bitmap = 0;
color_model_selected = 0;
is_cleared = 0;
+
+ for( int i = 0; i < SCREENCAP_BORDERS; i++ ) {
+ screencap_border[i] = 0;
+ }
return 0;
}
int VDeviceX11::open_input()
{
//printf("VDeviceX11::open_input 1\n");
- capture_bitmap = new BC_Capture(device->in_config->w,
+ capture_bitmap = new BC_Capture(device->in_config->w,
device->in_config->h,
device->in_config->screencapture_display);
//printf("VDeviceX11::open_input 2\n");
+// create overlay
+ device->mwindow->gui->lock_window("VDeviceX11::close_all");
+
+ screencap_border[0] = new BC_Popup(device->mwindow->gui,
+ device->input_x - SCREENCAP_PIXELS, device->input_y - SCREENCAP_PIXELS,
+ device->in_config->w + SCREENCAP_PIXELS * 2, SCREENCAP_PIXELS,
+ SCREENCAP_COLOR, 1);
+ screencap_border[1] = new BC_Popup(device->mwindow->gui,
+ device->input_x - SCREENCAP_PIXELS, device->input_y,
+ SCREENCAP_PIXELS, device->in_config->h,
+ SCREENCAP_COLOR, 1);
+ screencap_border[2] = new BC_Popup(device->mwindow->gui,
+ device->input_x - SCREENCAP_PIXELS, device->input_y + device->in_config->h,
+ device->in_config->w + SCREENCAP_PIXELS * 2, SCREENCAP_PIXELS,
+ SCREENCAP_COLOR, 1);
+ screencap_border[3] = new BC_Popup(device->mwindow->gui,
+ device->input_x + device->in_config->w, device->input_y,
+ SCREENCAP_PIXELS, device->in_config->h,
+ SCREENCAP_COLOR, 1);
+
+ for( int i=0; i<SCREENCAP_BORDERS; ++i ) {
+ BC_Popup *box = screencap_border[i];
+ box->set_bg_color(SCREENCAP_COLOR);
+ box->clear_box(0, 0, box->get_w(), box->get_h());
+ box->flash(0);
+ box->show_window();
+ }
+
+ device->mwindow->gui->unlock_window();
+
return 0;
}
int VDeviceX11::open_output()
{
- if(output)
- {
+ if( output ) {
output->lock_canvas("VDeviceX11::open_output");
output->get_canvas()->lock_window("VDeviceX11::open_output");
- if(!device->single_frame)
+ if( !device->single_frame )
output->start_video();
else
output->start_single();
output->get_canvas()->unlock_window();
// Enable opengl in the first routine that needs it, to reduce the complexity.
-
output->unlock_canvas();
}
return 0;
int VDeviceX11::output_visible()
{
- if(!output) return 0;
+ if( !output ) return 0;
output->lock_canvas("VDeviceX11::output_visible");
- if(output->get_canvas()->get_hidden())
- {
+ if( output->get_canvas()->get_hidden() ) {
output->unlock_canvas();
- return 0;
+ return 0;
}
- else
- {
+ else {
output->unlock_canvas();
return 1;
}
int VDeviceX11::close_all()
{
- if(output)
- {
+ if( output ) {
output->lock_canvas("VDeviceX11::close_all 1");
output->get_canvas()->lock_window("VDeviceX11::close_all 1");
}
- if(output && output_frame)
- {
+ if( output && output_frame ) {
output->update_refresh(device, output_frame);
if( device->single_frame )
output->draw_refresh();
}
+ delete bitmap; bitmap = 0;
+ delete output_frame; output_frame = 0;
+ delete capture_bitmap; capture_bitmap = 0;
-
-
- if(bitmap)
- {
- delete bitmap;
- bitmap = 0;
- }
-
- if(output_frame)
- {
- delete output_frame;
- output_frame = 0;
- }
-
- if(capture_bitmap) delete capture_bitmap;
-
- if(output)
- {
-
+ if( output ) {
// Update the status bug
- if(!device->single_frame)
- {
+ if( !device->single_frame ) {
output->stop_video();
}
- else
- {
+ else {
output->stop_single();
}
output->unlock_canvas();
}
-
+ if( device->mwindow ) {
+ device->mwindow->gui->lock_window("VDeviceX11::close_all");
+ for( int i=0; i<SCREENCAP_BORDERS; ++i ) {
+ delete screencap_border[i];
+ screencap_border[i] = 0;
+ }
+ device->mwindow->gui->unlock_window();
+ }
+
reset_parameters();
+
return 0;
}
int VDeviceX11::read_buffer(VFrame *frame)
{
- capture_bitmap->capture_frame(frame, device->input_x, device->input_y);
+//printf("VDeviceX11::read_buffer %d colormodel=%d\n", __LINE__, frame->get_color_model());
+ device->mwindow->gui->lock_window("VDeviceX11::close_all");
+
+ screencap_border[0]->reposition_window(device->input_x - SCREENCAP_PIXELS,
+ device->input_y - SCREENCAP_PIXELS);
+ screencap_border[1]->reposition_window(device->input_x - SCREENCAP_PIXELS,
+ device->input_y);
+ screencap_border[2]->reposition_window(device->input_x - SCREENCAP_PIXELS,
+ device->input_y + device->in_config->h);
+ screencap_border[3]->reposition_window(device->input_x + device->in_config->w,
+ device->input_y);
+ device->mwindow->gui->flush();
+ device->mwindow->gui->unlock_window();
+
+
+ capture_bitmap->capture_frame(frame,
+ device->input_x, device->input_y, device->do_cursor);
return 0;
}
int VDeviceX11::get_best_colormodel(Asset *asset)
{
- return BC_RGB888;
+ return File::get_best_colormodel(asset, SCREENCAPTURE);
+// return BC_RGB888;
}
-int VDeviceX11::get_best_colormodel(int colormodel)
+int VDeviceX11::get_display_colormodel(int file_colormodel)
{
int result = -1;
- if(device->out_config->driver == PLAYBACK_X11_GL)
- {
- if(colormodel == BC_RGB888 ||
- colormodel == BC_RGBA8888 ||
- colormodel == BC_YUV888 ||
- colormodel == BC_YUVA8888 ||
- colormodel == BC_RGB_FLOAT ||
- colormodel == BC_RGBA_FLOAT)
- {
- return colormodel;
+ if( device->out_config->driver == PLAYBACK_X11_GL ) {
+ if( file_colormodel == BC_RGB888 ||
+ file_colormodel == BC_RGBA8888 ||
+ file_colormodel == BC_YUV888 ||
+ file_colormodel == BC_YUVA8888 ||
+ file_colormodel == BC_RGB_FLOAT ||
+ file_colormodel == BC_RGBA_FLOAT ) {
+ return file_colormodel;
}
+
return BC_RGB888;
}
- if(!device->single_frame)
- {
- switch(colormodel)
- {
- case BC_YUV420P:
- case BC_YUV422P:
- case BC_YUV422:
- result = colormodel;
- break;
+ if( !device->single_frame ) {
+ switch( file_colormodel ) {
+ case BC_YUV420P:
+ case BC_YUV422P:
+ case BC_YUV422:
+ result = file_colormodel;
+ break;
}
}
// 2 more colormodels are supported by OpenGL
- if(device->out_config->driver == PLAYBACK_X11_GL)
- {
- if(colormodel == BC_RGB_FLOAT ||
- colormodel == BC_RGBA_FLOAT)
- result = colormodel;
+ if( device->out_config->driver == PLAYBACK_X11_GL ) {
+ if( file_colormodel == BC_RGB_FLOAT ||
+ file_colormodel == BC_RGBA_FLOAT )
+ result = file_colormodel;
}
- if(result < 0)
- {
- switch(colormodel)
- {
- case BC_RGB888:
- case BC_RGBA8888:
- case BC_YUV888:
- case BC_YUVA8888:
- result = colormodel;
- break;
-
- default:
- output->lock_canvas("VDeviceX11::get_best_colormodel");
- result = output->get_canvas()->get_color_model();
- output->unlock_canvas();
- break;
+ if( result < 0 ) {
+ switch( file_colormodel ) {
+ case BC_RGB888:
+ case BC_RGBA8888:
+ case BC_YUV888:
+ case BC_YUVA8888:
+ case BC_RGB_FLOAT:
+ case BC_RGBA_FLOAT:
+ result = file_colormodel;
+ break;
+
+ default:
+ output->lock_canvas("VDeviceX11::get_display_colormodel");
+ result = output->get_canvas()->get_color_model();
+ output->unlock_canvas();
+ break;
}
}
}
-void VDeviceX11::new_output_buffer(VFrame **result, int colormodel)
+void VDeviceX11::new_output_buffer(VFrame **result, int file_colormodel, EDL *edl)
{
-//printf("VDeviceX11::new_output_buffer 1\n");
+// printf("VDeviceX11::new_output_buffer %d hardware_scaling=%d\n",
+// __LINE__, bitmap ? bitmap->hardware_scaling() : 0);
output->lock_canvas("VDeviceX11::new_output_buffer");
output->get_canvas()->lock_window("VDeviceX11::new_output_buffer 1");
// Get the best colormodel the display can handle.
- int best_colormodel = get_best_colormodel(colormodel);
+ int display_colormodel = get_display_colormodel(file_colormodel);
+//printf("VDeviceX11::new_output_buffer %d file_colormodel=%d display_colormodel=%d\n",
+// __LINE__, file_colormodel, display_colormodel);
// Only create OpenGL Pbuffer and texture.
if( device->out_config->driver == PLAYBACK_X11_GL ) {
// Create bitmap for initial load into texture.
// Not necessary to do through Playback3D.....yet
if( !output_frame ) {
- output_frame = new VFrame(0, -1,
- device->out_w, device->out_h, colormodel, -1);
-//BUFFER2(output_frame->get_rows()[0], "VDeviceX11::new_output_buffer 1");
+ output_frame = new VFrame(device->out_w, device->out_h, file_colormodel);
}
window_id = output->get_canvas()->get_id();
output_frame->set_opengl_state(VFrame::RAM);
}
else {
+ output->get_transfers(edl,
+ output_x1, output_y1, output_x2, output_y2,
+ canvas_x1, canvas_y1, canvas_x2, canvas_y2,
+// Canvas may be a different size than the temporary bitmap for pure software
+ -1, -1);
+ canvas_w = canvas_x2 - canvas_x1;
+ canvas_h = canvas_y2 - canvas_y1;
+// can the direct frame be used?
+ int direct_supported =
+ device->out_config->use_direct_x11 &&
+ !output->xscroll && !output->yscroll &&
+ output_x1 == 0 && output_x2 == device->out_w &&
+ output_y1 == 0 && output_y2 == device->out_h;
+
+// file wants direct frame but we need a temp
+ if( !direct_supported && file_colormodel == BC_BGR8888 )
+ file_colormodel = BC_RGB888;
+
// Conform existing bitmap to new colormodel and output size
if( bitmap ) {
+// printf("VDeviceX11::new_output_buffer %d bitmap=%dx%d canvas=%dx%d canvas=%dx%d\n",
+// __LINE__, bitmap->get_w(), bitmap->get_h(), canvas_w, canvas_h,);
+ int size_change = (
+ bitmap->get_w() != canvas_w ||
+ bitmap->get_h() != canvas_h );
+
// Restart if output size changed or output colormodel changed.
// May have to recreate if transferring between windowed and fullscreen.
- if( !color_model_selected || ( !bitmap->hardware_scaling() &&
- (bitmap->get_w() != output->get_canvas()->get_w() ||
- bitmap->get_h() != output->get_canvas()->get_h()) ) ||
- colormodel != output_frame->get_color_model() ) {
- int size_change =
- bitmap->get_w() != output->get_canvas()->get_w() ||
- bitmap->get_h() != output->get_canvas()->get_h();
-//printf("VDeviceX11::new_output_buffer %d\n", __LINE__);
+ if( !color_model_selected ||
+ file_colormodel != output_frame->get_color_model() ||
+ (!bitmap->hardware_scaling() && size_change) ) {
+//printf("VDeviceX11::new_output_buffer %d file_colormodel=%d prev "
+// "file_colormodel=%d bitmap=%p output_frame=%p\n", __LINE__,
+// file_colormodel, output_frame->get_color_model(), bitmap, output_frame);
delete bitmap; bitmap = 0;
delete output_frame; output_frame = 0;
-
-// Blank only if size changed
+// Clear borders if size changed
if( size_change ) {
+//printf("VDeviceX11::new_output_buffer %d w=%d h=%d "
+// "canvas_x1=%d canvas_y1=%d canvas_x2=%d canvas_y2=%d\n",
+// __LINE__, // (int)output->w, (int)output->h,
+// (int)canvas_x1, (int)canvas_y1, (int)canvas_x2, (int)canvas_y2);
output->get_canvas()->set_color(BLACK);
- output->get_canvas()->draw_box(0, 0, output->w, output->h);
- output->get_canvas()->flash();
+
+ if( canvas_y1 > 0 ) {
+ output->get_canvas()->draw_box(0, 0, output->w, canvas_y1);
+ output->get_canvas()->flash(0, 0, output->w, canvas_y1);
+ }
+
+ if( canvas_y2 < output->h ) {
+ output->get_canvas()->draw_box(0, canvas_y2, output->w, output->h - canvas_y2);
+ output->get_canvas()->flash(0, canvas_y2, output->w, output->h - canvas_y2);
+ }
+
+ if( canvas_x1 > 0 ) {
+ output->get_canvas()->draw_box(0, canvas_y1, canvas_x1, canvas_y2 - canvas_y1);
+ output->get_canvas()->flash(0, canvas_y1, canvas_x1, canvas_y2 - canvas_y1);
+ }
+
+ if( canvas_x2 < output->w ) {
+ output->get_canvas()->draw_box(canvas_x2, canvas_y1,
+ output->w - canvas_x2, canvas_y2 - canvas_y1);
+ output->get_canvas()->flash(canvas_x2, canvas_y1,
+ output->w - canvas_x2, canvas_y2 - canvas_y1);
+ }
}
}
}
// Create new bitmap
if( !bitmap ) {
-// Try hardware accelerated
+ int use_direct = 0;
bitmap_type = BITMAP_TEMP;
- switch( best_colormodel ) {
+//printf("VDeviceX11::new_output_buffer %d file_colormodel=%d display_colormodel=%d\n",
+// __LINE__, file_colormodel, display_colormodel);
+
+// Try hardware accelerated
+ switch( display_colormodel ) {
+// blit from the codec directly to the window, using the standard X11 color model.
+// Must scale in the codec. No cropping
+ case BC_BGR8888:
+ if( direct_supported ) {
+ bitmap_type = BITMAP_PRIMARY;
+ use_direct = 1;
+ }
+ break;
+
case BC_YUV420P:
if( device->out_config->driver == PLAYBACK_X11_XV &&
- output->get_canvas()->accel_available(best_colormodel, 0) &&
+ output->get_canvas()->accel_available(display_colormodel, 0) &&
!output->use_scrollbars )
bitmap_type = BITMAP_PRIMARY;
break;
case BC_YUV422P:
if( device->out_config->driver == PLAYBACK_X11_XV &&
- output->get_canvas()->accel_available(best_colormodel, 0) &&
+ output->get_canvas()->accel_available(display_colormodel, 0) &&
!output->use_scrollbars )
bitmap_type = BITMAP_PRIMARY;
else if( device->out_config->driver == PLAYBACK_X11_XV &&
output->get_canvas()->accel_available(BC_YUV422, 0) ) {
- bitmap = new BC_Bitmap(output->get_canvas(),
+ bitmap = new BC_Bitmap(output->get_canvas(),
device->out_w, device->out_h, BC_YUV422, 1);
}
break;
case BC_YUV422:
if( device->out_config->driver == PLAYBACK_X11_XV &&
- output->get_canvas()->accel_available(best_colormodel, 0) &&
- !output->use_scrollbars )
+ output->get_canvas()->accel_available(display_colormodel, 0) &&
+ !output->use_scrollbars ) {
bitmap_type = BITMAP_PRIMARY;
+ }
else if( device->out_config->driver == PLAYBACK_X11_XV &&
output->get_canvas()->accel_available(BC_YUV422P, 0) ) {
- bitmap = new BC_Bitmap(output->get_canvas(),
+ bitmap = new BC_Bitmap(output->get_canvas(),
device->out_w, device->out_h, BC_YUV422P, 1);
}
break;
}
if( bitmap_type == BITMAP_PRIMARY ) {
+ int bitmap_w = use_direct ? canvas_w : device->out_w;
+ int bitmap_h = use_direct ? canvas_h : device->out_h;
bitmap = new BC_Bitmap(output->get_canvas(),
- device->out_w, device->out_h, best_colormodel, 1);
+ bitmap_w, bitmap_h, display_colormodel, -1);
output_frame = new VFrame(bitmap,
- device->out_w, device->out_h, best_colormodel, -1);
+ bitmap_w, bitmap_h, display_colormodel, -1);
}
- else {
-// Try default colormodel
- best_colormodel = output->get_canvas()->get_color_model();
- bitmap = new BC_Bitmap(output->get_canvas(),
- output->get_canvas()->get_w(), output->get_canvas()->get_h(),
- best_colormodel, 1);
-// Intermediate frame
- output_frame = new VFrame(0, -1,
- device->out_w, device->out_h, colormodel, -1);
+// Make an intermediate frame
+ if( !bitmap ) {
+ display_colormodel = output->get_canvas()->get_color_model();
+// printf("VDeviceX11::new_output_buffer %d creating temp display_colormodel=%d "
+// "file_colormodel=%d %dx%d %dx%d %dx%d\n", __LINE__,
+// display_colormodel, file_colormodel, device->out_w, device->out_h,
+// output->get_canvas()->get_w(), output->get_canvas()->get_h(), canvas_w, canvas_h);
+ bitmap = new BC_Bitmap(output->get_canvas(),
+ canvas_w, canvas_h, display_colormodel, 1);
+ bitmap_type = BITMAP_TEMP;
}
+ if( bitmap_type == BITMAP_TEMP ) {
+// Intermediate frame
+//printf("VDeviceX11::new_output_buffer %d creating output_frame\n", __LINE__);
+ output_frame = new VFrame(device->out_w, device->out_h, file_colormodel);
+ }
color_model_selected = 1;
}
else if( bitmap_type == BITMAP_PRIMARY ) {
-// Update the ring buffer
output_frame->set_memory(bitmap);
}
}
int VDeviceX11::start_playback()
{
// Record window is initialized when its monitor starts.
- if(!device->single_frame)
+ if( !device->single_frame )
output->start_video();
return 0;
}
int VDeviceX11::stop_playback()
{
- if(!device->single_frame)
+ if( !device->single_frame )
output->stop_video();
// Record window goes back to monitoring
// get the last frame played and store it in the video_out
int VDeviceX11::write_buffer(VFrame *output_channels, EDL *edl)
{
-// The reason for not drawing single frame is that it is _always_ drawn
-// when drawing draw_refresh in cwindowgui and vwindowgui
- if( device->single_frame )
- return 0;
-
output->lock_canvas("VDeviceX11::write_buffer");
output->get_canvas()->lock_window("VDeviceX11::write_buffer 1");
-
-// Canvas may be a different size than the temporary bitmap for pure software
- int xfr_w, xfr_h;
- if(bitmap_type == BITMAP_TEMP && !bitmap->hardware_scaling()) {
- xfr_w = bitmap->get_w();
- xfr_h = bitmap->get_h();
- }
- else
- xfr_w = xfr_h = -1;
-
-//printf("VDeviceX11::write_buffer %d %d\n", __LINE__, output->get_canvas()->get_video_on());
- output->get_transfers(edl, output_x1, output_y1, output_x2, output_y2,
- canvas_x1, canvas_y1, canvas_x2, canvas_y2, xfr_w, xfr_h);
-
-// Convert colormodel
-#if 0
+// if( device->out_config->driver == PLAYBACK_X11_GL &&
+// output_frame->get_color_model() != BC_RGB888 ) {
// this is handled by overlay call in virtualvnode, using flatten alpha
// invoked when is_nested = -1 is passed to vdevicex11->overlay(...)
- if(device->out_config->driver == PLAYBACK_X11_GL &&
- output_frame->get_color_model() != BC_RGB888) {
- int cmodel = BC_RGB888;
- output->get_canvas()->unlock_window();
- output->unlock_canvas();
- output->mwindow->playback_3d->convert_cmodel(output, output_frame, cmodel);
- output_frame->reallocate(0,-1,0,0,0,output_frame->get_w(),output_frame->get_h(),cmodel,-1);
- output->lock_canvas("VDeviceX11::write_buffer 3");
- output->get_canvas()->lock_window("VDeviceX11::write_buffer 3");
- }
- else
-#endif
+// }
+
+// printf("VDeviceX11::write_buffer %d %d bitmap_type=%d\n",
+// __LINE__,
+// output->get_canvas()->get_video_on(),
+// bitmap_type);
+
+// int use_bitmap_extents = 0;
+// canvas_w = -1; canvas_h = -1;
+// // Canvas may be a different size than the temporary bitmap for pure software
+// if( bitmap_type == BITMAP_TEMP && !bitmap->hardware_scaling() ) {
+// canvas_w = bitmap->get_w();
+// canvas_h = bitmap->get_h();
+// }
+//
+// output->get_transfers(edl,
+// output_x1, output_y1, output_x2, output_y2,
+// canvas_x1, canvas_y1, canvas_x2, canvas_y2,
+// canvas_w, canvas_h);
+
+// Convert colormodel
if( bitmap_type == BITMAP_TEMP ) {
// printf("VDeviceX11::write_buffer 1 %d %d, %d %d %d %d -> %d %d %d %d\n",
-// output->w, output->h, in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h );
+// output->w, output->h, in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h);
// fflush(stdout);
-//printf("VDeviceX11::write_buffer %d output_channels=%p\n", __LINE__, output_channels);
+
+// printf("VDeviceX11::write_buffer %d output_channels=%p\n", __LINE__, output_channels);
+// printf("VDeviceX11::write_buffer %d input color_model=%d output color_model=%d\n",
+// __LINE__, output_channels->get_color_model(), bitmap->get_color_model());
if( bitmap->hardware_scaling() ) {
- BC_CModels::transfer(bitmap->get_row_pointers(), output_channels->get_rows(),
- 0, 0, 0, output_channels->get_y(), output_channels->get_u(), output_channels->get_v(),
+ BC_CModels::transfer(bitmap->get_row_pointers(), output_channels->get_rows(), 0, 0, 0,
+ output_channels->get_y(), output_channels->get_u(), output_channels->get_v(),
0, 0, output_channels->get_w(), output_channels->get_h(),
0, 0, bitmap->get_w(), bitmap->get_h(),
output_channels->get_color_model(), bitmap->get_color_model(),
0, output_channels->get_w(), bitmap->get_w());
}
else {
- BC_CModels::transfer(bitmap->get_row_pointers(), output_channels->get_rows(),
- 0, 0, 0, output_channels->get_y(), output_channels->get_u(), output_channels->get_v(),
+ BC_CModels::transfer(bitmap->get_row_pointers(), output_channels->get_rows(), 0, 0, 0,
+ output_channels->get_y(), output_channels->get_u(), output_channels->get_v(),
(int)output_x1, (int)output_y1, (int)(output_x2 - output_x1), (int)(output_y2 - output_y1),
0, 0, (int)(canvas_x2 - canvas_x1), (int)(canvas_y2 - canvas_y1),
output_channels->get_color_model(), bitmap->get_color_model(),
}
//printf("VDeviceX11::write_buffer 4 %p\n", bitmap);
-//for(i = 0; i < 1000; i += 4) bitmap->get_data()[i] = 128;
-//printf("VDeviceX11::write_buffer 2 %d %d %d\n", bitmap_type,
-// bitmap->get_color_model(), output->get_color_model());
-//fflush(stdout);
-//printf("VDeviceX11::write_buffer 2 %d %d, %f %f %f %f -> %f %f %f %f\n",
-// output->w, output->h, output_x1, output_y1, output_x2, output_y2,
+//for( i = 0; i < 1000; i += 4 ) bitmap->get_data()[i] = 128;
+//printf("VDeviceX11::write_buffer 2 %d %d %d\n", bitmap_type,
+// bitmap->get_color_model(),
+// output->get_color_model());fflush(stdout);
+
+// printf("VDeviceX11::write_buffer %d %dx%d %f %f %f %f -> %f %f %f %f\n",
+// __LINE__, // output->w, output->h,
+// output_x1, output_y1, output_x2, output_y2,
// canvas_x1, canvas_y1, canvas_x2, canvas_y2);
// Cause X server to display it
if( device->out_config->driver == PLAYBACK_X11_GL ) {
// Output is drawn in close_all if no video.
if( output->get_canvas()->get_video_on() ) {
+ canvas_w = -1; canvas_h = -1;
+// Canvas may be a different size than the temporary bitmap for pure software
+ if( bitmap_type == BITMAP_TEMP &&
+ !bitmap->hardware_scaling() ) {
+ canvas_w = bitmap->get_w();
+ canvas_h = bitmap->get_h();
+ }
+
+ output->get_transfers(edl,
+ output_x1, output_y1, output_x2, output_y2,
+ canvas_x1, canvas_y1, canvas_x2, canvas_y2,
+ canvas_w, canvas_h);
+
+//printf("VDeviceX11::write_buffer %d\n", __LINE__);
// Draw output frame directly. Not used for compositing.
output->get_canvas()->unlock_window();
output->unlock_canvas();
- output->mwindow->playback_3d->write_buffer(output,
- output_frame, output_x1, output_y1, output_x2, output_y2,
- canvas_x1, canvas_y1, canvas_x2, canvas_y2, is_cleared);
+ output->mwindow->playback_3d->write_buffer(output, output_frame,
+ output_x1, output_y1, output_x2, output_y2,
+ canvas_x1, canvas_y1, canvas_x2, canvas_y2,
+ is_cleared);
is_cleared = 0;
output->lock_canvas("VDeviceX11::write_buffer 2");
output->get_canvas()->lock_window("VDeviceX11::write_buffer 2");
}
}
- else if( bitmap->hardware_scaling() ) {
+ else
+ if( bitmap->hardware_scaling() ) {
output->get_canvas()->draw_bitmap(bitmap, !device->single_frame,
(int)canvas_x1, (int)canvas_y1,
(int)(canvas_x2 - canvas_x1), (int)(canvas_y2 - canvas_y1),
(int)output_x1, (int)output_y1,
- (int)(output_x2 - output_x1), (int)(output_y2 - output_y1), 0);
+ (int)(output_x2 - output_x1), (int)(output_y2 - output_y1),
+ 0);
}
else {
+//printf("VDeviceX11::write_buffer %d x=%d y=%d w=%d h=%d\n",
+// __LINE__, (int)canvas_x1, (int)canvas_y1,
+// output->get_canvas()->get_w(), output->get_canvas()->get_h());
+
output->get_canvas()->draw_bitmap(bitmap, !device->single_frame,
(int)canvas_x1, (int)canvas_y1,
- (int)(canvas_x2 - canvas_x1), (int)(canvas_y2 - canvas_y1), 0, 0,
- (int)(canvas_x2 - canvas_x1), (int)(canvas_y2 - canvas_y1), 0);
+ (int)(canvas_x2 - canvas_x1), (int)(canvas_y2 - canvas_y1),
+ 0, 0,
+ (int)(canvas_x2 - canvas_x1), (int)(canvas_y2 - canvas_y1),
+ 0);
+//printf("VDeviceX11::write_buffer %d bitmap=%p\n", __LINE__, bitmap);
}
-
output->get_canvas()->unlock_window();
output->unlock_canvas();
return 0;
void VDeviceX11::convert_cmodel(VFrame *output, int dst_cmodel)
{
this->output->mwindow->playback_3d->convert_cmodel(this->output,
- output,
+ output,
dst_cmodel);
}
void VDeviceX11::do_camera(VFrame *output, VFrame *input,
- float in_x1, float in_y1, float in_x2, float in_y2,
+ float in_x1, float in_y1, float in_x2, float in_y2,
float out_x1, float out_y1, float out_x2, float out_y2)
{
- this->output->mwindow->playback_3d->do_camera(
- this->output, output, input,
- in_x1, in_y1, in_x2, in_y2,
+ this->output->mwindow->playback_3d->do_camera(this->output,
+ output, input,
+ in_x1, in_y1, in_x2, in_y2,
out_x1, out_y1, out_x2, out_y2);
}
return keyframe->disable_opengl_masking ? 0 : 1;
}
-void VDeviceX11::do_mask(VFrame *output_temp,
- int64_t start_position_project, MaskAutos *keyframe_set,
- MaskAuto *keyframe, MaskAuto *default_auto)
+void VDeviceX11::do_mask(VFrame *output_temp, int64_t start_position_project,
+ MaskAutos *keyframe_set, MaskAuto *keyframe, MaskAuto *default_auto)
{
- this->output->mwindow->playback_3d->do_mask(output,
- output_temp, start_position_project,
- keyframe_set, keyframe, default_auto);
+ this->output->mwindow->playback_3d->do_mask(output, output_temp,
+ start_position_project, keyframe_set, keyframe, default_auto);
}
-void VDeviceX11::overlay(VFrame *output_frame, VFrame *input,
+void VDeviceX11::overlay(VFrame *output_frame, VFrame *input,
// This is the transfer from track to output frame
- float in_x1, float in_y1, float in_x2, float in_y2,
- float out_x1, float out_y1, float out_x2, float out_y2,
- float alpha /*0-1*/, int mode, EDL *edl, int is_nested)
+ float in_x1, float in_y1, float in_x2, float in_y2,
+ float out_x1, float out_y1, float out_x2, float out_y2,
+ float alpha, // 0 - 1
+ int mode, EDL *edl, int is_nested)
{
int interpolation_type = edl->session->interpolation_type;
// printf("VDeviceX11::overlay 1:\n"
// "in_x1=%f in_y1=%f in_x2=%f in_y2=%f\n"
// "out_x1=%f out_y1=%f out_x2=%f out_y2=%f\n",
-// in_x1, in_y1, in_x2, in_y2,
-// out_x1, out_y1, out_x2, out_y2);
+// in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
// Convert node coords to canvas coords in here
// If single frame playback or nested EDL, use full sized PBuffer as output.
- if(device->single_frame || is_nested > 0)
- {
+ if( device->single_frame || is_nested > 0 ) {
output->mwindow->playback_3d->overlay(output, input,
- in_x1, in_y1, in_x2, in_y2,
- out_x1, out_y1, out_x2, out_y2,
- alpha, mode, interpolation_type,
- output_frame, is_nested);
-// printf("VDeviceX11::overlay 1 %p %d %d %d\n",
-// output_frame,
-// output_frame->get_w(),
-// output_frame->get_h(),
+ in_x1, in_y1, in_x2, in_y2,
+ out_x1, out_y1, out_x2, out_y2, alpha, // 0 - 1
+ mode, interpolation_type, output_frame, is_nested);
+// printf("VDeviceX11::overlay 1 %p %d %d %d\n",
+// output_frame, output_frame->get_w(), output_frame->get_h(),
// output_frame->get_opengl_state());
}
- else
- {
+ else {
output->lock_canvas("VDeviceX11::overlay");
output->get_canvas()->lock_window("VDeviceX11::overlay");
// This is the transfer from output frame to canvas
- output->get_transfers(edl,
- output_x1, output_y1, output_x2, output_y2,
+ output->get_transfers(edl,
+ output_x1, output_y1, output_x2, output_y2,
canvas_x1, canvas_y1, canvas_x2, canvas_y2,
-1, -1);
float track_y2 = (float)(output_y2 - out_y2) / track_yscale + in_y2;
// Clamp canvas coords to track boundary
- if(track_x1 < 0)
- {
+ if( track_x1 < 0 ) {
float difference = -track_x1;
track_x1 += difference;
canvas_x1 += difference * track_xscale * canvas_xscale;
}
- if(track_y1 < 0)
- {
+ if( track_y1 < 0 ) {
float difference = -track_y1;
track_y1 += difference;
canvas_y1 += difference * track_yscale * canvas_yscale;
}
- if(track_x2 > input->get_w())
- {
+ if( track_x2 > input->get_w() ) {
float difference = track_x2 - input->get_w();
track_x2 -= difference;
canvas_x2 -= difference * track_xscale * canvas_xscale;
}
- if(track_y2 > input->get_h())
- {
+ if( track_y2 > input->get_h() ) {
float difference = track_y2 - input->get_h();
track_y2 -= difference;
canvas_y2 -= difference * track_yscale * canvas_yscale;
}
// Overlay directly from track buffer to canvas, skipping output buffer
- if(track_x2 > track_x1 && track_y2 > track_y1 &&
- canvas_x2 > canvas_x1 && canvas_y2 > canvas_y1)
- {
+ if( track_x2 > track_x1 && track_y2 > track_y1 &&
+ canvas_x2 > canvas_x1 && canvas_y2 > canvas_y1 ) {
output->mwindow->playback_3d->overlay(output, input,
- track_x1, track_y1, track_x2, track_y2,
- canvas_x1, canvas_y1, canvas_x2, canvas_y2,
- alpha, mode, interpolation_type, 0, is_nested);
+ track_x1, track_y1, track_x2, track_y2,
+ canvas_x1, canvas_y1, canvas_x2, canvas_y2, alpha, // 0 - 1
+ mode, interpolation_type, 0, is_nested);
}
}
}
int read_buffer(VFrame *frame);
int reset_parameters();
// User always gets the colormodel requested
- void new_output_buffer(VFrame **output, int colormodel);
+ void new_output_buffer(VFrame **output, int colormodel, EDL *edl);
int open_output();
int start_playback();
// is passed to this to create the VFrame to which the output is rendered.
// For OpenGL, it creates the array of row pointers used to upload the video
// frame to the texture, the texture, and the PBuffer.
- int get_best_colormodel(int colormodel);
+ int get_display_colormodel(int file_colormodel);
+
+// windows which overlay the screencap area
+#define SCREENCAP_BORDERS 4
+#define SCREENCAP_PIXELS 5
+#define SCREENCAP_COLOR GREEN
+ BC_Popup *screencap_border[SCREENCAP_BORDERS];
// Bitmap to be written to device
BC_Bitmap *bitmap;
int texture_h;
int color_model;
int color_model_selected;
-// Transfer coordinates from the output frame to the canvas
-// for last frame rendered.
+// Transfer coordinates from the output frame to the canvas.
+// Calculated in new_output_buffer & retained for write_buffer
// These stick the last frame to the display.
// Must be floats to support OpenGL
float output_x1, output_y1, output_x2, output_y2;
float canvas_x1, canvas_y1, canvas_x2, canvas_y2;
+// rounded integer dimensions
+ int canvas_w, canvas_h;
// Screen capture
BC_Capture *capture_bitmap;
// Set when OpenGL rendering has cleared the frame buffer before write_buffer
single_frame = 0;
channel_changed = 0;
picture_changed = 0;
+ odd_field_first = 0;
+ do_cursor = 0;
return 0;
}
return 0;
}
+void VideoDevice::set_do_cursor(int do_cursor, int do_big_cursor)
+{
+ int cursor_scale = 0;
+ if(do_cursor)
+ {
+ cursor_scale = 1;
+ if(do_big_cursor)
+ {
+ cursor_scale = 2;
+ }
+ }
+
+ this->do_cursor = cursor_scale;
+}
+
int VideoDevice::set_channel(Channel *channel)
{
int result = 0;
if(input_base) input_base->goose_input();
}
-void VideoDevice::new_output_buffer(VFrame **output, int colormodel)
+void VideoDevice::new_output_buffer(VFrame **output, int colormodel, EDL *edl)
{
if(!output_base) return;
- output_base->new_output_buffer(output, colormodel);
+ output_base->new_output_buffer(output, colormodel, edl);
}
void set_quality(int quality);
// Change field order
int set_field_order(int odd_field_first);
+ void set_do_cursor(int do_cursor, int do_big_cursor);
// Set frames to clear after translation change.
int set_latency_counter(int value);
// Values from -100 to 100
int interrupt_playback();
// Get output buffer for playback using colormodel.
// colormodel argument should be as close to best_colormodel as possible
- void new_output_buffer(VFrame **output, int colormodel);
+ void new_output_buffer(VFrame **output, int colormodel, EDL *edl);
int wait_for_startup();
int wait_for_completion();
int output_visible(); // Whether the output is visible or not.
// All the input sources on the device
ArrayList<Channel*> input_sources;
int odd_field_first;
+ int do_cursor;
// Quality for the JPEG compressor
int quality;
// Single frame mode for playback
{
File *file = 0;
- if(debug) printf("VModule::import_frame %d cache=%p\n",
- __LINE__,
- get_cache());
- if(current_edit->asset)
- {
+//printf("VModule::import_frame %d cache=%p\n", __LINE__, get_cache());
+ if( current_edit->asset ) {
get_cache()->age();
file = get_cache()->check_out(current_edit->asset,
get_edl());
int use_cache = renderengine &&
renderengine->command->single_frame();
- int use_asynchronous = !use_cache && renderengine &&
+// int use_asynchronous = !use_cache &&
+// renderengine &&
// Try to make rendering go faster.
// But converts some formats to YUV420, which may degrade input format.
-// renderengine->command->realtime &&
- renderengine->get_edl()->session->video_asynchronous;
+//// renderengine->command->realtime &&
+// renderengine->get_edl()->session->video_asynchronous;
if(file)
{
if(debug) printf("VModule::import_frame %d\n", __LINE__);
- if(use_asynchronous)
- file->start_video_decode_thread();
- else
+// if(use_asynchronous)
+// file->start_video_decode_thread();
+// else
file->stop_video_thread();
int64_t normalized_position = Units::to_int64(position *
!EQUIV(in_w, asset_w) ||
!EQUIV(in_h, asset_h))
{
- if(debug) printf("VModule::import_frame %d file -> temp -> output\n", __LINE__);
+//printf("VModule::import_frame %d file -> temp -> output\n", __LINE__);
get_edl()->session->interpolation_type);
}
result = 1;
+
output->copy_stacks((*input));
+
+
+//printf("VModule::import_frame %d\n", __LINE__);
+//(*input)->dump_params();
+//output->dump_params();
}
else
// file -> output
}
result = 1;
}
+
+// printf("VModule::import_frame %d cache=%p\n",
+// __LINE__,
+// get_cache());
+
}
else
// Source is silence
int use_brender = 0;
int result = 0;
int use_cache = renderengine->command->single_frame();
- int use_asynchronous =
- renderengine->command->realtime &&
- renderengine->get_edl()->session->video_every_frame &&
- renderengine->get_edl()->session->video_asynchronous;
+// int use_asynchronous =
+// renderengine->command->realtime &&
+// renderengine->get_edl()->session->video_every_frame &&
+// renderengine->get_edl()->session->video_asynchronous;
const int debug = 0;
// Determine the rendering strategy for this frame.
// Get output buffer from device
if(renderengine->command->realtime && !renderengine->is_nested)
{
- renderengine->video->new_output_buffer(&video_out, colormodel);
+ renderengine->video->new_output_buffer(&video_out,
+ colormodel,
+ renderengine->get_edl());
}
if(debug) printf("VRender::process_buffer %d video_out=%p\n", __LINE__, video_out);
corrected_position--;
// Cache single frames only
- if(use_asynchronous)
- file->start_video_decode_thread();
- else
+// if(use_asynchronous)
+// file->start_video_decode_thread();
+// else
file->stop_video_thread();
if(use_cache) file->set_cache_frames(1);
int64_t normalized_position = (int64_t)(corrected_position *
renderengine->get_vcache(),
1,
use_cache,
- use_asynchronous);
+ 0);
+// use_asynchronous);
if(debug) printf("VRender::process_buffer %d\n", __LINE__);
}
current_position,
renderengine->command->get_direction());
}
-// ffmpeg files are side effected by color_model, affects colorspace,color_range
- if( asset && asset->format != FILE_FFMPEG )
+ if( asset )
{
file = renderengine->get_vcache()->check_out(asset,
renderengine->get_edl());
if(file)
{
colormodel = file->get_best_colormodel(driver);
+//printf("VRender::get_colormodel %d driver=%d colormodel=%d\n", __LINE__, driver, colormodel);
renderengine->get_vcache()->check_in(asset);
}
+// ffmpeg files are side effected by color_model, affects colorspace,color_range
+// if( asset->format == FILE_FFMPEG && !BC_CModels::is_yuv(colormodel) )
+// colormodel = BC_BGR8888;
}
}
CHECK_HEADERS([XINERAMA], [Xinerama headers], [X11/extensions/Xinerama.h])
CHECK_LIB([XV], [Xv], [XvQueryExtension])
CHECK_HEADERS([XV], [Xlib Xv extention], [X11/Xlib.h X11/extensions/Xvlib.h])
+CHECK_LIB([XFIXES], [Xfixes], [XFixesQueryVersion])
CHECK_LIB([BZ2], [bz2], [BZ2_bzDecompress])
CHECK_LIB([FONTCONFIG], [fontconfig], [FcInit])
CHECK_LIB([FREETYPE], [freetype], [FT_Init_FreeType])
loglevel=fatal
formatprobesize=5000000
scan_all_pmts=1
-threads=auto
$(OBJDIR)/bcbitmap.o \
$(OBJDIR)/bcbutton.o \
$(OBJDIR)/bccapture.o \
+ $(OBJDIR)/bccolors.o \
$(OBJDIR)/bccmodels.o \
$(OBJDIR)/bccounter.o \
$(OBJDIR)/bcclipboard.o \
#include "bcwindowbase.inc"
#include "bcbitmap.inc"
#include "bccmodels.h"
-#include "colors.h"
+#include "bccolors.h"
#include "condition.h"
#include "linklist.h"
#include "mutex.h"
#include "bcpixmap.h"
#include "bcresources.h"
#include "bcsignals.h"
-#include "colors.h"
+#include "bccolors.h"
#include "fonts.h"
#include "keys.h"
#include "language.h"
#include "bcresources.h"
#include "bcwindowbase.h"
#include "bccmodels.h"
+#include "bccolors.h"
+#include "clip.h"
#include "language.h"
#include "vframe.h"
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xutil.h>
-
-
-
-
+#include <X11/extensions/Xfixes.h>
// Byte orders:
// 24 bpp packed: bgr
int BC_Capture::init_window(const char *display_path)
{
int bits_per_pixel;
- if(display_path && display_path[0] == 0) display_path = NULL;
- if((display = XOpenDisplay(display_path)) == NULL)
- {
+ if( display_path && display_path[0] == 0 ) display_path = NULL;
+ if( (display = XOpenDisplay(display_path)) == NULL ) {
printf(_("cannot connect to X server.\n"));
- if(getenv("DISPLAY") == NULL)
+ if( getenv("DISPLAY") == NULL )
printf(_("'DISPLAY' environment variable not set.\n"));
exit(-1);
return 1;
// test shared memory
// This doesn't ensure the X Server is on the local host
- if(use_shm && !XShmQueryExtension(display))
- {
+ if( use_shm && !XShmQueryExtension(display) ) {
use_shm = 0;
}
return 0;
int BC_Capture::allocate_data()
{
// try shared memory
- if(!display) return 1;
- if(use_shm)
- {
+ if( !display ) return 1;
+ if( use_shm ) {
ximage = XShmCreateImage(display, vis, default_depth, ZPixmap, (char*)NULL, &shm_info, w, h);
shm_info.shmid = shmget(IPC_PRIVATE, h * ximage->bytes_per_line, IPC_CREAT | 0600);
- if(shm_info.shmid == -1)
- {
+ if( shm_info.shmid == -1 ) {
perror("BC_Capture::allocate_data shmget");
abort();
}
BC_Resources::error = 0;
XShmAttach(display, &shm_info);
XSync(display, False);
- if(BC_Resources::error)
- {
+ if( BC_Resources::error ) {
XDestroyImage(ximage);
shmdt(shm_info.shmaddr);
use_shm = 0;
}
}
- if(!use_shm)
- {
+ if( !use_shm ) {
// need to use bytes_per_line for some X servers
data = 0;
ximage = XCreateImage(display, vis, default_depth, ZPixmap, 0, (char*)data, w, h, 8, 0);
}
row_data = new unsigned char*[h];
- for(int i = 0; i < h; i++)
- {
+ for( int i = 0; i < h; i++ ) {
row_data[i] = &data[i * ximage->bytes_per_line];
}
// This differs from the depth parameter of the top_level.
int BC_Capture::delete_data()
{
- if(!display) return 1;
- if(data)
- {
- if(use_shm)
- {
+ if( !display ) return 1;
+ if( data ) {
+ if( use_shm ) {
XShmDetach(display, &shm_info);
XDestroyImage(ximage);
shmdt(shm_info.shmaddr);
}
- else
- {
+ else {
XDestroyImage(ximage);
}
int BC_Capture::get_h() { return h; }
// Capture a frame from the screen
-#define CAPTURE_FRAME_HEAD \
- for(int i = 0; i < h; i++) \
- { \
- unsigned char *input_row = row_data[i]; \
- unsigned char *output_row = (unsigned char*)frame->get_rows()[i]; \
- for(int j = 0; j < w; j++) \
- {
-
-#define CAPTURE_FRAME_TAIL \
- } \
- }
+#define RGB_TO_YUV(y, u, v, r, g, b) { \
+ YUV::yuv.rgb_to_yuv_8(r, g, b, y, u, v); \
+ bclamp(y, 0,0xff); bclamp(u, 0,0xff); bclamp(v, 0,0xff); }
-
-
-int BC_Capture::capture_frame(VFrame *frame, int &x1, int &y1)
+int BC_Capture::capture_frame(VFrame *frame, int &x1, int &y1,
+ int do_cursor) // the scale of the cursor if nonzero
{
- if(!display) return 1;
- if(x1 < 0) x1 = 0;
- if(y1 < 0) y1 = 0;
- if(x1 > get_top_w() - w) x1 = get_top_w() - w;
- if(y1 > get_top_h() - h) y1 = get_top_h() - h;
+ if( !display ) return 1;
+ if( x1 < 0 ) x1 = 0;
+ if( y1 < 0 ) y1 = 0;
+ if( x1 > get_top_w() - w ) x1 = get_top_w() - w;
+ if( y1 > get_top_h() - h ) y1 = get_top_h() - h;
// Read the raw data
- if(use_shm)
+ if( use_shm )
XShmGetImage(display, rootwin, ximage, x1, y1, 0xffffffff);
else
XGetSubImage(display, rootwin, x1, y1, w, h, 0xffffffff, ZPixmap, ximage, 0, 0);
frame->get_w(), frame->get_h(),
bitmap_color_model, frame->get_color_model(),
0, frame->get_w(), w);
+
+ if( do_cursor ) {
+ XFixesCursorImage *cursor;
+ cursor = XFixesGetCursorImage(display);
+ if( cursor ) {
+//printf("BC_Capture::capture_frame %d cursor=%p colormodel=%d\n",
+// __LINE__, cursor, frame->get_color_model());
+ int scale = do_cursor;
+ int cursor_x = cursor->x - x1 - cursor->xhot * scale;
+ int cursor_y = cursor->y - y1 - cursor->yhot * scale;
+ int w = frame->get_w();
+ int h = frame->get_h();
+ for( int i = 0; i < cursor->height; i++ ) {
+ for( int yscale = 0; yscale < scale; yscale++ ) {
+ if( cursor_y + i * scale + yscale >= 0 &&
+ cursor_y + i * scale + yscale < h ) {
+ unsigned char *src = (unsigned char*)(cursor->pixels +
+ i * cursor->width);
+ int dst_y = cursor_y + i * scale + yscale;
+ int dst_x = cursor_x;
+ for( int j = 0; j < cursor->width; j++ ) {
+ for( int xscale = 0; xscale < scale ; xscale++ ) {
+ if( cursor_x + j * scale + xscale >= 0 &&
+ cursor_x + j * scale + xscale < w ) {
+ int a = src[3];
+ int invert_a = 0xff - a;
+ int r = src[2];
+ int g = src[1];
+ int b = src[0];
+ switch( frame->get_color_model() ) {
+ case BC_RGB888: {
+ unsigned char *dst = frame->get_rows()[dst_y] +
+ dst_x * 3;
+ dst[0] = (r * a + dst[0] * invert_a) / 0xff;
+ dst[1] = (g * a + dst[1] * invert_a) / 0xff;
+ dst[2] = (b * a + dst[2] * invert_a) / 0xff;
+ break; }
+
+ case BC_YUV420P: {
+ unsigned char *dst_y_ = frame->get_y() +
+ dst_y * w + dst_x;
+ unsigned char *dst_u = frame->get_u() +
+ (dst_y / 2) * (w / 2) + (dst_x / 2);
+ unsigned char *dst_v = frame->get_v() +
+ (dst_y / 2) * (w / 2) + (dst_x / 2);
+ int y, u, v;
+ RGB_TO_YUV(y, u, v, r, g, b);
+
+ *dst_y_ = (y * a + *dst_y_ * invert_a) / 0xff;
+ *dst_u = (u * a + *dst_u * invert_a) / 0xff;
+ *dst_v = (v * a + *dst_v * invert_a) / 0xff;
+ break; }
+ }
+ }
+ dst_x++;
+ }
+ src += sizeof(long);
+ }
+ }
+ }
+ }
+
+// This frees cursor->pixels
+ XFree(cursor);
+ }
+ }
return 0;
}
int init_window(const char *display_path);
// x1 and y1 are automatically adjusted if out of bounds
- int capture_frame(VFrame *frame, int &x1, int &y1);
+ int capture_frame(VFrame *frame, int &x1, int &y1,
+ int do_cursor=0); // the scale of the cursor if nonzero
int get_w();
int get_h();
int in_x, int in_y, int in_w, int in_h, int in_rowspan,
int bg_color);
- static void init_yuv();
static int bc_to_x(int color_model);
static void bcxfer_stop_slicers();
};
*
*/
-#include "cicolors.h"
+#include "bccolors.h"
#include <stdio.h>
*
*/
-#ifndef CICOLORS_H
-#define CICOLORS_H
+#ifndef __BCCOLORS_H__
+#define __BCCOLORS_H__
// Duplicate filename in guicast
};
-
-
-
-
-
-
-
-
-
-
-
-
class HSV
{
public:
};
+// standard colors
+#define BLACK 0x000000
+#define WHITE 0xFFFFFF
+
+#define LTBLUE 0x9090FF
+#define BLUE 0x0000FF
+#define DKBLUE 0x000090
+
+#define LTPINK 0xFFC0C0
+#define PINK 0xFF8080
+#define RED 0xFF0000
+
+#define LTGREEN 0xC0FFC0
+#define GREEN 0x00FF00
+#define DKGREEN 0x009000
+
+#define YELLOW 0xFFFF00
+#define LTYELLOW 0xFFFFA0
+#define MEYELLOW 0xFFFF00
+#define MDYELLOW 0xFFFFD2
+#define DKYELLOW 0xFFFFB4
+
+#define LTCYAN 0x00CBCB
+#define MECYAN 0x009696
+#define MDCYAN 0x007E7E
+#define DKCYAN 0x004949
+
+#define LTPURPLE 0xFFC0FF
+#define MEPURPLE 0xFF00FF
+#define MDPURPLE 0xC000C0
+#define DKPURPLE 0xA000A0
+
+#define LTGREY 0xE0E0E0
+#define MEGREY 0xAFAFAF
+#define DMGREY 0x999999
+#define MDGREY 0x7D7D7D
+#define DKGREY 0x4B4B4B
+
+#define BLOND 0xb4b487
+#define SLBLUE 0x6040c0
+
+#define MNGREY 0xe6e6e6
+#define FGGREY 0xe3e3e3
+#define MNBLUE 0x003cff
+#define ORANGE 0xffdd76
+#define FTGREY 0xbcbcbc
+
#endif
/*
* CINELERRA
- * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
+ * Copyright (C) 1997-2017 Adam Williams <broadcast at earthling dot net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
image_number = 2;
}
- int column_offset = get_column_offset(number) - xposition + LISTBOX_BORDER;
- int column_width = get_column_width(number, 1);
gui->draw_3segmenth(get_column_offset(number) - xposition + LISTBOX_BORDER,
LISTBOX_BORDER,
get_column_width(number, 1) + get_resources()->listbox_title_overlap,
column_bg[image_number]);
-// Column title sort order
- if(number == sort_column)
- {
- BC_Pixmap *src;
- if(sort_order == SORT_ASCENDING)
- src = column_sort_dn;
- else
- src = column_sort_up;
+ int title_x = -xposition + get_column_offset(number) +
+ LISTBOX_MARGIN + LISTBOX_BORDER;
+ title_x += get_resources()->listbox_title_margin;
- int x = column_offset +
- column_width -
- LISTBOX_BORDER;
- if(x > items_w) x = items_w;
- x -= 5 + src->get_w();
+ gui->set_color(get_resources()->listbox_title_color);
+ gui->draw_text(title_x,
+ LISTBOX_MARGIN + LISTBOX_BORDER + get_text_ascent(MEDIUMFONT),
+ column_titles[number]);
+
+// Column sort order
+ if(number == sort_column) {
+ BC_Pixmap *src = sort_order == SORT_ASCENDING ?
+ column_sort_dn : column_sort_up;
+
+// int column_offset = get_column_offset(number) - xposition + LISTBOX_BORDER;
+// int column_width = get_column_width(number, 1);
+// int toggle_x = column_offset + column_width - LISTBOX_BORDER;
+// if( toggle_x > items_w ) toggle_x = items_w;
+// toggle_x -= 5 + src->get_w();
+
+ int x = title_x +
+ get_text_width(MEDIUMFONT, column_titles[number]) +
+ LISTBOX_MARGIN;
+
gui->draw_pixmap(src,
x,
title_h / 2 - src->get_h() / 2 + LISTBOX_BORDER);
}
-
-
- int x = -xposition +
- get_column_offset(number) +
- LISTBOX_MARGIN +
- LISTBOX_BORDER;
- x += get_resources()->listbox_title_margin;
-
- gui->set_color(get_resources()->listbox_title_color);
- gui->draw_text(x,
- LISTBOX_MARGIN + LISTBOX_BORDER + get_text_ascent(MEDIUMFONT),
- _(column_titles[number]));
}
int BC_ListBox::draw_titles(int flash)
#include "bcscrollbar.h"
#include "bcsubwindow.h"
#include "bctoggle.h"
-#include "colors.h"
+#include "bccolors.h"
#define BCPOPUPLISTBOX_W 25
#define BCPOPUPLISTBOX_H 25
#include "arraylist.h"
#include "bcpixmap.inc"
-#include "colors.h"
+#include "bccolors.h"
#include "vframe.h"
#include "bcpopupmenu.h"
#include "bcresources.h"
#include "bcsignals.h"
-#include "colors.h"
+#include "bccolors.h"
#include "fonts.h"
#include "keys.h"
#include <string.h>
#include "bcresources.h"
#include "bcsignals.h"
#include "bcwindowbase.h"
-#include "colors.h"
+#include "bccolors.h"
#include <string.h>
void set_hotkey_text(const char *text);
int set_shift(int value = 1);
int set_alt(int value = 1);
- void set_ctrl(int value);
+ void set_ctrl(int value = 1);
int deactivate_submenus(BC_MenuPopup *exclude);
int activate_submenu();
#include "bcpixmap.h"
#include "bcresources.h"
#include "bcwindow.h"
-#include "colors.h"
+#include "bccolors.h"
#include "fonts.h"
#include "vframe.h"
#include <string.h>
#include "bcpopup.h"
#include "bcresources.h"
#include "clip.h"
-#include "colors.h"
+#include "bccolors.h"
#include "fonts.h"
#include "rotateframe.h"
#include "units.h"
#include "bcpopupmenu.h"
#include "bcresources.h"
#include "bcsignals.h"
-#include "colors.h"
+#include "bccolors.h"
#include "fonts.h"
#include <string.h>
#include "vframe.h"
#include "bcpot.h"
#include "bcresources.h"
-#include "colors.h"
+#include "bccolors.h"
#include "keys.h"
#include "units.h"
#include "vframe.h"
#define PROGRESS_UP 0
#define PROGRESS_HI 1
-#include "colors.h"
+#include "bccolors.h"
#include "fonts.h"
#include "bcprogress.h"
#include "bcpixmap.h"
#include "bcsignals.h"
#include "bcsynchronous.h"
#include "bcwindowbase.h"
-#include "colors.h"
+#include "bccolors.h"
#include "bccmodels.h"
#include "cstrdup.h"
#include "fonts.h"
"-*-bitstream charter-bold-r-normal-*-*-0-%d-%d-p-0-iso8859-1"; // 160
static const char *def_big_font2 =
"-*-nimbus sans l-bold-r-normal-*-*-0-%d-%d-p-0-iso8859-1"; // 160
+static const char *def_clock_font = "-*-helvetica-bold-r-normal-*-%d-*"; // 16
+static const char *def_clock_font2 = "-*-helvetica-bold-r-normal-*-%d-*"; // 18
static const char *def_small_fontset = "-*-helvetica-medium-r-normal-*-%d-*";// 10
static const char *def_medium_fontset = "-*-helvetica-bold-r-normal-*-%d-*"; // 14
static const char *def_large_fontset = "-*-helvetica-bold-r-normal-*-%d-*"; // 18
static const char *def_big_fontset = "-*-helvetica-bold-r-normal-*-%d-*"; // 24
+static const char *def_clock_fontset = "-*-helvetica-bold-r-normal-*-%d-*"; // 16
+
static const char *def_small_font_xft = "Sans:pixelsize=%.4f"; // 10.6667
static const char *def_small_b_font_xft = "Sans:bold:pixelsize=%.4f"; // 10.6667
static const char *def_medium_font_xft = "Sans:pixelsize=%.4f"; // 13.3333
static const char *def_large_b_font_xft = "Sans:bold:pixelsize=%.4f"; // 21.3333
static const char *def_big_font_xft = "Sans:pixelsize=37.3333"; // 37.3333
static const char *def_big_b_font_xft = "Sans:bold:pixelsize=37.33333"; // 37.3333
+static const char *def_clock_font_xft = "Sans:pixelsize=16"; // 16
#define default_font_xft2 "-microsoft-verdana-*-*-*-*-*-*-*-*-*-*-*-*"
const char* BC_Resources::large_font2 = 0;
const char* BC_Resources::big_font = 0;
const char* BC_Resources::big_font2 = 0;
+const char* BC_Resources::clock_font = 0;
+const char* BC_Resources::clock_font2 = 0;
const char* BC_Resources::small_fontset = 0;
const char* BC_Resources::medium_fontset = 0;
const char* BC_Resources::large_fontset = 0;
const char* BC_Resources::big_fontset = 0;
+const char* BC_Resources::clock_fontset = 0;
const char* BC_Resources::small_font_xft = 0;
const char* BC_Resources::small_font_xft2 = 0;
const char* BC_Resources::small_b_font_xft = 0;
const char* BC_Resources::big_font_xft = 0;
const char* BC_Resources::big_font_xft2 = 0;
const char* BC_Resources::big_b_font_xft = 0;
+const char* BC_Resources::clock_font_xft = 0;
+const char* BC_Resources::clock_font_xft2 = 0;
#define def_font(v, s...) do { sprintf(string,def_##v,s); v = cstrdup(string); } while(0)
#define set_font(v, s) do { sprintf(string, "%s", s); v = cstrdup(string); } while(0)
def_font(large_font, iround(scale*18));
def_font(large_font2, iround(scale*20));
def_font(big_font, iround(scale*160), iround(scale*160));
- def_font(big_font2, iround(scale*160), iround(scale*160));
+ def_font(big_font2, iround(scale*16), iround(scale*16));
+ def_font(clock_font, iround(scale*16), iround(scale*16));
+ def_font(clock_font2, iround(scale*16), iround(scale*16));
def_font(small_fontset, iround(scale*10));
def_font(medium_fontset, iround(scale*14));
def_font(large_fontset, iround(scale*18));
def_font(big_fontset, iround(scale*24));
+ def_font(clock_fontset, iround(scale*16));
def_font(small_font_xft, (scale*10.6667));
def_font(small_b_font_xft, (scale*10.6667));
def_font(medium_font_xft, (scale*13.3333));
def_font(large_b_font_xft, (scale*21.3333));
def_font(big_font_xft, (scale*37.3333));
def_font(big_b_font_xft, (scale*37.3333));
+ def_font(clock_font_xft, (scale*16));
set_font(small_font_xft2, default_font_xft2);
set_font(medium_font_xft2, default_font_xft2);
set_font(large_font_xft2, default_font_xft2);
set_font(big_font_xft2, default_font_xft2);
+ set_font(clock_font_xft2, default_font_xft2);
}
void BC_Resources::finit_font_defs()
{
delete [] large_font2;
delete [] big_font;
delete [] big_font2;
+ delete [] clock_font;
+ delete [] clock_font2;
delete [] small_fontset;
delete [] medium_fontset;
delete [] large_fontset;
delete [] big_fontset;
+ delete [] clock_fontset;
delete [] small_font_xft;
delete [] small_b_font_xft;
delete [] medium_font_xft;
delete [] large_b_font_xft;
delete [] big_font_xft;
delete [] big_b_font_xft;
+ delete [] clock_font_xft;
delete [] small_font_xft2;
delete [] medium_font_xft2;
delete [] large_font_xft2;
delete [] big_font_xft2;
+ delete [] clock_font_xft2;
}
double font_scale, icon_scale;
// fonts
- static const char *small_font;
- static const char *medium_font;
- static const char *large_font;
- static const char *big_font;
-// Backup of fonts in case the first choices don't exist
- static const char *small_font2;
- static const char *medium_font2;
- static const char *large_font2;
- static const char *big_font2;
+ static const char *small_font, *small_font2;
+ static const char *medium_font, *medium_font2;
+ static const char *large_font, *large_font2;
+ static const char *big_font, *big_font2;
+ static const char *clock_font, *clock_font2;
static const char *small_fontset;
static const char *medium_fontset;
static const char *large_fontset;
static const char *big_fontset;
+ static const char *clock_fontset;
static const char *small_font_xft, *small_b_font_xft;
static const char *medium_font_xft, *medium_b_font_xft;
static const char *large_font_xft, *large_b_font_xft;
static const char *big_font_xft, *big_b_font_xft;
+ static const char *clock_font_xft, *clock_b_font_xft;
// Backup of fonts in case the first choices don't exist
static const char *small_font_xft2;
static const char *medium_font_xft2;
static const char *large_font_xft2;
static const char *big_font_xft2;
+ static const char *clock_font_xft2;
+
void init_font_defs(double scale);
void finit_font_defs();
#include "bcresources.h"
#include "bcscrollbar.h"
#include "clip.h"
-#include "colors.h"
+#include "bccolors.h"
#include "vframe.h"
#include <string.h>
#include "bcpixmap.h"
#include "bcresources.h"
#include "bcslider.h"
-#include "colors.h"
+#include "bccolors.h"
#include "fonts.h"
#include "keys.h"
#include "units.h"
#include "bcsignals.h"
#include "bctextbox.h"
#include "clip.h"
-#include "colors.h"
+#include "bccolors.h"
#include <ctype.h>
#include "cursors.h"
#include "filesystem.h"
#include "keys.h"
+#include "language.h"
#include <math.h>
#include "bctimer.h"
#include "vframe.h"
delete suggestions_popup;
suggestions->remove_all_objects();
delete suggestions;
+ delete menu;
delete [] wtext;
if( size > 0 )
delete [] text;
separators = 0;
xscroll = 0;
yscroll = 0;
+ menu = 0;
dirty = 1;
selection_active = 0;
return 0;
int BC_TextBox::initialize()
{
+
if (!skip_cursor)
skip_cursor = new Timer;
skip_cursor->update();
draw(0);
set_cursor(IBEAM_CURSOR, 0, 0);
show_window(0);
+
+ add_subwindow(menu = new BC_TextMenu(this));
+ menu->create_objects();
+
return 0;
}
const int debug = 0;
if(!enabled) return 0;
- if(get_buttonpress() != WHEEL_UP &&
- get_buttonpress() != WHEEL_DOWN &&
- get_buttonpress() != LEFT_BUTTON &&
- get_buttonpress() != MIDDLE_BUTTON) return 0;
-
-
+// if(get_buttonpress() != WHEEL_UP &&
+// get_buttonpress() != WHEEL_DOWN &&
+// get_buttonpress() != LEFT_BUTTON &&
+// get_buttonpress() != MIDDLE_BUTTON) return 0;
if(debug) printf("BC_TextBox::button_press_event %d\n", __LINE__);
update_scroll = 1;
}
else
+ if(get_buttonpress() == RIGHT_BUTTON)
+ {
+ menu->activate_menu();
+ }
+ else
{
cursor_letter = get_cursor_letter(top_level->cursor_x, top_level->cursor_y);
if( ctrl_down() ) {
switch( get_keypress() ) {
case 'c': case 'C': {
- if(highlight_letter1 != highlight_letter2) {
- copy_selection(SECONDARY_SELECTION);
- result = 1;
- }
+ result = copy(0);
break; }
case 'v': case 'V': {
- paste_selection(SECONDARY_SELECTION);
- find_ibeam(1);
- if(keypress_draw) draw(1);
+ result = paste(0);
dispatch_event = 1;
- result = 1;
break; }
case 'x': case 'X': {
- if(highlight_letter1 != highlight_letter2) {
- copy_selection(SECONDARY_SELECTION);
- delete_selection(highlight_letter1, highlight_letter2, wtext_len);
- highlight_letter2 = ibeam_letter = highlight_letter1;
- }
-
- find_ibeam(1);
- if(keypress_draw) draw(1);
+ result = cut(0);
dispatch_event = 1;
- result = 1;
break; }
case 'u': case 'U': {
if( shift_down() ) {
}
+int BC_TextBox::cut(int do_update)
+{
+ if( highlight_letter1 != highlight_letter2 ) {
+ int wtext_len = wtext_update();
+ copy_selection(SECONDARY_SELECTION);
+ delete_selection(highlight_letter1, highlight_letter2, wtext_len);
+ highlight_letter2 = ibeam_letter = highlight_letter1;
+ }
+
+ find_ibeam(1);
+ if( keypress_draw )
+ draw(1);
+
+ if( do_update ) {
+ skip_cursor->update();
+ handle_event();
+ }
+ return 1;
+}
+
+int BC_TextBox::copy(int do_update)
+{
+ int result = 0;
+ if( highlight_letter1 != highlight_letter2 ) {
+ copy_selection(SECONDARY_SELECTION);
+ result = 1;
+ if( do_update ) {
+ skip_cursor->update();
+ }
+ }
+ return result;
+}
+
+int BC_TextBox::paste(int do_update)
+{
+ paste_selection(SECONDARY_SELECTION);
+ find_ibeam(1);
+ if( keypress_draw )
+ draw(1);
+ if( do_update ) {
+ skip_cursor->update();
+ handle_event();
+ }
+ return 1;
+}
+
+
int BC_TextBox::uses_text()
{
return 1;
tumbler->set_boundaries(min, max);
}
+
+
+BC_TextMenu::BC_TextMenu(BC_TextBox *textbox)
+ : BC_PopupMenu(0, 0, 0, "", 0)
+{
+ this->textbox = textbox;
+}
+
+BC_TextMenu::~BC_TextMenu()
+{
+}
+
+void BC_TextMenu::create_objects()
+{
+ add_item(new BC_TextMenuCut(this));
+ add_item(new BC_TextMenuCopy(this));
+ add_item(new BC_TextMenuPaste(this));
+}
+
+
+BC_TextMenuCut::BC_TextMenuCut(BC_TextMenu *menu)
+ : BC_MenuItem(_("Cut"))
+{
+ this->menu = menu;
+}
+
+int BC_TextMenuCut::handle_event()
+{
+ menu->textbox->cut(1);
+
+ return 0;
+}
+
+
+BC_TextMenuCopy::BC_TextMenuCopy(BC_TextMenu *menu)
+ : BC_MenuItem(_("Copy"))
+{
+ this->menu = menu;
+}
+
+int BC_TextMenuCopy::handle_event()
+{
+ menu->textbox->copy(1);
+ return 0;
+}
+
+
+BC_TextMenuPaste::BC_TextMenuPaste(BC_TextMenu *menu)
+ : BC_MenuItem(_("Paste"))
+{
+ this->menu = menu;
+}
+
+int BC_TextMenuPaste::handle_event()
+{
+ menu->textbox->paste(1);
+ return 0;
+}
+
+
void BC_TumbleTextBox::set_tooltip(const char *text)
{
textbox->set_tooltip(text);
#define BCTEXTBOX_H
#include "bclistbox.h"
+#include "bcmenuitem.h"
+#include "bcpopupmenu.h"
#include "bcsubwindow.h"
#include "bctumble.h"
#include "fonts.h"
class BC_ScrollTextBoxXScroll;
class BC_ScrollTextBoxYScroll;
class BC_ScrollTextBoxText;
-
+class BC_TextMenu;
class BC_TextBox : public BC_SubWindow
{
int reposition_window(int x, int y, int w = -1, int rows = -1);
int uses_text();
+ int cut(int do_update);
+ int copy(int do_update);
+ int paste(int do_update);
+
static int calculate_h(BC_WindowBase *gui, int font, int has_border, int rows);
static int calculate_row_h(int rows, BC_WindowBase *parent_window, int has_border = 1, int font = MEDIUMFONT);
static int pixels_to_rows(BC_WindowBase *window, int font, int pixels);
BC_ScrollTextBoxYScroll *yscroll;
private:
int reset_parameters(int rows, int has_border, int font, int size);
+ BC_TextMenu *menu;
void draw(int flush);
void draw_border();
void draw_cursor();
};
+class BC_TextMenu : public BC_PopupMenu
+{
+public:
+ BC_TextMenu(BC_TextBox *textbox);
+ ~BC_TextMenu();
+
+ void create_objects();
+
+ BC_TextBox *textbox;
+};
+
+class BC_TextMenuCut : public BC_MenuItem
+{
+public:
+ BC_TextMenuCut(BC_TextMenu *menu);
+ int handle_event();
+ BC_TextMenu *menu;
+};
+
+class BC_TextMenuCopy : public BC_MenuItem
+{
+public:
+ BC_TextMenuCopy(BC_TextMenu *menu);
+ int handle_event();
+ BC_TextMenu *menu;
+};
+
+class BC_TextMenuPaste : public BC_MenuItem
+{
+public:
+ BC_TextMenuPaste(BC_TextMenu *menu);
+ int handle_event();
+ BC_TextMenu *menu;
+};
+
+
#endif
#define BCTITLE_H
#include "bcsubwindow.h"
-#include "colors.h"
+#include "bccolors.h"
#include "fonts.h"
class BC_Title : public BC_SubWindow
#include "bcsignals.h"
#include "bctoggle.h"
#include "clip.h"
-#include "colors.h"
+#include "bccolors.h"
#include "cursors.h"
#include "fonts.h"
#include "vframe.h"
#include <string.h>
-BC_Toggle::BC_Toggle(int x, int y,
- VFrame **data,
- int value,
- const char *caption,
- int bottom_justify,
- int font,
- int color)
+BC_Toggle::BC_Toggle(int x, int y, VFrame **data, int value,
+ const char *caption, int bottom_justify, int font, int color)
: BC_SubWindow(x, y, 0, 0, -1)
{
this->data = data;
- for(int i = 0; i < TOGGLE_IMAGES; i++)
- images[i] = 0;
+ for( int i=0; i<TOGGLE_IMAGES; ++i ) images[i] = 0;
bg_image = 0;
status = value ? BC_Toggle::TOGGLE_CHECKED : BC_Toggle::TOGGLE_UP;
this->value = value;
strcpy(this->caption, caption);
this->bottom_justify = bottom_justify;
this->font = font;
- if(color >= 0)
- this->color = color;
- else
- this->color = get_resources()->default_text_color;
+ this->color = color >= 0 ? color : get_resources()->default_text_color;
select_drag = 0;
enabled = 1;
underline = -1;
BC_Toggle::~BC_Toggle()
{
- for(int i = 0; i < TOGGLE_IMAGES; i++) if(images[i]) delete images[i];
+ for( int i=0; i<TOGGLE_IMAGES; ++i ) delete images[i];
delete bg_image;
}
{
// Get the image
set_images(data);
- calculate_extents(this,
- data,
- bottom_justify,
- &text_line,
- &w,
- &h,
- &toggle_x,
- &toggle_y,
- &text_x,
- &text_y,
- &text_w,
- &text_h,
+ calculate_extents(this, data, bottom_justify,
+ &text_line, &w, &h, &toggle_x, &toggle_y,
+ &text_x, &text_y, &text_w, &text_h,
has_caption() ? caption : 0,
font);
void BC_Toggle::calculate_extents(BC_WindowBase *gui,
- VFrame **images,
- int bottom_justify,
- int *text_line,
- int *w,
- int *h,
- int *toggle_x,
- int *toggle_y,
- int *text_x,
- int *text_y,
- int *text_w,
- int *text_h,
- const char *caption,
- int font)
+ VFrame **images, int bottom_justify,
+ int *text_line, int *w, int *h, int *toggle_x, int *toggle_y,
+ int *text_x, int *text_y, int *text_w, int *text_h,
+ const char *caption, int font)
{
BC_Resources *resources = get_resources();
VFrame *frame = images[0];
*text_w = 0;
*text_h = 0;
- if(caption)
- {
+ if( caption ) {
*text_w = gui->get_text_width(font, caption);
*text_h = gui->get_text_height(font);
- if(resources->toggle_highlight_bg)
- {
+ if( resources->toggle_highlight_bg ) {
*text_w += resources->toggle_text_margin * 2;
*text_h = MAX(*text_h, resources->toggle_highlight_bg->get_h());
}
- if(*text_h > *h)
- {
+ if( *text_h > *h ) {
*toggle_y = (*text_h - *h) >> 1;
*h = *text_h;
}
else
*text_y = (*h - *text_h) >> 1;
- if(bottom_justify)
- {
+ if( bottom_justify ) {
*text_y = *h - *text_h;
*text_line = *h - gui->get_text_descent(font);
}
{
delete bg_image;
bg_image = 0;
- for(int i = 0; i < TOGGLE_IMAGES; i++)
- {
- if(images[i]) delete images[i];
+ for( int i=0; i<TOGGLE_IMAGES; ++i ) {
+ delete images[i];
images[i] = new BC_Pixmap(top_level, data[i], PIXMAP_ALPHA);
}
BC_Resources *resources = get_resources();
- if(resources->toggle_highlight_bg)
- {
+ if( resources->toggle_highlight_bg ) {
bg_image = new BC_Pixmap(top_level,
resources->toggle_highlight_bg,
PIXMAP_ALPHA);
{
BC_Resources *resources = get_resources();
draw_top_background(parent_window, 0, 0, get_w(), get_h());
- if(has_caption())
- {
- if(enabled &&
+ if( has_caption() ) {
+ if( enabled &&
(status == BC_Toggle::TOGGLE_UPHI ||
status == BC_Toggle::TOGGLE_DOWN ||
- status == BC_Toggle::TOGGLE_CHECKEDHI))
- {
+ status == BC_Toggle::TOGGLE_CHECKEDHI) ) {
// Draw highlight image
- if(bg_image)
- {
+ if( bg_image ) {
int x = text_x;
int y = text_line - get_text_ascent(font) / 2 -
bg_image->get_h() / 2;
}
set_opaque();
- if(enabled)
+ if( enabled )
set_color(color);
else
set_color(get_resources()->disabled_text_color);
caption);
// Draw underline
- if(underline >= 0)
- {
+ if( underline >= 0 ) {
int x = text_x + resources->toggle_text_margin;
int y = text_line + 1;
int x1 = get_text_width(current_font, caption, underline) + x;
}
draw_pixmap(images[status]);
- if(flash) this->flash(0);
- if(flush) this->flush();
+ if( flash ) this->flash(0);
+ if( flush ) this->flush();
return 0;
}
void BC_Toggle::enable()
{
enabled = 1;
- if(parent_window) draw_face(1, 1);
+ if( parent_window ) draw_face(1, 1);
}
void BC_Toggle::disable()
{
enabled = 0;
- if(parent_window) draw_face(1, 1);
+ if( parent_window ) draw_face(1, 1);
}
void BC_Toggle::set_status(int value)
int BC_Toggle::repeat_event(int64_t duration)
{
- if(tooltip_text && tooltip_text[0] != 0 &&
+ if( tooltip_text && tooltip_text[0] != 0 &&
duration == top_level->get_resources()->tooltip_delay &&
- (status == BC_Toggle::TOGGLE_UPHI || status == BC_Toggle::TOGGLE_CHECKEDHI))
- {
+ (status == BC_Toggle::TOGGLE_UPHI || status == BC_Toggle::TOGGLE_CHECKEDHI) ) {
show_tooltip();
return 1;
}
int BC_Toggle::cursor_enter_event()
{
- if(top_level->event_win == win && enabled)
- {
- if(top_level->button_down)
+ if( top_level->event_win == win && enabled ) {
+ if( top_level->button_down )
status = BC_Toggle::TOGGLE_DOWN;
else
status = value ? BC_Toggle::TOGGLE_CHECKEDHI : BC_Toggle::TOGGLE_UPHI;
int BC_Toggle::cursor_leave_event()
{
hide_tooltip();
- if(!value && status == BC_Toggle::TOGGLE_UPHI)
- {
+ if( !value && status == BC_Toggle::TOGGLE_UPHI ) {
status = BC_Toggle::TOGGLE_UP;
draw_face(1, 1);
}
else
- if(status == BC_Toggle::TOGGLE_CHECKEDHI)
- {
+ if( status == BC_Toggle::TOGGLE_CHECKEDHI ) {
status = BC_Toggle::TOGGLE_CHECKED;
draw_face(1, 1);
}
int BC_Toggle::button_press_event()
{
hide_tooltip();
- if(top_level->event_win == win && get_buttonpress() == 1 && enabled)
- {
+ if( top_level->event_win == win && get_buttonpress() == 1 && enabled ) {
status = BC_Toggle::TOGGLE_DOWN;
// Change value now for select drag mode.
// Radial always goes to 1
- if(select_drag)
- {
- if(!is_radial)
+ if( select_drag ) {
+ if( !is_radial )
value = !value;
else
value = 1;
int result = 0;
hide_tooltip();
- if(top_level->event_win == win)
- {
+ if( top_level->event_win == win ) {
// Keep value regardless of status if drag mode.
- if(select_drag)
- {
- if(value)
+ if( select_drag ) {
+ if( value )
status = BC_Toggle::TOGGLE_CHECKEDHI;
else
status = BC_Toggle::TOGGLE_UPHI;
}
else
// Change value only if button down for default mode.
- if(status == BC_Toggle::TOGGLE_DOWN)
- {
+ if( status == BC_Toggle::TOGGLE_DOWN ) {
// Radial always goes to 1.
- if(!value || is_radial)
- {
+ if( !value || is_radial ) {
status = BC_Toggle::TOGGLE_CHECKEDHI;
value = 1;
}
- else
- {
+ else {
status = BC_Toggle::TOGGLE_UPHI;
value = 0;
}
int BC_Toggle::cursor_motion_event()
{
- if(top_level->button_down &&
+ if( top_level->button_down &&
top_level->event_win == win &&
- !cursor_inside())
- {
- if(status == BC_Toggle::TOGGLE_DOWN)
- {
- if(value)
+ !cursor_inside() ) {
+ if( status == BC_Toggle::TOGGLE_DOWN ) {
+ if( value )
status = BC_Toggle::TOGGLE_CHECKED;
else
status = BC_Toggle::TOGGLE_UP;
draw_face(1, 1);
}
else
- if(status == BC_Toggle::TOGGLE_UPHI)
- {
+ if( status == BC_Toggle::TOGGLE_UPHI ) {
status = BC_Toggle::TOGGLE_CHECKEDHI;
draw_face(1, 1);
}
int BC_Toggle::set_value(int value, int draw)
{
- if(value != this->value)
- {
+ if( value != this->value ) {
this->value = value;
- if(value)
- {
- switch(status)
- {
- case BC_Toggle::TOGGLE_UP:
- status = BC_Toggle::TOGGLE_CHECKED;
- break;
- case BC_Toggle::TOGGLE_UPHI:
- status = BC_Toggle::TOGGLE_CHECKEDHI;
- break;
+ if( value ) {
+ switch( status ) {
+ case BC_Toggle::TOGGLE_UP:
+ status = BC_Toggle::TOGGLE_CHECKED;
+ break;
+ case BC_Toggle::TOGGLE_UPHI:
+ status = BC_Toggle::TOGGLE_CHECKEDHI;
+ break;
}
}
- else
- switch(status)
- {
+ else {
+ switch( status ) {
case BC_Toggle::TOGGLE_CHECKED:
status = BC_Toggle::TOGGLE_UP;
break;
case BC_Toggle::TOGGLE_CHECKEDHI:
status = BC_Toggle::TOGGLE_UPHI;
break;
+ }
}
- if(draw) draw_face(1, 1);
+ if( draw ) draw_face(1, 1);
}
return 0;
}
return (caption != 0 && caption[0] != 0);
}
-BC_Radial::BC_Radial(int x,
- int y,
- int value,
- const char *caption,
- int font,
- int color)
- : BC_Toggle(x,
- y,
+BC_Radial::BC_Radial(int x, int y, int value,
+ const char *caption, int font, int color)
+ : BC_Toggle(x, y,
BC_WindowBase::get_resources()->radial_images,
- value,
- caption,
- 0,
- font,
- color)
+ value, caption, 0, font, color)
{
is_radial = 1;
}
-BC_CheckBox::BC_CheckBox(int x,
- int y,
- int value,
- const char *caption,
- int font,
- int color)
- : BC_Toggle(x,
- y,
+BC_CheckBox::BC_CheckBox(int x, int y, int value,
+ const char *caption, int font, int color)
+ : BC_Toggle(x, y,
BC_WindowBase::get_resources()->checkbox_images,
- value,
- caption,
- 0,
- font,
- color)
+ value, caption, 0, font, color)
{
this->value = 0;
}
-BC_CheckBox::BC_CheckBox(int x,
- int y,
- int *value,
- const char *caption,
- int font,
- int color)
- : BC_Toggle(x,
- y,
+BC_CheckBox::BC_CheckBox(int x, int y, int *value,
+ const char *caption, int font, int color)
+ : BC_Toggle(x, y,
BC_WindowBase::get_resources()->checkbox_images,
- *value,
- caption,
- 1,
- font,
- color)
+ *value, caption, 1, font, color)
{
this->value = value;
}
return 1;
}
+int BC_CheckBox::calculate_h(BC_WindowBase *gui, int font)
+{
+ int w, h;
+ calculate_extents(gui, &w, &h, "X", font);
+ return h;
+}
-BC_Label::BC_Label(int x,
- int y,
- int value,
- int font,
- int color)
- : BC_Toggle(x,
- y,
- BC_WindowBase::get_resources()->label_images,
- value,
- "",
- 0,
- font,
- color)
+BC_Label::BC_Label(int x, int y, int value, int font, int color)
+ : BC_Toggle(x, y,
+ BC_WindowBase::get_resources()->label_images, value,
+ "", 0, font, color)
{
}
#include "bcbitmap.inc"
#include "bcsubwindow.h"
-#include "colors.h"
+#include "bccolors.h"
#include "fonts.h"
#include "vframe.inc"
int font = MEDIUMFONT,
int color = -1);
virtual int handle_event();
+ static int calculate_h(BC_WindowBase *gui, int font=MEDIUMFONT);
static void calculate_extents(BC_WindowBase *gui, int *w, int *h,
const char *caption="", int font=MEDIUMFONT);
#include "bcwindowbase.h"
#include "bcwindowevents.h"
#include "bccmodels.h"
-#include "colors.h"
+#include "bccolors.h"
#include "condition.h"
#include "cursors.h"
#include "bchash.h"
}
else
#endif
+ {
+// _XftDisplayInfo needs a lock.
+ get_resources()->create_window_lock->lock("BC_WindowBase::~BC_WindowBase");
XCloseDisplay(display);
+ get_resources()->create_window_lock->unlock();
+ }
// clipboard uses a different display connection
clipboard->stop_clipboard();
delete clipboard;
#ifdef HAVE_LIBXXF86VM
vm_switched = 0;
#endif
- smallfont_xft = 0;
- bold_largefont_xft = 0;
- bold_mediumfont_xft = 0;
- bold_smallfont_xft = 0;
input_method = 0;
input_context = 0;
+ smallfont = 0;
+ mediumfont = 0;
+ largefont = 0;
+ bigfont = 0;
+ clockfont = 0;
+
+ smallfont_xft = 0;
mediumfont_xft = 0;
largefont_xft = 0;
bigfont_xft = 0;
+ clockfont_xft = 0;
+
+ bold_smallfont_xft = 0;
+ bold_mediumfont_xft = 0;
+ bold_largefont_xft = 0;
#ifdef SINGLE_THREAD
completion_lock = new Condition(0, "BC_WindowBase::completion_lock");
#else
if( !(bigfont = XLoadQueryFont(display, _(resources.big_font2))) )
bigfont = XLoadQueryFont(display, "fixed");
+ if((clockfont = XLoadQueryFont(display, _(resources.clock_font))) == NULL)
+ if((clockfont = XLoadQueryFont(display, _(resources.clock_font2))) == NULL)
+ clockfont = XLoadQueryFont(display, "fixed");
+
init_xft();
if(get_resources()->use_fontset)
{
largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
bigfontset = XCreateFontSet(display, resources.big_fontset, &m, &n, &d);
if( !bigfontset )
- largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
- if(bigfontset && largefontset && mediumfontset && smallfontset) {
+ bigfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
+ clockfontset = XCreateFontSet(display, resources.clock_fontset, &m, &n, &d);
+ if( !clockfontset )
+ clockfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
+ if(clockfontset && bigfontset && largefontset && mediumfontset && smallfontset) {
curr_fontset = mediumfontset;
get_resources()->use_fontset = 1;
}
if(!(bigfont_xft =
XftFontOpenXlfd(display, screen, resources.big_font_xft2)))
bigfont_xft = XftFontOpenXlfd(display, screen, "fixed");
+ if(!(clockfont_xft =
+ (resources.clock_font_xft[0] == '-' ?
+ XftFontOpenXlfd(display, screen, resources.clock_font_xft) :
+ XftFontOpenName(display, screen, resources.clock_font_xft))) )
+ clockfont_xft = XftFontOpenXlfd(display, screen, "fixed");
+
if(!(bold_smallfont_xft =
(resources.small_b_font_xft[0] == '-' ?
XftFontOpenName(display, screen, resources.large_b_font_xft))) )
bold_largefont_xft = XftFontOpenXlfd(display, screen, "fixed");
-// Extension failed to locate fonts
if( !smallfont_xft || !mediumfont_xft || !largefont_xft || !bigfont_xft ||
- !bold_largefont_xft || !bold_mediumfont_xft || !bold_largefont_xft ) {
+ !bold_largefont_xft || !bold_mediumfont_xft || !bold_largefont_xft ||
+ !clockfont_xft ) {
printf("BC_WindowBase::init_fonts: no xft fonts found:"
- " %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n",
+ " %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n",
resources.small_font_xft, smallfont_xft,
resources.medium_font_xft, mediumfont_xft,
resources.large_font_xft, largefont_xft,
resources.big_font_xft, bigfont_xft,
+ resources.clock_font_xft, clockfont_xft,
resources.small_b_font_xft, bold_smallfont_xft,
resources.medium_b_font_xft, bold_mediumfont_xft,
resources.large_b_font_xft, bold_largefont_xft);
get_resources()->use_xft = 0;
exit(1);
}
+// _XftDisplayInfo needs a lock.
+ XftDefaultHasRender(display);
#endif // HAVE_XFT
}
case MEDIUMFONT: return top_level->mediumfont; break;
case LARGEFONT: return top_level->largefont; break;
case BIGFONT: return top_level->bigfont; break;
+ case CLOCKFONT: return top_level->clockfont; break;
}
return 0;
}
case MEDIUMFONT: fs = top_level->mediumfontset; break;
case LARGEFONT: fs = top_level->largefontset; break;
case BIGFONT: fs = top_level->bigfontset; break;
+ case CLOCKFONT: fs = top_level->clockfontset; break;
}
}
case MEDIUMFONT: return (XftFont*)top_level->mediumfont_xft;
case LARGEFONT: return (XftFont*)top_level->largefont_xft;
case BIGFONT: return (XftFont*)top_level->bigfont_xft;
+ case CLOCKFONT: return (XftFont*)top_level->clockfont_xft;
case MEDIUMFONT_3D: return (XftFont*)top_level->bold_mediumfont_xft;
case SMALLFONT_3D: return (XftFont*)top_level->bold_smallfont_xft;
case LARGEFONT_3D: return (XftFont*)top_level->bold_largefont_xft;
#endif
-
-
-
-
-
-
-
int BC_WindowBase::get_current_font()
{
return top_level->current_font;
case MEDIUMFONT: fs = top_level->mediumfontset; break;
case LARGEFONT: fs = top_level->largefontset; break;
case BIGFONT: fs = top_level->bigfontset; break;
+ case CLOCKFONT: fs = top_level->clockfontset; break;
}
}
// Font sets
- XFontSet smallfontset, mediumfontset, largefontset, bigfontset, curr_fontset;
-
+ XFontSet smallfontset, mediumfontset, largefontset, bigfontset, clockfontset;
+ XFontSet curr_fontset;
// Fonts
int current_font;
- XFontStruct *smallfont, *mediumfont, *largefont, *bigfont;
-
+ XFontStruct *smallfont, *mediumfont, *largefont, *bigfont, *clockfont;
// Must be void so users don't need to include the wrong libpng version.
- void *smallfont_xft, *mediumfont_xft, *largefont_xft, *bigfont_xft;
-
+ void *smallfont_xft, *mediumfont_xft, *largefont_xft, *bigfont_xft, *clockfont_xft;
+ void *bold_smallfont_xft, *bold_mediumfont_xft, *bold_largefont_xft;
int line_width;
int line_dashes;
- void *bold_largefont_xft, *bold_mediumfont_xft, *bold_smallfont_xft;
int64_t current_color;
// Coordinate of drag start
int drag_x, drag_y;
#include "bctimer.h"
#include "bcwindowbase.h"
#include "clip.h"
-#include "colors.h"
+#include "bccolors.h"
#include "cursors.h"
#include "fonts.h"
#include "vframe.h"
// Hide cursor if video enabled
update_video_cursor();
-//printf("BC_WindowBase::draw_bitmap 1\n");
+//printf("BC_WindowBase::draw_bitmap %d dest_y=%d\n", __LINE__, dest_y);
if(dest_w <= 0 || dest_h <= 0)
{
// Use hardware scaling to canvas dimensions if proper color model.
#define SMALLFONT 1
#define MEDIUMFONT 2
#define LARGEFONT 3
-#define MEDIUM_7SEGMENT 4
-#define BIGFONT 5
+#define BIGFONT 4
+#define CLOCKFONT 5
+#define MEDIUM_7SEGMENT 6 // no longer used
// Specialized fonts not available in every widget
#define BOLDFACE 0x8000
#include "bctoggle.h"
#include "bctumble.h"
#include "bcwindow.h"
-#include "colors.h"
+#include "bccolors.h"
#include "fonts.h"
#include "bctimer.h"
#include "errorbox.h"
#include "bcwindow.h"
#include "bcsignals.h"
-#include "colors.h"
+#include "bccolors.h"
#include "fonts.h"
#include "thread.h"
#include "vframe.h"
int VFrame::copy_from(VFrame *frame)
{
+ if(this->w != frame->get_w() ||
+ this->h != frame->get_h())
+ {
+ printf("VFrame::copy_from %d sizes differ src %dx%d != dst %dx%d\n",
+ __LINE__,
+ frame->get_w(),
+ frame->get_h(),
+ get_w(),
+ get_h());
+ return 1;
+ }
+
int w = MIN(this->w, frame->get_w());
int h = MIN(this->h, frame->get_h());
timestamp = frame->timestamp;
}
}
+
void VFrame::draw_rect(int x1, int y1, int x2, int y2)
{
draw_line(x1, y1, x2, y1);
draw_line(x1, y2 - 1, x1, y1 + 1);
}
+
+void VFrame::draw_oval(int x1, int y1, int x2, int y2)
+{
+ int w = x2 - x1;
+ int h = y2 - y1;
+ int center_x = (x2 + x1) / 2;
+ int center_y = (y2 + y1) / 2;
+ int x_table[h / 2];
+
+//printf("VFrame::draw_oval %d %d %d %d %d\n", __LINE__, x1, y1, x2, y2);
+
+ for(int i = 0; i < h / 2; i++) {
+// A^2 = -(B^2) + C^2
+ x_table[i] = (int)(sqrt(-SQR(h / 2 - i) + SQR(h / 2)) * w / h);
+//printf("VFrame::draw_oval %d i=%d x=%d\n", __LINE__, i, x_table[i]);
+ }
+
+ for(int i = 0; i < h / 2 - 1; i++) {
+ int x3 = x_table[i];
+ int x4 = x_table[i + 1];
+
+ if(x4 > x3 + 1) {
+ for(int j = x3; j < x4; j++) {
+ draw_pixel(center_x + j, y1 + i);
+ draw_pixel(center_x - j, y1 + i);
+ draw_pixel(center_x + j, y2 - i - 1);
+ draw_pixel(center_x - j, y2 - i - 1);
+ }
+ }
+ else {
+ draw_pixel(center_x + x3, y1 + i);
+ draw_pixel(center_x - x3, y1 + i);
+ draw_pixel(center_x + x3, y2 - i - 1);
+ draw_pixel(center_x - x3, y2 - i - 1);
+ }
+ }
+
+ draw_pixel(center_x, y1);
+ draw_pixel(center_x, y2 - 1);
+ draw_pixel(x1, center_y);
+ draw_pixel(x2 - 1, center_y);
+ draw_pixel(x1, center_y - 1);
+ draw_pixel(x2 - 1, center_y - 1);
+}
+
+
void VFrame::draw_arrow(int x1, int y1, int x2, int y2, int sz)
{
double angle = atan((float)(y2 - y1) / (float)(x2 - x1));
void draw_arrow(int x1, int y1, int x2, int y2, int sz=10);
void draw_x(int x1, int y1, int sz=2);
void draw_t(int x1, int y1, int sz=2);
+ void draw_oval(int x1, int y1, int x2, int y2);
// 3D scene graphs
// Not integrated with shmem because that only affects codecs
#include "bctimer.h"
#include "bcwindow.h"
-#include "colors.h"
+#include "bccolors.h"
#include "keys.h"
#include "mutex.h"
#include "condition.h"
gamma gradient histogram histogram_bezier threshold
plugin_dirs += exotic
-exotic := aging burn dot holo oil edge
+exotic := aging burn dot holo oil edge spherecam
plugin_dirs += audio_tools
audio_tools := audioscope cdripper compressor dcoffset delayaudio \
*
*/
#include "c41.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "clip.h"
#include "edlsession.h"
#include "filexml.h"
shiftinterlace \
slide \
spectrogram \
+ spherecam \
svg \
swapchannels \
swapframes \
#include "bchash.h"
#include "filexml.h"
#include "language.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "samples.h"
#include "theme.h"
#include "transportque.inc"
#include "bchash.inc"
#include "bctimer.inc"
-#include "colors.h"
+#include "bccolors.h"
#include "guicast.h"
#include "mutex.h"
#include "pluginaclient.h"
#include "language.h"
#include "loadbalance.h"
#include "playback3d.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "vframe.h"
#include "workarounds.h"
#include "bluebananaconfig.h"
#include "bluebananawindow.h"
#include "loadbalance.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#define SELECT_LOOKUP_SIZE 1024
#ifndef BLUEBANANASLIDER_H
#define BLUEBANANASLIDER_H
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "bluebanana.h"
#include "bluebananawindow.h"
#ifndef BLUEBANANAWINDOW_H
#define BLUEBANANAWINDOW_H
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "pluginserver.h"
#include "mwindow.h"
#include "brightnesswindow.h"
#include "loadbalance.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
class BrightnessConfig
#include "effecttv.h"
#include "filexml.h"
#include "language.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "burn.h"
#include "burnwindow.h"
#include "effecttv.inc"
#include "loadbalance.h"
#include "mutex.h"
-#include "cicolors.inc"
+#include "bccolors.inc"
#include "pluginvclient.h"
#include "burnwindow.h"
#include <sys/types.h>
#include "language.h"
#include "loadbalance.h"
#include "playback3d.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "vframe.h"
#include "language.h"
#include "loadbalance.h"
#include "playback3d.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "vframe.h"
#include "color3waywindow.h"
#include "condition.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "guicast.h"
#include "loadbalance.h"
#include "pluginvclient.h"
#include "colorbalancewindow.h"
#include "condition.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "guicast.h"
#include "pluginvclient.h"
#include "thread.h"
#include "arraylist.h"
#include "bccmodels.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "clip.h"
#include "edlsession.h"
#include "filexml.h"
#include "guicast.h"
#include "language.h"
#include "loadbalance.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "bchash.h"
#include "filexml.h"
#include "language.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "samples.h"
#include "echo.h"
#include "theme.h"
#include "bchash.h"
#include "filexml.h"
#include "language.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "samples.h"
#include "echocancel.h"
#include "theme.h"
*/
#include "affine.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "clip.h"
#include "filexml.h"
#include "language.h"
#include "gamma.h"
#include "bchash.h"
#include "language.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "../interpolate/aggregated.h"
#include "playback3d.h"
#include "workarounds.h"
#include "gammawindow.h"
#include "loadbalance.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "guicast.h"
#include "pluginvclient.h"
#include "thread.h"
#include "guicast.h"
#include "loadbalance.h"
#include "overlayframe.inc"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "thread.h"
#include "vframe.inc"
#include "language.h"
#include "loadbalance.h"
#include "playback3d.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "vframe.h"
#include "workarounds.h"
#include "histogramconfig.h"
#include "histogramwindow.inc"
#include "loadbalance.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "keyframe.h"
#include "language.h"
#include "loadbalance.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "vframe.h"
#include "bistogramconfig.h"
#include "bistogramwindow.inc"
#include "loadbalance.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "holo.h"
#include "holowindow.h"
#include "language.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include <stdint.h>
#include <stdio.h>
#include "holowindow.h"
#include "loadbalance.h"
#include "mutex.h"
-#include "cicolors.inc"
+#include "bccolors.inc"
#include "pluginvclient.h"
#include <stdint.h>
#include "guicast.h"
#include "language.h"
#include "loadbalance.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "playback3d.h"
#include "pluginvclient.h"
#include "vframe.h"
delete engine;
}
-const char* InterpolatePixelsMain::plugin_title() { return _("Interpolate Pixels"); }
+const char* InterpolatePixelsMain::plugin_title() { return _("Interpolate Bayer"); }
int InterpolatePixelsMain::is_realtime() { return 1; }
float color_matrix[9];
memcpy(color_matrix, server->color_matrix, sizeof(color_matrix));
+// printf("InterpolatePixelsUnit::process_package %d color_matrix=", __LINE__);
+// for(int i = 0; i < 9; i++)
+// {
+// printf("%f ", color_matrix[i]);
+// }
+// printf("\n");
+
y1 = MAX(y1, 1);
y2 = MIN(y2, h - 1);
b = current_row[BLUE];
}
- out_row[0] = r * color_matrix[0] + g * color_matrix[1] + b * color_matrix[2];
- out_row[1] = r * color_matrix[3] + g * color_matrix[4] + b * color_matrix[5];
- out_row[2] = r * color_matrix[6] + g * color_matrix[7] + b * color_matrix[8];
+// out_row[0] = r * color_matrix[0] + g * color_matrix[1] + b * color_matrix[2];
+// out_row[1] = r * color_matrix[3] + g * color_matrix[4] + b * color_matrix[5];
+// out_row[2] = r * color_matrix[6] + g * color_matrix[7] + b * color_matrix[8];
+
+ out_row[0] = r;
+ out_row[1] = g;
+ out_row[2] = b;
+
prev_row += components;
current_row += components;
next_row += components;
b = (prev_row[BLUE] + next_row[BLUE]) / 2;
}
- out_row[0] = r * color_matrix[0] + g * color_matrix[1] + b * color_matrix[2];
- out_row[1] = r * color_matrix[3] + g * color_matrix[4] + b * color_matrix[5];
- out_row[2] = r * color_matrix[6] + g * color_matrix[7] + b * color_matrix[8];
+// out_row[0] = r * color_matrix[0] + g * color_matrix[1] + b * color_matrix[2];
+// out_row[1] = r * color_matrix[3] + g * color_matrix[4] + b * color_matrix[5];
+// out_row[2] = r * color_matrix[6] + g * color_matrix[7] + b * color_matrix[8];
+
+ out_row[0] = r;
+ out_row[1] = g;
+ out_row[2] = b;
+
prev_row += components;
current_row += components;
next_row += components;
char string[BCTEXTLEN];
string[0] = 0;
plugin->get_output()->get_params()->get("DCRAW_MATRIX", string);
+
+// printf("InterpolatePixelsEngine::init_packages %d\n", __LINE__);
+// plugin->get_output()->dump_params();
+
sscanf(string,
"%f %f %f %f %f %f %f %f %f",
&color_matrix[0],
OBJS = $(OBJDIR)/interpolatevideo.o \
$(OBJDIR)/interpolatewindow.o \
$(OBJDIR)/opticflow.o \
+ $(OBJDIR)/motioncache-hv.o \
$(OBJDIR)/motionscan-hv.o
-CFLAGS += -DMotionScan=MotionHVScan
-
PLUGIN = interpolatevideo
include ../../plugin_config
$(OBJDIR)/interpolatevideo.o: interpolatevideo.C
$(OBJDIR)/interpolatewindow.o: interpolatewindow.C
$(OBJDIR)/opticflow.o: opticflow.C
+$(OBJDIR)/motionscan-hv.o: motioncache-hv.C motioncache-hv.h
$(OBJDIR)/motionscan-hv.o: motionscan-hv.C motionscan-hv.h
// Get macroblock size
x_macroblocks = frames[0]->get_w() / config.macroblock_size;
y_macroblocks = frames[0]->get_h() / config.macroblock_size;
+// printf("InterpolateVideo::create_macroblocks %d %d %d %d\n",
+// __LINE__,
+// config.macroblock_size,
+// x_macroblocks,
+// y_macroblocks);
if(config.macroblock_size * x_macroblocks < frames[0]->get_w())
{
--- /dev/null
+../motion-hv/motioncache-hv.C
\ No newline at end of file
--- /dev/null
+../motion-hv/motioncache-hv.h
\ No newline at end of file
--- /dev/null
+../motion-hv/motioncache-hv.inc
\ No newline at end of file
#include "clip.h"
#include "interpolatevideo.h"
+#include "motioncache-hv.h"
#include "motionscan-hv.h"
#include "opticflow.h"
struct timeval start_time;
gettimeofday(&start_time, 0);
- if(!motion) motion = new MotionScan(1, 1);
+ if(!motion) motion = new MotionHVScan(1, 1);
motion->set_test_match(0);
+ motion->set_cache(server->downsample_cache);
+
// printf("OpticFlowUnit::process_package %d %d %d\n",
// __LINE__,
// pkg->macroblock0,
for(int i = pkg->macroblock0; i < pkg->macroblock1; i++)
{
OpticFlowMacroblock *mb = plugin->macroblocks.get(i);
+//printf("OpticFlowUnit::process_package %d i=%d x=%d y=%d\n", __LINE__, i, mb->x, mb->y);
motion->scan_frame(plugin->frames[0],
// Frame after motion
plugin->frames[1],
plugin->config.macroblock_size,
mb->x,
mb->y,
- MotionScan::TRACK_PREVIOUS,
- MotionScan::CALCULATE,
+ MotionHVScan::TRACK_PREVIOUS,
+ MotionHVScan::CALCULATE,
// Get it to do the subpixel step
- MotionScan::STABILIZE,
+ MotionHVScan::STABILIZE,
0,
0,
0,
0,
0,
0);
+//printf("OpticFlowUnit::process_package 2\n", __LINE__);
mb->dx = motion->dx_result;
total_packages)
{
this->plugin = plugin;
+ downsample_cache = 0;
}
OpticFlow::~OpticFlow()
{
+ if(downsample_cache)
+ {
+//printf("OpticFlow::~OpticFlow %d %p\n", __LINE__, downsample_cache);
+ delete downsample_cache;
+ }
}
void OpticFlow::init_packages()
{
-//printf("OpticFlow::init_packages %d %d\n", __LINE__, get_total_packages());
+ if(!downsample_cache)
+ {
+ downsample_cache = new MotionHVCache();
+ }
+
+ downsample_cache->clear();
+
for(int i = 0; i < get_total_packages(); i++)
{
OpticFlowPackage *pkg = (OpticFlowPackage*)get_package(i);
pkg->macroblock0 = plugin->total_macroblocks * i / get_total_packages();
pkg->macroblock1 = plugin->total_macroblocks * (i + 1) / get_total_packages();
+// printf("OpticFlow::init_packages %d %d %d %d %d\n",
+// __LINE__,
+// plugin->total_macroblocks,
+// get_total_packages(),
+// pkg->macroblock0,
+// pkg->macroblock1);
}
}
#include "interpolatevideo.inc"
#include "loadbalance.h"
+#include "motioncache-hv.inc"
#include "motionscan-hv.inc"
#include "opticflow.inc"
OpticFlowUnit(OpticFlow *server);
~OpticFlowUnit();
void process_package(LoadPackage *package);
- MotionScan *motion;
+ MotionHVScan *motion;
OpticFlow *server;
};
LoadClient* new_client();
LoadPackage* new_package();
InterpolateVideo *plugin;
+ MotionHVCache *downsample_cache;
};
#include "filexml.h"
#include "guicast.h"
#include "language.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "vframe.h"
#include "bccmodels.h"
#include "effecttv.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "vframe.h"
#include <stdint.h>
#ifndef EFFECTTV_H
#define EFFECTTV_H
-#include "cicolors.h"
+#include "bccolors.h"
#include "vframe.inc"
#include <stdint.h>
OBJS := \
$(OBJDIR)/motion-hv.o \
+ $(OBJDIR)/motioncache-hv.o \
$(OBJDIR)/motionscan-hv.o \
$(OBJDIR)/motionwindow-hv.o
include ../../plugin_config
$(OBJDIR)/motion-hv.o: motion-hv.C
+$(OBJDIR)/motioncache-hv.o: motioncache-hv.C
$(OBJDIR)/motionscan-hv.o: motionscan-hv.C
$(OBJDIR)/motionwindow-hv.o: motionwindow-hv.C
track_frame == that.track_frame &&
bottom_is_master == that.bottom_is_master &&
horizontal_only == that.horizontal_only &&
- vertical_only == that.vertical_only;
+ vertical_only == that.vertical_only &&
+ tracking_type == that.tracking_type;
}
void MotionHVConfig::copy_from(MotionHVConfig &that)
--- /dev/null
+/*
+ * CINELERRA
+ * Copyright (C) 2016 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+
+
+// store previously scaled images here for operations
+// with multiple motion scans on the same frame.
+
+
+#include "bcsignals.h"
+#include "clip.h"
+#include "motioncache-hv.h"
+#include "mutex.h"
+#include <stdint.h>
+#include "vframe.h"
+
+
+MotionHVCacheItem::MotionHVCacheItem()
+{
+}
+
+MotionHVCacheItem::~MotionHVCacheItem()
+{
+//printf("MotionHVCacheItem::~MotionHVCacheItem %d image=%p\n", __LINE__, image);
+ if(image)
+ {
+ delete image;
+ }
+}
+
+
+
+MotionHVCache::MotionHVCache()
+{
+ lock = new Mutex("MotionHVCache::lock");
+}
+
+MotionHVCache::~MotionHVCache()
+{
+//printf("MotionHVCache::~MotionHVCache %d this=%p\n", __LINE__, this);
+
+ delete lock;
+ clear();
+}
+
+void MotionHVCache::clear()
+{
+ images.remove_all_objects();
+}
+
+
+
+#define DOWNSAMPLE(type, temp_type, components, max) \
+{ \
+ temp_type r; \
+ temp_type g; \
+ temp_type b; \
+ temp_type a; \
+ type **in_rows = (type**)src->get_rows(); \
+ type **out_rows = (type**)dst->get_rows(); \
+ \
+ for(int i = 0; i < h; i += downsample) \
+ { \
+ int y1 = MAX(i, 0); \
+ int y2 = MIN(i + downsample, h); \
+ \
+ \
+ for(int j = 0; \
+ j < w; \
+ j += downsample) \
+ { \
+ int x1 = MAX(j, 0); \
+ int x2 = MIN(j + downsample, w); \
+ \
+ temp_type scale = (x2 - x1) * (y2 - y1); \
+ if(x2 > x1 && y2 > y1) \
+ { \
+ \
+/* Read in values */ \
+ r = 0; \
+ g = 0; \
+ b = 0; \
+ if(components == 4) a = 0; \
+ \
+ for(int k = y1; k < y2; k++) \
+ { \
+ type *row = in_rows[k] + x1 * components; \
+ for(int l = x1; l < x2; l++) \
+ { \
+ r += *row++; \
+ g += *row++; \
+ b += *row++; \
+ if(components == 4) a += *row++; \
+ } \
+ } \
+ \
+/* Write average */ \
+ r /= scale; \
+ g /= scale; \
+ b /= scale; \
+ if(components == 4) a /= scale; \
+ \
+ type *row = out_rows[y1 / downsample] + \
+ x1 / downsample * components; \
+ *row++ = r; \
+ *row++ = g; \
+ *row++ = b; \
+ if(components == 4) *row++ = a; \
+ } \
+ } \
+/*printf("DOWNSAMPLE 3 %d\n", i);*/ \
+ } \
+}
+
+
+
+
+void MotionHVCache::downsample_frame(VFrame *dst,
+ VFrame *src,
+ int downsample)
+{
+ int h = src->get_h();
+ int w = src->get_w();
+
+//PRINT_TRACE
+//printf("downsample=%d w=%d h=%d dst=%d %d\n", downsample, w, h, dst->get_w(), dst->get_h());
+ switch(src->get_color_model())
+ {
+ case BC_RGB888:
+ DOWNSAMPLE(uint8_t, int64_t, 3, 0xff)
+ break;
+ case BC_RGB_FLOAT:
+ DOWNSAMPLE(float, float, 3, 1.0)
+ break;
+ case BC_RGBA8888:
+ DOWNSAMPLE(uint8_t, int64_t, 4, 0xff)
+ break;
+ case BC_RGBA_FLOAT:
+ DOWNSAMPLE(float, float, 4, 1.0)
+ break;
+ case BC_YUV888:
+ DOWNSAMPLE(uint8_t, int64_t, 3, 0xff)
+ break;
+ case BC_YUVA8888:
+ DOWNSAMPLE(uint8_t, int64_t, 4, 0xff)
+ break;
+ }
+//PRINT_TRACE
+}
+
+VFrame* MotionHVCache::get_image(int ratio,
+ int is_previous,
+ int downsampled_w,
+ int downsampled_h,
+ VFrame *src)
+{
+ lock->lock("MotionHVCache::get_image 1");
+
+ for(int i = 0; i < images.size(); i++)
+ {
+ if(images.get(i)->ratio == ratio &&
+ images.get(i)->is_previous == is_previous)
+ {
+ VFrame *result = images.get(i)->image;
+ lock->unlock();
+ return result;
+ }
+ }
+
+
+//PRINT_TRACE
+ VFrame *result = new VFrame();
+ result->set_use_shm(0);
+ result->reallocate(0,
+ -1,
+ 0,
+ 0,
+ 0,
+ downsampled_w + 1,
+ downsampled_h + 1,
+ src->get_color_model(),
+ -1);
+ downsample_frame(result,
+ src,
+ ratio);
+
+
+ MotionHVCacheItem *item = new MotionHVCacheItem();
+ item->image = result;
+ item->is_previous = is_previous;
+ item->ratio = ratio;
+ images.append(item);
+
+ lock->unlock();
+
+ return result;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ * CINELERRA
+ * Copyright (C) 2016 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+
+#ifndef MOTIONCACHE_HV_H
+#define MOTIONCACHE_HV_H
+
+// store previously scaled intermediates here for operations
+// with multiple motion scans on the same frame.
+
+#include "arraylist.h"
+#include "mutex.inc"
+#include "vframe.inc"
+
+class MotionHVCacheItem
+{
+public:
+ MotionHVCacheItem();
+ ~MotionHVCacheItem();
+
+ VFrame *image;
+ int ratio;
+ int is_previous;
+};
+
+
+class MotionHVCache
+{
+public:
+ MotionHVCache();
+ ~MotionHVCache();
+
+ VFrame *get_image(int ratio,
+ int is_previous,
+ int downsampled_w,
+ int downsampled_h,
+ VFrame *src);
+
+ void clear();
+
+ void downsample_frame(VFrame *dst,
+ VFrame *src,
+ int downsample);
+
+ ArrayList<MotionHVCacheItem*> images;
+ Mutex *lock;
+};
+
+
+
+
+
+#endif
+
+
--- /dev/null
+#ifndef MOTIONCACHE_HV_INC
+#define MOTIONCACHE_HV_INC
+
+class MotionHVCache;
+
+#endif
+
+
#include "affine.h"
#include "bcsignals.h"
#include "clip.h"
+#include "motioncache-hv.h"
#include "motionscan-hv.h"
#include "mutex.h"
#include "vframe.h"
)
{
test_match = 1;
- downsampled_previous = 0;
- downsampled_current = 0;
rotated_current = 0;
rotater = 0;
+ downsample_cache = 0;
+ shared_downsample = 0;
}
MotionHVScan::~MotionHVScan()
{
- delete downsampled_previous;
- delete downsampled_current;
- if(rotated_current)
- {
- for(int i = 0; i < total_rotated; i++)
- {
+ if(downsample_cache && !shared_downsample) {
+ delete downsample_cache;
+ downsample_cache = 0;
+ shared_downsample = 0;
+ }
+
+ if(rotated_current) {
+ for(int i = 0; i < total_rotated; i++) {
delete rotated_current[i];
}
-
delete [] rotated_current;
}
delete rotater;
this->test_match = value;
}
-
-
-
-#define DOWNSAMPLE(type, temp_type, components, max) \
-{ \
- temp_type r; \
- temp_type g; \
- temp_type b; \
- temp_type a; \
- type **in_rows = (type**)src->get_rows(); \
- type **out_rows = (type**)dst->get_rows(); \
- \
- for(int i = 0; i < h; i += downsample) \
- { \
- int y1 = MAX(i, 0); \
- int y2 = MIN(i + downsample, h); \
- \
- \
- for(int j = 0; \
- j < w; \
- j += downsample) \
- { \
- int x1 = MAX(j, 0); \
- int x2 = MIN(j + downsample, w); \
- \
- temp_type scale = (x2 - x1) * (y2 - y1); \
- if(x2 > x1 && y2 > y1) \
- { \
- \
-/* Read in values */ \
- r = 0; \
- g = 0; \
- b = 0; \
- if(components == 4) a = 0; \
- \
- for(int k = y1; k < y2; k++) \
- { \
- type *row = in_rows[k] + x1 * components; \
- for(int l = x1; l < x2; l++) \
- { \
- r += *row++; \
- g += *row++; \
- b += *row++; \
- if(components == 4) a += *row++; \
- } \
- } \
- \
-/* Write average */ \
- r /= scale; \
- g /= scale; \
- b /= scale; \
- if(components == 4) a /= scale; \
- \
- type *row = out_rows[y1 / downsample] + \
- x1 / downsample * components; \
- *row++ = r; \
- *row++ = g; \
- *row++ = b; \
- if(components == 4) *row++ = a; \
- } \
- } \
-/*printf("DOWNSAMPLE 3 %d\n", i);*/ \
- } \
-}
-
-
-
-
-void MotionHVScan::downsample_frame(VFrame *dst,
- VFrame *src,
- int downsample)
+void MotionHVScan::set_cache(MotionHVCache *cache)
{
- int h = src->get_h();
- int w = src->get_w();
-
-//PRINT_TRACE
-//printf("downsample=%d w=%d h=%d dst=%d %d\n", downsample, w, h, dst->get_w(), dst->get_h());
- switch(src->get_color_model())
- {
- case BC_RGB888:
- DOWNSAMPLE(uint8_t, int64_t, 3, 0xff)
- break;
- case BC_RGB_FLOAT:
- DOWNSAMPLE(float, float, 3, 1.0)
- break;
- case BC_RGBA8888:
- DOWNSAMPLE(uint8_t, int64_t, 4, 0xff)
- break;
- case BC_RGBA_FLOAT:
- DOWNSAMPLE(float, float, 4, 1.0)
- break;
- case BC_YUV888:
- DOWNSAMPLE(uint8_t, int64_t, 3, 0xff)
- break;
- case BC_YUVA8888:
- DOWNSAMPLE(uint8_t, int64_t, 4, 0xff)
- break;
- }
-//PRINT_TRACE
+ this->downsample_cache = cache;
+ shared_downsample = 1;
}
+
double MotionHVScan::step_to_angle(int step, double center)
{
if(step < angle_steps / 2)
if(current_downsample > 1)
{
- if(!downsampled_previous ||
- downsampled_previous->get_w() != downsampled_prev_w ||
- downsampled_previous->get_h() != downsampled_prev_h)
+ if(!downsample_cache)
{
- delete downsampled_previous;
- downsampled_previous = new VFrame();
- downsampled_previous->set_use_shm(0);
- downsampled_previous->reallocate(0,
- -1,
- 0,
- 0,
- 0,
- downsampled_prev_w + 1,
- downsampled_prev_h + 1,
- previous_frame_arg->get_color_model(),
- -1);
+ downsample_cache = new MotionHVCache();
+ shared_downsample = 0;
}
- if(!downsampled_current ||
- downsampled_current->get_w() != downsampled_current_w ||
- downsampled_current->get_h() != downsampled_current_h)
+
+ if(!shared_downsample)
{
- delete downsampled_current;
- downsampled_current = new VFrame();
- downsampled_current->set_use_shm(0);
- downsampled_current->reallocate(0,
- -1,
- 0,
- 0,
- 0,
- downsampled_current_w + 1,
- downsampled_current_h + 1,
- current_frame_arg->get_color_model(),
- -1);
+ downsample_cache->clear();
}
+ previous_frame = downsample_cache->get_image(current_downsample,
+ 1,
+ downsampled_prev_w,
+ downsampled_prev_h,
+ previous_frame_arg);
+ current_frame = downsample_cache->get_image(current_downsample,
+ 0,
+ downsampled_current_w,
+ downsampled_current_h,
+ current_frame_arg);
- downsample_frame(downsampled_previous,
- previous_frame_arg,
- current_downsample);
- downsample_frame(downsampled_current,
- current_frame_arg,
- current_downsample);
- previous_frame = downsampled_previous;
- current_frame = downsampled_current;
}
else
#include "affine.inc"
#include "loadbalance.h"
+#include "motioncache-hv.inc"
#include "vframe.inc"
#include <stdint.h>
LoadPackage* new_package();
// Test for identical frames before scanning
void set_test_match(int value);
+ void set_cache(MotionHVCache *cache);
// Invoke the motion engine for a search
// Frame before motion
int color_model);
-
+ MotionHVCache *downsample_cache;
+ int shared_downsample;
AffineEngine *rotater;
// Pointer to downsampled frame before motion
VFrame *previous_frame;
// Frames passed from user
VFrame *previous_frame_arg;
VFrame *current_frame_arg;
-// Downsampled frames
- VFrame *downsampled_previous;
- VFrame *downsampled_current;
// rotated versions of current_frame
VFrame **rotated_current;
// allocation of rotated_current array, a copy of angle_steps
OBJS := \
$(OBJDIR)/downsampleengine.o \
+ $(OBJDIR)/motioncache-hv.o \
$(OBJDIR)/motionscan-hv.o \
$(OBJDIR)/motion.o \
$(OBJDIR)/motionwindow.o
$(OBJDIR)/downsampleengine.o: downsampleengine.C
$(OBJDIR)/motion.o: motion.C
+$(OBJDIR)/motionscan-hv.o: motioncache-hv.C
$(OBJDIR)/motionscan-hv.o: motionscan-hv.C
$(OBJDIR)/motionwindow.o: motionwindow.C
--- /dev/null
+../motion-hv/motioncache-hv.C
\ No newline at end of file
--- /dev/null
+../motion-hv/motioncache-hv.h
\ No newline at end of file
--- /dev/null
+../motion-hv/motioncache-hv.inc
\ No newline at end of file
/*
* CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ * Copyright (C) 2017 Adam Williams <broadcast at earthling dot net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
{
if(thread)
{
- thread->window->lock_window();
- ((ReverbWindow*)thread->window)->level_init->update(config.level_init);
- ((ReverbWindow*)thread->window)->delay_init->update(config.delay_init);
- ((ReverbWindow*)thread->window)->ref_level1->update(config.ref_level1);
- ((ReverbWindow*)thread->window)->ref_level2->update(config.ref_level2);
- ((ReverbWindow*)thread->window)->ref_total->update(config.ref_total);
- ((ReverbWindow*)thread->window)->ref_length->update(config.ref_length);
- ((ReverbWindow*)thread->window)->lowpass1->update(config.lowpass1);
- ((ReverbWindow*)thread->window)->lowpass2->update(config.lowpass2);
- thread->window->unlock_window();
- }
-}
-
-
-
-
-int Reverb::load_from_file(char *path)
-{
- int result = 0;
- int length;
- char string[1024];
-
- FILE *in = fopen(path, "rb");
- if( in )
- {
- fseek(in, 0, SEEK_END);
- length = ftell(in);
- fseek(in, 0, SEEK_SET);
- (void)fread(string, length, 1, in);
- fclose(in);
-// read_data(string);
- }
- else
- {
- perror("fopen:");
-// failed
- ErrorBox errorbox("");
- char string[1024];
- sprintf(string, _("Couldn't open %s."), path);
- errorbox.create_objects(string);
- errorbox.run_window();
- result = 1;
+ if(load_configuration())
+ {
+//printf("Reverb::update_gui %d %d\n", __LINE__, config.ref_length);
+ thread->window->lock_window("Reverb::update_gui");
+ ((ReverbWindow*)thread->window)->level_init->update(config.level_init);
+ ((ReverbWindow*)thread->window)->delay_init->update(config.delay_init);
+ ((ReverbWindow*)thread->window)->ref_level1->update(config.ref_level1);
+ ((ReverbWindow*)thread->window)->ref_level2->update(config.ref_level2);
+ ((ReverbWindow*)thread->window)->ref_total->update(config.ref_total);
+ ((ReverbWindow*)thread->window)->ref_length->update(config.ref_length);
+ ((ReverbWindow*)thread->window)->lowpass1->update(config.lowpass1);
+ ((ReverbWindow*)thread->window)->lowpass2->update(config.lowpass2);
+ thread->window->unlock_window();
+ }
}
-
- return result;
}
-int Reverb::save_to_file(char *path)
-{
- int result = 0;
- char string[1024];
- {
-// ConfirmSave confirm;
-// result = confirm.test_file("", path);
- }
- if(!result)
- {
- FILE *out = fopen(path, "wb");
- if( out )
- {
-// save_data(string);
- fwrite(string, strlen(string), 1, out);
- fclose(out);
- }
- else
- {
- result = 1;
-// failed
- ErrorBox errorbox("");
- char string[1024];
- sprintf(string, _("Couldn't save %s."), path);
- errorbox.create_objects(string);
- errorbox.run_window();
- result = 1;
- }
- }
- return result;
-}
+// int Reverb::load_from_file(char *path)
+// {
+// FILE *in;
+// int result = 0;
+// int length;
+// char string[1024];
+//
+// if(in = fopen(path, "rb"))
+// {
+// fseek(in, 0, SEEK_END);
+// length = ftell(in);
+// fseek(in, 0, SEEK_SET);
+// int temp = fread(string, length, 1, in);
+// fclose(in);
+// // read_data(string);
+// }
+// else
+// {
+// perror("fopen:");
+// // failed
+// ErrorBox errorbox("");
+// char string[1024];
+// sprintf(string, _("Couldn't open %s."), path);
+// errorbox.create_objects(string);
+// errorbox.run_window();
+// result = 1;
+// }
+//
+// return result;
+// }
+//
+// int Reverb::save_to_file(char *path)
+// {
+// FILE *out;
+// int result = 0;
+// char string[1024];
+//
+// {
+// // ConfirmSave confirm;
+// // result = confirm.test_file("", path);
+// }
+//
+// if(!result)
+// {
+// if(out = fopen(path, "wb"))
+// {
+// // save_data(string);
+// fwrite(string, strlen(string), 1, out);
+// fclose(out);
+// }
+// else
+// {
+// result = 1;
+// // failed
+// ErrorBox errorbox("");
+// char string[1024];
+// sprintf(string, _("Couldn't save %s."), path);
+// errorbox.create_objects(string);
+// errorbox.run_window();
+// result = 1;
+// }
+// }
+//
+// return result;
+// }
ReverbEngine::ReverbEngine(Reverb *plugin)
: Thread(1, 0, 0)
~Reverb();
void update_gui();
- int load_from_file(char *data);
- int save_to_file(char *data);
+// int load_from_file(char *data);
+// int save_to_file(char *data);
// data for reverb
char config_directory[1024];
ReverbWindow::ReverbWindow(Reverb *reverb)
: PluginClientWindow(reverb,
- 250,
- 230,
- 250,
+ 300,
+ 230,
+ 300,
230,
0)
{
void ReverbWindow::create_objects()
{
- int x = 170, y = 10;
+ int x = 200, y = 10;
add_tool(new BC_Title(5, y + 10, _("Initial signal level:")));
add_tool(level_init = new ReverbLevelInit(reverb, x, y)); y += 25;
add_tool(new BC_Title(5, y + 10, _("ms before reflections:")));
return 1;
}
-ReverbMenu::ReverbMenu(Reverb *reverb, ReverbWindow *window)
- : BC_MenuBar(0, 0, window->get_w())
-{
- this->window = window;
- this->reverb = reverb;
-}
-
-ReverbMenu::~ReverbMenu()
-{
- delete load;
- delete save;
- //delete set_default;
- for(int i = 0; i < total_loads; i++)
- {
- delete prev_load[i];
- }
- delete prev_load_thread;
-}
-
-void ReverbMenu::create_objects(BC_Hash *defaults)
-{
- add_menu(filemenu = new BC_Menu(_("File")));
- filemenu->add_item(load = new ReverbLoad(reverb, this));
- filemenu->add_item(save = new ReverbSave(reverb, this));
- //filemenu->add_item(set_default = new ReverbSetDefault);
- load_defaults(defaults);
- prev_load_thread = new ReverbLoadPrevThread(reverb, this);
-}
-
-int ReverbMenu::load_defaults(BC_Hash *defaults)
-{
- FileSystem fs;
- total_loads = defaults->get("TOTAL_LOADS", 0);
- if(total_loads > 0)
- {
- filemenu->add_item(new BC_MenuItem("-"));
- char string[1024], path[1024], filename[1024];
-
- for(int i = 0; i < total_loads; i++)
- {
- sprintf(string, "LOADPREVIOUS%d", i);
- defaults->get(string, path);
- fs.extract_name(filename, path);
-//printf("ReverbMenu::load_defaults %s\n", path);
- filemenu->add_item(prev_load[i] = new ReverbLoadPrev(reverb, this, filename, path));
- }
- }
- return 0;
-}
-
-int ReverbMenu::save_defaults(BC_Hash *defaults)
-{
- if(total_loads > 0)
- {
- defaults->update("TOTAL_LOADS", total_loads);
- char string[1024];
-
- for(int i = 0; i < total_loads; i++)
- {
- sprintf(string, "LOADPREVIOUS%d", i);
- defaults->update(string, prev_load[i]->path);
- }
- }
- return 0;
-}
-
-int ReverbMenu::add_load(char *path)
-{
- if(total_loads == 0)
- {
- filemenu->add_item(new BC_MenuItem("-"));
- }
-
-// test for existing copy
- FileSystem fs;
- char text[1024], new_path[1024]; // get text and path
- fs.extract_name(text, path);
- strcpy(new_path, path);
-
- for(int i = 0; i < total_loads; i++)
- {
- if(!strcmp(prev_load[i]->get_text(), text)) // already exists
- { // swap for top load
- for(int j = i; j > 0; j--) // move preceeding loads down
- {
- prev_load[j]->set_text(prev_load[j - 1]->get_text());
- prev_load[j]->set_path(prev_load[j - 1]->path);
- }
- prev_load[0]->set_text(text);
- prev_load[0]->set_path(new_path);
- return 1;
- }
- }
-
-// add another load
- if(total_loads < TOTAL_LOADS)
- {
- filemenu->add_item(prev_load[total_loads] = new ReverbLoadPrev(reverb, this));
- total_loads++;
- }
-
-// cycle loads down
- for(int i = total_loads - 1; i > 0; i--)
- {
- // set menu item text
- prev_load[i]->set_text(prev_load[i - 1]->get_text());
- // set filename
- prev_load[i]->set_path(prev_load[i - 1]->path);
- }
-
-// set up the new load
- prev_load[0]->set_text(text);
- prev_load[0]->set_path(new_path);
- return 0;
-}
-
-ReverbLoad::ReverbLoad(Reverb *reverb, ReverbMenu *menu)
- : BC_MenuItem(_("Load..."))
-{
- this->reverb = reverb;
- this->menu = menu;
- thread = new ReverbLoadThread(reverb, menu);
-}
-ReverbLoad::~ReverbLoad()
-{
- delete thread;
-}
-int ReverbLoad::handle_event()
-{
- thread->start();
- return 0;
-}
-
-ReverbSave::ReverbSave(Reverb *reverb, ReverbMenu *menu)
- : BC_MenuItem(_("Save..."))
-{
- this->reverb = reverb;
- this->menu = menu;
- thread = new ReverbSaveThread(reverb, menu);
-}
-ReverbSave::~ReverbSave()
-{
- delete thread;
-}
-int ReverbSave::handle_event()
-{
- thread->start();
- return 0;
-}
-
-ReverbSetDefault::ReverbSetDefault()
- : BC_MenuItem(_("Set default"))
-{
-}
-int ReverbSetDefault::handle_event()
-{
- return 0;
-}
-
-ReverbLoadPrev::ReverbLoadPrev(Reverb *reverb, ReverbMenu *menu, char *filename, char *path)
- : BC_MenuItem(filename)
-{
- this->reverb = reverb;
- this->menu = menu;
- strcpy(this->path, path);
-}
-ReverbLoadPrev::ReverbLoadPrev(Reverb *reverb, ReverbMenu *menu)
- : BC_MenuItem("")
-{
- this->reverb = reverb;
- this->menu = menu;
-}
-int ReverbLoadPrev::handle_event()
-{
- menu->prev_load_thread->set_path(path);
- menu->prev_load_thread->start();
- return 0;
-}
-int ReverbLoadPrev::set_path(char *path)
-{
- strcpy(this->path, path);
- return 0;
-}
-
-
-ReverbSaveThread::ReverbSaveThread(Reverb *reverb, ReverbMenu *menu)
- : Thread()
-{
- this->reverb = reverb;
- this->menu = menu;
-}
-ReverbSaveThread::~ReverbSaveThread()
-{
-}
-void ReverbSaveThread::run()
-{
- int result = 0;
- {
- ReverbSaveDialog dialog(reverb);
- dialog.create_objects();
- result = dialog.run_window();
-// if(!result) strcpy(reverb->config_directory, dialog.get_path());
- }
- if(!result)
- {
- result = reverb->save_to_file(reverb->config_directory);
- menu->add_load(reverb->config_directory);
- }
-}
-
-ReverbSaveDialog::ReverbSaveDialog(Reverb *reverb)
- : BC_FileBox(0,
- 0,
- reverb->config_directory,
- _("Save reverb"),
- _("Select the reverb file to save as"), 0, 0)
-{
- this->reverb = reverb;
-}
-ReverbSaveDialog::~ReverbSaveDialog()
-{
-}
-int ReverbSaveDialog::ok_event()
-{
- set_done(0);
- return 0;
-}
-int ReverbSaveDialog::cancel_event()
-{
- set_done(1);
- return 0;
-}
-
-
-
-ReverbLoadThread::ReverbLoadThread(Reverb *reverb, ReverbMenu *menu)
- : Thread()
-{
- this->reverb = reverb;
- this->menu = menu;
-}
-ReverbLoadThread::~ReverbLoadThread()
-{
-}
-void ReverbLoadThread::run()
-{
- int result = 0;
- {
- ReverbLoadDialog dialog(reverb);
- dialog.create_objects();
- result = dialog.run_window();
-// if(!result) strcpy(reverb->config_directory, dialog.get_path());
- }
- if(!result)
- {
- result = reverb->load_from_file(reverb->config_directory);
- if(!result)
- {
- menu->add_load(reverb->config_directory);
- reverb->send_configure_change();
- }
- }
-}
-
-ReverbLoadPrevThread::ReverbLoadPrevThread(Reverb *reverb, ReverbMenu *menu) : Thread()
-{
- this->reverb = reverb;
- this->menu = menu;
-}
-ReverbLoadPrevThread::~ReverbLoadPrevThread()
-{
-}
-void ReverbLoadPrevThread::run()
-{
- int result = 0;
- strcpy(reverb->config_directory, path);
- result = reverb->load_from_file(path);
- if(!result)
- {
- menu->add_load(path);
- reverb->send_configure_change();
- }
-}
-int ReverbLoadPrevThread::set_path(char *path)
-{
- strcpy(this->path, path);
- return 0;
-}
-
-
-
-
-
-ReverbLoadDialog::ReverbLoadDialog(Reverb *reverb)
- : BC_FileBox(0,
- 0,
- reverb->config_directory,
- _("Load reverb"),
- _("Select the reverb file to load from"), 0, 0)
-{
- this->reverb = reverb;
-}
-ReverbLoadDialog::~ReverbLoadDialog()
-{
-}
-int ReverbLoadDialog::ok_event()
-{
- set_done(0);
- return 0;
-}
-int ReverbLoadDialog::cancel_event()
-{
- set_done(1);
- return 0;
-}
+// ReverbMenu::ReverbMenu(Reverb *reverb, ReverbWindow *window)
+// : BC_MenuBar(0, 0, window->get_w())
+// {
+// this->window = window;
+// this->reverb = reverb;
+// }
+//
+// ReverbMenu::~ReverbMenu()
+// {
+// delete load;
+// delete save;
+// //delete set_default;
+// for(int i = 0; i < total_loads; i++)
+// {
+// delete prev_load[i];
+// }
+// delete prev_load_thread;
+// }
+//
+// void ReverbMenu::create_objects(BC_Hash *defaults)
+// {
+// add_menu(filemenu = new BC_Menu(_("File")));
+// filemenu->add_item(load = new ReverbLoad(reverb, this));
+// filemenu->add_item(save = new ReverbSave(reverb, this));
+// //filemenu->add_item(set_default = new ReverbSetDefault);
+// load_defaults(defaults);
+// prev_load_thread = new ReverbLoadPrevThread(reverb, this);
+// }
+//
+// int ReverbMenu::load_defaults(BC_Hash *defaults)
+// {
+// FileSystem fs;
+// total_loads = defaults->get("TOTAL_LOADS", 0);
+// if(total_loads > 0)
+// {
+// filemenu->add_item(new BC_MenuItem("-"));
+// char string[1024], path[1024], filename[1024];
+//
+// for(int i = 0; i < total_loads; i++)
+// {
+// sprintf(string, "LOADPREVIOUS%d", i);
+// defaults->get(string, path);
+// fs.extract_name(filename, path);
+// //printf("ReverbMenu::load_defaults %s\n", path);
+// filemenu->add_item(prev_load[i] = new ReverbLoadPrev(reverb, this, filename, path));
+// }
+// }
+// return 0;
+// }
+//
+// int ReverbMenu::save_defaults(BC_Hash *defaults)
+// {
+// if(total_loads > 0)
+// {
+// defaults->update("TOTAL_LOADS", total_loads);
+// char string[1024];
+//
+// for(int i = 0; i < total_loads; i++)
+// {
+// sprintf(string, "LOADPREVIOUS%d", i);
+// defaults->update(string, prev_load[i]->path);
+// }
+// }
+// return 0;
+// }
+//
+// int ReverbMenu::add_load(char *path)
+// {
+// if(total_loads == 0)
+// {
+// filemenu->add_item(new BC_MenuItem("-"));
+// }
+//
+// // test for existing copy
+// FileSystem fs;
+// char text[1024], new_path[1024]; // get text and path
+// fs.extract_name(text, path);
+// strcpy(new_path, path);
+//
+// for(int i = 0; i < total_loads; i++)
+// {
+// if(!strcmp(prev_load[i]->get_text(), text)) // already exists
+// { // swap for top load
+// for(int j = i; j > 0; j--) // move preceeding loads down
+// {
+// prev_load[j]->set_text(prev_load[j - 1]->get_text());
+// prev_load[j]->set_path(prev_load[j - 1]->path);
+// }
+// prev_load[0]->set_text(text);
+// prev_load[0]->set_path(new_path);
+// return 1;
+// }
+// }
+//
+// // add another load
+// if(total_loads < TOTAL_LOADS)
+// {
+// filemenu->add_item(prev_load[total_loads] = new ReverbLoadPrev(reverb, this));
+// total_loads++;
+// }
+//
+// // cycle loads down
+// for(int i = total_loads - 1; i > 0; i--)
+// {
+// // set menu item text
+// prev_load[i]->set_text(prev_load[i - 1]->get_text());
+// // set filename
+// prev_load[i]->set_path(prev_load[i - 1]->path);
+// }
+//
+// // set up the new load
+// prev_load[0]->set_text(text);
+// prev_load[0]->set_path(new_path);
+// return 0;
+// }
+//
+// ReverbLoad::ReverbLoad(Reverb *reverb, ReverbMenu *menu)
+// : BC_MenuItem(_("Load..."))
+// {
+// this->reverb = reverb;
+// this->menu = menu;
+// thread = new ReverbLoadThread(reverb, menu);
+// }
+// ReverbLoad::~ReverbLoad()
+// {
+// delete thread;
+// }
+// int ReverbLoad::handle_event()
+// {
+// thread->start();
+// return 0;
+// }
+//
+// ReverbSave::ReverbSave(Reverb *reverb, ReverbMenu *menu)
+// : BC_MenuItem(_("Save..."))
+// {
+// this->reverb = reverb;
+// this->menu = menu;
+// thread = new ReverbSaveThread(reverb, menu);
+// }
+// ReverbSave::~ReverbSave()
+// {
+// delete thread;
+// }
+// int ReverbSave::handle_event()
+// {
+// thread->start();
+// return 0;
+// }
+//
+// ReverbSetDefault::ReverbSetDefault()
+// : BC_MenuItem(_("Set default"))
+// {
+// }
+// int ReverbSetDefault::handle_event()
+// {
+// return 0;
+// }
+//
+// ReverbLoadPrev::ReverbLoadPrev(Reverb *reverb, ReverbMenu *menu, char *filename, char *path)
+// : BC_MenuItem(filename)
+// {
+// this->reverb = reverb;
+// this->menu = menu;
+// strcpy(this->path, path);
+// }
+// ReverbLoadPrev::ReverbLoadPrev(Reverb *reverb, ReverbMenu *menu)
+// : BC_MenuItem("")
+// {
+// this->reverb = reverb;
+// this->menu = menu;
+// }
+// int ReverbLoadPrev::handle_event()
+// {
+// menu->prev_load_thread->set_path(path);
+// menu->prev_load_thread->start();
+// }
+// int ReverbLoadPrev::set_path(char *path)
+// {
+// strcpy(this->path, path);
+// }
+//
+//
+// ReverbSaveThread::ReverbSaveThread(Reverb *reverb, ReverbMenu *menu)
+// : Thread()
+// {
+// this->reverb = reverb;
+// this->menu = menu;
+// }
+// ReverbSaveThread::~ReverbSaveThread()
+// {
+// }
+// void ReverbSaveThread::run()
+// {
+// int result = 0;
+// {
+// ReverbSaveDialog dialog(reverb);
+// dialog.create_objects();
+// result = dialog.run_window();
+// // if(!result) strcpy(reverb->config_directory, dialog.get_path());
+// }
+// if(!result)
+// {
+// result = reverb->save_to_file(reverb->config_directory);
+// menu->add_load(reverb->config_directory);
+// }
+// }
+//
+// ReverbSaveDialog::ReverbSaveDialog(Reverb *reverb)
+// : BC_FileBox(0,
+// 0,
+// reverb->config_directory,
+// _("Save reverb"),
+// _("Select the reverb file to save as"), 0, 0)
+// {
+// this->reverb = reverb;
+// }
+// ReverbSaveDialog::~ReverbSaveDialog()
+// {
+// }
+// int ReverbSaveDialog::ok_event()
+// {
+// set_done(0);
+// return 0;
+// }
+// int ReverbSaveDialog::cancel_event()
+// {
+// set_done(1);
+// return 0;
+// }
+//
+//
+//
+// ReverbLoadThread::ReverbLoadThread(Reverb *reverb, ReverbMenu *menu)
+// : Thread()
+// {
+// this->reverb = reverb;
+// this->menu = menu;
+// }
+// ReverbLoadThread::~ReverbLoadThread()
+// {
+// }
+// void ReverbLoadThread::run()
+// {
+// int result = 0;
+// {
+// ReverbLoadDialog dialog(reverb);
+// dialog.create_objects();
+// result = dialog.run_window();
+// // if(!result) strcpy(reverb->config_directory, dialog.get_path());
+// }
+// if(!result)
+// {
+// result = reverb->load_from_file(reverb->config_directory);
+// if(!result)
+// {
+// menu->add_load(reverb->config_directory);
+// reverb->send_configure_change();
+// }
+// }
+// }
+//
+// ReverbLoadPrevThread::ReverbLoadPrevThread(Reverb *reverb, ReverbMenu *menu) : Thread()
+// {
+// this->reverb = reverb;
+// this->menu = menu;
+// }
+// ReverbLoadPrevThread::~ReverbLoadPrevThread()
+// {
+// }
+// void ReverbLoadPrevThread::run()
+// {
+// int result = 0;
+// strcpy(reverb->config_directory, path);
+// result = reverb->load_from_file(path);
+// if(!result)
+// {
+// menu->add_load(path);
+// reverb->send_configure_change();
+// }
+// }
+// int ReverbLoadPrevThread::set_path(char *path)
+// {
+// strcpy(this->path, path);
+// return 0;
+// }
+//
+//
+//
+//
+//
+// ReverbLoadDialog::ReverbLoadDialog(Reverb *reverb)
+// : BC_FileBox(0,
+// 0,
+// reverb->config_directory,
+// _("Load reverb"),
+// _("Select the reverb file to load from"), 0, 0)
+// {
+// this->reverb = reverb;
+// }
+// ReverbLoadDialog::~ReverbLoadDialog()
+// {
+// }
+// int ReverbLoadDialog::ok_event()
+// {
+// set_done(0);
+// return 0;
+// }
+// int ReverbLoadDialog::cancel_event()
+// {
+// set_done(1);
+// return 0;
+// }
#include "filexml.h"
#include "guicast.h"
#include "language.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "vframe.h"
#include "bchash.h"
#include "filexml.h"
#include "language.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "samples.h"
#include "spectrogram.h"
#include "theme.h"
--- /dev/null
+include ../../plugin_defs
+
+OBJS = $(OBJDIR)/spherecam.o
+
+PLUGIN = spherecam
+
+include ../../plugin_config
+
+$(OBJDIR)/spherecam.o: spherecam.C
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2017 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "affine.h"
+#include "bcdisplayinfo.h"
+#include "bchash.h"
+#include "bcsignals.h"
+#include "clip.h"
+#include "filexml.h"
+#include "language.h"
+#include "spherecam.h"
+#include "theme.h"
+
+#include <string.h>
+
+// largely based on equations from http://paulbourke.net/dome/fish2/
+
+REGISTER_PLUGIN(SphereCamMain)
+
+
+SphereCamConfig::SphereCamConfig()
+{
+ feather = 0;
+
+ for( int i = 0; i < EYES; i++ ) {
+ enabled[i] = 1;
+ fov[i] = 180;
+ radius[i] = 100.0;
+ center_y[i] = 50.0;
+ rotate_y[i] = 50.0;
+ rotate_z[i] = 0;
+ }
+
+ center_x[0] = 25.0;
+ center_x[1] = 75.0;
+ rotate_x[0] = 50.0;
+ rotate_x[1] = 100.0;
+ draw_guides = 1;
+ mode = SphereCamConfig::DO_NOTHING;
+}
+
+int SphereCamConfig::equivalent(SphereCamConfig &that)
+{
+ for( int i = 0; i < EYES; i++ ) {
+ if( enabled[i] != that.enabled[i] ||
+ !EQUIV(fov[i], that.fov[i]) ||
+ !EQUIV(radius[i], that.radius[i]) ||
+ !EQUIV(center_x[i], that.center_x[i]) ||
+ !EQUIV(center_y[i], that.center_y[i]) ||
+ !EQUIV(rotate_x[i], that.rotate_x[i]) ||
+ !EQUIV(rotate_y[i], that.rotate_y[i]) ||
+ !EQUIV(rotate_z[i], that.rotate_z[i]) ) {
+ return 0;
+ }
+ }
+
+ if( feather != that.feather || mode != that.mode ||
+ draw_guides != that.draw_guides ) {
+ return 0;
+ }
+
+
+ return 1;
+}
+
+void SphereCamConfig::copy_from(SphereCamConfig &that)
+{
+ *this = that;
+}
+
+void SphereCamConfig::interpolate(SphereCamConfig &prev,
+ SphereCamConfig &next,
+ int64_t prev_frame,
+ int64_t next_frame,
+ int64_t current_frame)
+{
+ double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
+ double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
+
+ for( int i = 0; i < EYES; i++ ) {
+ enabled[i] = prev.enabled[i];
+ fov[i] = prev.fov[i] * prev_scale + next.fov[i] * next_scale;
+ radius[i] = prev.radius[i] * prev_scale + next.radius[i] * next_scale;
+ center_x[i] = prev.center_x[i] * prev_scale + next.center_x[i] * next_scale;
+ center_y[i] = prev.center_y[i] * prev_scale + next.center_y[i] * next_scale;
+ rotate_x[i] = prev.rotate_x[i] * prev_scale + next.rotate_x[i] * next_scale;
+ rotate_y[i] = prev.rotate_y[i] * prev_scale + next.rotate_y[i] * next_scale;
+ rotate_z[i] = prev.rotate_z[i] * prev_scale + next.rotate_z[i] * next_scale;
+ }
+
+ feather = prev.feather * prev_scale + next.feather * next_scale;
+ draw_guides = prev.draw_guides;
+ mode = prev.mode;
+
+ boundaries();
+}
+
+void SphereCamConfig::boundaries()
+{
+ for( int i = 0; i < EYES; i++ ) {
+ CLAMP(fov[i], 1.0, 359.0);
+ CLAMP(radius[i], 1.0, 150.0);
+ CLAMP(center_x[i], 0.0, 100.0);
+ CLAMP(center_y[i], 0.0, 100.0);
+ CLAMP(rotate_x[i], 0.0, 100.0);
+ CLAMP(rotate_y[i], 0.0, 100.0);
+ CLAMP(rotate_z[i], -180.0, 180.0);
+ }
+
+ CLAMP(feather, 0, 50);
+}
+
+
+SphereCamSlider::SphereCamSlider(SphereCamMain *client,
+ SphereCamGUI *gui,
+ SphereCamText *text,
+ float *output,
+ int x,
+ int y,
+ float min,
+ float max)
+ : BC_FSlider(x,
+ y,
+ 0,
+ gui->get_w() / 2 - client->get_theme()->widget_border * 3 - 100,
+ gui->get_w() / 2 - client->get_theme()->widget_border * 3 - 100,
+ min,
+ max,
+ *output)
+{
+ this->gui = gui;
+ this->client = client;
+ this->output = output;
+ this->text = text;
+ set_precision(0.01);
+}
+
+int SphereCamSlider::handle_event()
+{
+ *output = get_value();
+ text->update(*output);
+ client->send_configure_change();
+ return 1;
+}
+
+
+SphereCamText::SphereCamText(SphereCamMain *client,
+ SphereCamGUI *gui,
+ SphereCamSlider *slider,
+ float *output,
+ int x,
+ int y)
+ : BC_TextBox(x, y, 100, 1, *output)
+{
+ this->gui = gui;
+ this->client = client;
+ this->output = output;
+ this->slider = slider;
+}
+
+int SphereCamText::handle_event()
+{
+ *output = atof(get_text());
+ slider->update(*output);
+ client->send_configure_change();
+ return 1;
+}
+
+
+SphereCamToggle::SphereCamToggle(SphereCamMain *client,
+ int *output, int x, int y, const char *text)
+ : BC_CheckBox(x, y, *output, text)
+{
+ this->output = output;
+ this->client = client;
+}
+
+int SphereCamToggle::handle_event()
+{
+ *output = get_value();
+ client->send_configure_change();
+ return 1;
+}
+
+
+SphereCamMode::SphereCamMode(SphereCamMain *plugin,
+ SphereCamGUI *gui, int x, int y)
+ : BC_PopupMenu(x, y, calculate_w(gui), "", 1)
+{
+ this->plugin = plugin;
+ this->gui = gui;
+}
+
+int SphereCamMode::handle_event()
+{
+ plugin->config.mode = from_text(get_text());
+ plugin->send_configure_change();
+ return 1;
+
+}
+
+void SphereCamMode::create_objects()
+{
+ add_item(new BC_MenuItem(to_text(SphereCamConfig::DO_NOTHING)));
+ add_item(new BC_MenuItem(to_text(SphereCamConfig::EQUIRECT)));
+ add_item(new BC_MenuItem(to_text(SphereCamConfig::ALIGN)));
+ update(plugin->config.mode);
+}
+
+void SphereCamMode::update(int mode)
+{
+ char string[BCTEXTLEN];
+ sprintf(string, "%s", to_text(mode));
+ set_text(string);
+}
+
+int SphereCamMode::calculate_w(SphereCamGUI *gui)
+{
+ int result = 0;
+ result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(SphereCamConfig::EQUIRECT)));
+ result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(SphereCamConfig::DO_NOTHING)));
+ result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(SphereCamConfig::ALIGN)));
+ return result + 50;
+}
+
+int SphereCamMode::from_text(char *text)
+{
+ for( int i = 0; i < 3; i++ ) {
+ if( !strcmp(text, to_text(i)) ) {
+ return i;
+ }
+ }
+
+ return SphereCamConfig::EQUIRECT;
+}
+
+const char* SphereCamMode::to_text(int mode)
+{
+ switch( mode ) {
+ case SphereCamConfig::DO_NOTHING:
+ return "Do nothing";
+ break;
+ case SphereCamConfig::EQUIRECT:
+ return "Equirectangular";
+ break;
+ case SphereCamConfig::ALIGN:
+ return "Align only";
+ break;
+ }
+ return "Equirectangular";
+}
+
+
+SphereCamGUI::SphereCamGUI(SphereCamMain *client)
+ : PluginClientWindow(client, 640, 600, 640, 600, 0)
+{
+ this->client = client;
+}
+
+SphereCamGUI::~SphereCamGUI()
+{
+}
+
+
+void SphereCamGUI::create_objects()
+{
+ int margin = client->get_theme()->widget_border;
+ int margin2 = margin;
+ int y = margin;
+ int x[EYES];
+
+ x[0] = margin;
+ x[1] = get_w() / 2 + margin / 2;
+
+ BC_Title *title;
+
+ for( int i = 0; i < EYES; i++ ) {
+ int x3 = x[i];
+ y = margin;
+
+ add_tool(title = new BC_Title(x[i], y,
+ i == 0 ? _("Left Eye") : _("Right Eye"), LARGEFONT));
+ y += title->get_h() + margin2;
+
+ add_tool(enabled[i] = new SphereCamToggle(client,
+ &client->config.enabled[i], x3, y, _("Enabled")));
+ y += enabled[i]->get_h() + margin2;
+
+ add_tool(title = new BC_Title(x3, y, _("FOV:")));
+ y += title->get_h() + margin2;
+ add_tool(fov_slider[i] = new SphereCamSlider(client, this,
+ 0, &client->config.fov[i], x3, y, 1, 359));
+ fov_slider[i]->set_precision(0.1);
+ x3 += fov_slider[i]->get_w() + margin;
+ add_tool(fov_text[i] = new SphereCamText(client, this,
+ fov_slider[i], &client->config.fov[i], x3, y));
+ fov_slider[i]->text = fov_text[i];
+ y += fov_text[i]->get_h() + margin2;
+
+ x3 = x[i];
+ add_tool(title = new BC_Title(x3, y, _("Radius:")));
+ y += title->get_h() + margin2;
+ add_tool(radius_slider[i] = new SphereCamSlider(client, this,
+ 0, &client->config.radius[i], x3, y, 1, 150));
+ radius_slider[i]->set_precision(0.1);
+ x3 += radius_slider[i]->get_w() + margin;
+ add_tool(radius_text[i] = new SphereCamText(client, this,
+ radius_slider[i], &client->config.radius[i], x3, y));
+ radius_slider[i]->text = radius_text[i];
+ y += radius_text[i]->get_h() + margin2;
+
+ x3 = x[i];
+ add_tool(title = new BC_Title(x3, y, _("Input X:")));
+ y += title->get_h() + margin2;
+ add_tool(centerx_slider[i] = new SphereCamSlider(client, this,
+ 0, &client->config.center_x[i], x3, y, 0, 100));
+ centerx_slider[i]->set_precision(0.1);
+ x3 += centerx_slider[i]->get_w() + margin;
+ add_tool(centerx_text[i] = new SphereCamText(client, this,
+ centerx_slider[i], &client->config.center_x[i], x3, y));
+ centerx_slider[i]->text = centerx_text[i];
+ y += centerx_text[i]->get_h() + margin2;
+
+ x3 = x[i];
+ add_tool(title = new BC_Title(x3, y, _("Input Y:")));
+ y += title->get_h() + margin2;
+ add_tool(centery_slider[i] = new SphereCamSlider(client, this,
+ 0, &client->config.center_y[i], x3, y, 0, 100));
+ centery_slider[i]->set_precision(0.1);
+ x3 += centery_slider[i]->get_w() + margin;
+ add_tool(centery_text[i] = new SphereCamText(client, this,
+ centery_slider[i], &client->config.center_y[i], x3, y));
+ centery_slider[i]->text = centery_text[i];
+ y += centery_text[i]->get_h() + margin2;
+
+ x3 = x[i];
+ add_tool(title = new BC_Title(x3, y, _("Output X:")));
+ y += title->get_h() + margin2;
+ add_tool(rotatex_slider[i] = new SphereCamSlider(client, this,
+ 0, &client->config.rotate_x[i], x3, y, 0, 100));
+ rotatex_slider[i]->set_precision(0.1);
+ x3 += rotatex_slider[i]->get_w() + margin;
+ add_tool(rotatex_text[i] = new SphereCamText(client, this,
+ rotatex_slider[i], &client->config.rotate_x[i], x3, y));
+ rotatex_slider[i]->text = rotatex_text[i];
+ y += rotatex_text[i]->get_h() + margin2;
+
+ x3 = x[i];
+ add_tool(title = new BC_Title(x3, y, _("Output Y:")));
+ y += title->get_h() + margin2;
+ add_tool(rotatey_slider[i] = new SphereCamSlider(client, this,
+ 0, &client->config.rotate_y[i], x3, y, 0, 100));
+ rotatey_slider[i]->set_precision(0.1);
+ x3 += rotatey_slider[i]->get_w() + margin;
+ add_tool(rotatey_text[i] = new SphereCamText(client, this,
+ rotatey_slider[i], &client->config.rotate_y[i], x3, y));
+ rotatey_slider[i]->text = rotatey_text[i];
+ y += rotatey_text[i]->get_h() + margin2;
+
+ x3 = x[i];
+ add_tool(title = new BC_Title(x3, y, _("Rotate:")));
+ y += title->get_h() + margin2;
+ add_tool(rotatez_slider[i] = new SphereCamSlider(client, this,
+ 0, &client->config.rotate_z[i], x3, y, -180, 180));
+ rotatez_slider[i]->set_precision(0.1);
+ x3 += rotatez_slider[i]->get_w() + margin;
+ add_tool(rotatez_text[i] = new SphereCamText(client, this,
+ rotatez_slider[i], &client->config.rotate_z[i], x3, y));
+ rotatez_slider[i]->text = rotatez_text[i];
+ y += rotatez_text[i]->get_h() + margin2;
+ }
+
+ int x3 = x[0];
+ add_tool(title = new BC_Title(x3, y, _("Feather:")));
+ y += title->get_h() + margin2;
+ add_tool(feather_slider = new SphereCamSlider(client, this,
+ 0, &client->config.feather, x3, y, 0, 100));
+ feather_slider->set_precision(0.1);
+ x3 += feather_slider->get_w() + margin;
+ add_tool(feather_text = new SphereCamText(client, this,
+ feather_slider, &client->config.feather, x3, y));
+ feather_slider->text = feather_text;
+ y += feather_text->get_h() + margin2;
+
+//printf("SphereCamGUI::create_objects %d %f\n", __LINE__, client->config.distance);
+
+ x3 = x[0];
+ add_tool(draw_guides = new SphereCamToggle(client,
+ &client->config.draw_guides, x3, y, _("Draw guides")));
+ y += draw_guides->get_h() + margin2;
+
+ add_tool(title = new BC_Title(x3, y, _("Mode:")));
+ add_tool(mode = new SphereCamMode(client,
+ this,
+ x3 + title->get_w() + margin,
+ y));
+ mode->create_objects();
+ y += mode->get_h() + margin2;
+
+ show_window();
+ flush();
+}
+
+
+SphereCamMain::SphereCamMain(PluginServer *server)
+ : PluginVClient(server)
+{
+ engine = 0;
+ affine = 0;
+}
+
+SphereCamMain::~SphereCamMain()
+{
+ delete engine;
+ delete affine;
+}
+
+NEW_WINDOW_MACRO(SphereCamMain, SphereCamGUI)
+LOAD_CONFIGURATION_MACRO(SphereCamMain, SphereCamConfig)
+int SphereCamMain::is_realtime() { return 1; }
+const char* SphereCamMain::plugin_title() { return N_("Sphere Cam"); }
+
+void SphereCamMain::update_gui()
+{
+ if( !thread ) return;
+ if( !load_configuration() ) return;
+ ((SphereCamGUI*)thread->window)->lock_window("SphereCamMain::update_gui");
+ SphereCamGUI *window = (SphereCamGUI*)thread->window;
+
+ for( int i = 0; i < EYES; i++ ) {
+ window->enabled[i]->update(config.enabled[i]);
+
+ window->fov_slider[i]->update(config.fov[i]);
+ window->fov_text[i]->update(config.fov[i]);
+
+ window->radius_slider[i]->update(config.radius[i]);
+ window->radius_text[i]->update(config.radius[i]);
+
+ window->centerx_slider[i]->update(config.center_x[i]);
+ window->centerx_text[i]->update(config.center_x[i]);
+
+ window->centery_slider[i]->update(config.center_y[i]);
+ window->centery_text[i]->update(config.center_y[i]);
+
+ window->rotatex_slider[i]->update(config.rotate_x[i]);
+ window->rotatex_text[i]->update(config.rotate_x[i]);
+
+ window->rotatey_slider[i]->update(config.rotate_y[i]);
+ window->rotatey_text[i]->update(config.rotate_y[i]);
+
+ window->rotatez_slider[i]->update(config.rotate_z[i]);
+ window->rotatez_text[i]->update(config.rotate_z[i]);
+ }
+
+ window->feather_slider->update(config.feather);
+ window->feather_text->update(config.feather);
+
+ window->mode->update(config.mode);
+ window->draw_guides->update(config.draw_guides);
+ window->unlock_window();
+}
+
+void SphereCamMain::save_data(KeyFrame *keyframe)
+{
+ FileXML output;
+ char string[BCTEXTLEN];
+
+// cause data to be stored directly in text
+ output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
+ output.tag.set_title("SPHERECAM");
+
+ for( int i = 0; i < EYES; i++ ) {
+ sprintf(string, "ENABLED_%d", i);
+ output.tag.set_property(string, config.enabled[i]);
+ sprintf(string, "FOV_%d", i);
+ output.tag.set_property(string, config.fov[i]);
+ sprintf(string, "RADIUS_%d", i);
+ output.tag.set_property(string, config.radius[i]);
+ sprintf(string, "CENTER_X_%d", i);
+ output.tag.set_property(string, config.center_x[i]);
+ sprintf(string, "CENTER_Y_%d", i);
+ output.tag.set_property(string, config.center_y[i]);
+ sprintf(string, "ROTATE_X_%d", i);
+ output.tag.set_property(string, config.rotate_x[i]);
+ sprintf(string, "ROTATE_Y_%d", i);
+ output.tag.set_property(string, config.rotate_y[i]);
+ sprintf(string, "ROTATE_Z_%d", i);
+ output.tag.set_property(string, config.rotate_z[i]);
+ }
+
+ output.tag.set_property("FEATHER", config.feather);
+ output.tag.set_property("DRAW_GUIDES", config.draw_guides);
+ output.tag.set_property("MODE", config.mode);
+ output.append_tag();
+ output.terminate_string();
+}
+
+
+void SphereCamMain::read_data(KeyFrame *keyframe)
+{
+ FileXML input;
+ char string[BCTEXTLEN];
+
+
+ input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
+
+ int result = 0;
+
+ while(!result)
+ {
+ result = input.read_tag();
+
+ if( !result ) {
+ if( input.tag.title_is("SPHERECAM") ) {
+ for( int i = 0; i < EYES; i++ ) {
+ sprintf(string, "ENABLED_%d", i);
+ config.enabled[i] = input.tag.get_property(string, config.enabled[i]);
+ sprintf(string, "FOV_%d", i);
+ config.fov[i] = input.tag.get_property(string, config.fov[i]);
+ sprintf(string, "RADIUS_%d", i);
+ config.radius[i] = input.tag.get_property(string, config.radius[i]);
+ sprintf(string, "CENTER_X_%d", i);
+ config.center_x[i] = input.tag.get_property(string, config.center_x[i]);
+ sprintf(string, "CENTER_Y_%d", i);
+ config.center_y[i] = input.tag.get_property(string, config.center_y[i]);
+ sprintf(string, "ROTATE_X_%d", i);
+ config.rotate_x[i] = input.tag.get_property(string, config.rotate_x[i]);
+ sprintf(string, "ROTATE_Y_%d", i);
+ config.rotate_y[i] = input.tag.get_property(string, config.rotate_y[i]);
+ sprintf(string, "ROTATE_Z_%d", i);
+ config.rotate_z[i] = input.tag.get_property(string, config.rotate_z[i]);
+ }
+
+ config.feather = input.tag.get_property("FEATHER", config.feather);
+ config.draw_guides = input.tag.get_property("DRAW_GUIDES", config.draw_guides);
+ config.mode = input.tag.get_property("MODE", config.mode);
+ }
+ }
+ }
+}
+
+
+
+int SphereCamMain::process_buffer(VFrame *frame,
+ int64_t start_position,
+ double frame_rate)
+{
+ load_configuration();
+
+ VFrame *input = new_temp(frame->get_w(), frame->get_h(), frame->get_color_model());
+
+ read_frame(input, 0, start_position, frame_rate, 0); // use opengl
+
+// find_lenses();
+ calculate_extents();
+
+ if( config.mode == SphereCamConfig::DO_NOTHING ) {
+ get_output()->copy_from(input);
+ }
+ else {
+ get_output()->clear_frame();
+ if( !engine ) engine = new SphereCamEngine(this);
+ engine->process_packages();
+ }
+
+ if( config.draw_guides ) {
+// input regions
+// printf("SphereCamMain::process_buffer %d %d %d\n", __LINE__, out_x1[0], out_x4[0]);
+ for( int eye = 0; eye < EYES; eye++ ) {
+ if( config.enabled[eye] ) {
+// input regions
+ get_output()->draw_oval(input_x[eye] - radius[eye],
+ input_y[eye] - radius[eye],
+ input_x[eye] + radius[eye],
+ input_y[eye] + radius[eye]);
+
+
+// output regions. If they overlap, don't xor out the line
+ if( eye == 0 || (out_x1[eye] != out_x1[0] && out_x1[eye] != out_x4[0]) ) {
+ get_output()->draw_line(out_x1[eye], 0, out_x1[eye], h);
+ }
+
+ if( eye == 0 || (out_x4[eye] != out_x4[0] && out_x4[eye] != out_x1[0]) ) {
+ get_output()->draw_line(out_x4[eye], 0, out_x4[eye], h);
+ }
+
+ if( feather != 0 && eye == 1 ) {
+// crosshatch feather of right eye only, since only the right eye feathers
+ int feather_gap = h / 20;
+ for( int j = 0; j < h + feather; j += feather_gap ) {
+ draw_feather(out_x1[eye], out_x1[eye] + feather, eye, j);
+ draw_feather(out_x4[eye] - feather, out_x4[eye], eye, j);
+ }
+ }
+ }
+ }
+
+ }
+
+ return 0;
+}
+
+void SphereCamMain::draw_feather(int left, int right, int eye, int y)
+{
+ int slope = 1;
+ if( eye == 1 ) {
+ slope = -1;
+ }
+
+// wrap
+ if( left < 0 ) {
+ int left2 = w + left;
+ get_output()->draw_line(left2, y, left2 + right - left, y + feather * slope);
+ }
+
+ if( right > w ) {
+ int right2 = right - w;
+ get_output()->draw_line(0, y, right2, y + feather * slope);
+
+ }
+
+// proper
+ get_output()->draw_line(left, y, right, y + feather * slope);
+
+}
+
+
+// void SphereCamMain::find_lenses()
+// {
+// }
+
+
+void SphereCamMain::calculate_extents()
+{
+ w = get_output()->get_w();
+ h = get_output()->get_h();
+
+ feather = (int)(config.feather * w / 100);
+
+ for( int i = 0; i < EYES; i++ ) {
+// input regions
+ input_x[i] = (int)(config.center_x[i] * w / 100);
+ input_y[i] = (int)(config.center_y[i] * h / 100);
+ radius[i] = (int)(h / 2 * config.radius[i] / 100);
+
+// output regions
+ output_x[i] = (int)(config.rotate_x[i] * w / 100);
+ output_y[i] = (int)(config.rotate_y[i] * h / 100);
+
+
+// Assume each lens fills 1/2 the width
+ out_x1[i] = output_x[i] - w / 4 - feather / 2;
+ out_x2[i] = output_x[i];
+ out_x3[i] = output_x[i];
+ out_x4[i] = output_x[i] + w / 4 + feather / 2;
+ }
+
+// If the output isn't 50% apart, we have to expand the left eye to fill the feathering region
+//printf("SphereCamMain::calculate_extents %d %f\n", __LINE__, config.rotate_x[0] - config.rotate_x[1]);
+ float x_separation = config.rotate_x[0] - config.rotate_x[1];
+ if( !EQUIV(fabs(x_separation), 50) ) {
+ if( x_separation < -50 ) {
+ out_x4[0] += (-49.5 - x_separation) * w / 100;
+ }
+ else
+ if( x_separation < 0 ) {
+ out_x1[0] -= (x_separation + 50) * w / 100;
+ }
+ else
+ if( x_separation < 50 ) {
+ out_x4[0] += (50.5 - x_separation) * w / 100;
+ }
+ else {
+ out_x1[0] -= (x_separation - 49.5) * w / 100;
+ }
+ }
+
+
+// wrap around
+ for( int i = 0; i < EYES; i++ ) {
+ if( out_x1[i] < 0 ) {
+ out_x1[i] = w + out_x1[i];
+ out_x2[i] = w;
+ out_x3[i] = 0;
+ }
+
+ if( out_x4[i] > w ) {
+ out_x2[i] = w;
+ out_x3[i] = 0;
+ out_x4[i] -= w;
+ }
+
+// printf("SphereCamMain::calculate_extents %d i=%d x=%d y=%d radius=%d\n",
+// __LINE__,
+// i,
+// center_x[i],
+// center_y[i],
+// radius[i]);
+ }
+}
+
+SphereCamPackage::SphereCamPackage()
+ : LoadPackage() {}
+
+SphereCamUnit::SphereCamUnit(SphereCamEngine *engine, SphereCamMain *plugin)
+ : LoadClient(engine)
+{
+ this->plugin = plugin;
+}
+
+
+SphereCamUnit::~SphereCamUnit()
+{
+}
+
+
+
+// interpolate & accumulate a pixel in the output
+#define BLEND_PIXEL(type, components) \
+ if( x_in < 0.0 || x_in >= w - 1 || \
+ y_in < 0.0 || y_in >= h - 1 ) { \
+ out_row += components; \
+ } \
+ else { \
+ float y1_fraction = y_in - floor(y_in); \
+ float y2_fraction = 1.0 - y1_fraction; \
+ float x1_fraction = x_in - floor(x_in); \
+ float x2_fraction = 1.0 - x1_fraction; \
+ type *in_pixel1 = in_rows[(int)y_in] + (int)x_in * components; \
+ type *in_pixel2 = in_rows[(int)y_in + 1] + (int)x_in * components; \
+ for( int i = 0; i < components; i++ ) { \
+ float value = in_pixel1[i] * x2_fraction * y2_fraction + \
+ in_pixel2[i] * x2_fraction * y1_fraction + \
+ in_pixel1[i + components] * x1_fraction * y2_fraction + \
+ in_pixel2[i + components] * x1_fraction * y1_fraction; \
+ value = *out_row * inv_a + value * a; \
+ *out_row++ = (type)value; \
+ } \
+ }
+
+
+// nearest neighbor & accumulate a pixel in the output
+#define BLEND_NEAREST(type, components) \
+ if( x_in < 0.0 || x_in >= w - 1 || \
+ y_in < 0.0 || y_in >= h - 1 ) { \
+ out_row += components; \
+ } \
+ else { \
+ type *in_pixel = in_rows[(int)y_in] + (int)x_in * components; \
+ for( int i = 0; i < components; i++ ) { \
+ float value = in_pixel[i]; \
+ value = *out_row * inv_a + value * a; \
+ *out_row++ = (type)value; \
+ } \
+ }
+
+
+#define COLORSPACE_SWITCH(function) \
+ switch( plugin->get_input()->get_color_model() ) { \
+ case BC_RGB888: function(unsigned char, 3, 0x0); break; \
+ case BC_RGBA8888: function(unsigned char, 4, 0x0); break; \
+ case BC_RGB_FLOAT: function(float, 3, 0.0); break; \
+ case BC_RGBA_FLOAT: function(float, 4, 0.0); break; \
+ case BC_YUV888: function(unsigned char, 3, 0x80); break; \
+ case BC_YUVA8888: function(unsigned char, 4, 0x80); break; \
+ }
+
+void SphereCamUnit::process_equirect(SphereCamPackage *pkg)
+{
+ VFrame *input = plugin->get_temp();
+ VFrame *output = plugin->get_output();
+
+
+// overlay a single eye
+#define PROCESS_EQUIRECT(type, components, chroma) \
+{ \
+ type **in_rows = (type**)input->get_rows(); \
+ type **out_rows = (type**)output->get_rows(); \
+ \
+ for( int out_y = row1; out_y < row2; out_y++ ) { \
+ type *out_row = out_rows[out_y]; \
+/* polar angle - -M_PI/2 to M_PI/2 */ \
+ float y_diff = out_y - output_y; \
+ float phi = M_PI / 2 * (y_diff / radius); \
+ \
+ for( int out_x = 0; out_x < w; out_x++ ) { \
+/* alpha */ \
+ float a = alpha[out_x]; \
+ float inv_a = 1.0f - a; \
+ if( a > 0 ) { \
+/* polar angle */ \
+ float x_diff = out_x - output_x; \
+/* -M_PI/2 to M_PI/2 */ \
+ float theta = M_PI / 2 * (x_diff / radius); \
+/* vector in 3D space */ \
+ float vect_x = cos(phi) * sin(theta); \
+ float vect_y = cos(phi) * cos(theta); \
+ float vect_z = sin(phi); \
+/* fisheye angle & radius */ \
+ float theta2 = atan2(vect_z, vect_x) - rotate_z; \
+ float phi2 = atan2(hypot(vect_x, vect_z), vect_y); \
+ float r = radius * 2 * phi2 / fov; \
+/* pixel in fisheye space */ \
+ float x_in = input_x + r * cos(theta2); \
+ float y_in = input_y + r * sin(theta2); \
+ \
+ BLEND_PIXEL(type, components) \
+ } \
+ else { \
+ out_row += components; \
+ } \
+ } \
+ } \
+}
+
+ int row1 = pkg->row1;
+ int row2 = pkg->row2;
+ for( int eye = 0; eye < EYES; eye++ ) {
+ if( plugin->config.enabled[eye] ) {
+ int w = plugin->w;
+ int h = plugin->h;
+ float fov = plugin->config.fov[eye] * M_PI * 2 / 360;
+// float radius = plugin->radius[eye];
+ float radius = h / 2;
+ float input_x = plugin->input_x[eye];
+ float input_y = plugin->input_y[eye];
+ float output_x = plugin->output_x[eye];
+ float output_y = plugin->output_y[eye];
+ float rotate_z = plugin->config.rotate_z[eye] * M_PI * 2 / 360;
+ int feather = plugin->feather;
+ int out_x1 = plugin->out_x1[eye];
+ int out_x2 = plugin->out_x2[eye];
+ int out_x3 = plugin->out_x3[eye];
+ int out_x4 = plugin->out_x4[eye];
+
+// compute the alpha for every X
+ float alpha[w];
+ for( int i = 0; i < w; i++ ) {
+ alpha[i] = 0;
+ }
+
+ for( int i = out_x1; i < out_x2; i++ ) {
+ alpha[i] = 1.0f;
+ }
+
+ for( int i = out_x3; i < out_x4; i++ ) {
+ alpha[i] = 1.0f;
+ }
+
+ if( eye == 1 ) {
+ for( int i = out_x1; i < out_x1 + feather; i++ ) {
+ float value = (float)(i - out_x1) / feather;
+ if( i >= w ) {
+ alpha[i - w] = value;
+ }
+ else {
+ alpha[i] = value;
+ }
+ }
+
+ for( int i = out_x4 - feather; i < out_x4; i++ ) {
+ float value = (float)(out_x4 - i) / feather;
+ if( i < 0 ) {
+ alpha[w + i] = value;
+ }
+ else {
+ alpha[i] = value;
+ }
+ }
+ }
+
+
+//printf("SphereCamUnit::process_equirect %d rotate_x=%f rotate_y=%f rotate_z=%f\n",
+// __LINE__, rotate_x, rotate_y, rotate_z);
+
+ COLORSPACE_SWITCH(PROCESS_EQUIRECT)
+ }
+ }
+}
+
+
+
+void SphereCamUnit::process_align(SphereCamPackage *pkg)
+{
+ VFrame *input = plugin->get_temp();
+ VFrame *output = plugin->get_output();
+
+
+// overlay a single eye
+#define PROCESS_ALIGN(type, components, chroma) \
+{ \
+ type **in_rows = (type**)input->get_rows(); \
+ type **out_rows = (type**)output->get_rows(); \
+ \
+ for( int out_y = row1; out_y < row2; out_y++ ) { \
+ type *out_row = out_rows[out_y]; \
+/* polar angle */ \
+/* -M_PI/2 to M_PI/2 */ \
+ float y_diff = out_y - output_y; \
+ float phi = M_PI / 2 * (y_diff / radius); \
+ \
+ for( int out_x = 0; out_x < w; out_x++ ) { \
+/* alpha */ \
+ float a = alpha[out_x]; \
+ float inv_a = 1.0f - a; \
+ if( a > 0 ) { \
+/* polar angle */ \
+ float x_diff = out_x - output_x; \
+/* -M_PI/2 to M_PI/2 */ \
+ float theta = M_PI / 2 * (x_diff / radius); \
+ /* vector in 3D space */ \
+ float vect_x = cos(phi) * sin(theta); \
+ float vect_y = cos(phi) * cos(theta); \
+ float vect_z = sin(phi); \
+ /* fisheye angle & radius */ \
+ float theta2 = atan2(vect_z, vect_x) - rotate_z; \
+ float phi2 = atan2(hypot(vect_x, vect_z), vect_y); \
+ float r = radius * 2 * phi2 / fov; \
+ /* pixel in fisheye space */ \
+ float x_in = input_x + r * cos(theta2); \
+ float y_in = input_y + r * sin(theta2); \
+ \
+ BLEND_NEAREST(type, components) \
+ } \
+ else { \
+ out_row += components; \
+ } \
+ } \
+ } \
+}
+
+ int row1 = pkg->row1;
+ int row2 = pkg->row2;
+ for( int eye = 0; eye < EYES; eye++ ) {
+ if( plugin->config.enabled[eye] ) {
+ int w = plugin->w;
+ int h = plugin->h;
+ float fov = plugin->config.fov[eye] * M_PI * 2 / 360;
+// float radius = plugin->radius[eye];
+ float radius = h / 2;
+ float input_x = plugin->input_x[eye];
+ float input_y = plugin->input_y[eye];
+ float output_x = plugin->output_x[eye];
+ float output_y = plugin->output_y[eye];
+ float rotate_z = plugin->config.rotate_z[eye] * M_PI * 2 / 360;
+ int out_x1 = plugin->out_x1[eye];
+ int out_x2 = plugin->out_x2[eye];
+ int out_x3 = plugin->out_x3[eye];
+ int out_x4 = plugin->out_x4[eye];
+// left eye is opaque. right eye overlaps
+// compute the alpha for every X
+ float alpha[w];
+ for( int i = 0; i < w; i++ ) alpha[i] = 0;
+ float v = eye == 0 || !plugin->config.enabled[0] ? 1.0f : 0.5f;
+ for( int i = out_x1; i < out_x2; i++ ) alpha[i] = v;
+ for( int i = out_x3; i < out_x4; i++ ) alpha[i] = v;
+
+ COLORSPACE_SWITCH(PROCESS_ALIGN)
+ }
+ }
+}
+
+void SphereCamUnit::process_package(LoadPackage *package)
+{
+ SphereCamPackage *pkg = (SphereCamPackage*)package;
+
+ switch( plugin->config.mode ) {
+ case SphereCamConfig::EQUIRECT:
+ process_equirect(pkg);
+ break;
+ case SphereCamConfig::ALIGN:
+ process_align(pkg);
+ break;
+ }
+}
+
+
+SphereCamEngine::SphereCamEngine(SphereCamMain *plugin)
+ : LoadServer(plugin->PluginClient::smp + 1, plugin->PluginClient::smp + 1)
+// : LoadServer(1, 1)
+{
+ this->plugin = plugin;
+}
+
+SphereCamEngine::~SphereCamEngine()
+{
+}
+
+void SphereCamEngine::init_packages()
+{
+ for( int i = 0; i < LoadServer::get_total_packages(); i++ ) {
+ SphereCamPackage *package = (SphereCamPackage*)LoadServer::get_package(i);
+ package->row1 = plugin->get_input()->get_h() * i / LoadServer::get_total_packages();
+ package->row2 = plugin->get_input()->get_h() * (i + 1) / LoadServer::get_total_packages();
+ }
+}
+
+LoadClient* SphereCamEngine::new_client()
+{
+ return new SphereCamUnit(this, plugin);
+}
+
+LoadPackage* SphereCamEngine::new_package()
+{
+ return new SphereCamPackage;
+}
+
+
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2017 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "affine.h"
+#include "bcdisplayinfo.h"
+#include "bchash.h"
+#include "bcsignals.h"
+#include "clip.h"
+#include "filexml.h"
+#include "language.h"
+#include "360fuser.h"
+
+
+#include <string.h>
+
+
+
+// largely based on equations from http://paulbourke.net/dome/fish2/
+
+
+
+REGISTER_PLUGIN(Fuse360Main)
+
+
+
+
+Fuse360Config::Fuse360Config()
+{
+ fov = 1.0;
+ radius_x = 0.5;
+ radius_y = 0.5;
+ center_x = 50.0;
+ center_y = 50.0;
+ distance_x = 50;
+ distance_y = 0;
+ feather = 0;
+ translate_x = 0;
+ rotation = 0;
+ draw_guides = 1;
+ mode = Fuse360Config::DO_NOTHING;
+}
+
+int Fuse360Config::equivalent(Fuse360Config &that)
+{
+ if(EQUIV(fov, that.fov) &&
+ EQUIV(radius_x, that.radius_x) &&
+ EQUIV(radius_y, that.radius_y) &&
+ EQUIV(feather, that.feather) &&
+ EQUIV(center_x, that.center_x) &&
+ EQUIV(center_y, that.center_y) &&
+ EQUIV(distance_x, that.distance_x) &&
+ EQUIV(distance_y, that.distance_y) &&
+ EQUIV(translate_x, that.translate_x) &&
+ EQUIV(rotation, that.rotation) &&
+ mode == that.mode &&
+ draw_guides == that.draw_guides)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void Fuse360Config::copy_from(Fuse360Config &that)
+{
+ *this = that;
+}
+
+void Fuse360Config::interpolate(Fuse360Config &prev,
+ Fuse360Config &next,
+ int64_t prev_frame,
+ int64_t next_frame,
+ int64_t current_frame)
+{
+ double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
+ double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
+
+ fov = prev.fov * prev_scale + next.fov * next_scale;
+ radius_x = prev.radius_x * prev_scale + next.radius_x * next_scale;
+ radius_y = prev.radius_y * prev_scale + next.radius_y * next_scale;
+ feather = prev.feather * prev_scale + next.feather * next_scale;
+ center_x = prev.center_x * prev_scale + next.center_x * next_scale;
+ center_y = prev.center_y * prev_scale + next.center_y * next_scale;
+ distance_x = prev.distance_x * prev_scale + next.distance_x * next_scale;
+ distance_y = prev.distance_y * prev_scale + next.distance_y * next_scale;
+ rotation = prev.rotation * prev_scale + next.rotation * next_scale;
+ translate_x = prev.translate_x * prev_scale + next.translate_x * next_scale;
+ draw_guides = prev.draw_guides;
+ mode = prev.mode;
+
+ boundaries();
+}
+
+void Fuse360Config::boundaries()
+{
+ CLAMP(fov, 0.0, 1.0);
+ CLAMP(radius_x, 0.3, 1.0);
+ CLAMP(radius_y, 0.3, 1.0);
+ CLAMP(feather, 0, 50);
+ CLAMP(center_x, 0.0, 99.0);
+ CLAMP(center_y, 0.0, 99.0);
+ CLAMP(distance_x, 0.0, 100.0);
+ CLAMP(distance_y, -50.0, 50.0);
+ CLAMP(translate_x, -100, 100);
+ CLAMP(rotation, -180, 180);
+}
+
+
+
+
+Fuse360Slider::Fuse360Slider(Fuse360Main *client,
+ Fuse360GUI *gui,
+ Fuse360Text *text,
+ float *output,
+ int x,
+ int y,
+ float min,
+ float max)
+ : BC_FSlider(x, y, 0, 200, 200, min, max, *output)
+{
+ this->gui = gui;
+ this->client = client;
+ this->output = output;
+ this->text = text;
+ set_precision(0.01);
+}
+
+int Fuse360Slider::handle_event()
+{
+ float prev_output = *output;
+ *output = get_value();
+ text->update(*output);
+
+
+ client->send_configure_change();
+ return 1;
+}
+
+
+
+Fuse360Text::Fuse360Text(Fuse360Main *client,
+ Fuse360GUI *gui,
+ Fuse360Slider *slider,
+ float *output,
+ int x,
+ int y)
+ : BC_TextBox(x, y, 100, 1, *output)
+{
+ this->gui = gui;
+ this->client = client;
+ this->output = output;
+ this->slider = slider;
+}
+
+int Fuse360Text::handle_event()
+{
+ float prev_output = *output;
+ *output = atof(get_text());
+ slider->update(*output);
+
+
+ client->send_configure_change();
+ return 1;
+}
+
+
+
+Fuse360Toggle::Fuse360Toggle(Fuse360Main *client,
+ int *output,
+ int x,
+ int y,
+ const char *text)
+ : BC_CheckBox(x, y, *output, text)
+{
+ this->output = output;
+ this->client = client;
+}
+
+int Fuse360Toggle::handle_event()
+{
+ *output = get_value();
+ client->send_configure_change();
+ return 1;
+}
+
+
+
+
+
+
+
+
+
+
+Fuse360Mode::Fuse360Mode(Fuse360Main *plugin,
+ Fuse360GUI *gui,
+ int x,
+ int y)
+ : BC_PopupMenu(x,
+ y,
+ calculate_w(gui),
+ "",
+ 1)
+{
+ this->plugin = plugin;
+ this->gui = gui;
+}
+
+int Fuse360Mode::handle_event()
+{
+ plugin->config.mode = from_text(get_text());
+ plugin->send_configure_change();
+ return 1;
+
+}
+
+void Fuse360Mode::create_objects()
+{
+ add_item(new BC_MenuItem(to_text(Fuse360Config::DO_NOTHING)));
+ add_item(new BC_MenuItem(to_text(Fuse360Config::STRETCHXY)));
+ add_item(new BC_MenuItem(to_text(Fuse360Config::STANDARD)));
+ add_item(new BC_MenuItem(to_text(Fuse360Config::BLEND)));
+ update(plugin->config.mode);
+}
+
+void Fuse360Mode::update(int mode)
+{
+ char string[BCTEXTLEN];
+ sprintf(string, "%s", to_text(mode));
+ set_text(string);
+}
+
+int Fuse360Mode::calculate_w(Fuse360GUI *gui)
+{
+ int result = 0;
+ result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(Fuse360Config::STRETCHXY)));
+ result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(Fuse360Config::STANDARD)));
+ result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(Fuse360Config::BLEND)));
+ result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(Fuse360Config::DO_NOTHING)));
+ return result + 50;
+}
+
+int Fuse360Mode::from_text(char *text)
+{
+ for(int i = 0; i < 4; i++)
+ {
+ if(!strcmp(text, to_text(i)))
+ {
+ return i;
+ }
+ }
+
+ return Fuse360Config::STRETCHXY;
+}
+
+const char* Fuse360Mode::to_text(int mode)
+{
+ switch(mode)
+ {
+ case Fuse360Config::DO_NOTHING:
+ return "Do nothing";
+ break;
+ case Fuse360Config::STRETCHXY:
+ return "Stretch";
+ break;
+ case Fuse360Config::STANDARD:
+ return "Equirectangular";
+ break;
+ }
+ return "Blend";
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fuse360GUI::Fuse360GUI(Fuse360Main *client)
+ : PluginClientWindow(client,
+ 350,
+ 650,
+ 350,
+ 650,
+ 0)
+{
+ this->client = client;
+}
+
+Fuse360GUI::~Fuse360GUI()
+{
+}
+
+
+void Fuse360GUI::create_objects()
+{
+ int x = 10;
+ int y = 10;
+ int x1;
+ int margin = 10;
+ BC_Title *title;
+ Fuse360Toggle *toggle;
+
+// add_tool(title = new BC_Title(x, y, _("Field of View:")));
+// y += title->get_h() + 5;
+// add_tool(fov_slider = new Fuse360Slider(client,
+// this,
+// 0,
+// &client->config.fov,
+// x,
+// y,
+// 0.0001,
+// 1.0));
+//
+//
+// x1 = x + fov_slider->get_w() + margin;
+// add_tool(fov_text = new Fuse360Text(client,
+// this,
+// fov_slider,
+// &client->config.fov,
+// x1,
+// y));
+// fov_slider->text = fov_text;
+// y += fov_text->get_h() + margin;
+
+
+
+
+ add_tool(title = new BC_Title(x, y, _("Eye Radius X:")));
+ y += title->get_h() + 5;
+ add_tool(radiusx_slider = new Fuse360Slider(client,
+ this,
+ 0,
+ &client->config.radius_x,
+ x,
+ y,
+ 0.3,
+ 1.0));
+ x1 = x + radiusx_slider->get_w() + margin;
+ add_tool(radiusx_text = new Fuse360Text(client,
+ this,
+ radiusx_slider,
+ &client->config.radius_x,
+ x1,
+ y));
+ radiusx_slider->text = radiusx_text;
+ y += radiusx_text->get_h() + 5;
+
+
+ add_tool(title = new BC_Title(x, y, _("Eye Radius Y:")));
+ y += title->get_h() + margin;
+ add_tool(radiusy_slider = new Fuse360Slider(client,
+ this,
+ 0,
+ &client->config.radius_y,
+ x,
+ y,
+ 0.3,
+ 1.0));
+ x1 = x + radiusy_slider->get_w() + margin;
+ add_tool(radiusy_text = new Fuse360Text(client,
+ this,
+ radiusy_slider,
+ &client->config.radius_y,
+ x1,
+ y));
+ radiusy_slider->text = radiusy_text;
+ y += radiusy_text->get_h() + margin;
+
+
+// add_tool(title = new BC_Title(x, y, _("Center X:")));
+// y += title->get_h() + 5;
+// add_tool(centerx_slider = new Fuse360Slider(client,
+// this,
+// 0,
+// &client->config.center_x,
+// x,
+// y,
+// 0.0,
+// 99.0));
+// x1 = x + centerx_slider->get_w() + margin;
+// add_tool(centerx_text = new Fuse360Text(client,
+// this,
+// centerx_slider,
+// &client->config.center_x,
+// x1,
+// y));
+// centerx_slider->text = centerx_text;
+// centerx_slider->set_precision(0.1);
+// y += centerx_text->get_h() + margin;
+//
+//
+// add_tool(title = new BC_Title(x, y, _("Center Y:")));
+// y += title->get_h() + 5;
+// add_tool(centery_slider = new Fuse360Slider(client,
+// this,
+// 0,
+// &client->config.center_y,
+// x,
+// y,
+// 0.0,
+// 99.0));
+// x1 = x + centery_slider->get_w() + margin;
+// add_tool(centery_text = new Fuse360Text(client,
+// this,
+// centery_slider,
+// &client->config.center_y,
+// x1,
+// y));
+// centery_slider->text = centery_text;
+// centery_slider->set_precision(0.1);
+// y += centery_text->get_h() + margin;
+
+
+
+
+ add_tool(title = new BC_Title(x, y, _("X Eye Spacing:")));
+ y += title->get_h() + 5;
+ add_tool(distancex_slider = new Fuse360Slider(client,
+ this,
+ 0,
+ &client->config.distance_x,
+ x,
+ y,
+ 0.0,
+ 100.0));
+ x1 = x + distancex_slider->get_w() + margin;
+ add_tool(distancex_text = new Fuse360Text(client,
+ this,
+ distancex_slider,
+ &client->config.distance_x,
+ x1,
+ y));
+ distancex_slider->text = distancex_text;
+ distancex_slider->set_precision(0.1);
+ y += distancex_text->get_h() + margin;
+
+
+
+
+
+
+
+ add_tool(title = new BC_Title(x, y, _("Y Eye Spacing:")));
+ y += title->get_h() + 5;
+ add_tool(distancey_slider = new Fuse360Slider(client,
+ this,
+ 0,
+ &client->config.distance_y,
+ x,
+ y,
+ -50,
+ 50));
+ x1 = x + distancey_slider->get_w() + margin;
+ add_tool(distancey_text = new Fuse360Text(client,
+ this,
+ distancey_slider,
+ &client->config.distance_y,
+ x1,
+ y));
+ distancey_slider->text = distancey_text;
+ distancey_slider->set_precision(0.1);
+ y += distancey_text->get_h() + margin;
+
+
+
+
+
+
+ add_tool(title = new BC_Title(x, y, _("X Translation:")));
+ y += title->get_h() + 5;
+ add_tool(translatex_slider = new Fuse360Slider(client,
+ this,
+ 0,
+ &client->config.translate_x,
+ x,
+ y,
+ -50.0,
+ 50.0));
+ x1 = x + translatex_slider->get_w() + margin;
+ add_tool(translatex_text = new Fuse360Text(client,
+ this,
+ translatex_slider,
+ &client->config.translate_x,
+ x1,
+ y));
+ translatex_slider->text = translatex_text;
+ translatex_slider->set_precision(0.1);
+ y += translatex_text->get_h() + margin;
+
+
+
+
+
+
+ add_tool(title = new BC_Title(x, y, _("Feather:")));
+ y += title->get_h() + 5;
+ add_tool(feather_slider = new Fuse360Slider(client,
+ this,
+ 0,
+ &client->config.feather,
+ x,
+ y,
+ 0,
+ 50));
+ x1 = x + feather_slider->get_w() + margin;
+ add_tool(feather_text = new Fuse360Text(client,
+ this,
+ feather_slider,
+ &client->config.feather,
+ x1,
+ y));
+ feather_slider->text = feather_text;
+ feather_slider->set_precision(1);
+ y += feather_text->get_h() + margin;
+
+
+
+
+
+
+ add_tool(title = new BC_Title(x, y, _("Rotation:")));
+ y += title->get_h() + 5;
+ add_tool(rotation_slider = new Fuse360Slider(client,
+ this,
+ 0,
+ &client->config.rotation,
+ x,
+ y,
+ -180,
+ 180));
+ x1 = x + rotation_slider->get_w() + margin;
+ add_tool(rotation_text = new Fuse360Text(client,
+ this,
+ rotation_slider,
+ &client->config.rotation,
+ x1,
+ y));
+ rotation_slider->text = rotation_text;
+ rotation_slider->set_precision(0.1);
+ y += rotation_text->get_h() + margin;
+
+
+
+
+
+
+
+//printf("Fuse360GUI::create_objects %d %f\n", __LINE__, client->config.distance);
+
+
+ add_tool(draw_guides = new Fuse360Toggle(client,
+ &client->config.draw_guides,
+ x,
+ y,
+ _("Draw guides")));
+ y += draw_guides->get_h() + margin;
+
+
+ add_tool(title = new BC_Title(x, y, _("Mode:")));
+ add_tool(mode = new Fuse360Mode(client,
+ this,
+ x + title->get_w() + margin,
+ y));
+ mode->create_objects();
+ y += mode->get_h() + margin;
+
+
+
+ show_window();
+ flush();
+}
+
+
+
+
+
+
+
+Fuse360Main::Fuse360Main(PluginServer *server)
+ : PluginVClient(server)
+{
+ engine = 0;
+ affine = 0;
+}
+
+Fuse360Main::~Fuse360Main()
+{
+ delete engine;
+ delete affine;
+}
+
+NEW_WINDOW_MACRO(Fuse360Main, Fuse360GUI)
+LOAD_CONFIGURATION_MACRO(Fuse360Main, Fuse360Config)
+int Fuse360Main::is_realtime() { return 1; }
+const char* Fuse360Main::plugin_title() { return N_("360 Fuser"); }
+
+void Fuse360Main::update_gui()
+{
+ if(thread)
+ {
+ if(load_configuration())
+ {
+ ((Fuse360GUI*)thread->window)->lock_window("Fuse360Main::update_gui");
+// ((Fuse360GUI*)thread->window)->fov_slider->update(config.fov);
+// ((Fuse360GUI*)thread->window)->fov_text->update(config.fov);
+ ((Fuse360GUI*)thread->window)->radiusx_slider->update(config.radius_x);
+ ((Fuse360GUI*)thread->window)->radiusx_text->update(config.radius_x);
+ ((Fuse360GUI*)thread->window)->radiusy_slider->update(config.radius_y);
+ ((Fuse360GUI*)thread->window)->radiusy_text->update(config.radius_y);
+// ((Fuse360GUI*)thread->window)->centerx_slider->update(config.center_x);
+// ((Fuse360GUI*)thread->window)->centerx_text->update(config.center_x);
+// ((Fuse360GUI*)thread->window)->centery_slider->update(config.center_y);
+// ((Fuse360GUI*)thread->window)->centery_text->update(config.center_y);
+ ((Fuse360GUI*)thread->window)->distancex_slider->update(config.distance_x);
+ ((Fuse360GUI*)thread->window)->distancex_text->update(config.distance_x);
+ ((Fuse360GUI*)thread->window)->distancey_slider->update(config.distance_y);
+ ((Fuse360GUI*)thread->window)->distancey_text->update(config.distance_y);
+ ((Fuse360GUI*)thread->window)->translatex_slider->update(config.translate_x);
+ ((Fuse360GUI*)thread->window)->translatex_text->update(config.translate_x);
+ ((Fuse360GUI*)thread->window)->feather_slider->update(config.feather);
+ ((Fuse360GUI*)thread->window)->feather_text->update(config.feather);
+ ((Fuse360GUI*)thread->window)->rotation_slider->update(config.rotation);
+ ((Fuse360GUI*)thread->window)->rotation_text->update(config.rotation);
+ ((Fuse360GUI*)thread->window)->mode->update(config.mode);
+ ((Fuse360GUI*)thread->window)->draw_guides->update(config.draw_guides);
+ ((Fuse360GUI*)thread->window)->unlock_window();
+ }
+ }
+}
+
+
+void Fuse360Main::save_data(KeyFrame *keyframe)
+{
+ FileXML output;
+ char string[BCTEXTLEN];
+
+
+
+// cause data to be stored directly in text
+ output.set_shared_string(keyframe->get_data(), MESSAGESIZE);
+ output.tag.set_title("360FUSER");
+ output.tag.set_property("FOCAL_LENGTH", config.fov);
+ output.tag.set_property("RADIUS_X", config.radius_x);
+ output.tag.set_property("RADIUS_Y", config.radius_y);
+ output.tag.set_property("FEATHER", config.feather);
+ output.tag.set_property("CENTER_X", config.center_x);
+ output.tag.set_property("CENTER_Y", config.center_y);
+ output.tag.set_property("DISTANCE_X", config.distance_x);
+ output.tag.set_property("DISTANCE_Y", config.distance_y);
+ output.tag.set_property("TRANSLATE_X", config.translate_x);
+ output.tag.set_property("ROTATION", config.rotation);
+ output.tag.set_property("DRAW_GUIDES", config.draw_guides);
+ output.tag.set_property("MODE", config.mode);
+ output.append_tag();
+ output.terminate_string();
+
+}
+
+
+void Fuse360Main::read_data(KeyFrame *keyframe)
+{
+ FileXML input;
+ char string[BCTEXTLEN];
+
+
+ input.set_shared_string(keyframe->get_data(), strlen(keyframe->get_data()));
+
+ int result = 0;
+
+ while(!result)
+ {
+ result = input.read_tag();
+
+ if(!result)
+ {
+ if(input.tag.title_is("360FUSER"))
+ {
+ config.fov = input.tag.get_property("FOCAL_LENGTH", config.fov);
+ config.radius_x = input.tag.get_property("RADIUS_X", config.radius_x);
+ config.radius_y = input.tag.get_property("RADIUS_Y", config.radius_y);
+ config.feather = input.tag.get_property("FEATHER", config.feather);
+ config.center_x = input.tag.get_property("CENTER_X", config.center_x);
+ config.center_y = input.tag.get_property("CENTER_Y", config.center_y);
+ config.distance_x = input.tag.get_property("DISTANCE_X", config.distance_x);
+ config.distance_y = input.tag.get_property("DISTANCE_Y", config.distance_y);
+ config.translate_x = input.tag.get_property("TRANSLATE_X", config.translate_x);
+ config.rotation = input.tag.get_property("ROTATION", config.rotation);
+ config.draw_guides = input.tag.get_property("DRAW_GUIDES", config.draw_guides);
+ config.mode = input.tag.get_property("MODE", config.mode);
+ }
+ }
+ }
+}
+
+
+
+int Fuse360Main::process_buffer(VFrame *frame,
+ int64_t start_position,
+ double frame_rate)
+{
+ load_configuration();
+
+ VFrame *input = new_temp(frame->get_w(), frame->get_h(), frame->get_color_model());
+
+ read_frame(input,
+ 0,
+ start_position,
+ frame_rate,
+ 0); // use opengl
+
+ calculate_extents();
+
+// always rotate it
+ if(!EQUIV(config.rotation, 0))
+ {
+ int center_x = w / 2;
+ int center_y = h / 2;
+ int center_x1 = w / 4;
+ int center_y1 = h / 2;
+ int center_x2 = w * 3 / 4;
+ int center_y2 = h / 2;
+ int radius_x = 0;
+ int radius_y = 0;
+
+ radius_x = config.radius_x * w / 2;
+ radius_y = config.radius_y * h;
+
+ if(!affine) affine = new AffineEngine(PluginClient::smp + 1,
+ PluginClient::smp + 1);
+ affine->set_in_pivot(center_x1, center_y1);
+ affine->set_in_viewport(0, 0, center_x, h);
+ affine->set_out_viewport(0, 0, center_x, h);
+ affine->rotate(get_output(),
+ input,
+ config.rotation);
+
+ affine->set_in_pivot(center_x2, center_y2);
+ affine->set_in_viewport(center_x, 0, w - center_x, h);
+ affine->set_out_viewport(center_x, 0, w - center_x, h);
+ affine->rotate(get_output(),
+ input,
+ -config.rotation);
+
+ input->copy_from(get_output());
+ get_output()->clear_frame();
+
+ }
+
+ if(config.mode == Fuse360Config::DO_NOTHING)
+ {
+ get_output()->copy_from(input);
+ }
+ else
+ {
+
+ if(!engine) engine = new Fuse360Engine(this);
+ engine->process_packages();
+ }
+
+
+
+ if(config.draw_guides)
+ {
+
+ get_output()->draw_line(center_x, 0, center_x, h);
+
+// draw lenses
+ get_output()->draw_oval(center_x1 - radius_x + distance_x,
+ center_y1 - radius_y + distance_y,
+ center_x1 + radius_x + distance_x,
+ center_y1 + radius_y + distance_y);
+ get_output()->draw_oval(center_x2 - radius_x - distance_x,
+ center_y2 - radius_y - distance_y,
+ center_x2 + radius_x - distance_x,
+ center_y2 + radius_y - distance_y);
+
+// draw feather
+ get_output()->draw_line(feather_x1, 0, feather_x1, h);
+ get_output()->draw_line(feather_x2, 0, feather_x2, h);
+
+
+ }
+
+ return 0;
+}
+
+
+void Fuse360Main::calculate_extents()
+{
+ w = get_output()->get_w();
+ h = get_output()->get_h();
+ center_x = w / 2;
+ center_y = h / 2;
+ center_x1 = w * 1 / 4;
+ center_y1 = h / 2;
+ center_x2 = w * 3 / 4;
+ center_y2 = h / 2;
+ radius_x = 0;
+ radius_y = 0;
+ distance_x = (int)((50 - config.distance_x) * w / 100 / 2);
+ distance_y = (int)(config.distance_y * h / 100 / 2);
+ feather = (int)(config.feather * w / 100);
+ feather_x1 = center_x - (int)(config.feather * w / 100 / 2);
+ feather_x2 = center_x + (int)(config.feather * w / 100 / 2);
+ radius_x = config.radius_x * w / 2;
+ radius_y = config.radius_y * h;
+//printf("Fuse360Main::calculate_extents %d radius_y=%d\n", __LINE__, radius_y);
+}
+
+
+
+
+
+Fuse360Package::Fuse360Package()
+ : LoadPackage() {}
+
+
+
+
+
+Fuse360Unit::Fuse360Unit(Fuse360Engine *engine, Fuse360Main *plugin)
+ : LoadClient(engine)
+{
+ this->plugin = plugin;
+}
+
+
+Fuse360Unit::~Fuse360Unit()
+{
+}
+
+
+
+void Fuse360Unit::process_blend(Fuse360Package *pkg)
+{
+ VFrame *input = plugin->get_temp();
+ VFrame *output = plugin->get_output();
+
+ int row1 = pkg->row1;
+ int row2 = pkg->row2;
+ int width = input->get_w();
+ int height = input->get_h();
+
+#define PROCESS_BLEND(type, components, chroma) \
+{ \
+ type **in_rows = (type**)input->get_rows(); \
+ type **out_rows = (type**)output->get_rows(); \
+ type black[4] = { 0, chroma, chroma, 0 }; \
+ \
+ for(int y = row1; y < row2; y++) \
+ { \
+ type *out_row = out_rows[y]; \
+ type *in_row = in_rows[y]; \
+ \
+ for(int x = 0; x < width; x++) \
+ { \
+ } \
+ } \
+}
+
+
+ switch(plugin->get_input()->get_color_model())
+ {
+ case BC_RGB888:
+ PROCESS_BLEND(unsigned char, 3, 0x0);
+ break;
+ case BC_RGBA8888:
+ PROCESS_BLEND(unsigned char, 4, 0x0);
+ break;
+ case BC_RGB_FLOAT:
+ PROCESS_BLEND(float, 3, 0.0);
+ break;
+ case BC_RGBA_FLOAT:
+ PROCESS_BLEND(float, 4, 0.0);
+ break;
+ case BC_YUV888:
+ PROCESS_BLEND(unsigned char, 3, 0x80);
+ break;
+ case BC_YUVA8888:
+ PROCESS_BLEND(unsigned char, 4, 0x80);
+ break;
+ }
+
+}
+
+// interpolate 1 eye
+#define BLEND_PIXEL(type, components) \
+ if(x_in < 0.0 || x_in >= w - 1 || \
+ y_in < 0.0 || y_in >= h - 1) \
+ { \
+ *out_row++ = black[0]; \
+ *out_row++ = black[1]; \
+ *out_row++ = black[2]; \
+ if(components == 4) *out_row++ = black[3]; \
+ } \
+ else \
+ { \
+ float y1_fraction = y_in - floor(y_in); \
+ float y2_fraction = 1.0 - y1_fraction; \
+ float x1_fraction = x_in - floor(x_in); \
+ float x2_fraction = 1.0 - x1_fraction; \
+ type *in_pixel1 = in_rows[(int)y_in] + (int)x_in * components; \
+ type *in_pixel2 = in_rows[(int)y_in + 1] + (int)x_in * components; \
+ for(int i = 0; i < components; i++) \
+ { \
+ *out_row++ = (type)(in_pixel1[i] * x2_fraction * y2_fraction + \
+ in_pixel2[i] * x2_fraction * y1_fraction + \
+ in_pixel1[i + components] * x1_fraction * y2_fraction + \
+ in_pixel2[i + components] * x1_fraction * y1_fraction); \
+ } \
+ }
+
+
+// interpolate 2 eyes
+#define BLEND_PIXEL2(type, components) \
+ type pixel1[components], pixel2[components]; \
+ \
+/* calculate the left eye */ \
+ if(x_in1 < 0.0 || x_in1 >= w - 1 || \
+ y_in1 < 0.0 || y_in1 >= h - 1) \
+ { \
+ pixel1[0] = black[0]; \
+ pixel1[1] = black[1]; \
+ pixel1[2] = black[2]; \
+ if(components == 4) pixel1[3] = black[3]; \
+ } \
+ else \
+ { \
+ float y1_fraction = y_in1 - floor(y_in1); \
+ float y2_fraction = 1.0 - y1_fraction; \
+ float x1_fraction = x_in1 - floor(x_in1); \
+ float x2_fraction = 1.0 - x1_fraction; \
+ type *in_pixel1 = in_rows[(int)y_in1] + (int)x_in1 * components; \
+ type *in_pixel2 = in_rows[(int)y_in1 + 1] + (int)x_in1 * components; \
+ for(int i = 0; i < components; i++) \
+ { \
+ pixel1[i] = (type)(in_pixel1[i] * x2_fraction * y2_fraction + \
+ in_pixel2[i] * x2_fraction * y1_fraction + \
+ in_pixel1[i + components] * x1_fraction * y2_fraction + \
+ in_pixel2[i + components] * x1_fraction * y1_fraction); \
+ } \
+ } \
+ \
+ \
+/* calculate the right eye */ \
+ if(x_in2 < 0.0 || x_in2 >= w - 1 || \
+ y_in2 < 0.0 || y_in2 >= h - 1) \
+ { \
+ pixel2[0] = black[0]; \
+ pixel2[1] = black[1]; \
+ pixel2[2] = black[2]; \
+ if(components == 4) pixel2[3] = black[3]; \
+ } \
+ else \
+ { \
+ float y1_fraction = y_in2 - floor(y_in2); \
+ float y2_fraction = 1.0 - y1_fraction; \
+ float x1_fraction = x_in2 - floor(x_in2); \
+ float x2_fraction = 1.0 - x1_fraction; \
+ type *in_pixel1 = in_rows[(int)y_in2] + (int)x_in2 * components; \
+ type *in_pixel2 = in_rows[(int)y_in2 + 1] + (int)x_in2 * components; \
+ for(int i = 0; i < components; i++) \
+ { \
+ pixel2[i] = (type)(in_pixel1[i] * x2_fraction * y2_fraction + \
+ in_pixel2[i] * x2_fraction * y1_fraction + \
+ in_pixel1[i + components] * x1_fraction * y2_fraction + \
+ in_pixel2[i + components] * x1_fraction * y1_fraction); \
+ } \
+ } \
+ \
+/* blend the 2 eyes */ \
+ for(int i = 0; i < components; i++) \
+ { \
+ *out_row++ = (type)(pixel1[i] * (1.0f - fraction) + \
+ pixel2[i] * fraction); \
+ } \
+
+
+
+
+#define COLORSPACE_SWITCH(function) \
+ switch(plugin->get_input()->get_color_model()) \
+ { \
+ case BC_RGB888: \
+ function(unsigned char, 3, 0x0); \
+ break; \
+ case BC_RGBA8888: \
+ function(unsigned char, 4, 0x0); \
+ break; \
+ case BC_RGB_FLOAT: \
+ function(float, 3, 0.0); \
+ break; \
+ case BC_RGBA_FLOAT: \
+ function(float, 4, 0.0); \
+ break; \
+ case BC_YUV888: \
+ function(unsigned char, 3, 0x80); \
+ break; \
+ case BC_YUVA8888: \
+ function(unsigned char, 4, 0x80); \
+ break; \
+ }
+
+
+double Fuse360Unit::calculate_max_z(double a, double r)
+{
+ if(a < 0) a += 2 * M_PI;
+
+ if(a < M_PI / 4)
+ {
+ return r / cos(a); // bottom right edge
+ }
+ else
+ if(a < 3 * M_PI / 4)
+ {
+ return r / cos(M_PI / 2 - a); // bottom edge
+ }
+ else
+ if(a < 5 * M_PI / 4)
+ {
+ return r / cos(M_PI - a); // left edge
+ }
+ else
+ if(a < 7 * M_PI / 4)
+ {
+ return r / cos(3 * M_PI / 2 - a); // top edge
+ }
+ else
+ {
+ return r / cos(a); // top right edge
+ }
+}
+
+void Fuse360Unit::process_stretch(Fuse360Package *pkg)
+{
+ VFrame *input = plugin->get_temp();
+ VFrame *output = plugin->get_output();
+
+ float fov = plugin->config.fov;
+ int row1 = pkg->row1;
+ int row2 = pkg->row2;
+ int center_x1 = plugin->center_x1;
+ int center_x2 = plugin->center_x2;
+ int center_y1 = plugin->center_y1;
+ int center_y2 = plugin->center_y2;
+ int center_x = plugin->center_x;
+ int center_y = plugin->center_y;
+ int w = plugin->w;
+ int h = plugin->h;
+ double radius = plugin->radius_x;
+
+
+#define PROCESS_STRETCH(type, components, chroma) \
+{ \
+ type **in_rows = (type**)input->get_rows(); \
+ type **out_rows = (type**)output->get_rows(); \
+ type black[4] = { 0, chroma, chroma, 0 }; \
+ \
+ for(int y = row1; y < row2; y++) \
+ { \
+ type *out_row = out_rows[y]; \
+ type *in_row = in_rows[y]; \
+ double y_diff = y - center_y1; \
+ \
+/* left eye */ \
+ for(int x = 0; x < center_x; x++) \
+ { \
+ double x_diff = x - center_x1; \
+/* polar output coordinate */ \
+ double z = hypot(x_diff, y_diff); \
+ double a = atan2(y_diff, x_diff); \
+ \
+/* scale the magnitude to the radius */ \
+ double scaled_z = z * radius / calculate_max_z(a, radius); \
+/* xy input coordinate */ \
+ double x_in = scaled_z * cos(a) + center_x1; \
+ double y_in = scaled_z * sin(a) + center_y1; \
+ \
+ if(x_in < center_x) \
+ { \
+ BLEND_PIXEL(type, components) \
+ } \
+ } \
+ } \
+ \
+ for(int y = row1; y < row2; y++) \
+ { \
+ type *out_row = out_rows[y] + center_x * components; \
+ type *in_row = in_rows[y]; \
+ double y_diff = y - center_y2; \
+ \
+/* right eye */ \
+ for(int x = center_x; x < w; x++) \
+ { \
+ double x_diff = x - center_x2; \
+/* polar output coordinate */ \
+ double z = hypot(x_diff, y_diff); \
+ double a = atan2(y_diff, x_diff); \
+ \
+/* scale the magnitude to the radius */ \
+ double scaled_z = z * radius / calculate_max_z(a, radius); \
+/* xy input coordinate */ \
+ double x_in = scaled_z * cos(a) + center_x2; \
+ double y_in = scaled_z * sin(a) + center_y2; \
+ \
+ if(x_in >= center_x) \
+ { \
+ BLEND_PIXEL(type, components) \
+ } \
+ } \
+ } \
+}
+
+
+
+ COLORSPACE_SWITCH(PROCESS_STRETCH)
+}
+
+
+
+
+
+void Fuse360Unit::process_standard(Fuse360Package *pkg)
+{
+ VFrame *input = plugin->get_temp();
+ VFrame *output = plugin->get_output();
+
+ float fov = plugin->config.fov;
+ int row1 = pkg->row1;
+ int row2 = pkg->row2;
+ int center_x1 = plugin->center_x1;
+ int center_x2 = plugin->center_x2;
+ int center_y1 = plugin->center_y1;
+ int center_y2 = plugin->center_y2;
+ int center_x = plugin->center_x;
+ int center_y = plugin->center_y;
+ int feather = plugin->feather;
+ int feather_x1 = plugin->feather_x1;
+ int feather_x2 = plugin->feather_x2;
+ int w = plugin->w;
+ int h = plugin->h;
+ float radius_x = plugin->radius_x;
+ float radius_y = plugin->radius_y;
+ int distance_x = plugin->distance_x;
+ int distance_y = plugin->distance_y;
+// field of view of the fisheye
+ float FOV = M_PI;
+
+#define PROCESS_STANDARD(type, components, chroma) \
+{ \
+ type **in_rows = (type**)input->get_rows(); \
+ type **out_rows = (type**)output->get_rows(); \
+ type black[4] = { 0, chroma, chroma, 0 }; \
+ \
+/* left eye */ \
+ for(int y = row1; y < row2; y++) \
+ { \
+ type *out_row = out_rows[y]; \
+ \
+/* -M_PI/2 to M_PI/2 */ \
+ float y_diff = y - center_y1; \
+/* polar angles */ \
+ float phi = M_PI / 2 * (y_diff / radius_y); \
+ for(int x = 0; x < feather_x1; x++) \
+ { \
+ float x_diff = x - center_x1; \
+/* polar angles */ \
+/* -M_PI/2 to M_PI/2 */ \
+ float theta = M_PI / 2 * (x_diff / radius_x); \
+/* vector in 3D space */ \
+ float vect_x = cos(phi) * sin(theta); \
+ float vect_y = cos(phi) * cos(theta); \
+ float vect_z = sin(phi); \
+/* fisheye angle & radius */ \
+ float theta2 = atan2(vect_z, vect_x); \
+ float phi2 = atan2(hypot(vect_x, vect_z), vect_y); \
+ float r = radius_x * 2 * phi2 / FOV; \
+/* pixel in fisheye space */ \
+ float x_in = center_x1 + r * cos(theta2); \
+ float y_in = center_y1 + r * sin(theta2); \
+ \
+ BLEND_PIXEL(type, components) \
+ } \
+ } \
+ \
+ \
+ \
+/* right eye */ \
+ for(int y = row1; y < row2; y++) \
+ { \
+ type *out_row = out_rows[y] + components * feather_x2; \
+ \
+/* -M_PI/2 to M_PI/2 */ \
+ float y_diff = y - center_y2; \
+/* polar angles */ \
+ float phi = M_PI / 2 * (y_diff / radius_y); \
+ for(int x = feather_x2; x < w; x++) \
+ { \
+ float x_diff = x - center_x2; \
+/* polar angles */ \
+/* -M_PI/2 to M_PI/2 */ \
+ float theta = M_PI / 2 * (x_diff / radius_x); \
+/* vector in 3D space */ \
+ float vect_x = cos(phi) * sin(theta); \
+ float vect_y = cos(phi) * cos(theta); \
+ float vect_z = sin(phi); \
+/* fisheye angle & radius */ \
+ float theta2 = atan2(vect_z, vect_x); \
+ float phi2 = atan2(hypot(vect_x, vect_z), vect_y); \
+ float r = radius_x * 2 * phi2 / FOV; \
+/* pixel in fisheye space */ \
+ float x_in = center_x2 + r * cos(theta2); \
+ float y_in = center_y2 + r * sin(theta2); \
+ \
+ BLEND_PIXEL(type, components) \
+ } \
+ } \
+ \
+ \
+}
+
+ COLORSPACE_SWITCH(PROCESS_STANDARD)
+}
+
+
+
+void Fuse360Unit::process_package(LoadPackage *package)
+{
+ Fuse360Package *pkg = (Fuse360Package*)package;
+
+ switch(plugin->config.mode)
+ {
+ case Fuse360Config::STRETCHXY:
+ process_stretch(pkg);
+ break;
+ case Fuse360Config::STANDARD:
+ process_standard(pkg);
+ break;
+ case Fuse360Config::BLEND:
+ process_blend(pkg);
+ break;
+ }
+}
+
+
+
+
+
+Fuse360Engine::Fuse360Engine(Fuse360Main *plugin)
+// : LoadServer(plugin->PluginClient::smp + 1, plugin->PluginClient::smp + 1)
+ : LoadServer(1, 1)
+{
+ this->plugin = plugin;
+}
+
+Fuse360Engine::~Fuse360Engine()
+{
+}
+
+void Fuse360Engine::init_packages()
+{
+ for(int i = 0; i < LoadServer::get_total_packages(); i++)
+ {
+ Fuse360Package *package = (Fuse360Package*)LoadServer::get_package(i);
+ package->row1 = plugin->get_input()->get_h() * i / LoadServer::get_total_packages();
+ package->row2 = plugin->get_input()->get_h() * (i + 1) / LoadServer::get_total_packages();
+ }
+}
+
+LoadClient* Fuse360Engine::new_client()
+{
+ return new Fuse360Unit(this, plugin);
+}
+
+LoadPackage* Fuse360Engine::new_package()
+{
+ return new Fuse360Package;
+}
+
+
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2017 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef FUSE360_H
+#define FUSE360_H
+
+
+#include "affine.inc"
+#include "bchash.inc"
+#include "guicast.h"
+#include "loadbalance.h"
+#include "pluginvclient.h"
+#include "thread.h"
+
+
+class SphereCamEngine;
+class SphereCamGUI;
+class SphereCamMain;
+class SphereCamText;
+
+#define EYES 2
+
+class SphereCamSlider : public BC_FSlider
+{
+public:
+ SphereCamSlider(SphereCamMain *client,
+ SphereCamGUI *gui,
+ SphereCamText *text,
+ float *output,
+ int x,
+ int y,
+ float min,
+ float max);
+ int handle_event();
+
+ SphereCamGUI *gui;
+ SphereCamMain *client;
+ SphereCamText *text;
+ float *output;
+};
+
+class SphereCamText : public BC_TextBox
+{
+public:
+ SphereCamText(SphereCamMain *client,
+ SphereCamGUI *gui,
+ SphereCamSlider *slider,
+ float *output,
+ int x,
+ int y);
+ int handle_event();
+
+ SphereCamGUI *gui;
+ SphereCamMain *client;
+ SphereCamSlider *slider;
+ float *output;
+};
+
+
+class SphereCamToggle : public BC_CheckBox
+{
+public:
+ SphereCamToggle(SphereCamMain *client,
+ int *output,
+ int x,
+ int y,
+ const char *text);
+ int handle_event();
+
+ SphereCamMain *client;
+ int *output;
+};
+
+
+class SphereCamMode : public BC_PopupMenu
+{
+public:
+ SphereCamMode(SphereCamMain *plugin,
+ SphereCamGUI *gui,
+ int x,
+ int y);
+ int handle_event();
+ void create_objects();
+ static int calculate_w(SphereCamGUI *gui);
+ static int from_text(char *text);
+ static const char* to_text(int mode);
+ void update(int mode);
+ SphereCamMain *plugin;
+ SphereCamGUI *gui;
+};
+
+
+class SphereCamGUI : public PluginClientWindow
+{
+public:
+ SphereCamGUI(SphereCamMain *client);
+ ~SphereCamGUI();
+
+ void create_objects();
+
+ SphereCamMain *client;
+ SphereCamToggle *enabled[EYES];
+ SphereCamSlider *fov_slider[EYES];
+ SphereCamText *fov_text[EYES];
+ SphereCamSlider *radius_slider[EYES];
+ SphereCamText *radius_text[EYES];
+ SphereCamSlider *centerx_slider[EYES];
+ SphereCamText *centerx_text[EYES];
+ SphereCamSlider *centery_slider[EYES];
+ SphereCamText *centery_text[EYES];
+ SphereCamSlider *rotatex_slider[EYES];
+ SphereCamText *rotatex_text[EYES];
+ SphereCamSlider *rotatey_slider[EYES];
+ SphereCamText *rotatey_text[EYES];
+ SphereCamSlider *rotatez_slider[EYES];
+ SphereCamText *rotatez_text[EYES];
+ SphereCamSlider *feather_slider;
+ SphereCamText *feather_text;
+
+ SphereCamMode *mode;
+ SphereCamToggle *draw_guides;
+};
+
+class SphereCamConfig
+{
+public:
+ SphereCamConfig();
+ int equivalent(SphereCamConfig &that);
+ void copy_from(SphereCamConfig &that);
+ void interpolate(SphereCamConfig &prev,
+ SphereCamConfig &next,
+ int64_t prev_frame,
+ int64_t next_frame,
+ int64_t current_frame);
+ void boundaries();
+
+
+ int enabled[EYES];
+// degrees 1-359
+ float fov[EYES];
+// radius of each eye 1-150
+ float radius[EYES];
+// center of 2 eyes 0-100
+ float center_x[EYES];
+ float center_y[EYES];
+// rotation 0-359
+ float rotate_x[EYES];
+ float rotate_y[EYES];
+ float rotate_z[EYES];
+// amount to feather eye edges 0-50
+ float feather;
+ int draw_guides;
+ int mode;
+ enum
+ {
+// draw guides only
+ DO_NOTHING,
+// the standard algorithm
+ EQUIRECT,
+// alignment only
+ ALIGN,
+ };
+};
+
+
+
+
+
+class SphereCamPackage : public LoadPackage
+{
+public:
+ SphereCamPackage();
+ int row1, row2;
+};
+
+
+class SphereCamUnit : public LoadClient
+{
+public:
+ SphereCamUnit(SphereCamEngine *engine, SphereCamMain *plugin);
+ ~SphereCamUnit();
+
+
+ void process_package(LoadPackage *package);
+ void process_equirect(SphereCamPackage *pkg);
+ void process_align(SphereCamPackage *pkg);
+ double calculate_max_z(double a, double r);
+
+
+ SphereCamEngine *engine;
+ SphereCamMain *plugin;
+};
+
+class SphereCamEngine : public LoadServer
+{
+public:
+ SphereCamEngine(SphereCamMain *plugin);
+ ~SphereCamEngine();
+
+ void init_packages();
+ LoadClient* new_client();
+ LoadPackage* new_package();
+
+ SphereCamMain *plugin;
+};
+
+class SphereCamMain : public PluginVClient
+{
+public:
+ SphereCamMain(PluginServer *server);
+ ~SphereCamMain();
+
+ PLUGIN_CLASS_MEMBERS2(SphereCamConfig)
+ int process_buffer(VFrame *frame,
+ int64_t start_position,
+ double frame_rate);
+ void draw_feather(int left, int right, int eye, int y);
+ int is_realtime();
+ void update_gui();
+ void save_data(KeyFrame *keyframe);
+ void read_data(KeyFrame *keyframe);
+ void calculate_extents();
+ double calculate_max_z(double a, int r);
+
+// config values converted to pixels
+ int w;
+ int h;
+
+// the center of the output regions, shifted by the rotations
+ int output_x[EYES];
+ int output_y[EYES];
+// The output of each eye is split into 2 halves so it can wrap around
+ int out_x1[EYES];
+ int out_y1[EYES];
+ int out_x2[EYES];
+ int out_y2[EYES];
+ int out_x3[EYES];
+ int out_y3[EYES];
+ int out_x4[EYES];
+ int out_y4[EYES];
+// the center of the input regions
+ int input_x[EYES];
+ int input_y[EYES];
+// radius of the input regions for drawing the guide only
+ int radius[EYES];
+// pixels to add to the output regions
+ int feather;
+
+ SphereCamEngine *engine;
+ AffineEngine *affine;
+};
+
+
+
+#endif
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 2017 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef FUSE360_H
+#define FUSE360_H
+
+
+#include "affine.inc"
+#include "bchash.inc"
+#include "guicast.h"
+#include "loadbalance.h"
+#include "pluginvclient.h"
+#include "thread.h"
+
+
+class Fuse360Engine;
+class Fuse360GUI;
+class Fuse360Main;
+class Fuse360Text;
+
+
+class Fuse360Slider : public BC_FSlider
+{
+public:
+ Fuse360Slider(Fuse360Main *client,
+ Fuse360GUI *gui,
+ Fuse360Text *text,
+ float *output,
+ int x,
+ int y,
+ float min,
+ float max);
+ int handle_event();
+
+ Fuse360GUI *gui;
+ Fuse360Main *client;
+ Fuse360Text *text;
+ float *output;
+};
+
+class Fuse360Text : public BC_TextBox
+{
+public:
+ Fuse360Text(Fuse360Main *client,
+ Fuse360GUI *gui,
+ Fuse360Slider *slider,
+ float *output,
+ int x,
+ int y);
+ int handle_event();
+
+ Fuse360GUI *gui;
+ Fuse360Main *client;
+ Fuse360Slider *slider;
+ float *output;
+};
+
+
+class Fuse360Toggle : public BC_CheckBox
+{
+public:
+ Fuse360Toggle(Fuse360Main *client,
+ int *output,
+ int x,
+ int y,
+ const char *text);
+ int handle_event();
+
+ Fuse360Main *client;
+ int *output;
+};
+
+
+class Fuse360Mode : public BC_PopupMenu
+{
+public:
+ Fuse360Mode(Fuse360Main *plugin,
+ Fuse360GUI *gui,
+ int x,
+ int y);
+ int handle_event();
+ void create_objects();
+ static int calculate_w(Fuse360GUI *gui);
+ static int from_text(char *text);
+ static const char* to_text(int mode);
+ void update(int mode);
+ Fuse360Main *plugin;
+ Fuse360GUI *gui;
+};
+
+
+class Fuse360GUI : public PluginClientWindow
+{
+public:
+ Fuse360GUI(Fuse360Main *client);
+ ~Fuse360GUI();
+
+ void create_objects();
+
+ Fuse360Main *client;
+// Fuse360Slider *fov_slider;
+// Fuse360Text *fov_text;
+ Fuse360Slider *radiusx_slider;
+ Fuse360Text *radiusx_text;
+ Fuse360Slider *radiusy_slider;
+ Fuse360Text *radiusy_text;
+// Fuse360Slider *centerx_slider;
+// Fuse360Text *centerx_text;
+// Fuse360Slider *centery_slider;
+// Fuse360Text *centery_text;
+ Fuse360Slider *distancex_slider;
+ Fuse360Text *distancex_text;
+ Fuse360Slider *distancey_slider;
+ Fuse360Text *distancey_text;
+ Fuse360Slider *translatex_slider;
+ Fuse360Text *translatex_text;
+ Fuse360Slider *feather_slider;
+ Fuse360Text *feather_text;
+ Fuse360Slider *rotation_slider;
+ Fuse360Text *rotation_text;
+
+ Fuse360Mode *mode;
+ Fuse360Toggle *draw_guides;
+};
+
+class Fuse360Config
+{
+public:
+ Fuse360Config();
+ int equivalent(Fuse360Config &that);
+ void copy_from(Fuse360Config &that);
+ void interpolate(Fuse360Config &prev,
+ Fuse360Config &next,
+ int64_t prev_frame,
+ int64_t next_frame,
+ int64_t current_frame);
+ void boundaries();
+
+
+
+ float fov;
+// radius of each eye
+ float radius_x;
+ float radius_y;
+// amount to feather eye edges
+ float feather;
+// center of 2 eyes
+ float center_x;
+ float center_y;
+// X distance between 2 eyes
+ float distance_x;
+// Y offset between 2 eyes
+ float distance_y;
+// translate output position
+ float translate_x;
+ float rotation;
+ int draw_guides;
+ int mode;
+ enum
+ {
+// align guides only
+ DO_NOTHING,
+// rectilinear
+ STRETCHXY,
+// the standard blend
+ STANDARD,
+// don't stretch eyes
+ BLEND
+ };
+};
+
+
+
+
+
+class Fuse360Package : public LoadPackage
+{
+public:
+ Fuse360Package();
+ int row1, row2;
+};
+
+
+class Fuse360Unit : public LoadClient
+{
+public:
+ Fuse360Unit(Fuse360Engine *engine, Fuse360Main *plugin);
+ ~Fuse360Unit();
+
+
+ void process_package(LoadPackage *package);
+ void process_stretch(Fuse360Package *pkg);
+ void process_blend(Fuse360Package *pkg);
+ void process_standard(Fuse360Package *pkg);
+ double calculate_max_z(double a, double r);
+
+
+ Fuse360Engine *engine;
+ Fuse360Main *plugin;
+};
+
+class Fuse360Engine : public LoadServer
+{
+public:
+ Fuse360Engine(Fuse360Main *plugin);
+ ~Fuse360Engine();
+
+ void init_packages();
+ LoadClient* new_client();
+ LoadPackage* new_package();
+
+ Fuse360Main *plugin;
+};
+
+class Fuse360Main : public PluginVClient
+{
+public:
+ Fuse360Main(PluginServer *server);
+ ~Fuse360Main();
+
+ PLUGIN_CLASS_MEMBERS2(Fuse360Config)
+ int process_buffer(VFrame *frame,
+ int64_t start_position,
+ double frame_rate);
+ int is_realtime();
+ void update_gui();
+ void save_data(KeyFrame *keyframe);
+ void read_data(KeyFrame *keyframe);
+ void calculate_extents();
+ double calculate_max_z(double a, int r);
+
+ int w;
+ int h;
+ int center_x;
+ int center_y;
+ int center_x1;
+ int center_y1;
+ int center_x2;
+ int center_y2;
+ int radius_x;
+ int radius_y;
+ int distance_x;
+ int distance_y;
+ int feather;
+ int feather_x1;
+ int feather_x2;
+
+ Fuse360Engine *engine;
+ AffineEngine *affine;
+};
+
+
+
+#endif
#include "filexml.h"
#include "guicast.h"
#include "language.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "swapframes.h"
#include "vframe.h"
*/
#include "histogramengine.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "vframe.h"
#include <stdio.h>
#include "histogramengine.inc"
#include "loadbalance.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "vframe.inc"
#include <stdint.h>
#include "filexml.h"
#include "histogramengine.h"
#include "language.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "threshold.h"
#include "thresholdwindow.h"
#include "vframe.h"
#include "histogramengine.inc"
#include "loadbalance.h"
#include "thresholdwindow.inc"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "filexml.h"
#include "keyframe.h"
#include "language.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "timeavg.h"
#include "timeavgwindow.h"
#include "transportque.h"
#include "guicast.h"
#include "loadbalance.h"
#include "overlayframe.inc"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "thread.h"
#include "vframe.inc"
TimeStretchRTConfig::TimeStretchRTConfig()
{
- scale = 1;
+// scale = 1;
+ num = 1;
+ denom = 1;
size = 40;
}
int TimeStretchRTConfig::equivalent(TimeStretchRTConfig &src)
{
- return fabs(scale - src.scale) < 0.0001 && size == src.size;
+// return fabs(scale - src.scale) < 0.0001 && size == src.size;
+ return fabs(num - src.num) < 0.0001 &&
+ fabs(denom - src.denom) < 0.0001 &&
+ size == src.size;
}
void TimeStretchRTConfig::copy_from(TimeStretchRTConfig &src)
{
- this->scale = src.scale;
+ this->num = src.num;
+ this->denom = src.denom;
+// this->scale = src.scale;
this->size = src.size;
}
int64_t next_frame,
int64_t current_frame)
{
- this->scale = prev.scale;
+ this->num = prev.num;
+ this->denom = prev.denom;
+// this->scale = prev.scale;
this->size = prev.size;
boundaries();
}
void TimeStretchRTConfig::boundaries()
{
- if(fabs(scale) < 0.01) scale = 0.01;
- if(fabs(scale) > 100) scale = 100;
+ if(num < 0.0001) num = 0.0001;
+ if(denom < 0.0001) denom = 0.0001;
+// if(fabs(scale) < 0.01) scale = 0.01;
+// if(fabs(scale) > 100) scale = 100;
if(size < 10) size = 10;
if(size > 1000) size = 1000;
}
TimeStretchRTWindow::TimeStretchRTWindow(TimeStretchRT *plugin)
: PluginClientWindow(plugin,
+ 210,
+ 200,
+ 200,
210,
- 160,
- 200,
- 160,
0)
{
this->plugin = plugin;
void TimeStretchRTWindow::create_objects()
{
int x = 10, y = 10;
+ int margin = plugin->get_theme()->widget_border;
BC_Title *title = 0;
- add_subwindow(title = new BC_Title(x, y, _("Fraction of original speed:")));
+ add_subwindow(title = new BC_Title(x, y, _("Input samples:")));
y += title->get_h() + plugin->get_theme()->widget_border;
- scale = new TimeStretchRTScale(this,
- plugin,
- x,
- y);
- scale->create_objects();
-
- y += scale->get_h() + plugin->get_theme()->widget_border;
- add_subwindow(title = new BC_Title(x, y, _("Window size (ms):")));
+ num = new TimeStretchRTScale(this,
+ plugin,
+ x,
+ y,
+ &plugin->config.num);
+ num->create_objects();
+ y += num->get_h() + margin;
+
+ add_subwindow(title = new BC_Title(x, y, _("Output samples:")));
y += title->get_h() + plugin->get_theme()->widget_border;
+ denom = new TimeStretchRTScale(this,
+ plugin,
+ x,
+ y,
+ &plugin->config.denom);
+ denom->create_objects();
+
+ y += denom->get_h() + margin;
+ add_subwindow(title = new BC_Title(x, y, _("Window size (ms):")));
+ y += title->get_h() + margin;
size = new TimeStretchRTSize(this,
plugin,
x,
TimeStretchRTScale::TimeStretchRTScale(TimeStretchRTWindow *window,
TimeStretchRT *plugin,
int x,
- int y)
+ int y,
+ double *value)
: BC_TumbleTextBox(window,
- (float)(1.0 / plugin->config.scale),
+ (float)*value,
(float)0.0001,
(float)1000,
x,
100)
{
this->plugin = plugin;
+ this->value = value;
set_increment(0.01);
}
int TimeStretchRTScale::handle_event()
{
- plugin->config.scale = 1.0 / atof(get_text());
+ *value = atof(get_text());
+ plugin->config.boundaries();
plugin->send_configure_change();
return 1;
}
{
need_reconfigure = load_configuration();
- if(!engine) engine = new TimeStretchEngine(config.scale,
+ if(!engine) engine = new TimeStretchEngine(config.denom / config.num,
sample_rate,
config.size);
// Get start position of the input.
// Sample 0 is the keyframe position
-//printf("TimeStretchRT::process_buffer %d %f\n", __LINE__, config.scale);
if(need_reconfigure)
{
int64_t prev_position = edl_to_local(
prev_position = get_source_start();
}
- source_start = (int64_t)((start_position - prev_position) /
- config.scale) + prev_position;
+ source_start = (int64_t)((start_position - prev_position) *
+ config.num / config.denom) + prev_position;
engine->reset();
- engine->update(config.scale, sample_rate, config.size);
+ engine->update(config.denom / config.num, sample_rate, config.size);
need_reconfigure = 0;
-//printf("TimeStretchRT::process_buffer %d start_position=" _LD
-// " prev_position=%jd scale=%f source_start=%jd\n",
-// __LINE__, start_position, prev_position, config.scale, source_start);
+// printf("TimeStretchRT::process_buffer %d start_position=%lld prev_position=%lld scale=%f source_start=%lld\n",
+// __LINE__,
+// start_position,
+// prev_position,
+// config.scale,
+// source_start);
}
// process buffers until output length is reached
// cause data to be stored directly in text
output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
output.tag.set_title("TIMESTRETCHRT");
- output.tag.set_property("SCALE", config.scale);
+ output.tag.set_property("NUM", config.num);
+ output.tag.set_property("DENOM", config.denom);
output.tag.set_property("SIZE", config.size);
output.append_tag();
output.tag.set_title("/TIMESTRETCHRT");
{
if(input.tag.title_is("TIMESTRETCHRT"))
{
- config.scale = input.tag.get_property("SCALE", config.scale);
+ config.num = input.tag.get_property("NUM", config.num);
+ config.denom = input.tag.get_property("DENOM", config.denom);
config.size = input.tag.get_property("SIZE", config.size);
}
}
{
thread->window->lock_window("TimeStretchRT::update_gui");
- ((TimeStretchRTWindow*)thread->window)->scale->update((float)(1.0 / config.scale));
+ ((TimeStretchRTWindow*)thread->window)->num->update((float)config.num);
+ ((TimeStretchRTWindow*)thread->window)->denom->update((float)config.denom);
((TimeStretchRTWindow*)thread->window)->size->update((int64_t)config.size);
thread->window->unlock_window();
}
int64_t prev_frame,
int64_t next_frame,
int64_t current_frame);
- double scale;
+// double scale;
+ double num;
+ double denom;
int size;
};
TimeStretchRTScale(TimeStretchRTWindow *window,
TimeStretchRT *plugin,
int x,
- int y);
+ int y,
+ double *value);
int handle_event();
TimeStretchRT *plugin;
+ double *value;
};
void create_objects();
TimeStretchRT *plugin;
- TimeStretchRTScale *scale;
+ TimeStretchRTScale *num;
+ TimeStretchRTScale *denom;
TimeStretchRTSize *size;
};
#include "guicast.h"
#include "language.h"
#include "loadbalance.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "fonts.h"
#include "scopewindow.h"
#include "filexml.h"
#include "guicast.h"
#include "language.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "vframe.h"
class YUVEngine;
#include "bcbase.h"
-#include "colors.h"
+#include "bccolors.h"
#include "yuvwindow.h"
#include "pluginvclient.h"
#include "mutex.h"
#include "pluginvclient.h"
#include "bctitle.h"
-#include "colors.h"
+#include "bccolors.h"
#include "fonts.h"
class yuv411Toggle;
#include "filexml.h"
#include "guicast.h"
#include "language.h"
-#include "cicolors.h"
+#include "bccolors.h"
#include "pluginvclient.h"
#include "vframe.h"
--- /dev/null
+diff -ur libXft-2.3.2.orig/src/xftdpy.c libXft-2.3.2/src/xftdpy.c
+--- libXft-2.3.2.orig/src/xftdpy.c 2014-06-06 00:05:07.000000000 -0600
++++ libXft-2.3.2/src/xftdpy.c 2017-10-17 08:55:30.227746279 -0600
+@@ -22,6 +22,11 @@
+
+ #include "xftint.h"
+
++#include <pthread.h>
++static pthread_mutex_t info_mutex = PTHREAD_MUTEX_INITIALIZER;
++static inline void info_lock() { pthread_mutex_lock(&info_mutex); }
++static inline void info_unlock() { pthread_mutex_unlock(&info_mutex); }
++
+ _X_HIDDEN XftDisplayInfo *_XftDisplayInfo;
+
+ static int
+@@ -48,10 +53,12 @@
+ /*
+ * Unhook from the global list
+ */
++ info_lock();
+ for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next)
+ if (info->display == dpy)
+ break;
+ *prev = info->next;
++ info_unlock();
+
+ free (info);
+ return 0;
+@@ -66,6 +73,7 @@
+ int i;
+ int event_base, error_base;
+
++ info_lock();
+ for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next)
+ {
+ if (info->display == dpy)
+@@ -79,9 +87,12 @@
+ info->next = _XftDisplayInfo;
+ _XftDisplayInfo = info;
+ }
++ info_unlock();
+ return info;
+ }
+ }
++ info_unlock();
++
+ if (!createIfNecessary)
+ return NULL;
+
+@@ -157,8 +168,10 @@
+ }
+ info->fonts = NULL;
+
++ info_lock();
+ info->next = _XftDisplayInfo;
+ _XftDisplayInfo = info;
++ info_unlock();
+
+ info->glyph_memory = 0;
+ info->max_glyph_memory = XftDefaultGetInteger (dpy,
+Only in libXft-2.3.2: tags