|
1 /* |
|
2 * Copyright (c) 2002-2007 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: This class is a RecordControl. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 #include <jdebug.h> |
|
21 #include "cmmarecordcontrol.h" |
|
22 #include "cmmaplayer.h" |
|
23 |
|
24 |
|
25 _LIT(KControlName, "RecordControl"); |
|
26 |
|
27 CMMARecordControl::CMMARecordControl(CMMAPlayer* aPlayer): |
|
28 iState(ERecordUninitialized), |
|
29 iPlayer(aPlayer), |
|
30 iStartTime(0) |
|
31 { |
|
32 } |
|
33 |
|
34 |
|
35 CMMARecordControl::~CMMARecordControl() |
|
36 { |
|
37 iRecordPauseTimer.Cancel(); |
|
38 iRecordPauseTimer.Close(); |
|
39 |
|
40 if (iPlayer) |
|
41 { |
|
42 iPlayer->RemoveStateListener(this); |
|
43 } |
|
44 |
|
45 delete iOutputStream; |
|
46 |
|
47 iFile.Close(); |
|
48 iFs.Delete(iFilename); |
|
49 iFs.Close(); |
|
50 } |
|
51 |
|
52 void CMMARecordControl::WaitForPauseL(const TInt64& aMediaTime) |
|
53 { |
|
54 // reusing time variable |
|
55 TInt64 time = iStartTime - aMediaTime + KMinRecordPauseInterval; |
|
56 iStartTime = 0; |
|
57 DEBUG_INT("CMMARecordControl::WaitForPauseL wait time = %d", (TInt)time); |
|
58 // if time > 0, time between record and pause is smaller than |
|
59 // KMinRecordPauseInterval and we have to wait. |
|
60 if (time > 0) |
|
61 { |
|
62 TRequestStatus status; |
|
63 iRecordPauseTimer.Cancel(); |
|
64 iRecordPauseTimer.After(status, I64INT(time)); |
|
65 User::WaitForRequest(status); |
|
66 // Status ignored because recording must be stopped. |
|
67 } |
|
68 } |
|
69 |
|
70 void CMMARecordControl::ConstructL() |
|
71 { |
|
72 User::LeaveIfError(iRecordPauseTimer.CreateLocal()); |
|
73 |
|
74 User::LeaveIfError(iFs.Connect()); |
|
75 |
|
76 // create temporary file for recording |
|
77 User::LeaveIfError(iFile.Temp(iFs, |
|
78 KMMARecordTempDirectory, |
|
79 iFilename, |
|
80 EFileRead | EFileWrite | EFileShareAny)); |
|
81 |
|
82 iPlayer->AddStateListenerL(this); |
|
83 } |
|
84 |
|
85 void CMMARecordControl::StartRecordL() |
|
86 { |
|
87 DEBUG("MMA:CMMARecordControl::StartRecordL+"); |
|
88 |
|
89 // Initialize needs to be done only once after setRecordLocation or |
|
90 // setRecordStream and before commit or reset. Although startRecord can be |
|
91 // called several times in the process, the initialization must happen |
|
92 // only in the first call to startRecord |
|
93 if (iState == ERecordUninitialized) |
|
94 { |
|
95 InitializeL(); |
|
96 } |
|
97 |
|
98 iState = ERecordStandBy; |
|
99 // calling next state if player is already started |
|
100 NextStateL(iPlayer->State()); |
|
101 |
|
102 iPlayer->GetMediaTime(&iStartTime); |
|
103 iPlayer->PostLongEvent(CMMAPlayerEvent::ERecordStarted, iStartTime); |
|
104 |
|
105 DEBUG("MMA:CMMARecordControl::StartRecordL-"); |
|
106 } |
|
107 |
|
108 |
|
109 void CMMARecordControl::StopRecordL() |
|
110 { |
|
111 DEBUG("MMA:CMMARecordControl::StopRecordL+"); |
|
112 if (iState == ERecordRecording) |
|
113 { |
|
114 NextStateL(iPlayer->State()); |
|
115 } |
|
116 |
|
117 iState = ERecordInitialized; |
|
118 |
|
119 // ask mediatime again for more accurate value |
|
120 TInt64 time; |
|
121 iPlayer->GetMediaTime(&time); |
|
122 iPlayer->PostLongEvent(CMMAPlayerEvent::ERecordStopped, time); |
|
123 |
|
124 DEBUG("MMA:CMMARecordControl::StopRecordL-"); |
|
125 } |
|
126 |
|
127 |
|
128 void CMMARecordControl::CommitL() |
|
129 { |
|
130 DEBUG("MMA:CMMARecordControl::CommitL+"); |
|
131 // reset the recorder if already initialized |
|
132 if (iState > ERecordUninitialized) |
|
133 { |
|
134 DoResetL(); |
|
135 } |
|
136 else |
|
137 { |
|
138 // not even initialized yet, just inform java |
|
139 iOutputStream->WriteL(KNullDesC8); |
|
140 return; |
|
141 } |
|
142 iState = ERecordUninitialized; |
|
143 |
|
144 // Create buffer for file context |
|
145 TInt fileSize; |
|
146 User::LeaveIfError(iFile.Size(fileSize)); |
|
147 DEBUG_INT("MMA:CMMARecordControl::CommitL size in bytes = %d", fileSize); |
|
148 |
|
149 HBufC8* data = HBufC8::NewLC(fileSize); |
|
150 |
|
151 // Read file context |
|
152 TPtr8 dataPtr = data->Des(); |
|
153 TInt pos(0); |
|
154 User::LeaveIfError(iFile.Seek(ESeekStart, pos)); |
|
155 User::LeaveIfError(iFile.Read(dataPtr)); |
|
156 User::LeaveIfError(iFile.SetSize(0)); |
|
157 User::LeaveIfError(iFile.Flush()); |
|
158 |
|
159 // Write whole video data to stream |
|
160 iOutputStream->WriteL(dataPtr); |
|
161 CleanupStack::PopAndDestroy(data); |
|
162 |
|
163 DEBUG("MMA:CMMARecordControl::CommitL-"); |
|
164 } |
|
165 |
|
166 |
|
167 void CMMARecordControl::ResetL() |
|
168 { |
|
169 DEBUG("MMA:CMMARecordControl::ResetL+"); |
|
170 // reset the recorder if already initialized |
|
171 if (iState > ERecordUninitialized) |
|
172 { |
|
173 DoResetL(); |
|
174 DEBUG("MMA:CMMARecordControl::DoResetL done"); |
|
175 iState = ERecordUninitialized; |
|
176 |
|
177 // Empty file that it can be reused |
|
178 User::LeaveIfError(iFile.SetSize(0)); |
|
179 User::LeaveIfError(iFile.Flush()); |
|
180 } |
|
181 |
|
182 DEBUG("MMA:CMMARecordControl::ResetL-"); |
|
183 } |
|
184 |
|
185 void CMMARecordControl::SetRecordStream(CMMAOutputStream* aStream) |
|
186 { |
|
187 DEBUG("MMA:CMMARecordControl::SetRecordStream"); |
|
188 __ASSERT_DEBUG(aStream, User::Panic( |
|
189 _L("CMMAVideoRecordControl:: Stream is NULL."), |
|
190 KErrArgument)); |
|
191 delete iOutputStream; |
|
192 iOutputStream = aStream; |
|
193 } |
|
194 |
|
195 |
|
196 HBufC* CMMARecordControl::GetContentTypeL() |
|
197 { |
|
198 DEBUG("MMA:CMMARecordControl::GetContentTypeL"); |
|
199 return iPlayer->ContentType(); |
|
200 } |
|
201 |
|
202 const TDesC& CMMARecordControl::ClassName() const |
|
203 { |
|
204 return KControlName; |
|
205 } |
|
206 |
|
207 void CMMARecordControl::StateChanged(TInt aState) |
|
208 { |
|
209 TRAPD(err, NextStateL(aState)); |
|
210 if (err) |
|
211 { |
|
212 Error(err); |
|
213 } |
|
214 } |
|
215 |
|
216 void CMMARecordControl::Error(TInt aErrorCode) |
|
217 { |
|
218 DEBUG_INT("MMA:CMMARecordControl::Error %d", aErrorCode); |
|
219 TBuf<KRecordErrorMessageSize> errorMessage; |
|
220 errorMessage.Format(KMMARecordErrorMsg, aErrorCode); |
|
221 iPlayer->PostStringEvent(CMMAPlayerEvent::ERecordError, |
|
222 errorMessage); |
|
223 } |
|
224 |
|
225 void CMMARecordControl::HandleRecordSizeLimit() |
|
226 { |
|
227 // commit the stream |
|
228 iOutputStream->Commit(); |
|
229 TInt64 time; |
|
230 iPlayer->GetMediaTime(&time); |
|
231 iPlayer->PostLongEvent(CMMAPlayerEvent::ERecordStopped, time); |
|
232 } |
|
233 |
|
234 void CMMARecordControl::NextStateL(TInt aPlayerState) |
|
235 { |
|
236 DEBUG_INT("MMA:CMMARecordControl::NextStateL Player state = %d", aPlayerState); |
|
237 DEBUG_INT("MMA:CMMARecordControl::NextStateL internal state = %d", iState); |
|
238 switch (iState) |
|
239 { |
|
240 case ERecordUninitialized: |
|
241 { |
|
242 DEBUG("MMA:CMMARecordControl::NextStateL: case ERecordUninitialized"); |
|
243 // This is the initial state. |
|
244 // To getinto this state, commit or reset must be called |
|
245 // To get out of this state startRecord must be called |
|
246 |
|
247 break; |
|
248 } |
|
249 case ERecordInitialized: |
|
250 { |
|
251 DEBUG("MMA:CMMARecordControl::NextStateL: case ERecordInitialized"); |
|
252 // To get into this state stopRecord must be called. |
|
253 // To get out of this state startRecord, commit or reset must be |
|
254 // called |
|
255 break; |
|
256 } |
|
257 case ERecordStandBy: |
|
258 { |
|
259 DEBUG("MMA:CMMARecordControl::NextStateL: case ERecordStandBy"); |
|
260 // To get into this state startRecord must be called. |
|
261 // To get out of this state stopRecord, commit or reset must be |
|
262 // called, or state of the Player must change to STARTED |
|
263 |
|
264 |
|
265 // start the actual recording if player is started |
|
266 if (aPlayerState == CMMAPlayer::EStarted) |
|
267 { |
|
268 DEBUG("MMA:CMMARecordControl::NextStateL: ERecordStandBy -> ERecordRecording"); |
|
269 DoStartRecordL(); |
|
270 iState = ERecordRecording; |
|
271 } |
|
272 break; |
|
273 } |
|
274 case ERecordRecording: |
|
275 { |
|
276 DEBUG("MMA:CMMARecordControl::NextStateL: case ERecordRecording"); |
|
277 |
|
278 // To get into this state startRecord must have been called and |
|
279 // the Player must be in STARTED state. |
|
280 // To get out of this state, stopRecord, commit or reset must be |
|
281 // called or the Player must change to a state other than STARTED |
|
282 TInt64 time; |
|
283 iPlayer->GetMediaTime(&time); |
|
284 WaitForPauseL(time); |
|
285 DoStopRecordL(); |
|
286 iState = ERecordStandBy; |
|
287 break; |
|
288 } |
|
289 default: |
|
290 { |
|
291 DEBUG("MMA:CMMARecordControl::NextStateL: case default - code should not reach here!!"); |
|
292 __ASSERT_DEBUG(KErrGeneral, User::Invariant()); // This will newer occur |
|
293 break; |
|
294 } |
|
295 } |
|
296 } |
|
297 |
|
298 // END OF FILE |