Skip to content

Commit

Permalink
Add sources
Browse files Browse the repository at this point in the history
  • Loading branch information
MSDN-WhiteKnight committed Apr 4, 2021
1 parent 016f155 commit 7efc118
Show file tree
Hide file tree
Showing 26 changed files with 6,396 additions and 2 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -348,3 +348,7 @@ MigrationBackup/

# Ionide (cross platform F# VS Code tools) working folder
.ionide/

##########################################################################################
distr/
Info/
29 changes: 27 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,27 @@
# media-player
Small audio and video player for Windows
# Small Media Player

Лицензия: [BSD 2.0](LICENSE)

Легкий проигрыватель мультимедиа файлов для Windows без встроенных кодеков. Основные особенности программы:
- воспроизведение аудиофайлов: WAV, WMA, MP3 и др.
- воспроизведение видеофайлов: WMV, AVI, MPEG и др.
- воспроизведение Audio CD (только WinXP)
- совместим с любыми DirectShow-декодерами сторонних разработчиков, обеспечивающими поддержку других форматов
- просмотр изображений (BMP, JPEG, GIF, PNG) с автоматической прокруткой слайдов
- небольшой размер и потребление системных ресурсов
- оконный и полноэкранный режим при просмотре видео
- редактирование списка воспроизведения
- режимы воспроизведения: повтор списка, повтор одного файла, случайный порядок
- загрузка и сохранение списков воспроизведения в формате M3U
- поддержка информационных тэгов ID3V1, ID3V2, APE, FLAC
- автоматическое отображение обложек альбомов из файлов JPEG, BMP, PNG
- запоминание позиции последнего воспроизведенного файла при закрытии
- возможность создания ассоциаций с файлами и папками в проводнике Windows
- управление горячими клавишами
- отображение информации о используемых кодеках и характеристиках аудио- и видеопотоков воспроизводимого файла
- возможность свернуть в значок системной панели
- простой и понятный интерфейс

Поддерживаемые ОС: Windows XP, Vista, 7, 8, 10

Для запуска требуется Visual C++ 2012 Redistributable (x86).
315 changes: 315 additions & 0 deletions SmallMediaPlayer/DirectShowStuff.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
/* Small Media Player
* Copyright (c) 2021, MSDN.WhiteKnight (https://github.com/smallsoft-rus/media-player)
* License: BSD 2.0 */
#define UNICODE
#include "DirectShowStuff.h"
IBaseFilter* FindFilter(TCHAR* FilterName){
HRESULT hr;
// Create the System Device Enumerator.
ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr))
{ return NULL;}

// Obtain a class enumerator for the dshow filters category.
IEnumMoniker *pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_LegacyAmFilterCategory, &pEnumCat, 0);

if (hr == S_OK)
{
// Enumerate the monikers.
IMoniker *pMoniker = NULL;
ULONG cFetched;
while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
(void **)&pPropBag);
if (SUCCEEDED(hr))
{
// To retrieve the filter's friendly name, do the following:
VARIANT varName;
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
if (SUCCEEDED(hr)){
if(wcscmp(FilterName,varName.bstrVal)==0){

// To create an instance of the filter, do the following:
IBaseFilter *pFilter;
hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,
(void**)&pFilter);
// Now add the filter to the graph.
//Remember to release pFilter later.
VariantClear(&varName);
pPropBag->Release();
pMoniker->Release();
pEnumCat->Release();
pSysDevEnum->Release();
return pFilter;

}
}

pPropBag->Release();
}
pMoniker->Release();
}
pEnumCat->Release();
}
pSysDevEnum->Release();
return NULL;

}
void MyFreeMediaType(AM_MEDIA_TYPE& mt)
{
if (mt.cbFormat != 0)
{
CoTaskMemFree((PVOID)mt.pbFormat);
mt.cbFormat = 0;
mt.pbFormat = NULL;
}
if (mt.pUnk != NULL)
{
// Unecessary because pUnk should not be used, but safest.
mt.pUnk->Release();
mt.pUnk = NULL;
}
}
void MyDeleteMediaType(AM_MEDIA_TYPE *pmt)
{
if (pmt != NULL)
{
MyFreeMediaType(*pmt);
CoTaskMemFree(pmt);
}
}
void ShowError(HRESULT hr,ERROR_TYPE et){
TCHAR buf[MAX_ERROR_TEXT_LEN]=L"";
TCHAR message[256]=L"";

switch(et){
case SYSTEM_ERROR:AMGetErrorTextW(hr,buf,sizeof(buf));
lstrcpy(message,L"Системная ошибка");break;
case PLAY_ERROR:AMGetErrorTextW(hr,buf,sizeof(buf));
lstrcpy(message,L"Ошибка воспроизведения");break;
case ERROR_NOTSUPPORTED:lstrcpy(message,L"Ошибка");
lstrcpy(buf,L"Операция не поддерживается");break;
case ERROR_NOPROPERTIES:lstrcpy(message,L"Ошибка");
lstrcpy(buf,L"Декодер не имеет настраиваемых свойств");break;

}
MessageBox(NULL,buf,message,MB_OK|MB_ICONERROR);
}
HRESULT GetUnconnectedPin(
IBaseFilter *pFilter, // Pointer to the filter.
PIN_DIRECTION PinDir, // Direction of the pin to find.
IPin **ppPin) // Receives a pointer to the pin.
{
*ppPin = 0;
IEnumPins *pEnum = 0;
IPin *pPin = 0;
HRESULT hr = pFilter->EnumPins(&pEnum);
if (FAILED(hr))
{
return hr;

}
while (pEnum->Next(1, &pPin, NULL) == S_OK)
{
PIN_DIRECTION ThisPinDir;
pPin->QueryDirection(&ThisPinDir);
if (ThisPinDir == PinDir)
{
IPin *pTmp = 0;
hr = pPin->ConnectedTo(&pTmp);
if (SUCCEEDED(hr)) // Already connected, not the pin we want.
{
pTmp->Release();
}
else // Unconnected, this is the pin we want.
{
pEnum->Release();
*ppPin = pPin;
return S_OK;
}
}
pPin->Release();
}
pEnum->Release();
// Did not find a matching pin.
return E_FAIL;
}

IPin* GetOutputPin( IBaseFilter *pFilter )
{

IEnumPins *pEnum = 0;
IPin *pPin = 0;
HRESULT hr = pFilter->EnumPins(&pEnum);
if (FAILED(hr))
{
return NULL;

}
while (pEnum->Next(1, &pPin, NULL) == S_OK)
{
PIN_DIRECTION ThisPinDir;
pPin->QueryDirection(&ThisPinDir);
if (ThisPinDir == PINDIR_OUTPUT)
{
pEnum->Release();
return pPin;
}
pPin->Release();
}
pEnum->Release();
// Did not find a matching pin.
return NULL;
}

HRESULT FindPin(
IBaseFilter *pFilter, // Pointer to the filter.
TCHAR* name,
IPin **ppPin) // Receives a pointer to the pin.
{

IEnumPins *pEnum = 0;
IPin *pPin = 0;
PIN_INFO pi={0};
HRESULT hr = pFilter->EnumPins(&pEnum);
if (FAILED(hr))
{
return hr;

}
while (pEnum->Next(1, &pPin, NULL) == S_OK)
{
pPin->QueryPinInfo(&pi);
if(lstrcmp(pi.achName,name)==0){
pEnum->Release();
*ppPin=pPin;
return S_OK;
}
pPin->Release();
}
pEnum->Release();
// Did not find a matching pin.
return E_FAIL;
}


BOOL CheckMediaType(IPin* pin,GUID mediatype){
IEnumMediaTypes* pEnum;
AM_MEDIA_TYPE* mt=NULL;


pin->EnumMediaTypes(&pEnum);
while(pEnum->Next(1,&mt,NULL)==S_OK){
if(mt->majortype==mediatype){
MyDeleteMediaType(mt);
pEnum->Release();
return TRUE;}
MyDeleteMediaType(mt);

}
pEnum->Release();

return FALSE;

}

BOOL GetSubType(IPin* pin,GUID* pGuid){
IEnumMediaTypes* pEnum;
AM_MEDIA_TYPE* mt=NULL;
HRESULT hr;

pin->EnumMediaTypes(&pEnum);
hr=pEnum->Next(1,&mt,NULL);
if(FAILED(hr)){pEnum->Release();return FALSE;}
*pGuid=mt->subtype;
MyDeleteMediaType(mt);
pEnum->Release();
return TRUE;
}

BOOL ShowFilterProperties(IBaseFilter* pFilter){
ISpecifyPropertyPages *pProp;
HRESULT hr = pFilter->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pProp);
if (SUCCEEDED(hr))
{
// Get the filter's name and IUnknown pointer.
FILTER_INFO FilterInfo;
hr = pFilter->QueryFilterInfo(&FilterInfo);
IUnknown *pFilterUnk;
pFilter->QueryInterface(IID_IUnknown, (void **)&pFilterUnk);

// Show the page.
CAUUID caGUID;
pProp->GetPages(&caGUID);
pProp->Release();
OleCreatePropertyFrame(
NULL, // Parent window
0, 0, // Reserved
FilterInfo.achName, // Caption for the dialog box
1, // Number of objects (just the filter)
&pFilterUnk, // Array of object pointers.
caGUID.cElems, // Number of property pages
caGUID.pElems, // Array of property page CLSIDs
0, // Locale identifier
0, NULL // Reserved
);

// Clean up.
pFilterUnk->Release();
FilterInfo.pGraph->Release();
CoTaskMemFree(caGUID.pElems);
return TRUE;
}
return FALSE;
}

IBaseFilter* GetDownstreamFilter(IPin* PinOut){
IPin* pin=NULL;

HRESULT hr;
PIN_INFO pi={0};

hr=PinOut->ConnectedTo(&pin);
if(FAILED(hr))return NULL;
hr=pin->QueryPinInfo(&pi);
if(FAILED(hr))goto end_fail;
if(pi.pFilter==NULL)goto end_fail;
return pi.pFilter;

end_fail:
if(pi.pFilter!=NULL)pi.pFilter->Release();
if(pin!=NULL)pin->Release();
return NULL;

}

IBaseFilter* FindFileSource(IGraphBuilder* pGraph)
{
IEnumFilters *pEnum = NULL;
IBaseFilter *pFilter=NULL;
IFileSourceFilter* pSrc=NULL;
ULONG cFetched;

HRESULT hr = pGraph->EnumFilters(&pEnum);
if (FAILED(hr)) return NULL;

while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
{
hr=pFilter->QueryInterface(IID_IFileSourceFilter,(void**)&pSrc);
if(hr==E_NOINTERFACE||pSrc==NULL){
pFilter->Release();
continue;}
pSrc->Release();
pEnum->Release();
return pFilter;
}

pEnum->Release();
return NULL;
}
Loading

0 comments on commit 7efc118

Please sign in to comment.