1
/***************************************************************************
2
                      engineobserver.cpp  -  Observer pattern for engine
3
                         -------------------
4
begin                : Mar 14 2003
5
copyright            : (C) 2003 by Frederik Holljen
6
email                : fh@ez.no
7
***************************************************************************/
8
9
/***************************************************************************
10
 *                                                                         *
11
 *   This program is free software; you can redistribute it and/or modify  *
12
 *   it under the terms of the GNU General Public License as published by  *
13
 *   the Free Software Foundation; either version 2 of the License, or     *
14
 *   (at your option) any later version.                                   *
15
 *                                                                         *
16
 ***************************************************************************/
17
18
#include "EngineObserver.h"
19
20
#include "Debug.h"
21
22
//////////////////////////////////////////////////////////////////////////////////////////
23
/// CLASS EngineObserver
24
//////////////////////////////////////////////////////////////////////////////////////////
25
26
EngineObserver::EngineObserver( EngineSubject *s )
27
    : m_subject( s )
28
{
29
    Q_ASSERT( m_subject );
30
    m_subject->attach( this );
31
}
32
33
EngineObserver::~EngineObserver()
34
{
35
    m_subject->detach( this );
36
}
37
38
void
39
EngineObserver::engineStateChanged( Phonon::State currentState, Phonon::State oldState )
40
{
41
    Q_UNUSED( oldState );
42
    Q_UNUSED( currentState );
43
}
44
45
void
46
EngineObserver::enginePlaybackEnded( int finalPosition, int trackLength, PlaybackEndedReason reason )
47
{
48
    Q_UNUSED( finalPosition );
49
    Q_UNUSED( trackLength );
50
    Q_UNUSED( reason );
51
}
52
53
void
54
EngineObserver::engineNewTrackPlaying()
55
{
56
}
57
58
void
59
EngineObserver::engineNewMetaData( const QHash<qint64, QString> &newMetaData, bool trackChanged )
60
{
61
    Q_UNUSED( newMetaData );
62
    Q_UNUSED( trackChanged );
63
}
64
65
void
66
EngineObserver::engineVolumeChanged( int percent )
67
{
68
    Q_UNUSED( percent );
69
}
70
71
void
72
EngineObserver::engineMuteStateChanged( bool mute )
73
{
74
    Q_UNUSED( mute );
75
}
76
77
void
78
EngineObserver::engineTrackPositionChanged( long position , bool userSeek )
79
{
80
    Q_UNUSED( position );
81
    Q_UNUSED( userSeek );
82
}
83
84
void
85
EngineObserver::engineTrackLengthChanged( long seconds )
86
{
87
    Q_UNUSED( seconds );
88
}
89
90
//////////////////////////////////////////////////////////////////////////////////////////
91
/// CLASS EngineSubject
92
//////////////////////////////////////////////////////////////////////////////////////////
93
94
EngineSubject::EngineSubject()
95
    : m_realState( Phonon::StoppedState )
96
{}
97
98
EngineSubject::~EngineSubject()
99
{
100
    //do not delete the observers, we don't have ownership of them!
101
}
102
103
104
void EngineSubject::stateChangedNotify( Phonon::State newState, Phonon::State oldState )
105
{
106
    DEBUG_BLOCK
107
    // We explicitly block notifications where newState == buffering in enginecontroller, so if the old state = buffering we can ignore the playing update.
108
    if( newState == m_realState && newState != Phonon::PlayingState )  // To prevent Playing->Buffering->Playing->buffering.
109
        return;
110
    foreach( EngineObserver *observer, Observers )
111
    {
112
        observer->engineStateChanged( newState, oldState );
113
    }
114
    m_realState = newState;
115
}
116
117
void EngineSubject::playbackEnded( int finalPosition, int trackLength, EngineObserver::PlaybackEndedReason reason )
118
{
119
    foreach( EngineObserver *observer, Observers )
120
        observer->enginePlaybackEnded( finalPosition, trackLength, reason );
121
}
122
123
void
124
EngineSubject::newMetaDataNotify( const QHash<qint64, QString> &newMetaData, bool trackChanged )
125
{
126
    DEBUG_BLOCK
127
128
    if( trackChanged )
129
      m_metaDataHistory.clear();
130
131
    if( isMetaDataSpam( newMetaData ) )
132
      return;
133
134
    foreach( EngineObserver *observer, Observers )
135
        observer->engineNewMetaData( newMetaData, trackChanged );
136
}
137
138
void EngineSubject::volumeChangedNotify( int percent )
139
{
140
    foreach( EngineObserver *observer, Observers )
141
    {
142
        observer->engineVolumeChanged( percent );
143
    }
144
}
145
146
void EngineSubject::muteStateChangedNotify( bool mute )
147
{
148
        foreach( EngineObserver *observer, Observers )
149
    {
150
        observer->engineMuteStateChanged( mute );
151
    }
152
}
153
154
void EngineSubject::trackPositionChangedNotify( long position, bool userSeek )
155
{
156
    foreach( EngineObserver *observer, Observers )
157
    {
158
        observer->engineTrackPositionChanged( position, userSeek );
159
    }
160
}
161
162
163
void EngineSubject::trackLengthChangedNotify( long seconds )
164
{
165
    foreach( EngineObserver *observer, Observers )
166
    {
167
        observer->engineTrackLengthChanged( seconds );
168
    }
169
}
170
171
void
172
EngineSubject::newTrackPlaying() const
173
{
174
    foreach( EngineObserver *observer, Observers )
175
        observer->engineNewTrackPlaying();
176
}
177
178
179
void EngineSubject::attach( EngineObserver *observer )
180
{
181
    if( !observer )
182
        return;
183
    Observers.insert( observer );
184
}
185
186
187
void EngineSubject::detach( EngineObserver *observer )
188
{
189
    Observers.remove( observer );
190
}
191
192
/* Try to detect MetaData spam in Streams. */
193
bool EngineSubject::isMetaDataSpam( QHash<qint64, QString> newMetaData )
194
{
195
    // search for Metadata in history
196
    for( int i = 0; i < m_metaDataHistory.size(); i++)
197
    {
198
        if( m_metaDataHistory.at( i ) == newMetaData ) // we already had that one -> spam!
199
        {
200
            m_metaDataHistory.move( i, 0 ); // move spam to the beginning of the list
201
            return true;
202
        }
203
    }
204
205
    if( m_metaDataHistory.size() == 12 )
206
        m_metaDataHistory.removeLast();
207
208
    m_metaDataHistory.insert( 0, newMetaData );
209
    return false;
210
}