File indexing completed on 2024-05-19 04:49:56
0001 /**************************************************************************************** 0002 * Copyright (c) 2008-2012 Soren Harward <stharward@gmail.com> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify it under * 0005 * the terms of the GNU General Public License as published by the Free Software * 0006 * Foundation; either version 2 of the License, or (at your option) any later * 0007 * version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0012 * * 0013 * You should have received a copy of the GNU General Public License along with * 0014 * this program. If not, see <http://www.gnu.org/licenses/>. * 0015 ****************************************************************************************/ 0016 0017 #define DEBUG_PREFIX "Constraint::PlaylistDuration" 0018 0019 #include "PlaylistDuration.h" 0020 0021 #include "core/meta/Meta.h" 0022 #include "playlistgenerator/Constraint.h" 0023 #include "playlistgenerator/ConstraintFactory.h" 0024 0025 #include <cmath> 0026 #include <cstdlib> 0027 0028 Constraint* 0029 ConstraintTypes::PlaylistDuration::createFromXml( QDomElement& xmlelem, ConstraintNode* p ) 0030 { 0031 if ( p ) { 0032 return new PlaylistDuration( xmlelem, p ); 0033 } else { 0034 return nullptr; 0035 } 0036 } 0037 0038 Constraint* 0039 ConstraintTypes::PlaylistDuration::createNew( ConstraintNode* p ) 0040 { 0041 if ( p ) { 0042 return new PlaylistDuration( p ); 0043 } else { 0044 return nullptr; 0045 } 0046 } 0047 0048 ConstraintFactoryEntry* 0049 ConstraintTypes::PlaylistDuration::registerMe() 0050 { 0051 return new ConstraintFactoryEntry( QStringLiteral("PlaylistDuration"), 0052 i18n("Playlist Duration"), 0053 i18n("Sets the preferred duration of the playlist"), 0054 &PlaylistDuration::createFromXml, &PlaylistDuration::createNew ); 0055 } 0056 0057 ConstraintTypes::PlaylistDuration::PlaylistDuration( QDomElement& xmlelem, ConstraintNode* p ) 0058 : Constraint( p ) 0059 , m_duration( 0 ) 0060 , m_comparison( CompareNumEquals ) 0061 , m_strictness( 1.0 ) 0062 { 0063 QDomAttr a; 0064 0065 a = xmlelem.attributeNode( QStringLiteral("duration") ); 0066 if ( !a.isNull() ) { 0067 m_duration = a.value().toInt(); 0068 } else { 0069 // Accommodate schema change when PlaylistLength became PlaylistDuration 0070 a = xmlelem.attributeNode( QStringLiteral("length") ); 0071 if ( !a.isNull() ) 0072 m_duration = a.value().toInt(); 0073 } 0074 0075 0076 a = xmlelem.attributeNode( QStringLiteral("comparison") ); 0077 if ( !a.isNull() ) 0078 m_comparison = a.value().toInt(); 0079 0080 a = xmlelem.attributeNode( QStringLiteral("strictness") ); 0081 if ( !a.isNull() ) 0082 m_strictness = a.value().toDouble(); 0083 } 0084 0085 ConstraintTypes::PlaylistDuration::PlaylistDuration( ConstraintNode* p ) 0086 : Constraint( p ) 0087 , m_duration( 0 ) 0088 , m_comparison( CompareNumEquals ) 0089 , m_strictness( 1.0 ) 0090 { 0091 } 0092 0093 QWidget* 0094 ConstraintTypes::PlaylistDuration::editWidget() const 0095 { 0096 PlaylistDurationEditWidget* e = new PlaylistDurationEditWidget( m_duration, m_comparison, static_cast<int>( 10*m_strictness ) ); 0097 connect( e, &PlaylistDurationEditWidget::comparisonChanged, this, &PlaylistDuration::setComparison ); 0098 connect( e, &PlaylistDurationEditWidget::durationChanged, this, &PlaylistDuration::setDuration ); 0099 connect( e, &PlaylistDurationEditWidget::strictnessChanged, this, &PlaylistDuration::setStrictness ); 0100 return e; 0101 } 0102 0103 void 0104 ConstraintTypes::PlaylistDuration::toXml( QDomDocument& doc, QDomElement& elem ) const 0105 { 0106 QDomElement c = doc.createElement( QStringLiteral("constraint") ); 0107 c.setAttribute( QStringLiteral("type"), QStringLiteral("PlaylistDuration") ); 0108 c.setAttribute( QStringLiteral("duration"), QString::number( m_duration ) ); 0109 c.setAttribute( QStringLiteral("comparison"), QString::number( m_comparison ) ); 0110 c.setAttribute( QStringLiteral("strictness"), QString::number( m_strictness ) ); 0111 elem.appendChild( c ); 0112 } 0113 0114 QString 0115 ConstraintTypes::PlaylistDuration::getName() const 0116 { 0117 KLocalizedString v; 0118 if ( m_comparison == CompareNumEquals ) { 0119 v = ki18nc( "%1 is a length of time (e.g. 5:00 for 5 minutes)", "Playlist duration: equals %1"); 0120 } else if ( m_comparison == CompareNumGreaterThan ) { 0121 v = ki18nc( "%1 is a length of time (e.g. 5:00 for 5 minutes)", "Playlist duration: more than %1"); 0122 } else if ( m_comparison == CompareNumLessThan ) { 0123 v = ki18nc( "%1 is a length of time (e.g. 5:00 for 5 minutes)", "Playlist duration: less than %1"); 0124 } else { 0125 v = ki18n( "Playlist duration: unknown"); 0126 } 0127 v = v.subs( QTime(0, 0, 0).addMSecs( m_duration ).toString( QStringLiteral("H:mm:ss") ) ); 0128 return v.toString(); 0129 } 0130 0131 double 0132 ConstraintTypes::PlaylistDuration::satisfaction( const Meta::TrackList& tl ) const 0133 { 0134 qint64 l = 0; 0135 for( const Meta::TrackPtr &t : tl ) { 0136 l += t->length(); 0137 } 0138 0139 double factor = m_strictness * 0.0003; 0140 if ( m_comparison == CompareNumEquals ) { 0141 return 4.0 / ( ( 1.0 + exp( factor*( double )( l - m_duration ) ) )*( 1.0 + exp( factor*( double )( m_duration - l ) ) ) ); 0142 } else if ( m_comparison == CompareNumLessThan ) { 0143 return 1.0 / ( 1.0 + exp( factor*( double )( l - m_duration ) ) ); 0144 } else if ( m_comparison == CompareNumGreaterThan ) { 0145 return 1.0 / ( 1.0 + exp( factor*( double )( m_duration - l ) ) ); 0146 } 0147 return 1.0; 0148 } 0149 0150 quint32 0151 ConstraintTypes::PlaylistDuration::suggestPlaylistSize() const 0152 { 0153 if ( m_comparison == CompareNumLessThan ) { 0154 return static_cast<quint32>( m_duration ) / 300000 ; 0155 } else if ( m_comparison == CompareNumGreaterThan ) { 0156 return static_cast<quint32>( m_duration ) / 180000; 0157 } else { 0158 return static_cast<quint32>( m_duration ) / 240000; 0159 } 0160 } 0161 0162 void 0163 ConstraintTypes::PlaylistDuration::setComparison( const int c ) 0164 { 0165 m_comparison = c; 0166 Q_EMIT dataChanged(); 0167 } 0168 0169 void 0170 ConstraintTypes::PlaylistDuration::setDuration( const int v ) 0171 { 0172 m_duration = v; 0173 Q_EMIT dataChanged(); 0174 } 0175 0176 void 0177 ConstraintTypes::PlaylistDuration::setStrictness( const int sv ) 0178 { 0179 m_strictness = static_cast<double>(sv)/10.0; 0180 } 0181 0182 /****************************** 0183 * Edit Widget * 0184 ******************************/ 0185 0186 ConstraintTypes::PlaylistDurationEditWidget::PlaylistDurationEditWidget( const int duration, 0187 const int comparison, 0188 const int strictness ) : QWidget( nullptr ) 0189 { 0190 ui.setupUi( this ); 0191 0192 ui.timeEdit_Duration->setTime( QTime(0, 0, 0).addMSecs( duration ) ); 0193 ui.comboBox_Comparison->setCurrentIndex( comparison ); 0194 ui.slider_Strictness->setValue( strictness ); 0195 } 0196 0197 void 0198 ConstraintTypes::PlaylistDurationEditWidget::on_timeEdit_Duration_timeChanged( const QTime& t ) 0199 { 0200 Q_EMIT durationChanged( QTime(0, 0, 0).msecsTo( t ) ); 0201 Q_EMIT updated(); 0202 } 0203 0204 void 0205 ConstraintTypes::PlaylistDurationEditWidget::on_comboBox_Comparison_currentIndexChanged( const int v ) 0206 { 0207 Q_EMIT comparisonChanged( v ); 0208 Q_EMIT updated(); 0209 } 0210 0211 void 0212 ConstraintTypes::PlaylistDurationEditWidget::on_slider_Strictness_valueChanged( const int v ) 0213 { 0214 Q_EMIT strictnessChanged( v ); 0215 Q_EMIT updated(); 0216 }