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 }