突然表示される「Crash Report」の正体と対処法
Windowsで突然表示される「Crash Report」の正体と対処法のご紹介です。 Continue reading 突然表示される「Crash Report」の正体と対処法

seen from Malaysia
seen from China
seen from Netherlands
seen from United States
seen from Japan
seen from China

seen from Malaysia
seen from Brazil
seen from United States
seen from United States
seen from China

seen from United States

seen from Israel
seen from United States

seen from United States
seen from Australia

seen from Indonesia
seen from Malaysia

seen from Indonesia

seen from Singapore
突然表示される「Crash Report」の正体と対処法
Windowsで突然表示される「Crash Report」の正体と対処法のご紹介です。 Continue reading 突然表示される「Crash Report」の正体と対処法
Windows 10X’in En Son Sürümü, Win32 Uygulamalarını Destekleyebilir https://teknoleft.com.tr/windows-10xin-en-son-surumu-win32-uygulamalarini-destekleyebilir/
Hyper-V 仮想マシンのメモリを仮想化ホストからダンプする
Microsoft Hyper-V VM State to Memory Dump Converter
symsrv.dll が実行に必要なため、Debugging Tools for Windows をインストールしないと実行できない様子。
Debugging Tools for Windows は Windows SDK からインストールできる…?
Streaming MP3 files over HTTP with Direct Show
I recently needed to stream playback of remote MP3 files over HTTP on a Windows-based project and, for various reasons, didn't want to use any third party libraries. So I used the Direct Show API - a media library that is part of the Windows SDK.
The Direct Show API is only available in C++ and is based on COM. COM (the Component Object Model) might seem a bit odd or antiquated if you haven't come across it before, but it isn't too complicated to get to grips with. In essence it is a method of abstracting object interfaces, whereby the programmer queries opaque objects for their capabilities. The returned interfaces are similar to Objective-C protocols. If you are already familiar with Object Oriented Programming, a little background reading (here or here for example) should be enough to come to terms with COM.
Direct Show is a graph based system - similar to Audio Graphs in Core Audio on Mac OS X and iOS. Direct Show provides a Graph Builder interface (IGraphBuilder), which can be used to manually construct playback graphs from their component nodes, called Filters. However, the interface provides a useful RenderFile method which can automatically construct a playback graph for a given audio or video file. Though the documentation is vague on this point, the URL of a remote file can be passed as a parameter to this method. The resulting graph will stream the audio in the file, rather than download it.
So I thought I would share some code I wrote that wraps up this Direct Show functionality into a C++ class with a very simple interface:
class MusicPlayer { public: MusicPlayer(); ~MusicPlayer(); void streamMP3(MP3Info newMP3Request); void stop(); float getVolume() const; void setVolume(float newVolume); };
Each instance of the Music Player class creates a new thread for creation and control of playback graphs. The thread sits in an event loop for the lifetime of the instance. This prevents any buffering or fading from blocking the main thread, and the control thread's event loop provides a mechanism for responding to events signaled by the playback graphs themselves - such as reaching the end of a file or encountering a network error.
// Audio Control Thread Main Function void audioControlThreadMain(LPVOID p) { //... // thread event loop while(audioPlayer->_keepControlTheadAlive) { const HANDLE eventHandles[3] = {hPlayNewMP3Event, hStopPlaybackEvent, hPlaybackGraphEvent}; DWORD eventSignalled = WaitForMultipleObjects(3, eventHandles, false, 10000); switch (eventSignalled) { //...
Each new MP3 playback request is run on its own playback graph. As graphs are therefore being created and destroyed frequently, I wrapped this up in a couple of convenience functions, and created a struct type to hold a graph and all it's COM interfaces that I make use of:
typedef struct _PlaybackGraph { IGraphBuilder *graphBuilder; IMediaSeeking *seekInterface; IMediaControl *controlInterface; IMediaEvent *eventInterface; IBasicAudio *audioInterface; } PlaybackGraph; HRESULT createNewPlaybackGraphForURL(LPCWSTR mp3URL, PlaybackGraph *out_pGraph) { HRESULT hr; // Create the filter graph manager CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&graph); // Build the graph. graph->RenderFile(mp3URL, NULL); IMediaSeeking *seekInterface = NULL; graph->QueryInterface(IID_IMediaSeeking, (void **)&seekInterface); IMediaControl *controlInterface = NULL; igraph->QueryInterface(IID_IMediaControl, (void **)&controlInterface); IMediaEvent *eventInterface = NULL; graph->QueryInterface(IID_IMediaEvent, (void **)&eventInterface); IBasicAudio *audioInterface; graph->QueryInterface(IID_IBasicAudio, (void **)&audioInterface); out_pGraph->graphBuilder = graph; out_pGraph->seekInterface = seekInterface; out_pGraph->controlInterface = controlInterface; out_pGraph->eventInterface = eventInterface; out_pGraph->audioInterface = audioInterface; return S_OK; }
The Music Player class has an mCurrentPlaybackGraph member of the struct type to keep track of the currently playing graph and an mp3Request member to hold the details of a received playback request. When a Music Player instance receives a new playback request, it simply raises an event signal, which is processed in the control thread:
// Responding to a new MP3 Playback Event in the Audio Control Thread // grab the MP3 request from the audio player instance std::wstring mp3URL = audioPlayer->mp3Request.url; // create a playback graph for the MP3 PlaybackGraph newPlaybackGraph; createNewPlaybackGraphForURL(mp3URL.c_str(), &newPlaybackGraph); // start the new graph running newPlaybackGraph.controlInterface->Run(); // after starting to run, the graph will be in a paused state until it has // buffered enough of the MP3 to start playing, then it will unpause so we wait // for the unpaused event HANDLE hNewPlaybackGraphEvent = NULL; newPlaybackGraph.eventInterface->GetEventHandle((OAEVENT*)&hNewPlaybackGraphEvent); WaitForSingleObject(hNewPlaybackGraphEvent, 30000); // Set the new graph as the audio player instance's current graph, the player // instance will stop and release any old graph. audioPlayer->setCurrentPlaybackGraph(newPlaybackGraph); // Set the graph event handle so that the event loop will trigger on the new // graph's events hPlaybackGraphEvent = hNewPlaybackGraphEvent;
That's really all there is to it. The full code listing is available on Github.