sl@0
|
1 |
// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
|
sl@0
|
2 |
// All rights reserved.
|
sl@0
|
3 |
// This component and the accompanying materials are made available
|
sl@0
|
4 |
// under the terms of the License "Eclipse Public License v1.0"
|
sl@0
|
5 |
// which accompanies this distribution, and is available
|
sl@0
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
sl@0
|
7 |
//
|
sl@0
|
8 |
// Initial Contributors:
|
sl@0
|
9 |
// Nokia Corporation - initial contribution.
|
sl@0
|
10 |
//
|
sl@0
|
11 |
// Contributors:
|
sl@0
|
12 |
//
|
sl@0
|
13 |
// Description:
|
sl@0
|
14 |
// e32test\multimedia\t_soundmchan.cpp
|
sl@0
|
15 |
//
|
sl@0
|
16 |
//
|
sl@0
|
17 |
|
sl@0
|
18 |
/**
|
sl@0
|
19 |
@file Testing access to the shared chunk sound driver from multiple user side threads.
|
sl@0
|
20 |
*/
|
sl@0
|
21 |
|
sl@0
|
22 |
#include <e32test.h>
|
sl@0
|
23 |
#include <e32def.h>
|
sl@0
|
24 |
#include <e32def_private.h>
|
sl@0
|
25 |
#include "t_soundutils.h"
|
sl@0
|
26 |
|
sl@0
|
27 |
RTest Test(_L("T_SOUNDMCHAN"));
|
sl@0
|
28 |
|
sl@0
|
29 |
const TInt KHeapSize=0x4000;
|
sl@0
|
30 |
|
sl@0
|
31 |
enum TSecThreadTestId
|
sl@0
|
32 |
{
|
sl@0
|
33 |
ESecThreadConfigPlayback,
|
sl@0
|
34 |
ESecThreadConfigRecord,
|
sl@0
|
35 |
};
|
sl@0
|
36 |
struct SSecondaryThreadInfo
|
sl@0
|
37 |
{
|
sl@0
|
38 |
TSecThreadTestId iTestId;
|
sl@0
|
39 |
// TInt iExpectedRetVal;
|
sl@0
|
40 |
TThreadId iThreadId;
|
sl@0
|
41 |
TInt iDrvHandle;
|
sl@0
|
42 |
};
|
sl@0
|
43 |
|
sl@0
|
44 |
_LIT(KSndLddFileName,"ESOUNDSC.LDD");
|
sl@0
|
45 |
_LIT(KSndPddFileName,"SOUNDSC.PDD");
|
sl@0
|
46 |
|
sl@0
|
47 |
|
sl@0
|
48 |
LOCAL_C TInt secondaryThread(TAny* aTestInfo)
|
sl@0
|
49 |
{
|
sl@0
|
50 |
RTest stest(_L("Secondary test thread"));
|
sl@0
|
51 |
stest.Title();
|
sl@0
|
52 |
|
sl@0
|
53 |
stest.Start(_L("Check which test to perform"));
|
sl@0
|
54 |
SSecondaryThreadInfo& sti=*((SSecondaryThreadInfo*)aTestInfo);
|
sl@0
|
55 |
TInt r;
|
sl@0
|
56 |
switch(sti.iTestId)
|
sl@0
|
57 |
{
|
sl@0
|
58 |
case ESecThreadConfigPlayback:
|
sl@0
|
59 |
{
|
sl@0
|
60 |
stest.Next(_L("Duplicate the channel handle passed from main thread"));
|
sl@0
|
61 |
|
sl@0
|
62 |
// Get a reference to the main thread - which created the handle
|
sl@0
|
63 |
RThread thread;
|
sl@0
|
64 |
r=thread.Open(sti.iThreadId);
|
sl@0
|
65 |
stest(r==KErrNone);
|
sl@0
|
66 |
|
sl@0
|
67 |
// Duplicate the driver handle passed from the other thread - for this thread
|
sl@0
|
68 |
RSoundSc snddev;
|
sl@0
|
69 |
snddev.SetHandle(sti.iDrvHandle);
|
sl@0
|
70 |
r=snddev.Duplicate(thread);
|
sl@0
|
71 |
stest(r==KErrNone);
|
sl@0
|
72 |
thread.Close();
|
sl@0
|
73 |
|
sl@0
|
74 |
stest.Next(_L("Configure the driver"));
|
sl@0
|
75 |
// Read the capabilties of this device.
|
sl@0
|
76 |
TSoundFormatsSupportedV02Buf capsBuf;
|
sl@0
|
77 |
snddev.Caps(capsBuf);
|
sl@0
|
78 |
TSoundFormatsSupportedV02& caps=capsBuf();
|
sl@0
|
79 |
|
sl@0
|
80 |
// Read back the default configuration - which must be valid.
|
sl@0
|
81 |
TCurrentSoundFormatV02Buf formatBuf;
|
sl@0
|
82 |
snddev.AudioFormat(formatBuf);
|
sl@0
|
83 |
TCurrentSoundFormatV02& format=formatBuf();
|
sl@0
|
84 |
|
sl@0
|
85 |
if (caps.iEncodings&KSoundEncoding16BitPCM)
|
sl@0
|
86 |
format.iEncoding = ESoundEncoding16BitPCM;
|
sl@0
|
87 |
if (caps.iRates&KSoundRate16000Hz)
|
sl@0
|
88 |
format.iRate = ESoundRate16000Hz;
|
sl@0
|
89 |
if (caps.iChannels&KSoundStereoChannel)
|
sl@0
|
90 |
format.iChannels = 2;
|
sl@0
|
91 |
r=snddev.SetAudioFormat(formatBuf);
|
sl@0
|
92 |
stest(r==KErrNone);
|
sl@0
|
93 |
r=snddev.SetVolume(KSoundMaxVolume);
|
sl@0
|
94 |
stest(r==KErrNone);
|
sl@0
|
95 |
|
sl@0
|
96 |
stest.Next(_L("Close the channel again"));
|
sl@0
|
97 |
snddev.Close();
|
sl@0
|
98 |
|
sl@0
|
99 |
break;
|
sl@0
|
100 |
}
|
sl@0
|
101 |
|
sl@0
|
102 |
case ESecThreadConfigRecord:
|
sl@0
|
103 |
{
|
sl@0
|
104 |
stest.Next(_L("Use the channel passed from main thread to configure driver"));
|
sl@0
|
105 |
|
sl@0
|
106 |
break;
|
sl@0
|
107 |
}
|
sl@0
|
108 |
|
sl@0
|
109 |
default:
|
sl@0
|
110 |
break;
|
sl@0
|
111 |
}
|
sl@0
|
112 |
|
sl@0
|
113 |
// stest.Getch();
|
sl@0
|
114 |
stest.End();
|
sl@0
|
115 |
return(KErrNone);
|
sl@0
|
116 |
}
|
sl@0
|
117 |
|
sl@0
|
118 |
GLDEF_C TInt E32Main()
|
sl@0
|
119 |
|
sl@0
|
120 |
{
|
sl@0
|
121 |
__UHEAP_MARK;
|
sl@0
|
122 |
|
sl@0
|
123 |
Test.Title();
|
sl@0
|
124 |
|
sl@0
|
125 |
TInt r;
|
sl@0
|
126 |
Test.Start(_L("Load sound PDD"));
|
sl@0
|
127 |
r=User::LoadPhysicalDevice(KSndPddFileName);
|
sl@0
|
128 |
if (r==KErrNotFound)
|
sl@0
|
129 |
{
|
sl@0
|
130 |
Test.Printf(_L("Shared chunk sound driver not supported - test skipped\r\n"));
|
sl@0
|
131 |
Test.End();
|
sl@0
|
132 |
Test.Close();
|
sl@0
|
133 |
__UHEAP_MARKEND;
|
sl@0
|
134 |
return(KErrNone);
|
sl@0
|
135 |
}
|
sl@0
|
136 |
Test(r==KErrNone || r==KErrAlreadyExists);
|
sl@0
|
137 |
|
sl@0
|
138 |
Test.Next(_L("Load sound LDD"));
|
sl@0
|
139 |
r=User::LoadLogicalDevice(KSndLddFileName);
|
sl@0
|
140 |
Test(r==KErrNone || r==KErrAlreadyExists);
|
sl@0
|
141 |
|
sl@0
|
142 |
/** @SYMTestCaseID PBASE-T_SOUNDMCHAN-224
|
sl@0
|
143 |
@SYMTestCaseDesc Opening the channel - more than one channel
|
sl@0
|
144 |
@SYMTestPriority Critical
|
sl@0
|
145 |
@SYMTestActions 1) With the LDD and PDD installed and with all channels closed on the device,
|
sl@0
|
146 |
open a channel for playback on the device.
|
sl@0
|
147 |
2) Without closing the first playback channel, attempt to open a second channel
|
sl@0
|
148 |
for playback on the same device.
|
sl@0
|
149 |
@SYMTestExpectedResults 1) KErrNone - Channel opens successfully.
|
sl@0
|
150 |
2) Should fail with KErrInUse.
|
sl@0
|
151 |
@SYMREQ PREQ1073.4 */
|
sl@0
|
152 |
|
sl@0
|
153 |
__KHEAP_MARK;
|
sl@0
|
154 |
|
sl@0
|
155 |
Test.Next(_L("Open a channel on the play device"));
|
sl@0
|
156 |
RSoundSc snddev;
|
sl@0
|
157 |
r=snddev.Open(KSoundScTxUnit0);
|
sl@0
|
158 |
Test(r==KErrNone);
|
sl@0
|
159 |
|
sl@0
|
160 |
Test.Next(_L("Try opening the same unit a second time."));
|
sl@0
|
161 |
RSoundSc snddev2;
|
sl@0
|
162 |
r=snddev2.Open(KSoundScTxUnit0);
|
sl@0
|
163 |
Test(r==KErrInUse);
|
sl@0
|
164 |
|
sl@0
|
165 |
Test.Next(_L("Query play formats supported"));
|
sl@0
|
166 |
TSoundFormatsSupportedV02Buf capsBuf;
|
sl@0
|
167 |
snddev.Caps(capsBuf);
|
sl@0
|
168 |
TSoundFormatsSupportedV02& caps=capsBuf();
|
sl@0
|
169 |
PrintCaps(caps,Test);
|
sl@0
|
170 |
|
sl@0
|
171 |
Test.Next(_L("Try playing without setting the buffer config"));
|
sl@0
|
172 |
TRequestStatus pStat;
|
sl@0
|
173 |
snddev.PlayData(pStat,0,0x2000); // 8K
|
sl@0
|
174 |
User::WaitForRequest(pStat);
|
sl@0
|
175 |
Test(pStat.Int()==KErrNotReady);
|
sl@0
|
176 |
|
sl@0
|
177 |
Test.Next(_L("Configure the channel from a 2nd thread"));
|
sl@0
|
178 |
RThread thread;
|
sl@0
|
179 |
TRequestStatus tStat;
|
sl@0
|
180 |
SSecondaryThreadInfo sti;
|
sl@0
|
181 |
|
sl@0
|
182 |
sti.iTestId=ESecThreadConfigPlayback;
|
sl@0
|
183 |
sti.iThreadId=RThread().Id(); // Get the ID of this thread
|
sl@0
|
184 |
sti.iDrvHandle=snddev.Handle(); // Pass the channel handle
|
sl@0
|
185 |
|
sl@0
|
186 |
/** @SYMTestCaseID PBASE-T_SOUNDMCHAN-225
|
sl@0
|
187 |
@SYMTestCaseDesc Opening the channel - sharing the handle between threads
|
sl@0
|
188 |
@SYMTestPriority Critical
|
sl@0
|
189 |
@SYMTestActions 1) With the LDD and PDD installed and with all channels closed on the device, open a
|
sl@0
|
190 |
channel for playback on the device. Now create a second thread. Resume this
|
sl@0
|
191 |
thread - passing the handle to the playback channel to it. Wait for the second
|
sl@0
|
192 |
thread to terminate.
|
sl@0
|
193 |
2) In the second thread, duplicate the playback channel handle.
|
sl@0
|
194 |
3) In the second thread, using the duplicated handle, issue a request to set the audio configuration.
|
sl@0
|
195 |
4) In the second thread, using the duplicated handle, issue a request to set the volume.
|
sl@0
|
196 |
5) In the second thread, close the handle and exit the thread.
|
sl@0
|
197 |
6) In the first thread, read back the audio configuration.
|
sl@0
|
198 |
7) In the first thread, set the buffer configuration, and then issue a request to play
|
sl@0
|
199 |
audio data.
|
sl@0
|
200 |
8) In the first thread, close the channel.
|
sl@0
|
201 |
@SYMTestExpectedResults 1) KErrNone - Channel opens successfully.
|
sl@0
|
202 |
2) KErrNone - Duplication of the handle succeeds.
|
sl@0
|
203 |
3) KErrNone - Audio configured successfully.
|
sl@0
|
204 |
4) KErrNone - Volume set successfully.
|
sl@0
|
205 |
5) No errors occur closing the channel and exiting the thread.
|
sl@0
|
206 |
6) The audio configuration should correspond to that set by the second thread.
|
sl@0
|
207 |
7) KErrNone - Setting the buffer configuration and issuing a play request.
|
sl@0
|
208 |
8) No errors occur closing the channel.
|
sl@0
|
209 |
@SYMREQ PREQ1073.4 */
|
sl@0
|
210 |
|
sl@0
|
211 |
r=thread.Create(_L("Thread"),secondaryThread,KDefaultStackSize,KHeapSize,KHeapSize,&sti); // Create secondary thread
|
sl@0
|
212 |
Test(r==KErrNone);
|
sl@0
|
213 |
thread.Logon(tStat);
|
sl@0
|
214 |
thread.Resume();
|
sl@0
|
215 |
User::WaitForRequest(tStat);
|
sl@0
|
216 |
Test(tStat.Int()==KErrNone);
|
sl@0
|
217 |
// Test.Printf(_L("Thread exit info: Cat:%S, Reason:%x, Type:%d\r\n"),&thread.ExitCategory(),thread.ExitReason(),thread.ExitType());
|
sl@0
|
218 |
Test(thread.ExitType()==EExitKill);
|
sl@0
|
219 |
thread.Close();
|
sl@0
|
220 |
User::After(10000); // Wait 10ms
|
sl@0
|
221 |
|
sl@0
|
222 |
Test.Next(_L("Read back the play configuration"));
|
sl@0
|
223 |
TCurrentSoundFormatV02Buf formatBuf;
|
sl@0
|
224 |
snddev.AudioFormat(formatBuf);
|
sl@0
|
225 |
TCurrentSoundFormatV02& format=formatBuf();
|
sl@0
|
226 |
PrintConfig(format,Test);
|
sl@0
|
227 |
|
sl@0
|
228 |
Test.Next(_L("Set the buffer configuration"));
|
sl@0
|
229 |
RChunk chunk;
|
sl@0
|
230 |
TInt bufSize=BytesPerSecond(formatBuf()); // Large enough to hold 1 second of data.
|
sl@0
|
231 |
bufSize=ValidBufferSize(bufSize,caps.iRequestMinSize,formatBuf()); // Keep the buffer length valid for driver.
|
sl@0
|
232 |
TTestSharedChunkBufConfig bufferConfig;
|
sl@0
|
233 |
bufferConfig.iNumBuffers=1;
|
sl@0
|
234 |
bufferConfig.iBufferSizeInBytes=bufSize;
|
sl@0
|
235 |
bufferConfig.iFlags=0;
|
sl@0
|
236 |
TPckg<TTestSharedChunkBufConfig> bufferConfigBuf(bufferConfig);
|
sl@0
|
237 |
r=snddev.SetBufferChunkCreate(bufferConfigBuf,chunk);
|
sl@0
|
238 |
Test(r==KErrNone);
|
sl@0
|
239 |
snddev.GetBufferConfig(bufferConfigBuf);
|
sl@0
|
240 |
PrintBufferConf(bufferConfig,Test);
|
sl@0
|
241 |
Test(bufferConfig.iBufferSizeInBytes==bufSize);
|
sl@0
|
242 |
|
sl@0
|
243 |
Test.Next(_L("Start playing"));
|
sl@0
|
244 |
r=MakeSineTable(format);
|
sl@0
|
245 |
Test(r==KErrNone);
|
sl@0
|
246 |
r=SetToneFrequency(660,format);
|
sl@0
|
247 |
Test(r==KErrNone);
|
sl@0
|
248 |
TPtr8 ptr(chunk.Base()+bufferConfig.iBufferOffsetList[0],bufSize);
|
sl@0
|
249 |
WriteTone(ptr,format);
|
sl@0
|
250 |
snddev.PlayData(pStat,bufferConfig.iBufferOffsetList[0],bufSize,KSndFlagLastSample);
|
sl@0
|
251 |
User::WaitForRequest(pStat);
|
sl@0
|
252 |
Test(tStat.Int()==KErrNone);
|
sl@0
|
253 |
|
sl@0
|
254 |
Test.Next(_L("Close the drivers and the chunk"));
|
sl@0
|
255 |
chunk.Close();
|
sl@0
|
256 |
snddev.Close();
|
sl@0
|
257 |
|
sl@0
|
258 |
__KHEAP_MARKEND;
|
sl@0
|
259 |
|
sl@0
|
260 |
Test.Next(_L("Unload the drivers"));
|
sl@0
|
261 |
|
sl@0
|
262 |
r=User::FreeLogicalDevice(KDevSoundScName);
|
sl@0
|
263 |
Test.Printf(_L("Unloading %S.LDD - %d\r\n"),&KDevSoundScName,r);
|
sl@0
|
264 |
Test(r==KErrNone);
|
sl@0
|
265 |
|
sl@0
|
266 |
TName pddName(KDevSoundScName);
|
sl@0
|
267 |
_LIT(KPddWildcardExtension,".*");
|
sl@0
|
268 |
pddName.Append(KPddWildcardExtension);
|
sl@0
|
269 |
TFindPhysicalDevice findPD(pddName);
|
sl@0
|
270 |
TFullName findResult;
|
sl@0
|
271 |
r=findPD.Next(findResult);
|
sl@0
|
272 |
while (r==KErrNone)
|
sl@0
|
273 |
{
|
sl@0
|
274 |
r=User::FreePhysicalDevice(findResult);
|
sl@0
|
275 |
Test.Printf(_L("Unloading %S.PDD - %d\r\n"),&findResult,r);
|
sl@0
|
276 |
Test(r==KErrNone);
|
sl@0
|
277 |
findPD.Find(pddName); // Reset the find handle now that we have deleted something from the container.
|
sl@0
|
278 |
r=findPD.Next(findResult);
|
sl@0
|
279 |
}
|
sl@0
|
280 |
|
sl@0
|
281 |
Test.End();
|
sl@0
|
282 |
Test.Close();
|
sl@0
|
283 |
|
sl@0
|
284 |
Cleanup();
|
sl@0
|
285 |
|
sl@0
|
286 |
__UHEAP_MARKEND;
|
sl@0
|
287 |
|
sl@0
|
288 |
return(KErrNone);
|
sl@0
|
289 |
}
|