mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-12 18:59:59 +01:00
All filters now derive from FrameBufferFilter, which is always used in a CloneSource. Default FrameBufferFilter is Passthrough filter. Others are Delay and Image filters. Implemented UI selection of filter type, XML session save and load. Linked ImageFilter to Code editor.
230 lines
5.6 KiB
C++
230 lines
5.6 KiB
C++
/*
|
|
* This file is part of vimix - video live mixer
|
|
*
|
|
* **Copyright** (C) 2019-2022 Bruno Herbelin <bruno.herbelin@gmail.com>
|
|
*
|
|
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
|
**/
|
|
|
|
#include <gst/gst.h>
|
|
|
|
#include <glm/gtc/matrix_access.hpp>
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
|
|
#include "Log.h"
|
|
#include "defines.h"
|
|
#include "Resource.h"
|
|
#include "Decorations.h"
|
|
#include "Visitor.h"
|
|
#include "FrameBuffer.h"
|
|
#include "FrameBufferFilter.h"
|
|
#include "DelayFilter.h"
|
|
#include "ImageFilter.h"
|
|
|
|
#include "CloneSource.h"
|
|
|
|
CloneSource::CloneSource(Source *origin, uint64_t id) : Source(id), origin_(origin), paused_(false), filter_(nullptr)
|
|
{
|
|
// initial name copies the origin name: diplucates are namanged in session
|
|
name_ = origin->name();
|
|
|
|
// set symbol
|
|
symbol_ = new Symbol(Symbol::CLONE, glm::vec3(0.75f, 0.75f, 0.01f));
|
|
symbol_->scale_.y = 1.5f;
|
|
|
|
// init connecting line
|
|
connection_ = new DotLine;
|
|
connection_->color = glm::vec4(COLOR_HIGHLIGHT_SOURCE, 0.6f);
|
|
connection_->target = origin->groups_[View::MIXING]->translation_;
|
|
groups_[View::MIXING]->attach(connection_);
|
|
|
|
// default to pass-through filter
|
|
filter_ = new PassthroughFilter;
|
|
}
|
|
|
|
CloneSource::~CloneSource()
|
|
{
|
|
if (origin_)
|
|
origin_->clones_.remove(this);
|
|
|
|
delete filter_;
|
|
}
|
|
|
|
void CloneSource::init()
|
|
{
|
|
if (origin_ && origin_->ready_ && origin_->mode_ > Source::UNINITIALIZED && origin_->renderbuffer_) {
|
|
|
|
// create render Frame buffer matching size of images
|
|
FrameBuffer *renderbuffer = new FrameBuffer( origin_->frame()->resolution(), origin_->frame()->use_alpha() );
|
|
|
|
// set the renderbuffer of the source and attach rendering nodes
|
|
attach(renderbuffer);
|
|
|
|
// force update of activation mode
|
|
active_ = true;
|
|
|
|
// deep update to reorder
|
|
++View::need_deep_update_;
|
|
|
|
// done init
|
|
Log::Info("Source '%s' cloning source '%s'.", name().c_str(), origin_->name().c_str() );
|
|
}
|
|
}
|
|
|
|
void CloneSource::render()
|
|
{
|
|
if ( renderbuffer_ == nullptr )
|
|
init();
|
|
else {
|
|
|
|
// render filter image
|
|
filter_->draw( origin_->frame() );
|
|
|
|
// ensure correct output texture is displayed (could have changed if filter changed)
|
|
texturesurface_->setTextureIndex( filter_->texture() );
|
|
|
|
// render textured surface into frame buffer
|
|
renderbuffer_->begin();
|
|
texturesurface_->draw(glm::identity<glm::mat4>(), renderbuffer_->projection());
|
|
renderbuffer_->end();
|
|
ready_ = true;
|
|
}
|
|
}
|
|
|
|
void CloneSource::setActive (bool on)
|
|
{
|
|
// try to activate (may fail if source is cloned)
|
|
Source::setActive(on);
|
|
|
|
if (origin_) {
|
|
|
|
if ( mode_ > Source::UNINITIALIZED )
|
|
origin_->touch();
|
|
|
|
// change visibility of active surface (show preview of origin when inactive)
|
|
if (activesurface_) {
|
|
if (active_)
|
|
activesurface_->setTextureIndex(Resource::getTextureTransparent());
|
|
else
|
|
activesurface_->setTextureIndex(renderbuffer_->texture());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CloneSource::update(float dt)
|
|
{
|
|
Source::update(dt);
|
|
|
|
if (origin_) {
|
|
|
|
if (!paused_ && active_)
|
|
filter_->update(dt);
|
|
|
|
// update connection line target to position of origin source
|
|
connection_->target = glm::inverse( GlmToolkit::transform(groups_[View::MIXING]->translation_, glm::vec3(0), groups_[View::MIXING]->scale_) ) *
|
|
glm::vec4(origin_->groups_[View::MIXING]->translation_, 1.f);
|
|
}
|
|
}
|
|
|
|
void CloneSource::setFilter(FrameBufferFilter::Type T)
|
|
{
|
|
if (filter_)
|
|
delete filter_;
|
|
|
|
switch (T)
|
|
{
|
|
case FrameBufferFilter::FILTER_DELAY:
|
|
filter_ = new DelayFilter;
|
|
break;
|
|
case FrameBufferFilter::FILTER_IMAGE:
|
|
filter_ = new ImageFilter;
|
|
break;
|
|
default:
|
|
case FrameBufferFilter::FILTER_PASSTHROUGH:
|
|
filter_ = new PassthroughFilter;
|
|
break;
|
|
}
|
|
|
|
|
|
// TODO : resampling of renderbuffer
|
|
|
|
}
|
|
|
|
void CloneSource::play (bool on)
|
|
{
|
|
// if a different state is asked
|
|
if (paused_ == on) {
|
|
|
|
// play / pause filter to suspend clone
|
|
filter_->setEnabled( on );
|
|
|
|
// restart clean if was paused
|
|
if (paused_)
|
|
replay();
|
|
|
|
// toggle state
|
|
paused_ = !on;
|
|
}
|
|
}
|
|
|
|
bool CloneSource::playable () const
|
|
{
|
|
if (filter_ && filter_->enabled())
|
|
return true;
|
|
|
|
if (origin_)
|
|
return origin_->playable();
|
|
|
|
return false;
|
|
}
|
|
|
|
void CloneSource::replay()
|
|
{
|
|
// TODO: add reset to Filter
|
|
|
|
}
|
|
|
|
guint64 CloneSource::playtime () const
|
|
{
|
|
// TODO : get time of ImageFilter? Get Delay ?
|
|
|
|
return origin_->playtime();
|
|
}
|
|
|
|
|
|
uint CloneSource::texture() const
|
|
{
|
|
if (origin_)
|
|
return origin_->frame()->texture();
|
|
else
|
|
return Resource::getTextureBlack();
|
|
}
|
|
|
|
void CloneSource::accept(Visitor& v)
|
|
{
|
|
Source::accept(v);
|
|
if (!failed())
|
|
v.visit(*this);
|
|
}
|
|
|
|
glm::ivec2 CloneSource::icon() const
|
|
{
|
|
return glm::ivec2(ICON_SOURCE_CLONE);
|
|
}
|
|
|
|
std::string CloneSource::info() const
|
|
{
|
|
return "Clone";
|
|
}
|