VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/audiosniffer.c@ 33000

Last change on this file since 33000 was 32339, checked in by vboxsync, 14 years ago

Undid accidental commit of debug code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.8 KB
Line 
1/* $Id: audiosniffer.c 32339 2010-09-09 11:18:59Z vboxsync $ */
2/** @file
3 * VBox audio device: Audio sniffer device
4 */
5
6/*
7 * Copyright (C) 2006-2007 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_GROUP LOG_GROUP_DEV_AUDIO
19#define AUDIO_CAP "sniffer"
20#include <VBox/pdm.h>
21#include <VBox/err.h>
22
23#include <VBox/log.h>
24#include <iprt/assert.h>
25#include <iprt/uuid.h>
26#include <iprt/string.h>
27#include <iprt/alloc.h>
28
29#include "Builtins.h"
30#include "../../vl_vbox.h"
31
32#include "audio.h"
33#include "audio_int.h"
34
35typedef struct _AUDIOSNIFFERSTATE
36{
37 /** If the device is enabled. */
38 bool fEnabled;
39
40 /** Whether audio should reach the host driver too. */
41 bool fKeepHostAudio;
42
43 /** Pointer to device instance. */
44 PPDMDEVINS pDevIns;
45
46 /** Audio Sniffer port base interface. */
47 PDMIBASE IBase;
48 /** Audio Sniffer port interface. */
49 PDMIAUDIOSNIFFERPORT IPort;
50
51 /** Pointer to base interface of the driver. */
52 PPDMIBASE pDrvBase;
53 /** Audio Sniffer connector interface */
54 PPDMIAUDIOSNIFFERCONNECTOR pDrv;
55
56} AUDIOSNIFFERSTATE;
57
58static AUDIOSNIFFERSTATE *g_pData = NULL;
59
60/*
61 * Public sniffer callbacks to be called from audio driver.
62 */
63
64/* *** Subject to change ***
65 * Process audio output. The function is called when an audio output
66 * driver is about to play audio samples.
67 *
68 * It is expected that there is only one audio data flow,
69 * i.e. one voice.
70 *
71 * @param hw Audio samples information.
72 * @param pvSamples Pointer to audio samples.
73 * @param cSamples Number of audio samples in the buffer.
74 * @returns 'true' if audio also to be played back by the output driver.
75 * 'false' if audio should not be played.
76 */
77DECLCALLBACK(bool) sniffer_run_out (HWVoiceOut *hw, void *pvSamples, unsigned cSamples)
78{
79 int samplesPerSec;
80 int nChannels;
81 int bitsPerSample;
82 bool fUnsigned;
83
84 if (!g_pData || !g_pData->pDrv || !g_pData->fEnabled)
85 {
86 return true;
87 }
88
89 samplesPerSec = hw->info.freq;
90 nChannels = hw->info.nchannels;
91 bitsPerSample = hw->info.bits;
92 fUnsigned = (hw->info.sign == 0);
93
94 g_pData->pDrv->pfnAudioSamplesOut (g_pData->pDrv, pvSamples, cSamples,
95 samplesPerSec, nChannels, bitsPerSample, fUnsigned);
96
97 return g_pData->fKeepHostAudio;
98}
99
100
101/*
102 * Audio Sniffer PDM device.
103 */
104
105static DECLCALLBACK(int) iface_Setup (PPDMIAUDIOSNIFFERPORT pInterface, bool fEnable, bool fKeepHostAudio)
106{
107 AUDIOSNIFFERSTATE *pThis = RT_FROM_MEMBER(pInterface, AUDIOSNIFFERSTATE, IPort);
108
109 Assert(g_pData == pThis);
110
111 pThis->fEnabled = fEnable;
112 pThis->fKeepHostAudio = fKeepHostAudio;
113
114 return VINF_SUCCESS;
115}
116
117/**
118 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
119 */
120static DECLCALLBACK(void *) iface_QueryInterface(PPDMIBASE pInterface, const char *pszIID)
121{
122 AUDIOSNIFFERSTATE *pThis = RT_FROM_MEMBER(pInterface, AUDIOSNIFFERSTATE, IBase);
123 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
124 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIAUDIOSNIFFERPORT, &pThis->IPort);
125 return NULL;
126}
127
128/**
129 * Destruct a device instance.
130 *
131 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
132 * resources can be freed correctly.
133 *
134 * @returns VBox status.
135 * @param pDevIns The device instance data.
136 */
137static DECLCALLBACK(int) audioSnifferR3Destruct(PPDMDEVINS pDevIns)
138{
139 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
140
141 /* Zero the global pointer. */
142 g_pData = NULL;
143
144 return VINF_SUCCESS;
145}
146
147/**
148 * @interface_method_impl{PDMDEVREG,pfnConstruct}
149 */
150static DECLCALLBACK(int) audioSnifferR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
151{
152 int rc = VINF_SUCCESS;
153 AUDIOSNIFFERSTATE *pThis = PDMINS_2_DATA(pDevIns, AUDIOSNIFFERSTATE *);
154
155 Assert(iInstance == 0);
156 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
157
158 /*
159 * Validate configuration.
160 */
161 if (!CFGMR3AreValuesValid(pCfgHandle, "\0"))
162 {
163 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
164 }
165
166 /*
167 * Initialize data.
168 */
169 pThis->fEnabled = false;
170 pThis->fKeepHostAudio = true;
171 pThis->pDrv = NULL;
172
173 /*
174 * Interfaces
175 */
176 /* Base */
177 pThis->IBase.pfnQueryInterface = iface_QueryInterface;
178
179 /* Audio Sniffer port */
180 pThis->IPort.pfnSetup = iface_Setup;
181
182 /*
183 * Get the corresponding connector interface
184 */
185 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Audio Sniffer Port");
186
187 if (RT_SUCCESS(rc))
188 {
189 pThis->pDrv = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIAUDIOSNIFFERCONNECTOR);
190 AssertMsgStmt(pThis->pDrv, ("LUN #0 doesn't have a Audio Sniffer connector interface rc=%Rrc\n", rc),
191 rc = VERR_PDM_MISSING_INTERFACE);
192 }
193 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
194 {
195 Log(("%s/%d: warning: no driver attached to LUN #0.\n", pDevIns->pReg->szName, pDevIns->iInstance));
196 rc = VINF_SUCCESS;
197 }
198 else
199 {
200 AssertMsgFailed(("Failed to attach LUN #0. rc=%Rrc\n", rc));
201 }
202
203 if (RT_SUCCESS (rc))
204 {
205 /* Save PDM device instance data for future reference. */
206 pThis->pDevIns = pDevIns;
207
208 /* Save the pointer to created instance in the global variable, so other
209 * functions could reach it.
210 */
211 g_pData = pThis;
212 }
213
214 return rc;
215}
216
217/**
218 * The Audio Sniffer device registration structure.
219 */
220const PDMDEVREG g_DeviceAudioSniffer =
221{
222 /* u32Version */
223 PDM_DEVREG_VERSION,
224 /* szName */
225 "AudioSniffer",
226 /* szRCMod */
227 "",
228 /* szR0Mod */
229 "",
230 /* pszDescription */
231 "Audio Sniffer device. Redirects audio data to sniffer driver.",
232 /* fFlags */
233 PDM_DEVREG_FLAGS_DEFAULT_BITS,
234 /* fClass */
235 PDM_DEVREG_CLASS_AUDIO,
236 /* cMaxInstances */
237 1,
238 /* cbInstance */
239 sizeof(AUDIOSNIFFERSTATE),
240 /* pfnConstruct */
241 audioSnifferR3Construct,
242 /* pfnDestruct */
243 audioSnifferR3Destruct,
244 /* pfnRelocate */
245 NULL,
246 /* pfnIOCtl */
247 NULL,
248 /* pfnPowerOn */
249 NULL,
250 /* pfnReset */
251 NULL,
252 /* pfnSuspend */
253 NULL,
254 /* pfnResume */
255 NULL,
256 /* pfnAttach */
257 NULL,
258 /* pfnDetach */
259 NULL,
260 /* pfnQueryInterface */
261 NULL,
262 /* pfnInitComplete */
263 NULL,
264 /* pfnPowerOff */
265 NULL,
266 /* pfnSoftReset */
267 NULL,
268 PDM_DEVREG_VERSION
269};
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use