|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Buffer commands |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include"mpxplaybackcommandbuffer.h" |
|
20 #include "mpxlog.h" |
|
21 |
|
22 // ============================== MEMBER FUNCTIONS ============================ |
|
23 |
|
24 |
|
25 // ---------------------------------------------------------------------------- |
|
26 // Two-phased constructor |
|
27 // ---------------------------------------------------------------------------- |
|
28 // |
|
29 CMPXPlaybackCmdBuffer* CMPXPlaybackCmdBuffer::NewL( |
|
30 MMPXPlaybackCmdBufferObserver& aObserver) |
|
31 { |
|
32 CMPXPlaybackCmdBuffer* h=new(ELeave)CMPXPlaybackCmdBuffer(aObserver); |
|
33 CleanupStack::PushL(h); |
|
34 h->ConstructL(); |
|
35 CleanupStack::Pop(h); |
|
36 return h; |
|
37 } |
|
38 |
|
39 // ---------------------------------------------------------------------------- |
|
40 // C++ constructor can NOT contain any code that might leave. |
|
41 // ---------------------------------------------------------------------------- |
|
42 // |
|
43 CMPXPlaybackCmdBuffer::CMPXPlaybackCmdBuffer( |
|
44 MMPXPlaybackCmdBufferObserver& aObserver) |
|
45 : CTimer(EPriorityStandard), |
|
46 iObserver(aObserver) |
|
47 { |
|
48 CActiveScheduler::Add(this); |
|
49 } |
|
50 |
|
51 |
|
52 // ---------------------------------------------------------------------------- |
|
53 // Is this a command controlled by command buffer |
|
54 // ---------------------------------------------------------------------------- |
|
55 // |
|
56 TBool CMPXPlaybackCmdBuffer::CommandForBuffering(TMPXPlaybackCommand aCmd) const |
|
57 { |
|
58 switch(aCmd) |
|
59 { |
|
60 case EPbCmdPlay: |
|
61 case EPbCmdStop: |
|
62 case EPbCmdPause: |
|
63 case EPbCmdPlayPause: |
|
64 case EPbCmdNext: |
|
65 case EPbCmdPrevious: |
|
66 return ETrue; |
|
67 default: |
|
68 return EFalse; |
|
69 } |
|
70 } |
|
71 |
|
72 // ---------------------------------------------------------------------------- |
|
73 // Handle time out event |
|
74 // ---------------------------------------------------------------------------- |
|
75 // |
|
76 void CMPXPlaybackCmdBuffer::RunL() |
|
77 { |
|
78 MPX_DEBUG1("CMPXPlaybackCmdBuffer::RunL() entering"); |
|
79 |
|
80 if (!iEventProcessing && IsCommandBuffered()) |
|
81 // |
|
82 // Client is not currently processing any events, and there are new |
|
83 // events to deliver |
|
84 // |
|
85 { |
|
86 if (iEvent.iNavKeyBuffered) |
|
87 { |
|
88 iObserver.HandleCmdBufferSkipEventL( EPbsSkipEventEnd ); // notify end skip event |
|
89 } |
|
90 iIsCommandBuffered=EFalse; |
|
91 iEventProcessing=ETrue; // Handled by client |
|
92 iObserver.HandleCmdBufferEventL(iEvent); |
|
93 } |
|
94 |
|
95 MPX_DEBUG1("CMPXPlaybackCmdBuffer::RunL() exiting"); |
|
96 } |
|
97 |
|
98 // ---------------------------------------------------------------------------- |
|
99 // Handle leave in command handling |
|
100 // ---------------------------------------------------------------------------- |
|
101 // |
|
102 TInt CMPXPlaybackCmdBuffer::RunError(TInt /*aError*/) |
|
103 { |
|
104 MPX_DEBUG1("==>CMPXPlaybackCmdBuffer::RunL()"); |
|
105 ClearCommands(); |
|
106 iEventProcessing=EFalse; |
|
107 MPX_DEBUG1("<==CMPXPlaybackCmdBuffer::RunL()"); |
|
108 return KErrNone; |
|
109 } |
|
110 |
|
111 // ---------------------------------------------------------------------------- |
|
112 // Buffer a playback/skip command, along with the current state and position in |
|
113 // the track. Update playback state/position internally. When time-out, restore |
|
114 // state/position to playback engine. |
|
115 // ---------------------------------------------------------------------------- |
|
116 // |
|
117 void CMPXPlaybackCmdBuffer::BufferCommandL(TMPXPlaybackCommand aCmd, |
|
118 TMPXPlaybackState aState, |
|
119 TInt aPos) |
|
120 { |
|
121 MPX_DEBUG4("CMPXPlaybackCmdBuffer::BufferCommandL(%d, %d, %d) entering", aCmd, aState, aPos); |
|
122 |
|
123 if (!CommandForBuffering(aCmd) || |
|
124 (aCmd==EPbCmdPlay && aState==EPbStatePlaying) || |
|
125 (aCmd==EPbCmdPause && aState==EPbStatePaused)) |
|
126 { |
|
127 // This command does not change any state, so make sure |
|
128 // to negate any previous commands |
|
129 ClearCommands(); |
|
130 return; |
|
131 } |
|
132 |
|
133 TBool saveIsCmdBuffered = iIsCommandBuffered; |
|
134 iBufferTime = KPbMediaKeyIntervalMicroSeconds; |
|
135 const TInt KPbMediaKeyNoIntervalMicroSeconds=10; // 0.00001s |
|
136 const TInt KPbMediaKeySkipIntervalMicroSeconds=200000; // 0.2s or 200ms |
|
137 const TInt KPbMediaKeyPauseIntervalMicroSeconds=100000; // 0.1s or 100ms |
|
138 Cancel(); // Stop timer and wait again for any other events |
|
139 |
|
140 if (!iIsCommandBuffered) |
|
141 { |
|
142 iIsCommandBuffered=ETrue; |
|
143 iEvent.iTrackOffset=0; |
|
144 iEvent.iState=aState; |
|
145 iEvent.iNavKeyBuffered=EFalse; |
|
146 } |
|
147 |
|
148 if (!iEvent.iNavKeyBuffered) |
|
149 { |
|
150 iEvent.iPos = aPos; |
|
151 } |
|
152 |
|
153 switch(aCmd) |
|
154 { |
|
155 case EPbCmdNext: |
|
156 { |
|
157 iEvent.iTrackOffset++; |
|
158 iEvent.iNavKeyBuffered++; |
|
159 TBool savedStatus( iEventProcessing ); |
|
160 iEventProcessing = ETrue; |
|
161 iObserver.HandleCmdBufferSkipEventL( EPbsSkipEventNext ); // notify skip event |
|
162 iEventProcessing = savedStatus; |
|
163 if ( !saveIsCmdBuffered ) |
|
164 { |
|
165 iBufferTime = KPbMediaKeySkipIntervalMicroSeconds; // 0.2s or 200ms |
|
166 } |
|
167 break; |
|
168 } |
|
169 case EPbCmdPrevious: |
|
170 { |
|
171 if (!iEvent.iNavKeyBuffered && |
|
172 (aState==EPbStatePlaying || aState==EPbStatePaused) && |
|
173 iEvent.iPos > KPbReplayThresholdMiliSeconds) |
|
174 { |
|
175 MPX_DEBUG1("CMPXPlaybackCmdBuffer::BufferCommandL() Setting position 0"); |
|
176 aPos=0; |
|
177 } |
|
178 else |
|
179 { |
|
180 TBool savedStatus( iEventProcessing ); |
|
181 iEventProcessing = ETrue; |
|
182 iObserver.HandleCmdBufferSkipEventL( EPbsSkipEventPrevious ); // notify skip event |
|
183 iEventProcessing = savedStatus; |
|
184 iEvent.iTrackOffset--; |
|
185 } |
|
186 iEvent.iNavKeyBuffered++; |
|
187 break; |
|
188 } |
|
189 case EPbCmdPlay: |
|
190 iEvent.iState = EPbStatePlaying; |
|
191 if ( !saveIsCmdBuffered ) |
|
192 { |
|
193 iBufferTime = KPbMediaKeyNoIntervalMicroSeconds; |
|
194 } |
|
195 break; |
|
196 case EPbCmdPause: // From play to pause |
|
197 if (EPbStatePlaying == iEvent.iState) |
|
198 { |
|
199 iEvent.iState = EPbStatePaused; |
|
200 if ( !saveIsCmdBuffered ) |
|
201 { |
|
202 iBufferTime = KPbMediaKeyPauseIntervalMicroSeconds; |
|
203 } |
|
204 } |
|
205 break; |
|
206 case EPbCmdPlayPause: |
|
207 { |
|
208 if ( EPbStatePlaying == iEvent.iState ) |
|
209 { |
|
210 iEvent.iState = EPbStatePaused; |
|
211 if ( !saveIsCmdBuffered ) |
|
212 { |
|
213 iBufferTime = KPbMediaKeyPauseIntervalMicroSeconds; |
|
214 } |
|
215 break; |
|
216 } |
|
217 else |
|
218 { |
|
219 iEvent.iState = EPbStatePlaying; |
|
220 if ( !saveIsCmdBuffered ) |
|
221 { |
|
222 iBufferTime = KPbMediaKeyNoIntervalMicroSeconds; |
|
223 } |
|
224 } |
|
225 break; |
|
226 } |
|
227 case EPbCmdStop: |
|
228 iEvent.iState = EPbStateStopped; |
|
229 break; |
|
230 default: |
|
231 break; |
|
232 } |
|
233 // maintain pos unless track has changed |
|
234 iEvent.iPos=iEvent.iTrackOffset ? 0 : aPos; |
|
235 // |
|
236 if (!iEventProcessing) // If client isn't processing event |
|
237 { |
|
238 After(iBufferTime); |
|
239 } |
|
240 |
|
241 MPX_DEBUG1("CMPXPlaybackCmdBuffer::BufferCommandL() exiting"); |
|
242 } |
|
243 |
|
244 // ---------------------------------------------------------------------------- |
|
245 // Called by client when finished processing commands in buffer |
|
246 // ---------------------------------------------------------------------------- |
|
247 // |
|
248 void CMPXPlaybackCmdBuffer::CompleteCommand() |
|
249 { |
|
250 MPX_DEBUG1("CMPXPlaybackCmdBuffer::CompleteCommand() entering"); |
|
251 |
|
252 iEventProcessing=EFalse; // Client finished processing event |
|
253 if (IsCommandBuffered() && !IsActive()) |
|
254 { |
|
255 After(iBufferTime); |
|
256 } |
|
257 |
|
258 MPX_DEBUG1("CMPXPlaybackCmdBuffer::CompleteCommand() exiting"); |
|
259 } |
|
260 |
|
261 // ---------------------------------------------------------------------------- |
|
262 // Check if any commands buffered |
|
263 // ---------------------------------------------------------------------------- |
|
264 // |
|
265 TBool CMPXPlaybackCmdBuffer::IsCommandBuffered() const |
|
266 { |
|
267 return iIsCommandBuffered; |
|
268 } |
|
269 |
|
270 // ---------------------------------------------------------------------------- |
|
271 // Clear all commands |
|
272 // ---------------------------------------------------------------------------- |
|
273 // |
|
274 void CMPXPlaybackCmdBuffer::ClearCommands() |
|
275 { |
|
276 iIsCommandBuffered=EFalse; |
|
277 Cancel(); |
|
278 } |
|
279 |
|
280 |
|
281 |