HRESULT CVCamStream::Inactive()
{
	// we get here
	ShowOutput("inactive: about to release loopback");
	loopBackRelease();
	ShowOutput("loopback released");
	currentlyRunning = 0; //allow it to restart later...
	return CSourceStream::Inactive(); //parent method
}
예제 #2
0
int CBProfilerExecDlg::Execute(wxString exename, wxString dataname, struct_config config)
{
    // gprof optional parameters
    wxString param = config.txtExtra;
    if (config.chkAnnSource && !config.txtAnnSource.IsEmpty()) param << _T(" -A")  << config.txtAnnSource;
    if (config.chkMinCount)                                    param << _T(" -m ") << config.spnMinCount;
    if (config.chkBrief)                                       param << _T(" -b");
    if (config.chkFileInfo)                                    param << _T(" -i");
    if (config.chkUnusedFunctions)                             param << _T(" -z");
    if (config.chkStaticCallGraph)                             param << _T(" -c");
    if (config.chkNoStatic)                                    param << _T(" -a");
    if (config.chkSum)                                         param << _T(" -s");

    wxString cmd;
    cmd << _T("gprof ") << param << _T(" \"") << exename << _T("\" \"") << dataname << _T("\"");

    int pid = -1;

    { // begin lifetime of wxBusyInfo
      wxBusyInfo wait(_("Please wait, while running gprof..."), parent);
      Manager::Get()->GetLogManager()->DebugLog(F(_T("Profiler: Running command %s"), cmd.wx_str()));
      pid = wxExecute(cmd, gprof_output, gprof_errors);
    } // end lifetime of wxBusyInfo

    if (pid == -1)
    {
        wxString msg = _("Unable to execute gprof.\nBe sure the gprof executable is in the OS global path.\nC::B Profiler could not complete the operation.");
        cbMessageBox(msg, _("Error"), wxICON_ERROR | wxOK, (wxWindow*)Manager::Get()->GetAppWindow());
        Manager::Get()->GetLogManager()->DebugLog(msg);

        return -1;
    }
    else
    {
        wxXmlResource::Get()->LoadObject(this, parent, _T("dlgCBProfilerExec"),_T("wxScrollingDialog"));
        wxFont font(10, wxMODERN, wxNORMAL, wxNORMAL);
        outputFlatProfileArea     = XRCCTRL(*this, "lstFlatProfile",     wxListCtrl);
        outputHelpFlatProfileArea = XRCCTRL(*this, "txtHelpFlatProfile", wxTextCtrl);
        outputHelpFlatProfileArea->SetFont(font);
        outputCallGraphArea       = XRCCTRL(*this, "lstCallGraph",       wxListCtrl);
        outputHelpCallGraphArea   = XRCCTRL(*this, "txtHelpCallGraph",   wxTextCtrl);
        outputHelpCallGraphArea->SetFont(font);
        outputMiscArea            = XRCCTRL(*this, "txtMisc",            wxTextCtrl);
        outputMiscArea->SetFont(font);

        if(!gprof_output.IsEmpty())
            ShowOutput(gprof_output, false);
        else
            ShowOutput(gprof_errors, true);
    }

    return 0;
}
void propagateWithRawCurrentFormat(WAVEFORMATEX *toThis) {
	WAVEFORMATEX *pwfx;
	IMMDevice *pMMDevice;
	IAudioClient *pAudioClient;
    HANDLE hTask;
    DWORD nTaskIndex = 0;
    hTask = AvSetMmThreadCharacteristics(L"Capture", &nTaskIndex);

    HRESULT hr = get_default_device(&pMMDevice);
    if (FAILED(hr)) {
        assert(false);
    }
	// activate an (the default, for us, since we want loopback) IAudioClient
    hr = pMMDevice->Activate(
        __uuidof(IAudioClient),
        CLSCTX_ALL, NULL,
        (void**)&pAudioClient
    );
    if (FAILED(hr)) {
        ShowOutput("IMMDevice::Activate(IAudioClient) failed: hr = 0x%08x", hr);
		assert(false);
    }

	hr = pAudioClient->GetMixFormat(&pwfx);
    if (FAILED(hr)) {
        ShowOutput("IAudioClient::GetMixFormat failed: hr = 0x%08x\n", hr);
        CoTaskMemFree(pwfx);
        pAudioClient->Release();
   		assert(false);
    }
	pAudioClient->Stop();
    AvRevertMmThreadCharacteristics(hTask);
    pAudioClient->Release();
    pMMDevice->Release();
	memcpy(toThis, pwfx, sizeof(WAVEFORMATEX));
	CoTaskMemFree(pwfx); 
}
//
// FillBuffer
//
// Stuffs the buffer with data
// "they" call this, every so often...
HRESULT CVCamStream::FillBuffer(IMediaSample *pms) 
{	
	// I don't expect these...the parent controls this/us and doesn't call us when it is stopped I guess, so we should always be active...
	ShowOutput("requested audio frame");
	//assert(m_pParent->IsActive()); // one of these can cause freezing on "stop button" in FME
	//assert(!m_pParent->IsStopped());

    CheckPointer(pms,E_POINTER);
    BYTE *pData;
    HRESULT hr = pms->GetPointer(&pData);
    if (FAILED(hr)) {
		ShowOutput("fail 1");
		assert(false);
        return hr;
    }
    
	LONG totalWrote = -1;
	// the real meat -- get all the incoming data
	hr = LoopbackCaptureTakeFromBuffer(pData, pms->GetSize(), NULL, &totalWrote);
	if(FAILED(hr)) {
		// this one can return false during shutdown, so it's actually ok to just return from here...
		// assert(false);
		ShowOutput("shutdown 1");
		return hr;
	}

	CAutoLock cAutoLockShared(&gSharedState); // for the bFirstPacket boolean control, except there's probably still some odd race conditions er other...

	hr = pms->SetActualDataLength(totalWrote);
	if(FAILED(hr)) {
  	  	assert(false);
		return hr;
	}

    // Now set the sample's start and end time stamps...

	WAVEFORMATEX* pwfexCurrent = (WAVEFORMATEX*)m_mt.Format();
	CRefTime sampleTimeUsed = (REFERENCE_TIME)(UNITS * pms->GetActualDataLength()) / 
                     (REFERENCE_TIME)pwfexCurrent->nAvgBytesPerSec;
    CRefTime rtStart;
	if(bFirstPacket) { // either have bFirstPacket or true here...true seemed to help that one guy...
      m_pParent->StreamTime(rtStart); // gets current graph ref time [now] as its "start", as normal "capture" devices would, just in case that's better...
	  if(bFirstPacket)
	    ShowOutput("got an audio first packet or discontinuity detected");
	} else {
		// since there hasn't been discontinuity, I think we should be safe to tell it
		// that this packet starts where the previous packet ended off
		// since that's theoretically accurate...
		// exept that it ends up being bad [?]
		// I don't "think" this will hurt graphs that have no reference clock...hopefully...

		rtStart = m_rtPreviousSampleEndTime;

        // CRefTime cur_time;
	    // m_pParent->StreamTime(cur_time);
	    // rtStart = max(rtStart, cur_time);
		// hopefully this avoids this message/error:
		// [libmp3lame @ 00670aa0] Que input is backward in time
        // Audio timestamp 329016 < 329026 invalid, cliping00:05:29.05 bitrate= 738.6kbits/s
        // [libmp3lame @ 00670aa0] Que input is backward in time
	}

	// I once tried to change it to always have monotonicity of timestamps at this point, but it didn't fix any problems, and seems to do all right without it so maybe ok [?]
    m_rtPreviousSampleEndTime = rtStart + sampleTimeUsed;

	// NB that this *can* set it to a negative start time...hmm...which apparently is "ok" when a graph is just starting up it's expected...
    hr = pms->SetTime((REFERENCE_TIME*) &rtStart, (REFERENCE_TIME*) &m_rtPreviousSampleEndTime);
	if (FAILED(hr)) {
		assert(false);
        return hr;
    }
	// if we do SetTime(NULL, NULL) here then VLC can "play" it with directshows buffers of size 0ms.
	// however, then VLC cannot then stream it at all.  So we leave it set to some time, and just require you to have VLC buffers of at least 40 or 50 ms
	// [a possible VLC bug?] http://forum.videolan.org/viewtopic.php?f=14&t=92659&hilit=+50ms

	// whatever SetMediaTime even does...
    // hr = pms->SetMediaTime((REFERENCE_TIME*)&rtStart, (REFERENCE_TIME*)&m_rtPreviousSampleEndTime);
    //m_llSampleMediaTimeStart = m_rtSampleEndTime;

	if (FAILED(hr)) {
		assert(false);
        return hr;
    }

    // Set the sample's properties.
    hr = pms->SetPreroll(FALSE); // tell it that this isn't preroll, so to actually use it...I think.
    if (FAILED(hr)) {
		assert(false);
        return hr;
    }

    hr = pms->SetMediaType(NULL);
    if (FAILED(hr)) {
		assert(false);
        return hr;
    }
   
    hr = pms->SetDiscontinuity(bFirstPacket); // true for the first
    if (FAILED(hr)) {
		assert(false);
        return hr;
    }
    
	// Set TRUE on every sample for PCM audio http://msdn.microsoft.com/en-us/library/windows/desktop/dd407021%28v=vs.85%29.aspx
    hr = pms->SetSyncPoint(TRUE);
	if (FAILED(hr)) {
		assert(false);
        return hr;
    }
	FILTER_STATE State;
	m_pParent->GetState(0, &State);
	
	ShowOutput("sent audio frame, %d blips, state %d", totalBlips, State);

	bFirstPacket = false;
    return S_OK;

} // end FillBuffer
예제 #5
0
MainWidget::MainWidget(QWidget *parent, RunClass *runCl, QThreadPool *tPool, DataClass *dataCl)
{
    lProjectName = new QLabel("Project Name");
    leProjectName = new QLineEdit();
    leProjectName->setText("default");
    leProjectName->setAlignment(AlignHCenter);
    lLoad = new QLabel("Load input");
    pbLoad = new QPushButton("Load");
    lHeuristic = new QLabel("Heuristic parameter");
    sbHeuristic = new QSpinBox();
    sbHeuristic->setAlignment(AlignRight);
    lMCvariant = new QLabel("MC variant");
    cbMCvariant = new QComboBox();
    cbMCvariant->addItem("ASAP");
    cbMCvariant->addItem("Fixed time");
    lMCsamples = new QLabel("MC samples");
    sbMCsamples = new QSpinBox();
    sbMCsamples->setAlignment(AlignRight);
    sbMCsamples->setMaximum(1000000000);
    sbMCsamples->setValue(100);
    lProjectStart = new QLabel("Project starting date");
    deProjectStart = new QDateEdit();
    QDate *curDate = new QDate;
    deProjectStart->setDate(curDate->currentDate());
    deProjectStart->setAlignment(AlignRight);
    pbProgress = new QProgressBar();
    lRun = new QLabel("Run");
    pbRun = new QPushButton("Run");
    lShow = new QLabel("Show results");
    pbShow = new QPushButton("Show");
    teNotes = new QTextEdit();
    teNotes->setText("Notes");

    layProjectName = new QHBoxLayout();
    layLoad = new QHBoxLayout();
    layHeuristic = new QHBoxLayout();
    layMCvariant = new QHBoxLayout();
    layMCsamples = new QHBoxLayout();
    layProjectStart = new QHBoxLayout();
    layRun = new QHBoxLayout();
    layShow = new QHBoxLayout();

    layAll = new QVBoxLayout();

    layProjectName->addWidget(lProjectName);
    layProjectName->addWidget(leProjectName);
    layLoad->addWidget(lLoad);
    layLoad->addWidget(pbLoad);
    layHeuristic->addWidget(lHeuristic);
    layHeuristic->addWidget(sbHeuristic);
    layMCvariant->addWidget(lMCvariant);
    layMCvariant->addWidget(cbMCvariant);
    layMCsamples->addWidget(lMCsamples);
    layMCsamples->addWidget(sbMCsamples);
    layProjectStart->addWidget(lProjectStart);
    layProjectStart->addWidget(deProjectStart);
    layRun->addWidget(lRun);
    layRun->addWidget(pbRun);
    layShow->addWidget(lShow);
    layShow->addWidget(pbShow);

    layAll->addLayout(layProjectName);
    layAll->addLayout(layLoad);
    layAll->addLayout(layHeuristic);
    layAll->addLayout(layMCvariant);
    layAll->addLayout(layMCsamples);
    layAll->addLayout(layProjectStart);
    layAll->addLayout(layRun);
    layAll->addWidget(pbProgress);
    layAll->addLayout(layShow);
    layAll->addWidget(teNotes);

    resize(250,350);
    setLayout(layAll);
    setWindowTitle("BM risk prediction");

    connect(pbLoad, SIGNAL(clicked()), this, SLOT(loadInput()));
    connect(pbRun, SIGNAL(clicked()), this, SLOT(Run()));
    connect(pbShow, SIGNAL(clicked()), this, SLOT(ShowOutput()));

    data = dataCl;

    data->strProjectName = "default";
    data->inputData = "";
    data->input = data->inputData.toStdString();
    data->heurPar = 0;
    data->MCvar = 0;
    data->MCsamples = 100;
    data->startDate = curDate->currentDate();
    data->notes = "";
    data->mc_study_max = 0;
    data->mc_study_min = 0;

    runClass = runCl;
    threadPool = tPool;
    connect(runClass, SIGNAL(changeProgress(int)), pbProgress, SLOT(setValue(int)));
}
int main(int argc, char **argv)
{
    wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "program");

    wxInitializer initializer;
    if ( !initializer )
    {
        fprintf(stderr, "Failed to initialize the wxWidgets library, aborting.");
        return -1;
    }

    bool base_only_flags = false;

    bool wants_static = false;
    bool wants_shared = false;
    bool wants_unicode = false;
    bool wants_ANSI = false;
    bool wants_debug = false;
    bool wants_release = false;
    bool wants_version = false;
    bool show_version = false;

    bool do_list_option = false;
    bool do_cflags_option = false;
    bool do_libs_option = false;

    wxString version_value;
    wxString libs_value;
    wxString shell_value;
    wxString wxconfig_value;

    // Parse command line section
    if ( argc == 1 )
    {
        // If there were no command-line options supplied, emit a message
        // otherwise it's not obvious that the command ran successfully
        std::cout << "Welcome to the wx-config for MSys2!" << std::endl;
        std::cout << "For more information, run it again with the --help option" << std::endl;
        return 1;
    }
    else
    {
        try
        {
            cxxopts::Options options("wx-config.exe");

            options.add_options()
                ("shell", "Shell file", cxxopts::value<std::string>()
                    ->default_value("sh.exe")->implicit_value("sh.exe"), "C:/MSys2/usr/bin/sh.exe")
                ("wxconfig", "wx-config", cxxopts::value<std::string>()
                    ->default_value("")->implicit_value(""), "C:/MSys2/mingw32/bin/wx-config")
                ("static", "Uses a static configuration if found.", cxxopts::value<std::string>()
                    ->default_value("")->implicit_value("yes"))
                ("unicode", "Uses a unicode configuration if found.", cxxopts::value<std::string>()
                    ->default_value("")->implicit_value("yes"))
                ("debug", "Uses a debug configuration if found.", cxxopts::value<std::string>()
                    ->default_value("")->implicit_value("yes"))
                ("version", "Uses the wxWidgets version if found.", cxxopts::value<std::string>()
                    ->default_value("")->implicit_value("show-version"))
                ("libs", "Outputs all linker flags", cxxopts::value<std::string>()
                    ->default_value("")->implicit_value("std"))
                ("no-gui", "Outputs the base flags (non GUI) if cflags used.")
                ("cflags", "Outputs all pre-processor and C compiler flags.")
                ("list", "Lists the wxWidgets configurations found.")
                ("v,ver", "Outputs the revision of wx-config.exe")
                ("help", "wx-config.exe for MSys2 help message")
            ;

            options.parse(argc, argv);

            if (options.count("help"))
            {
                std::cout << options.help({""}) << std::endl;
                exit(0);
            }

            if (options.count("v"))
            {
                std::cout << "Beta version 0.24 with cxxopts" << std::endl;
                return 0;
            }

            if (options.count("list"))
            {
                do_list_option = true;
            }

            if (options.count("shell"))
            {
                shell_value = options["shell"].as<std::string>();
            }

            if (options.count("wxconfig"))
            {
                wxconfig_value = options["wxconfig"].as<std::string>();
            }

            if (options.count("static"))
            {
                if ("yes" == options["static"].as<std::string>()) {
                    wants_static = true;
                } else if ("no" == options["static"].as<std::string>()) {
                    wants_shared = true;
                }
            }

            if (options.count("unicode"))
            {
                if ("yes" == options["unicode"].as<std::string>()) {
                    wants_unicode = true;
                } else if ("no" == options["unicode"].as<std::string>()) {
                    wants_ANSI = true;
                }
            }

            if (options.count("debug"))
            {
                if ("yes" == options["debug"].as<std::string>()) {
                    wants_debug = true;
                } else if ("no" == options["debug"].as<std::string>()) {
                    wants_release = true;
                }
            }

            if (options.count("version"))
            {
                version_value = options["version"].as<std::string>();
                if ("show-version" == version_value) {
                    show_version = true;
                } else if ("" != version_value){
                    wants_version = true;
                }
            }

            if (options.count("libs"))
            {
                libs_value = options["libs"].as<std::string>();
                if ("" != libs_value) {
                    do_libs_option = true;
                }
            }
            if (options.count("no-gui"))
            {
                base_only_flags = true;
            }
            if (options.count("cflags"))
            {
                do_cflags_option = true;
            }
        }
        catch (const cxxopts::OptionException& e)
        {
            std::cout << "parsing command line options error: " << e.what() << std::endl;
            exit(1);
        }
    }

// Command line verification section
    wxString prefix_dir;
    wxString cmd_base;
    if ("sh.exe" == shell_value || wxFileName::IsFileExecutable(shell_value))
    {
        wxFileName shell = shell_value;
        wxString cygpath = "cygpath";
        if ("sh.exe" != shell_value){
            shell.Normalize();
            wxString path_to_shell = shell.GetPath(wxPATH_GET_VOLUME|wxPATH_GET_SEPARATOR);
            path_to_shell.Replace("\\", "/");

            if ("/" != path_to_shell){
                cygpath = path_to_shell + cygpath;
            }
        }
        if ("" == wxconfig_value){
            wxString cmd = cygpath + " --mixed /mingw64/bin/wx-config";
            wxArrayString output, errors;
            int code = wxExecute(cmd, output, errors);
            if (!code) wxconfig_value = output[0];
            if (!wxFileName::IsFileReadable(wxconfig_value)){
                wxconfig_value = "";
            }
        }
        if ("" == wxconfig_value){
            wxString cmd = cygpath + " --mixed /mingw32/bin/wx-config";
            wxArrayString output, errors;
            int code = wxExecute(cmd, output, errors);
            if (!code) wxconfig_value = output[0];
            if (!wxFileName::IsFileReadable(wxconfig_value)){
                wxconfig_value = "";
            }
        }
        if ("" == wxconfig_value){
            wxString cmd = cygpath + " --mixed /usr/local/bin/wx-config";
            wxArrayString output, errors;
            int code = wxExecute(cmd, output, errors);
            if (!code) wxconfig_value = output[0];
            if (!wxFileName::IsFileReadable(wxconfig_value)){
                wxconfig_value = "";
            }
        }

        wxFileName wx_config_norm = wxconfig_value;
        wx_config_norm.Normalize();
        wxString wx_config_fixed = wx_config_norm.GetLongPath();
        wx_config_fixed.Replace("\\", "/");
        // if (wxDir::Exists(prefix_value)

        /*
                wxString wx_config = "wx-config";
                if (wxCMD_SWITCH_ON == parser.FoundSwitch("static")){
                    if (wxFileName::FileExists(prefix_value + "bin/wx-config-static")){
                        wx_config = "wx-config-static";
                    }
                }
        */

        if ("sh.exe" != shell_value){
            cmd_base = shell.GetLongPath() + " -c '" + wx_config_fixed + " ";
        } else {
            cmd_base = wxString("sh.exe") + " -c '" + wx_config_fixed + " ";
        }

        prefix_dir = wxFileName(wxconfig_value).GetPath();
        prefix_dir.Replace("\\", "/");
        prefix_dir.Replace ("/bin","");
    }
    else
    {
        std::cout << "Shell command " << shell_value << " not found!" << std::endl;
        return 1;
    }

// Build command section
    wxString cmd = cmd_base + "--prefix=" + prefix_dir + " ";

    if (do_list_option)
    {
        cmd += "--list ";
    }
    if (do_cflags_option)
    {
        cmd += "--cflags ";
        if (base_only_flags) cmd += "base ";
    }
    if (wants_static)
    {
        cmd += "--static=yes ";
    }
    else if (wants_shared)
    {
        cmd += "--static=no ";
    }
    if (wants_unicode)
    {
        cmd += "--unicode=yes ";
    }
    else if (wants_ANSI)
    {
        cmd += "--unicode=no ";
    }
    if (wants_debug)
    {
        cmd += "--debug=yes ";
    }
    else if (wants_release)
    {
        cmd += "--debug=no ";
    }
    if (wants_version)
    {
        cmd += "--version=" + version_value + " ";
    }
    if (show_version)
    {
        cmd += "--version ";
    }

    if (do_libs_option)
    {
        cmd += "--libs " + libs_value + " ";
    }
    cmd += "'";

// Run command section
    wxArrayString output, errors;
    int code = wxExecute(cmd, output, errors);

    ShowOutput(output);
    ShowError(cmd, errors, wxT("Errors"));
    return code;
}
HRESULT propagateBufferOnce() {
	HRESULT hr = S_OK;

    // grab next audio chunk...
	int gotAnyAtAll = FALSE;
	DWORD start_time = timeGetTime();
    while (!shouldStop) {
        UINT32 nNextPacketSize;
        hr = pAudioCaptureClient->GetNextPacketSize(&nNextPacketSize); // get next packet, if one is ready...
        if (FAILED(hr)) {
            ShowOutput("IAudioCaptureClient::GetNextPacketSize failed after %u frames: hr = 0x%08x\n", pnFrames, hr);
            pAudioClient->Stop();
            AvRevertMmThreadCharacteristics(hTask);
            pAudioCaptureClient->Release();
            pAudioClient->Release();            
            return hr;
        }

        if (0 == nNextPacketSize) {
            // no data yet, we're waiting, between incoming chunks of audio. [occurs even with silence on the line--it just means no new data yet]

			DWORD millis_to_fill = (DWORD) (1.0/SECOND_FRACTIONS_TO_GRAB*1000); // truncate is ok :) -- 1s
			assert(millis_to_fill > 1); // sanity
			DWORD current_time = timeGetTime();
			if((current_time - start_time > millis_to_fill)) {
				// I don't think we ever get to here anymore...thankfully, since it's mostly broken code probably, anyway
				if(!gotAnyAtAll) {
				  // We get here [?]
				  assert(false); // want to know if this ever happens...it never should since we are using silence...
				}
			} else {
			  Sleep(1); // doesn't seem to hurt cpu--"sleep x ms"
			  continue;
			}
        } else {
		  gotAnyAtAll = TRUE;
		  totalSuccessFullyread++;
		}
		
        // get the captured data
        BYTE *pData;
        UINT32 nNumFramesToRead;
        DWORD dwFlags;

		// I guess it gives us...as much audio as possible to read...probably

        hr = pAudioCaptureClient->GetBuffer(
            &pData,
            &nNumFramesToRead,
            &dwFlags,
            NULL,
            NULL
        ); // ACTUALLY GET THE BUFFER which I assume it reads in the format of the fella we passed in
        
        
        if (FAILED(hr)) {
            ShowOutput("IAudioCaptureClient::GetBuffer failed after %u frames: hr = 0x%08x\n", pnFrames, hr);
            pAudioClient->Stop();
            AvRevertMmThreadCharacteristics(hTask);
            pAudioCaptureClient->Release();
            pAudioClient->Release();            
            return hr;            
        }

		{
  		  CAutoLock cAutoLockShared(&gSharedState);

			if( dwFlags == 0 ) {
			  // the good case, got audio packet
			  // we'll let fillbuffer set bFirstPacket = false; since it uses it to know if the next packet should restart, etc.
			} else if (bFirstPacket && AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY == dwFlags) {
				ShowOutput("Probably spurious glitch reported on first packet, or two discontinuity errors occurred before it read from the cached buffer\n");
				bFirstPacket = true; // won't hurt, even if it is a real first packet :)
				// LODO it should probably clear the buffers if it ever gets discontinuity
				// or "let" it clear the buffers then send the new data on
				// as we have any left-over data that will be assigned a wrong timestamp
				// but it won't be too far wrong, compared to what it would otherwise be with always
				// assigning it the current graph timestamp, like we used to...
			} else if (AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY == dwFlags) {
				  ShowOutput("IAudioCaptureClient::discontinuity GetBuffer set flags to 0x%08x after %u frames\n", dwFlags, pnFrames);
				  // expected your CPU gets behind or what not. I guess.
				  /*pAudioClient->Stop();
				  AvRevertMmThreadCharacteristics(hTask);
				  pAudioCaptureClient->Release();		  
				  pAudioClient->Release();            
				  return E_UNEXPECTED;*/
				  bFirstPacket = true;
			} else if (AUDCLNT_BUFFERFLAGS_SILENT == dwFlags) {
     		  // ShowOutput("IAudioCaptureClient::silence (just) from GetBuffer after %u frames\n", pnFrames);
			  // expected if there's silence (i.e. nothing playing), since we now include the "silence generator" work-around...
			} else {
			  // probably silence + discontinuity
     		  ShowOutput("IAudioCaptureClient::unknown discontinuity GetBuffer set flags to 0x%08x after %u frames\n", dwFlags, pnFrames);
			  bFirstPacket = true; // probably is some type of discontinuity :P
			}

			if(bFirstPacket)
				totalBlips++;

			if (0 == nNumFramesToRead) {
				ShowOutput("death failure: IAudioCaptureClient::GetBuffer said to read 0 frames after %u frames\n", pnFrames);
				pAudioClient->Stop();
				AvRevertMmThreadCharacteristics(hTask);
				pAudioCaptureClient->Release();
				pAudioClient->Release();
				return E_UNEXPECTED;            
			}

			pnFrames += nNumFramesToRead; // increment total count...		

			// lBytesToWrite typically 1792 bytes...
			LONG lBytesToWrite = nNumFramesToRead * nBlockAlign; // nBlockAlign is "audio block size" or frame size, for one audio segment...
			{
			  CAutoLock cObjectLock(&csMyLock);  // Lock the critical section, releases scope after block is over...

			  if(pBufLocalCurrentEndLocation > expectedMaxBufferSize) { 
				// this happens during VLC pauses...
				// I have no idea what I'm doing here... this doesn't fix it, but helps a bit... TODO FINISH THIS
				// it seems like if you're just straight recording then you want this big...otherwise you want it like size 0 and non-threaded [pausing with graphedit, for example]... [?]
				// if you were recording skype, you'd want it non realtime...hmm...
				// it seems that if the cpu is loaded, we run into this if it's for the next packet...hmm...
				// so basically we don't accomodate realtime at all currently...hmmm...
	  			ShowOutput("overfilled buffer, cancelling/flushing."); //over flow overflow appears VLC just keeps reading though, when paused [?] but not graphedit...or does it?
				pBufLocalCurrentEndLocation = 0;
				totalOverflows++;
				bFirstPacket = true;
			  }

			  for(INT i = 0; i < lBytesToWrite && pBufLocalCurrentEndLocation < expectedMaxBufferSize; i++) {
				pBufLocal[pBufLocalCurrentEndLocation++] = pData[i];
			  }
			}
		}
        
        hr = pAudioCaptureClient->ReleaseBuffer(nNumFramesToRead);
        if (FAILED(hr)) {
            ShowOutput("IAudioCaptureClient::ReleaseBuffer failed after %u frames: hr = 0x%08x\n", pnFrames, hr);
            pAudioClient->Stop();
            AvRevertMmThreadCharacteristics(hTask);
            pAudioCaptureClient->Release();
            pAudioClient->Release();            
            return hr;            
        }
        
		return hr;
    } // while !got anything && should continue loop

	return S_OK; // stop was called...

}
// we only call this once...per hit of the play button :)
HRESULT LoopbackCaptureSetup()
{
	assert(shouldStop); // duplicate starts would be odd...
	shouldStop = false; // allow graphs to restart, if they so desire...
	pnFrames = 0;
	bool bInt16 = true; // makes it actually work, for some reason...LODO
	
    HRESULT hr;
    hr = get_default_device(&m_pMMDevice); // so it can re-place our pointer...
    if (FAILED(hr)) {
        return hr;
    }

	// tell it to not overflow one buffer's worth <sigh> not sure if this is right or not, and thus we don't "cache" or "buffer" more than that much currently...
	// but a buffer size is a buffer size...hmm...as long as we keep it small though...
	assert(expectedMaxBufferSize <= pBufOriginalSize);
    // activate an (the default, for us, since we want loopback) IAudioClient
    hr = m_pMMDevice->Activate(
        __uuidof(IAudioClient),
        CLSCTX_ALL, NULL,
        (void**)&pAudioClient
    );
    if (FAILED(hr)) {
        ShowOutput("IMMDevice::Activate(IAudioClient) failed: hr = 0x%08x", hr);
        return hr;
    }
    
    // get the default device periodicity, why? I don't know...
    REFERENCE_TIME hnsDefaultDevicePeriod;
    hr = pAudioClient->GetDevicePeriod(&hnsDefaultDevicePeriod, NULL);
    if (FAILED(hr)) {
        ShowOutput("IAudioClient::GetDevicePeriod failed: hr = 0x%08x\n", hr);
        pAudioClient->Release();
        return hr;
    }

    // get the default device format (incoming...)
    WAVEFORMATEX *pwfx; // incoming wave...
	// apparently propogated by GetMixFormat...
    hr = pAudioClient->GetMixFormat(&pwfx);
    if (FAILED(hr)) {
        ShowOutput("IAudioClient::GetMixFormat failed: hr = 0x%08x\n", hr);
        CoTaskMemFree(pwfx);
        pAudioClient->Release();
        return hr;
    }

    if (true /*bInt16*/) {
        // coerce int-16 wave format
        // can do this in-place since we're not changing the size of the format
        // also, the engine will auto-convert from float to int for us
        switch (pwfx->wFormatTag) {
            case WAVE_FORMAT_IEEE_FLOAT:
				assert(false);// we never get here...I hope...
                pwfx->wFormatTag = WAVE_FORMAT_PCM;
                pwfx->wBitsPerSample = 16;
                pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample / 8;
                pwfx->nAvgBytesPerSec = pwfx->nBlockAlign * pwfx->nSamplesPerSec;
                break;

            case WAVE_FORMAT_EXTENSIBLE:
                {
                    // naked scope for case-local variable
                    PWAVEFORMATEXTENSIBLE pEx = reinterpret_cast<PWAVEFORMATEXTENSIBLE>(pwfx);
                    if (IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, pEx->SubFormat)) {
						// WE GET HERE!
                        pEx->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
                        pEx->Samples.wValidBitsPerSample = 16;
                        pwfx->wBitsPerSample = 16;
                        pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample / 8;
                        pwfx->nAvgBytesPerSec = pwfx->nBlockAlign * pwfx->nSamplesPerSec;
						/* scawah lodo...
						if(ifNotNullThenJustSetTypeOnly) {
							PWAVEFORMATEXTENSIBLE pEx2 = reinterpret_cast<PWAVEFORMATEXTENSIBLE>(ifNotNullThenJustSetTypeOnly);
							pEx2->SubFormat = pEx->SubFormat;
							pEx2->Samples.wValidBitsPerSample = pEx->Samples.wValidBitsPerSample;
						} */
                    } else {
                        ShowOutput("Don't know how to coerce mix format to int-16\n");
                        CoTaskMemFree(pwfx);
                        pAudioClient->Release();
                        return E_UNEXPECTED;
                    }
                }
                break;

            default:
                ShowOutput("Don't know how to coerce WAVEFORMATEX with wFormatTag = 0x%08x to int-16\n", pwfx->wFormatTag);
                CoTaskMemFree(pwfx);
                pAudioClient->Release();
                return E_UNEXPECTED;
        }
    }
	/* scawah setting stream types up to match...didn't seem to work well...

	if(ifNotNullThenJustSetTypeOnly) {
		// pwfx is set at this point...
		WAVEFORMATEX* pwfex = ifNotNullThenJustSetTypeOnly;
		// copy them all out as the possible format...hmm...


                pwfx->wFormatTag = WAVE_FORMAT_PCM;
                pwfx->wBitsPerSample = 16;
                pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample / 8;
                pwfx->nAvgBytesPerSec = pwfx->nBlockAlign * pwfx->nSamplesPerSec;


		pwfex->wFormatTag = pwfx->wFormatTag;
		pwfex->nChannels = pwfx->nChannels;
        pwfex->nSamplesPerSec = pwfx->nSamplesPerSec;
        pwfex->wBitsPerSample = pwfx->wBitsPerSample;
        pwfex->nBlockAlign = pwfx->nBlockAlign;
        pwfex->nAvgBytesPerSec = pwfx->nAvgBytesPerSec;
        pwfex->cbSize = pwfx->cbSize;
		//FILE *fp = fopen("/normal2", "w"); // fails on me? maybe juts a VLC thing...
		//fShowOutput(fp, "hello world %d %d %d %d %d %d %d", pwfex->wFormatTag, pwfex->nChannels, 
		//	pwfex->nSamplesPerSec, pwfex->wBitsPerSample, pwfex->nBlockAlign, pwfex->nAvgBytesPerSec, pwfex->cbSize );
		//fclose(fp);
		// cleanup
		// I might be leaking here...
		CoTaskMemFree(pwfx);
        pAudioClient->Release();
        //m_pMMDevice->Release();
		return hr;
	}*/

    MMCKINFO ckRIFF = {0};
    MMCKINFO ckData = {0};

    nBlockAlign = pwfx->nBlockAlign;
    

// avoid stuttering on close
// http://social.msdn.microsoft.com/forums/en-US/windowspro-audiodevelopment/thread/c7ba0a04-46ce-43ff-ad15-ce8932c00171/ 
	
//IAudioClient *pAudioClient = NULL;
//IAudioCaptureClient *pCaptureClient = NULL;
	
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDevice *pDevice = NULL;

IAudioRenderClient *pRenderClient = NULL;
WAVEFORMATEXTENSIBLE *captureDataFormat = NULL;
BYTE *captureData;

    REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;

    hr = CoCreateInstance(
           CLSID_MMDeviceEnumerator, NULL,
           CLSCTX_ALL, IID_IMMDeviceEnumerator,
           (void**)&pEnumerator);
    EXIT_ON_ERROR(hr)

    hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
    EXIT_ON_ERROR(hr)

    hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pAudioClient);
    EXIT_ON_ERROR(hr)

    hr = pAudioClient->GetMixFormat((WAVEFORMATEX **)&captureDataFormat);
    EXIT_ON_ERROR(hr)

	
    // Silence: initialise in sharedmode [this is the "silence" bug overwriter, so buffer doesn't matter as much...]
    hr = pAudioClient->Initialize(
                         AUDCLNT_SHAREMODE_SHARED,
                         0,
					     REFTIMES_PER_SEC, // buffer size a full 1.0s, though prolly doesn't matter here.
                         0,
                         pwfx,
                         NULL);
    EXIT_ON_ERROR(hr)

    // get the frame count
    UINT32  bufferFrameCount;
    hr = pAudioClient->GetBufferSize(&bufferFrameCount);
    EXIT_ON_ERROR(hr)

    // create a render client
    hr = pAudioClient->GetService(IID_IAudioRenderClient, (void**)&pRenderClient);
    EXIT_ON_ERROR(hr)

    // get the buffer
    hr = pRenderClient->GetBuffer(bufferFrameCount, &captureData);
    EXIT_ON_ERROR(hr)

    // release it
    hr = pRenderClient->ReleaseBuffer(bufferFrameCount, AUDCLNT_BUFFERFLAGS_SILENT);
    EXIT_ON_ERROR(hr)

    // release the audio client
    pAudioClient->Release();
    EXIT_ON_ERROR(hr)


    // create a new IAudioClient
    hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pAudioClient);
    EXIT_ON_ERROR(hr)

    // -============================ now the sniffing code initialization stuff, direct from mauritius... ===================================

	// call IAudioClient::Initialize
    // note that AUDCLNT_STREAMFLAGS_LOOPBACK and AUDCLNT_STREAMFLAGS_EVENTCALLBACK
    // do not work together...
    // the "data ready" event never gets set
    // so we're going to have to do this in a timer-driven loop...

    hr = pAudioClient->Initialize(
        AUDCLNT_SHAREMODE_SHARED,
        AUDCLNT_STREAMFLAGS_LOOPBACK,
        REFTIMES_PER_SEC, // buffer size a full 1.0s, seems ok VLC
		0, pwfx, 0
    );
    if (FAILED(hr)) {
        ShowOutput("IAudioClient::Initialize failed: hr = 0x%08x\n", hr);
        pAudioClient->Release();
        return hr;
    }
    CoTaskMemFree(pwfx);

    // activate an IAudioCaptureClient
    hr = pAudioClient->GetService(
        __uuidof(IAudioCaptureClient),
        (void**)&pAudioCaptureClient // CARE INSTANTIATION
    );
    if (FAILED(hr)) {
        ShowOutput("IAudioClient::GetService(IAudioCaptureClient) failed: hr 0x%08x\n", hr);
        pAudioClient->Release();
        return hr;
    }
    
    // register with MMCSS
    DWORD nTaskIndex = 0;

    hTask = AvSetMmThreadCharacteristics(L"Capture", &nTaskIndex);
    if (NULL == hTask) {
        DWORD dwErr = GetLastError();
        ShowOutput("AvSetMmThreadCharacteristics failed: last error = %u\n", dwErr);
        pAudioCaptureClient->Release();
        pAudioClient->Release();
        return HRESULT_FROM_WIN32(dwErr);
    }    

    // call IAudioClient::Start
    hr = pAudioClient->Start();
    if (FAILED(hr)) {
        ShowOutput("IAudioClient::Start failed: hr = 0x%08x\n", hr);
        AvRevertMmThreadCharacteristics(hTask);
        pAudioCaptureClient->Release();
        pAudioClient->Release();
        return hr;
    }
    
    bFirstPacket = true;

	// start the forever grabbing thread...
	DWORD dwThreadID;
    m_hThread = CreateThread(NULL,
                            0,
                            propagateBufferForever,
                            0,
                            0,
                            &dwThreadID);
    if(!m_hThread)
    {
        DWORD dwErr = GetLastError();
        return HRESULT_FROM_WIN32(dwErr);
    } else {
		// we...shouldn't need this...maybe?
		// seems to make no difference...
		hr = SetThreadPriority(m_hThread, THREAD_PRIORITY_TIME_CRITICAL);
        if (FAILED(hr)) { // of course we always want to be a high prio thread, right? [we don't use much cpu...]
		  return hr;
  	    }
	}

	return hr;
} // end LoopbackCaptureSetup
CVCamStream::~CVCamStream()
{
	// don't get here with any consistency...
	ShowOutput("destructor");
} 
STDMETHODIMP CVCam::Run(REFERENCE_TIME tStart) {
	ShowOutput("run called");
	((CVCamStream*) m_paStreams[0])->m_rtPreviousSampleEndTime = 0;
	return CSource::Run(tStart);
}
HRESULT CVCamStream::Exit()
{
	// never get here
    ShowOutput("exit method called");
	return S_OK;
}
//less useful, for VLC anyway..
HRESULT CVCamStream::Stop()
{
	// never get here
	ShowOutput("stop");
	return S_OK;
}
HRESULT CVCamStream::OnThreadDestroy()
{
	ShowOutput("OnThreadDestroy");
	return S_OK; 
}