mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-14 03:39:57 +01:00
New support for AUDIO
Allows looking for audio streams in media files (settings) and enabling / disabling audio for each MediaPlayer individually. Control of volume per media, saving in session file.
This commit is contained in:
@@ -743,9 +743,13 @@ void ImGuiVisitor::visit (MediaSource& s)
|
||||
{
|
||||
if (ImGui::Selectable( ICON_FA_MICROCHIP " / " ICON_FA_COGS " Auto select", &hwdec ))
|
||||
mp->setSoftwareDecodingForced(false);
|
||||
if (ImGui::IsItemHovered() && !hwdec)
|
||||
ImGuiToolkit::ToolTip( "Changing decoding will\nre-open the media" );
|
||||
hwdec = mp->softwareDecodingForced();
|
||||
if (ImGui::Selectable( ICON_FA_COGS " Software only", &hwdec ))
|
||||
mp->setSoftwareDecodingForced(true);
|
||||
if (ImGui::IsItemHovered() && !hwdec)
|
||||
ImGuiToolkit::ToolTip( "Changing decoding will\nre-open the media" );
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
@@ -756,6 +760,47 @@ void ImGuiVisitor::visit (MediaSource& s)
|
||||
ImGui::TextDisabled("Hardware decoding disabled");
|
||||
}
|
||||
|
||||
// enable / disable audio if available
|
||||
if (mp->audioAvailable()) {
|
||||
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
if (ImGui::BeginCombo("Audio", mp->audioEnabled() ? ICON_FA_VOLUME_UP " Enabled" : ICON_FA_VOLUME_MUTE " Disabled" ) )
|
||||
{
|
||||
if (ImGui::Selectable( ICON_FA_VOLUME_UP " Enable", mp->audioEnabled() ))
|
||||
mp->setAudioEnabled(true);
|
||||
if (ImGui::IsItemHovered() && !mp->audioEnabled())
|
||||
ImGuiToolkit::ToolTip( "Changing audio will\nre-open the media" );
|
||||
|
||||
if (ImGui::Selectable( ICON_FA_VOLUME_MUTE " Disable", !mp->audioEnabled() ))
|
||||
mp->setAudioEnabled(false);
|
||||
if (ImGui::IsItemHovered() && mp->audioEnabled())
|
||||
ImGuiToolkit::ToolTip( "Changing audio will\nre-open the media" );
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (mp->audioEnabled()) {
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
///
|
||||
/// AUDIO VOLUME
|
||||
///
|
||||
int vol = mp->audioVolume();
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
if ( ImGui::SliderInt("##Volume", &vol, 0, 100, "%d%%") )
|
||||
mp->setAudioVolume(vol);
|
||||
if (ImGui::IsItemHovered() && io.MouseWheel != 0.f ){
|
||||
vol = CLAMP(vol + int(10.f * io.MouseWheel), 0, 100);
|
||||
mp->setAudioVolume(vol);
|
||||
}
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
if (ImGuiToolkit::TextButton("Volume")) {
|
||||
mp->setAudioVolume(100);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "BaseToolkit.h"
|
||||
#include "GstToolkit.h"
|
||||
#include "Metronome.h"
|
||||
#include "Settings.h"
|
||||
|
||||
#include "MediaPlayer.h"
|
||||
|
||||
@@ -72,6 +73,10 @@ MediaPlayer::MediaPlayer()
|
||||
position_ = GST_CLOCK_TIME_NONE;
|
||||
loop_ = LoopMode::LOOP_REWIND;
|
||||
|
||||
// default audio disabled
|
||||
audio_enabled_ = false;
|
||||
audio_volume_ = 100;
|
||||
|
||||
// start index in frame_ stack
|
||||
write_index_ = 0;
|
||||
last_index_ = 0;
|
||||
@@ -241,6 +246,11 @@ MediaInfo MediaPlayer::UriDiscoverer(const std::string &uri)
|
||||
video_stream_info.log = "No video stream";
|
||||
|
||||
gst_discoverer_stream_info_list_free(streams);
|
||||
|
||||
// test audio
|
||||
GList *audios = gst_discoverer_info_get_audio_streams(info);
|
||||
video_stream_info.hasaudio = g_list_length(audios) > 0 && Settings::application.accept_audio;
|
||||
gst_discoverer_stream_info_list_free(audios);
|
||||
}
|
||||
|
||||
if (info)
|
||||
@@ -347,6 +357,8 @@ void MediaPlayer::execute_open()
|
||||
gint flags;
|
||||
// ENABLE ONLY VIDEO, NOT AUDIO AND TEXT SUBTITLES
|
||||
flags = GST_PLAY_FLAG_VIDEO;
|
||||
if (media_.hasaudio && audio_enabled_)
|
||||
flags |= GST_PLAY_FLAG_AUDIO;
|
||||
// ENABLE DEINTERLACING
|
||||
if (media_.interlaced)
|
||||
flags |= GST_PLAY_FLAG_DEINTERLACE;
|
||||
@@ -467,6 +479,9 @@ void MediaPlayer::execute_open()
|
||||
Log::Info("MediaPlayer %s Timeline [%ld %ld] %ld frames, %d gaps", std::to_string(id_).c_str(),
|
||||
timeline_.begin(), timeline_.end(), timeline_.numFrames(), timeline_.numGaps());
|
||||
|
||||
if (media_.hasaudio)
|
||||
Log::Info("MediaPlayer %s Audio track %s", std::to_string(id_).c_str(), audio_enabled_ ? "enabled" : "disabled");
|
||||
|
||||
opened_ = true;
|
||||
|
||||
// register media player
|
||||
@@ -1660,6 +1675,34 @@ void MediaPlayer::TimeCounter::tic ()
|
||||
}
|
||||
|
||||
|
||||
void MediaPlayer::setAudioEnabled(bool on)
|
||||
{
|
||||
// in case of change
|
||||
if (audio_enabled_ != on) {
|
||||
// toggle
|
||||
audio_enabled_ = on;
|
||||
|
||||
// if openned
|
||||
if (media_.hasaudio ) {
|
||||
// apply
|
||||
reopen();
|
||||
// reset volume
|
||||
setAudioVolume(audio_volume_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPlayer::setAudioVolume(int vol)
|
||||
{
|
||||
// set value
|
||||
audio_volume_ = CLAMP(vol, 0, 100);
|
||||
|
||||
// apply value
|
||||
if (pipeline_ && media_.hasaudio)
|
||||
gst_stream_volume_set_volume (GST_STREAM_VOLUME (pipeline_), GST_STREAM_VOLUME_FORMAT_LINEAR, gdouble(audio_volume_) * 0.01);
|
||||
|
||||
}
|
||||
|
||||
//static void audio_changed_callback (GstElement *pipeline, MediaPlayer *mp)
|
||||
//{
|
||||
// gint n_audio;
|
||||
|
||||
@@ -37,6 +37,7 @@ struct MediaInfo {
|
||||
GstClockTime dt;
|
||||
GstClockTime end;
|
||||
std::string log;
|
||||
bool hasaudio;
|
||||
|
||||
MediaInfo() {
|
||||
width = par_width = 1;
|
||||
@@ -49,6 +50,7 @@ struct MediaInfo {
|
||||
interlaced = false;
|
||||
seekable = false;
|
||||
valid = false;
|
||||
hasaudio = false;
|
||||
dt = GST_CLOCK_TIME_NONE;
|
||||
end = GST_CLOCK_TIME_NONE;
|
||||
log = "";
|
||||
@@ -264,6 +266,15 @@ public:
|
||||
void setVideoEffect(const std::string &pipeline_element);
|
||||
inline std::string videoEffect() { return video_filter_; }
|
||||
inline bool videoEffectAvailable() { return video_filter_available_; }
|
||||
/**
|
||||
* Enables or disables audio
|
||||
* NB: setAudioEnabled reopens the video
|
||||
* */
|
||||
void setAudioEnabled(bool on);
|
||||
void setAudioVolume(int vol);
|
||||
inline bool audioEnabled() const { return audio_enabled_; }
|
||||
inline int audioVolume() const { return audio_volume_; }
|
||||
inline bool audioAvailable() const { return media_.hasaudio; }
|
||||
/**
|
||||
* Accept visitors
|
||||
* */
|
||||
@@ -309,6 +320,8 @@ private:
|
||||
bool enabled_;
|
||||
bool rewind_on_disable_;
|
||||
bool force_software_decoding_;
|
||||
bool audio_enabled_;
|
||||
int audio_volume_;
|
||||
std::string decoder_name_;
|
||||
bool video_filter_available_;
|
||||
std::string video_filter_;
|
||||
|
||||
@@ -894,6 +894,14 @@ void SessionLoader::visit(MediaPlayer &n)
|
||||
n.setTimeline(tl);
|
||||
}
|
||||
|
||||
// audio
|
||||
int audiovolume = 100;
|
||||
mediaplayerNode->QueryIntAttribute("audio_volume", &audiovolume);
|
||||
n.setAudioVolume(audiovolume);
|
||||
bool audioenabled = false;
|
||||
mediaplayerNode->QueryBoolAttribute("audio", &audioenabled);
|
||||
n.setAudioEnabled(audioenabled);
|
||||
|
||||
// change play rate: will be activated in SessionLoader::visit (MediaSource& s)
|
||||
double speed = 1.0;
|
||||
mediaplayerNode->QueryDoubleAttribute("speed", &speed);
|
||||
|
||||
@@ -423,6 +423,11 @@ void SessionVisitor::visit(MediaPlayer &n)
|
||||
XMLElement *newelement = xmlDoc_->NewElement("MediaPlayer");
|
||||
newelement->SetAttribute("id", n.id());
|
||||
|
||||
if (n.audioAvailable()) {
|
||||
newelement->SetAttribute("audio", n.audioEnabled());
|
||||
newelement->SetAttribute("audio_volume", n.audioVolume());
|
||||
}
|
||||
|
||||
if (!n.singleFrame()) {
|
||||
newelement->SetAttribute("loop", (int) n.loop());
|
||||
newelement->SetAttribute("speed", n.playSpeed());
|
||||
|
||||
@@ -144,6 +144,7 @@ void Settings::Save(uint64_t runtime)
|
||||
applicationNode->SetAttribute("broadcast_port", application.broadcast_port);
|
||||
applicationNode->SetAttribute("loopback_camera", application.loopback_camera);
|
||||
applicationNode->SetAttribute("shm_socket_path", application.shm_socket_path.c_str());
|
||||
applicationNode->SetAttribute("accept_audio", application.accept_audio);
|
||||
pRoot->InsertEndChild(applicationNode);
|
||||
|
||||
// Widgets
|
||||
@@ -437,6 +438,7 @@ void Settings::Load()
|
||||
applicationNode->QueryIntAttribute("stream_protocol", &application.stream_protocol);
|
||||
applicationNode->QueryIntAttribute("broadcast_port", &application.broadcast_port);
|
||||
applicationNode->QueryIntAttribute("loopback_camera", &application.loopback_camera);
|
||||
applicationNode->QueryBoolAttribute("accept_audio", &application.accept_audio);
|
||||
|
||||
// text attributes
|
||||
const char *tmpstr = applicationNode->Attribute("shm_socket_path");
|
||||
|
||||
@@ -295,6 +295,9 @@ struct Application
|
||||
int shm_method;
|
||||
std::string shm_socket_path;
|
||||
|
||||
// audio
|
||||
bool accept_audio;
|
||||
|
||||
// Settings of widgets
|
||||
WidgetsConfig widget;
|
||||
|
||||
@@ -369,6 +372,7 @@ struct Application
|
||||
windows = std::vector<WindowConfig>(1+MAX_OUTPUT_WINDOW);
|
||||
windows[0].w = 1600;
|
||||
windows[0].h = 900;
|
||||
accept_audio = true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -1511,6 +1511,10 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
||||
ImGui::PopStyleColor(1);
|
||||
|
||||
ImGui::SetCursorScreenPos(imgarea.GetTL() + ImVec2(h_space_, v_space_));
|
||||
if ( mediaplayer_active_->audioEnabled())
|
||||
// Icon to inform audio decoding
|
||||
ImGui::Text("%s " ICON_FA_VOLUME_UP, ms->initials());
|
||||
else
|
||||
ImGui::Text("%s", ms->initials());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
@@ -1532,6 +1536,12 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
||||
ImGui::SetCursorScreenPos(imgarea.GetTL() + ImVec2(h_space_, v_space_));
|
||||
ImGui::Text("%s", info_.str().c_str());
|
||||
|
||||
// Icon to inform audio decoding
|
||||
if ( mediaplayer_active_->audioEnabled()) {
|
||||
ImGui::SetCursorScreenPos(imgarea.GetTL() + ImVec2( imgarea.GetWidth() - 2.f * ImGui::GetTextLineHeightWithSpacing(), 0.35f * tooltip_height));
|
||||
ImGui::Text(ICON_FA_VOLUME_UP);
|
||||
}
|
||||
|
||||
// Icon to inform hardware decoding
|
||||
if ( mediaplayer_active_->decoderName().compare("software") != 0) {
|
||||
ImGui::SetCursorScreenPos(imgarea.GetTL() + ImVec2( imgarea.GetWidth() - ImGui::GetTextLineHeightWithSpacing(), 0.35f * tooltip_height));
|
||||
|
||||
@@ -5330,15 +5330,13 @@ void Navigator::RenderMainPannelSettings()
|
||||
// System preferences
|
||||
//
|
||||
ImGuiToolkit::Spacing();
|
||||
// ImGuiToolkit::HelpMarker("If you encounter some rendering issues on your machine, "
|
||||
// "you can try to disable some of the OpenGL optimizations below.");
|
||||
// ImGui::SameLine();
|
||||
ImGui::TextDisabled("System");
|
||||
|
||||
static bool need_restart = false;
|
||||
static bool vsync = (Settings::application.render.vsync > 0);
|
||||
static bool multi = (Settings::application.render.multisampling > 0);
|
||||
static bool gpu = Settings::application.render.gpu_decoding;
|
||||
static bool audio = Settings::application.accept_audio;
|
||||
bool change = false;
|
||||
// hardware support deserves more explanation
|
||||
ImGuiToolkit::Indication("If enabled, tries to find a platform adapted hardware-accelerated "
|
||||
@@ -5349,6 +5347,12 @@ void Navigator::RenderMainPannelSettings()
|
||||
else
|
||||
ImGui::TextDisabled("Hardware en/decoding unavailable");
|
||||
|
||||
// audio support deserves more explanation
|
||||
ImGuiToolkit::Indication("If enabled, tries to find audio in openned videos "
|
||||
"and allows enabling audio for each source.", ICON_FA_VOLUME_OFF);
|
||||
ImGui::SameLine(0);
|
||||
change |= ImGuiToolkit::ButtonSwitch( "Audio support", &audio);
|
||||
|
||||
#ifndef NDEBUG
|
||||
change |= ImGuiToolkit::ButtonSwitch( "Vertical synchronization", &vsync);
|
||||
change |= ImGuiToolkit::ButtonSwitch( "Multisample antialiasing", &multi);
|
||||
@@ -5356,7 +5360,8 @@ void Navigator::RenderMainPannelSettings()
|
||||
if (change) {
|
||||
need_restart = ( vsync != (Settings::application.render.vsync > 0) ||
|
||||
multi != (Settings::application.render.multisampling > 0) ||
|
||||
gpu != Settings::application.render.gpu_decoding );
|
||||
gpu != Settings::application.render.gpu_decoding ||
|
||||
audio != Settings::application.accept_audio );
|
||||
}
|
||||
if (need_restart) {
|
||||
ImGuiToolkit::Spacing();
|
||||
@@ -5364,6 +5369,7 @@ void Navigator::RenderMainPannelSettings()
|
||||
Settings::application.render.vsync = vsync ? 1 : 0;
|
||||
Settings::application.render.multisampling = multi ? 3 : 0;
|
||||
Settings::application.render.gpu_decoding = gpu;
|
||||
Settings::application.accept_audio = audio;
|
||||
if (UserInterface::manager().TryClose())
|
||||
Rendering::manager().close();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user