Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Multimedia
Kdenlive
Commits
9f3c1670
Commit
9f3c1670
authored
Oct 10, 2019
by
Jean-Baptiste Mardelle
Browse files
Audiomix merge
parent
0ce0f757
Changes
24
Hide whitespace changes
Inline
Side-by-side
src/CMakeLists.txt
View file @
9f3c1670
...
...
@@ -41,6 +41,7 @@ endif()
### Find source files
add_subdirectory
(
abstractmodel
)
add_subdirectory
(
assets
)
add_subdirectory
(
audiomixer
)
add_subdirectory
(
bin
)
add_subdirectory
(
capture
)
add_subdirectory
(
dialogs
)
...
...
src/audiomixer/CMakeLists.txt
0 → 100644
View file @
9f3c1670
set
(
kdenlive_SRCS
${
kdenlive_SRCS
}
audiomixer/mixerwidget.cpp
audiomixer/audiolevelwidget.cpp
audiomixer/mixermanager.cpp PARENT_SCOPE
)
src/audiomixer/audiolevelwidget.cpp
0 → 100644
View file @
9f3c1670
/*
Copyright (C) 2016 Jean-Baptiste Mardelle <jb@kdenlive.org>
This file is part of Kdenlive. See www.kdenlive.org.
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) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor approved
by the membership of KDE e.V.), which shall act as a proxy
defined in Section 14 of version 3 of the license.
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 <http://www.gnu.org/licenses/>.
*/
#include "audiolevelwidget.hpp"
#include "core.h"
#include "profiles/profilemodel.hpp"
#include "mlt++/Mlt.h"
#include <cmath>
#include <QFont>
#include <QPaintEvent>
#include <QPainter>
#include <QFontDatabase>
const
double
log_factor
=
1.0
/
log10
(
1.0
/
127
);
static
inline
double
levelToDB
(
double
level
)
{
if
(
level
<=
0
)
{
return
-
100
;
}
return
100
*
(
1.0
-
log10
(
level
)
*
log_factor
);
}
AudioLevelWidget
::
AudioLevelWidget
(
int
width
,
QWidget
*
parent
)
:
QWidget
(
parent
)
,
audioChannels
(
2
)
,
m_width
(
width
)
,
m_channelWidth
(
width
/
2
)
,
m_channelDistance
(
2
)
,
m_channelFillWidth
(
m_channelWidth
)
{
setSizePolicy
(
QSizePolicy
::
Preferred
,
QSizePolicy
::
MinimumExpanding
);
setFont
(
QFontDatabase
::
systemFont
(
QFontDatabase
::
SmallestReadableFont
));
QFont
ft
=
font
();
ft
.
setPointSizeF
(
font
().
pointSize
()
*
0.8
);
setFont
(
ft
);
setMinimumWidth
(
4
);
}
AudioLevelWidget
::~
AudioLevelWidget
()
{
}
void
AudioLevelWidget
::
resizeEvent
(
QResizeEvent
*
event
)
{
drawBackground
(
m_peaks
.
size
());
}
void
AudioLevelWidget
::
refreshPixmap
()
{
drawBackground
(
m_peaks
.
size
());
}
void
AudioLevelWidget
::
drawBackground
(
int
channels
)
{
if
(
height
()
==
0
)
{
return
;
}
QSize
newSize
=
QWidget
::
size
();
if
(
!
newSize
.
isValid
())
{
return
;
}
m_offset
=
fontMetrics
().
boundingRect
(
QStringLiteral
(
"-45"
)).
width
()
+
5
;
newSize
.
setWidth
(
newSize
.
width
()
-
m_offset
);
QLinearGradient
gradient
(
0
,
newSize
.
height
(),
0
,
0
);
gradient
.
setColorAt
(
0.0
,
Qt
::
darkGreen
);
gradient
.
setColorAt
(
0.379
,
Qt
::
darkGreen
);
gradient
.
setColorAt
(
0.38
,
Qt
::
green
);
// -20db
gradient
.
setColorAt
(
0.868
,
Qt
::
green
);
gradient
.
setColorAt
(
0.869
,
Qt
::
yellow
);
// -2db
gradient
.
setColorAt
(
0.95
,
Qt
::
yellow
);
gradient
.
setColorAt
(
0.951
,
Qt
::
red
);
// 0db
m_pixmap
=
QPixmap
(
QWidget
::
size
());
if
(
m_pixmap
.
isNull
())
{
return
;
}
m_pixmap
.
fill
(
Qt
::
transparent
);
int
totalWidth
;
if
(
channels
<
2
)
{
m_channelWidth
=
newSize
.
width
()
/
2
;
totalWidth
=
m_channelWidth
;
}
else
{
m_channelWidth
=
(
newSize
.
width
()
-
(
channels
-
1
))
/
channels
;
totalWidth
=
channels
*
m_channelWidth
+
(
channels
-
1
);
}
QRect
rect
(
m_offset
,
0
,
newSize
.
width
(),
newSize
.
height
());
QPainter
p
(
&
m_pixmap
);
p
.
setOpacity
(
0.4
);
p
.
setFont
(
font
());
p
.
fillRect
(
rect
,
QBrush
(
gradient
));
// Channel labels are vertical along the bottom.
QVector
<
int
>
dbscale
;
dbscale
<<
0
<<
-
2
<<
-
5
<<
-
10
<<
-
15
<<
-
20
<<
-
30
<<
-
45
;
int
dbLabelCount
=
dbscale
.
size
();
// dB scale is vertical along the bottom
int
labelHeight
=
fontMetrics
().
ascent
();
for
(
int
i
=
0
;
i
<
dbLabelCount
;
i
++
)
{
int
value
=
dbscale
.
at
(
i
);
QString
label
=
QString
().
sprintf
(
"%d"
,
value
);
//int labelWidth = fontMetrics().width(label);
double
xf
=
m_pixmap
.
height
()
-
pow
(
10.0
,
(
double
)
dbscale
.
at
(
i
)
/
50.0
)
*
m_pixmap
.
height
()
*
40.0
/
42
;
/*if (xf + labelWidth / 2 > m_pixmap.height()) {
xf = height() - labelWidth / 2;
}*/
p
.
setPen
(
palette
().
dark
().
color
());
p
.
drawLine
(
m_offset
,
xf
,
m_offset
+
totalWidth
-
1
,
xf
);
xf
-=
labelHeight
*
2
/
3
;
p
.
setPen
(
palette
().
text
().
color
().
rgb
());
p
.
drawText
(
QRectF
(
0
,
xf
,
m_offset
-
5
,
labelHeight
),
label
,
QTextOption
(
Qt
::
AlignRight
));
}
p
.
setOpacity
(
isEnabled
()
?
1
:
0.5
);
p
.
setPen
(
palette
().
dark
().
color
());
// Clear space between the 2 channels
p
.
setCompositionMode
(
QPainter
::
CompositionMode_Source
);
if
(
m_channelWidth
<
4
)
{
// too many audio channels, simple line between channels
m_channelDistance
=
1
;
m_channelFillWidth
=
m_channelWidth
;
for
(
int
i
=
0
;
i
<
channels
;
i
++
)
{
p
.
drawLine
(
m_offset
+
i
*
(
m_channelWidth
+
m_channelDistance
),
0
,
i
*
(
m_channelWidth
+
m_channelDistance
),
rect
.
height
()
-
1
);
}
}
else
{
m_channelDistance
=
2
;
m_channelFillWidth
=
m_channelWidth
-
2
;
for
(
int
i
=
0
;
i
<
channels
;
i
++
)
{
p
.
drawRect
(
m_offset
+
i
*
(
m_channelWidth
+
m_channelDistance
),
0
,
m_channelWidth
-
1
,
rect
.
height
()
-
1
);
if
(
i
>
0
)
{
p
.
fillRect
(
m_offset
+
i
*
(
m_channelWidth
+
m_channelDistance
)
-
2
,
0
,
2
,
rect
.
height
(),
Qt
::
transparent
);
}
}
}
p
.
end
();
}
// cppcheck-suppress unusedFunction
void
AudioLevelWidget
::
setAudioValues
(
const
QVector
<
int
>
&
values
)
{
m_values
=
values
;
if
(
m_peaks
.
size
()
!=
m_values
.
size
())
{
m_peaks
=
values
;
drawBackground
(
values
.
size
());
}
else
{
for
(
int
i
=
0
;
i
<
m_values
.
size
();
i
++
)
{
m_peaks
[
i
]
--
;
if
(
m_values
.
at
(
i
)
>
m_peaks
.
at
(
i
))
{
m_peaks
[
i
]
=
m_values
.
at
(
i
);
}
}
}
update
();
}
void
AudioLevelWidget
::
setVisibility
(
bool
enable
)
{
if
(
enable
)
{
setVisible
(
true
);
setFixedWidth
(
m_width
);
}
else
{
// set height to 0 so the toolbar layout is not affected
setFixedHeight
(
0
);
setVisible
(
false
);
}
}
void
AudioLevelWidget
::
paintEvent
(
QPaintEvent
*
pe
)
{
if
(
!
isVisible
())
{
return
;
}
QPainter
p
(
this
);
p
.
setClipRect
(
pe
->
rect
());
QRect
rect
(
0
,
0
,
width
(),
height
());
if
(
m_values
.
isEmpty
())
{
p
.
setOpacity
(
0.2
);
p
.
drawPixmap
(
rect
,
m_pixmap
);
return
;
}
p
.
drawPixmap
(
rect
,
m_pixmap
);
p
.
setPen
(
palette
().
dark
().
color
());
p
.
setOpacity
(
0.9
);
int
width
=
m_channelDistance
==
1
?
rect
.
width
()
:
rect
.
width
()
-
1
;
for
(
int
i
=
0
;
i
<
m_values
.
count
();
i
++
)
{
if
(
m_values
.
at
(
i
)
>=
100
)
{
continue
;
}
int
val
=
(
50
+
m_values
.
at
(
i
))
/
150.0
*
rect
.
height
();
p
.
fillRect
(
m_offset
+
i
*
(
m_channelWidth
+
m_channelDistance
)
+
1
,
0
,
m_channelFillWidth
,
height
()
-
val
,
palette
().
dark
());
p
.
fillRect
(
m_offset
+
i
*
(
m_channelWidth
+
m_channelDistance
)
+
1
,
height
()
-
(
50
+
m_peaks
.
at
(
i
))
/
150.0
*
rect
.
height
(),
m_channelFillWidth
,
1
,
palette
().
text
());
}
}
src/audiomixer/audiolevelwidget.hpp
0 → 100644
View file @
9f3c1670
/*
Copyright (C) 2016 Jean-Baptiste Mardelle <jb@kdenlive.org>
This file is part of Kdenlive. See www.kdenlive.org.
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) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor approved
by the membership of KDE e.V.), which shall act as a proxy
defined in Section 14 of version 3 of the license.
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 <http://www.gnu.org/licenses/>.
*/
#ifndef AUDIOLEVELWIDGET_H
#define AUDIOLEVELWIDGET_H
#include <QWidget>
#include <memory>
namespace
Mlt
{
class
Filter
;
}
// namespace Mlt
class
AudioLevelWidget
:
public
QWidget
{
Q_OBJECT
public:
explicit
AudioLevelWidget
(
int
width
,
QWidget
*
parent
=
nullptr
);
~
AudioLevelWidget
()
override
;
void
refreshPixmap
();
int
audioChannels
;
bool
isValid
;
void
setVisibility
(
bool
enable
);
protected:
void
paintEvent
(
QPaintEvent
*
)
override
;
void
resizeEvent
(
QResizeEvent
*
event
)
override
;
private:
std
::
unique_ptr
<
Mlt
::
Filter
>
m_filter
;
int
m_width
;
int
m_offset
;
QPixmap
m_pixmap
;
QVector
<
int
>
m_peaks
;
QVector
<
int
>
m_values
;
int
m_channelWidth
;
int
m_channelDistance
;
int
m_channelFillWidth
;
void
drawBackground
(
int
channels
=
2
);
public
slots
:
void
setAudioValues
(
const
QVector
<
int
>
&
values
);
};
#endif
src/audiomixer/mixermanager.cpp
0 → 100644
View file @
9f3c1670
/***************************************************************************
* Copyright (C) 2019 by Jean-Baptiste Mardelle *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* 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) version 3 or any later version accepted by the *
* membership of KDE e.V. (or its successor approved by the membership *
* of KDE e.V.), which shall act as a proxy defined in Section 14 of *
* version 3 of the license. *
* *
* 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 <http://www.gnu.org/licenses/>. *
***************************************************************************/
#include "mixermanager.hpp"
#include "mixerwidget.hpp"
#include "timeline2/model/timelineitemmodel.hpp"
#include "mlt++/MltService.h"
#include "mlt++/MltTractor.h"
#include <klocalizedstring.h>
#include <QHBoxLayout>
#include <QModelIndex>
const
double
log_factor
=
1.0
/
log10
(
1.0
/
127
);
static
inline
double
levelToDB
(
double
level
)
{
if
(
level
<=
0
)
{
return
-
100
;
}
return
100
*
(
1.0
-
log10
(
level
)
*
log_factor
);
}
MixerManager
::
MixerManager
(
QWidget
*
parent
)
:
QWidget
(
parent
)
,
renderPosition
(
0
)
,
m_connectedWidgets
(
0
)
{
m_box
=
new
QHBoxLayout
;
m_box
->
addStretch
(
10
);
setLayout
(
m_box
);
m_timer
.
setSingleShot
(
true
);
m_timer
.
setInterval
(
100
);
connect
(
&
m_timer
,
&
QTimer
::
timeout
,
[
&
]
()
{
for
(
auto
w
:
m_mixers
)
{
w
.
second
->
updateAudioLevel
(
m_lastFrame
);
}
});
}
void
MixerManager
::
registerTrack
(
int
tid
,
std
::
shared_ptr
<
Mlt
::
Tractor
>
service
,
const
QString
&
trackTag
)
{
if
(
m_mixers
.
count
(
tid
)
>
0
)
{
// Track already registered
return
;
}
std
::
shared_ptr
<
MixerWidget
>
mixer
(
new
MixerWidget
(
tid
,
service
,
trackTag
,
this
));
connect
(
mixer
.
get
(),
&
MixerWidget
::
muteTrack
,
[
&
](
int
id
,
bool
mute
)
{
m_model
->
setTrackProperty
(
id
,
"hide"
,
mute
?
QStringLiteral
(
"1"
)
:
QStringLiteral
(
"3"
));
});
connect
(
this
,
&
MixerManager
::
updateLevels
,
mixer
.
get
(),
&
MixerWidget
::
updateAudioLevel
);
connect
(
mixer
.
get
(),
&
MixerWidget
::
updateConnection
,
[
&
](
int
id
,
bool
doConnect
)
{
//connect(this, &MixerManager::storeLevels, m_mixers[id].get(), &MixerWidget::storeAudioLevel, Qt::DirectConnection);
m_connectedWidgets
++
;
if
(
m_connectedWidgets
==
1
)
{
emit
connectMixerRenderer
(
true
);
}
});
connect
(
mixer
.
get
(),
&
MixerWidget
::
toggleSolo
,
[
&
](
int
trid
,
bool
solo
)
{
if
(
!
solo
)
{
// unmute
for
(
int
id
:
m_soloMuted
)
{
if
(
m_mixers
.
count
(
id
)
>
0
)
{
m_model
->
setTrackProperty
(
id
,
"hide"
,
QStringLiteral
(
"1"
));
}
}
m_soloMuted
.
clear
();
}
else
{
if
(
!
m_soloMuted
.
isEmpty
())
{
// Another track was solo, discard first
for
(
int
id
:
m_soloMuted
)
{
if
(
m_mixers
.
count
(
id
)
>
0
)
{
m_model
->
setTrackProperty
(
id
,
"hide"
,
QStringLiteral
(
"1"
));
}
}
m_soloMuted
.
clear
();
}
for
(
auto
item
:
m_mixers
)
{
if
(
item
.
first
>
-
1
&&
item
.
first
!=
trid
&&
!
item
.
second
->
isMute
())
{
m_model
->
setTrackProperty
(
item
.
first
,
"hide"
,
QStringLiteral
(
"3"
));
m_soloMuted
<<
item
.
first
;
item
.
second
->
unSolo
();
}
}
}
});
m_mixers
[
tid
]
=
mixer
;
m_box
->
insertWidget
(
0
,
mixer
.
get
());
}
void
MixerManager
::
deregisterTrack
(
int
tid
)
{
Q_ASSERT
(
m_mixers
.
count
(
tid
)
>
0
);
m_mixers
.
erase
(
tid
);
}
void
MixerManager
::
resetAudioValues
()
{
qDebug
()
<<
"======
\n\n
RESTTING AUDIO VALUES
\n\n
------------------_"
;
for
(
auto
item
:
m_mixers
)
{
item
.
second
.
get
()
->
clear
();
}
}
void
MixerManager
::
cleanup
()
{
for
(
auto
item
:
m_mixers
)
{
m_box
->
removeWidget
(
item
.
second
.
get
());
}
m_mixers
.
clear
();
m_connectedWidgets
=
0
;
}
void
MixerManager
::
setModel
(
std
::
shared_ptr
<
TimelineItemModel
>
model
)
{
// Insert master mixer
int
tid
=
-
1
;
m_model
=
model
;
connect
(
m_model
.
get
(),
&
TimelineItemModel
::
dataChanged
,
[
&
](
const
QModelIndex
&
topLeft
,
const
QModelIndex
&
bottomRight
,
const
QVector
<
int
>
&
roles
)
{
if
(
roles
.
contains
(
TimelineModel
::
IsDisabledRole
))
{
int
id
=
(
int
)
topLeft
.
internalId
();
if
(
m_mixers
.
count
(
id
)
>
0
)
{
m_mixers
[
id
]
->
setMute
(
m_model
->
data
(
topLeft
,
TimelineModel
::
IsDisabledRole
).
toBool
());
}
else
{
qDebug
()
<<
"=== MODEL DATA CHANGED: MUTE DONE TRACK NOT FOUND!!!"
;
}
}
});
Mlt
::
Tractor
*
service
=
model
->
tractor
();
if
(
m_mixers
.
count
(
tid
)
>
0
)
{
// delete previous master mixer
m_box
->
removeWidget
(
m_mixers
[
tid
].
get
());
m_mixers
.
erase
(
tid
);
}
std
::
shared_ptr
<
MixerWidget
>
mixer
(
new
MixerWidget
(
tid
,
service
,
i18n
(
"Master"
),
this
));
connect
(
mixer
.
get
(),
&
MixerWidget
::
muteTrack
,
[
&
](
int
/*id*/
,
bool
mute
)
{
qDebug
()
<<
"=== SETTING MUITE"
;
m_model
->
tractor
()
->
set
(
"hide"
,
mute
?
3
:
1
);
});
connect
(
this
,
&
MixerManager
::
updateLevels
,
mixer
.
get
(),
&
MixerWidget
::
updateAudioLevel
);
connect
(
mixer
.
get
(),
&
MixerWidget
::
updateConnection
,
[
&
](
int
id
,
bool
doConnect
)
{
//connect(this, &MixerManager::storeLevels, m_mixers[id].get(), &MixerWidget::storeAudioLevel, Qt::DirectConnection);
m_connectedWidgets
++
;
if
(
m_connectedWidgets
==
1
)
{
emit
connectMixerRenderer
(
true
);
}
});
m_mixers
[
tid
]
=
mixer
;
m_box
->
insertWidget
(
0
,
mixer
.
get
());
}
src/audiomixer/mixermanager.hpp
0 → 100644
View file @
9f3c1670
/***************************************************************************
* Copyright (C) 2019 by Jean-Baptiste Mardelle *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* 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) version 3 or any later version accepted by the *
* membership of KDE e.V. (or its successor approved by the membership *
* of KDE e.V.), which shall act as a proxy defined in Section 14 of *
* version 3 of the license. *
* *
* 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 <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef MIXERMANGER_H
#define MIXERMANGER_H
#include "definitions.h"
#include <memory>
#include <unordered_map>
#include <QWidget>
#include <QTimer>
namespace
Mlt
{
class
Tractor
;
}
class
MixerWidget
;
class
QHBoxLayout
;
class
TimelineItemModel
;
class
MixerManager
:
public
QWidget
{
Q_OBJECT
public:
MixerManager
(
QWidget
*
parent
);
/* @brief Shows the parameters of the given transition model */
void
registerTrack
(
int
tid
,
std
::
shared_ptr
<
Mlt
::
Tractor
>
service
,
const
QString
&
trackTag
);
void
deregisterTrack
(
int
tid
);
void
setModel
(
std
::
shared_ptr
<
TimelineItemModel
>
model
);
void
cleanup
();
public
slots
:
void
resetAudioValues
();
signals:
void
updateLevels
(
int
);
void
connectMixerRenderer
(
bool
);
void
triggerUpdate
();
public:
int
renderPosition
;
protected:
std
::
unordered_map
<
int
,
std
::
shared_ptr
<
MixerWidget
>>
m_mixers
;
private:
std
::
shared_ptr
<
Mlt
::
Tractor
>
m_masterService
;
std
::
shared_ptr
<
TimelineItemModel
>
m_model
;
QHBoxLayout
*
m_box
;
QTimer
m_timer
;
int
m_lastFrame
;
int
m_connectedWidgets
;
QVector
<
int
>
m_soloMuted
;
};
#endif
src/audiomixer/mixerwidget.cpp
0 → 100644
View file @
9f3c1670
/***************************************************************************
* Copyright (C) 2019 by Jean-Baptiste Mardelle *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* 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) version 3 or any later version accepted by the *
* membership of KDE e.V. (or its successor approved by the membership *
* of KDE e.V.), which shall act as a proxy defined in Section 14 of *
* version 3 of the license. *
* *
* 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 <http://www.gnu.org/licenses/>. *
***************************************************************************/
#include "mixerwidget.hpp"
#include "mlt++/MltFilter.h"
#include "mlt++/MltTractor.h"
#include "mlt++/MltProfile.h"
#include "mixerwidget.hpp"
#include "mixermanager.hpp"
#include "audiolevelwidget.hpp"
#include <klocalizedstring.h>
#include <KDualAction>
#include <QGridLayout>
#include <QToolButton>
#include <QCheckBox>
#include <QSlider>
#include <QSpinBox>
#include <QDial>
#include <QLabel>
#include <QFontDatabase>
const
double
log_factor
=
1.0
/
log10
(
1.0
/
127
);
static
inline
int
levelToDB
(
double
level
)
{
if
(
level
<=
0
)
{
return
-
100
;
}
return
100
*
(
1.0
-
log10
(
level
)
*
log_factor
);
}
void
MixerWidget
::
property_changed
(
mlt_service
,
MixerWidget
*
widget
,
char
*
/*name*/
)
{
if
(
!
widget
->
m_levels
.
contains
(
widget
->
m_manager
->
renderPosition
))
{
widget
->
m_levels
[
widget
->
m_manager
->
renderPosition
]
=
{
levelToDB
(
mlt_properties_get_double
(
MLT_FILTER_PROPERTIES
(
widget
->
m_monitorFilter
->
get_filter
()),
"_audio_level.0"
)),
levelToDB
(
mlt_properties_get_double
(
MLT_FILTER_PROPERTIES
(
widget
->
m_monitorFilter
->
get_filter
()),
"_audio_level.1"
))};