⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libovd.cpp

📁 PPC流行的播放软件gsplayer源码2.24版
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include <windows.h>
#include <tchar.h>
#include "libovd.h"

#include ".\tremor\ivorbiscodec.h"
#include ".\tremor\ivorbisfile.h"
#include ".\tremor\codebook.h"
#include ".\tremor\misc.h"

typedef struct
{
	FILE*			fp;
	OggVorbis_File	vf;
}LIBOV_STRUCT;

extern "C" void *calloc2( size_t num, size_t size )
{
	void* p = malloc(num * size);
	if (!p) return p;
	memset(p, 0, num * size);
	return p;
}

int UTF8toUCS2(char* pszSrc, WCHAR* pszDst, DWORD dwDstLen)
{
	DWORD dwLen = 0;
	while (*pszSrc) {
		if (++dwLen == dwDstLen)
			break;
		if ((*pszSrc & 0x80) == 0x0) {
			// 1 byte
			*pszDst++ = *pszSrc++;
		}
		else if ((*pszSrc & 0xE0) == 0xC0) {
			// 2 bytes
			*pszDst++ = (((WORD)*pszSrc & 0x1F) << 6) | ((WORD)*(pszSrc + 1) & 0x3F);
			pszSrc += 2;
		}
		else if ((*pszSrc & 0xE0) == 0xE0) {
			// 3 bytes
			*pszDst++ = (((WORD)*pszSrc & 0x0F) << 12) | (((WORD)*(pszSrc + 1) & 0x3F) << 6) | ((WORD)*(pszSrc + 2) & 0x3F);
			pszSrc += 3;
		}
	}

	*pszDst = NULL;
	return dwLen;
}

BOOL ovd_test_file(LPCTSTR pszFile)
{
	if (!_tcslen(pszFile))
		return FALSE;

	FILE* fp = _tfopen(pszFile, _T("rb"));
	if (!fp)
		return NULL;

	OggVorbis_File vf;
	int ret = ov_test(fp, &vf, NULL, 0);
	fclose(fp);
	ov_clear(&vf);

	return ret == 0;
}

HANDLE ovd_open_file(LPCTSTR pszFile)
{
	if (!_tcslen(pszFile))
		return NULL;

	FILE* fp = _tfopen(pszFile, _T("rb"));
	if (!fp)
		return NULL;

	LIBOV_STRUCT* lov = new LIBOV_STRUCT;
	if (ov_open(fp, &lov->vf, NULL, 0) < 0)
	{
		delete lov;
		fclose(fp);
		return NULL;
	}

	lov->fp = fp;
	return (HANDLE)lov;
}

void ovd_close(HANDLE hov)
{
	LIBOV_STRUCT* lov = (LIBOV_STRUCT*)hov;
	if (!lov) return;

	ov_clear(&lov->vf);
	if (lov->fp) 
		fclose(lov->fp);
	delete lov;
}

int ovd_read(HANDLE hov, LPBYTE pcmbuf, int pcmbuf_len, int* pcmout)
{
	*pcmout = 0;
	LIBOV_STRUCT* lov = (LIBOV_STRUCT*)hov;
	if (!lov) return OVD_FATAL_ERR;

	if (pcmbuf_len < OVD_PCMBUF_LEN)
		return OVD_NEED_MORE_OUTPUT;

	int ret = ov_read(&lov->vf, (char*)pcmbuf, pcmbuf_len, NULL);
	if (ret == 0)		// eof
		return OVD_EOF;
	else if (ret < 0)	// error
		return OVD_FATAL_ERR;

	// succeeded
	*pcmout = ret;
	return OVD_OK;
}

BOOL ovd_seek(HANDLE hov, LONGLONG samples)
{
	LIBOV_STRUCT* lov = (LIBOV_STRUCT*)hov;
	if (!lov) return FALSE;

	return ov_pcm_seek_page(&lov->vf, samples) == 0;
}

LONGLONG ovd_get_current(HANDLE hov)
{
	LIBOV_STRUCT* lov = (LIBOV_STRUCT*)hov;
	if (!lov) return FALSE;

	return ov_pcm_tell(&lov->vf);
}

LONGLONG ovd_get_duration(HANDLE hov)
{
	LIBOV_STRUCT* lov = (LIBOV_STRUCT*)hov;
	if (!lov) return FALSE;

	return ov_pcm_total(&lov->vf, -1);
}

BOOL ovd_get_info(HANDLE hov, ovd_info* info)
{
	LIBOV_STRUCT* lov = (LIBOV_STRUCT*)hov;
	if (!lov) return FALSE;

	vorbis_info* pvi = ov_info(&lov->vf, -1);
	if (!pvi)
		return FALSE;

	info->version = pvi->version;
	info->rate = pvi->rate;
	info->channels = pvi->channels;
	info->bitrate_lower = pvi->bitrate_lower;
	info->bitrate_nominal = pvi->bitrate_nominal;
	info->bitrate_upper = pvi->bitrate_upper;
	info->bitrate_window = pvi->bitrate_window;
	return TRUE;
}

void ovd_strupr(char* str)
{
	for (int i = 0; str[i] != NULL; i++) {
		if (str[i] >= 'a' && str[i] <= 'z')
			str[i] -= 'a' - 'A';
	}
}

#define OVD_COMMENT_TITLE		"TITLE"
#define OVD_COMMENT_ARTIST		"ARTIST"
#define OVD_COMMENT_ALBUM		"ALBUM"
#define OVD_COMMENT_GENRE		"GENRE"
#define OVD_COMMENT_COMMENT		"COMMENT"
#define OVD_COMMENT_DATE		"DATE"
#define OVD_COMMENT_TRACKNUM	"TRACKNUMBER"
BOOL ovd_get_comment(HANDLE hov, ovd_comment* comment)
{
	LIBOV_STRUCT* lov = (LIBOV_STRUCT*)hov;
	if (!lov) return FALSE;

	memset(comment, 0, sizeof(ovd_comment));
	vorbis_comment* p = ov_comment(&lov->vf, -1);
	for (int i = 0; i < p->comments; i++)
	{
		LPTSTR psz = NULL;
		char* s = strchr(p->user_comments[i], '=');
		if (s)
		{
			*s = NULL;
			ovd_strupr(p->user_comments[i]);
			if (strcmp(p->user_comments[i], OVD_COMMENT_DATE) == 0)
				psz = comment->szDate;
			else if (strcmp(p->user_comments[i], OVD_COMMENT_TRACKNUM) == 0)
				psz = comment->szTrackNum;
			else if (strcmp(p->user_comments[i], OVD_COMMENT_TITLE) == 0)
				psz = comment->szTitle;
			else if (strcmp(p->user_comments[i], OVD_COMMENT_ARTIST) == 0)
				psz = comment->szArtist;
			else if (strcmp(p->user_comments[i], OVD_COMMENT_ALBUM) == 0)
				psz = comment->szAlbum;
			else if (strcmp(p->user_comments[i], OVD_COMMENT_GENRE) == 0)
				psz = comment->szGenre;
			else if (strcmp(p->user_comments[i], OVD_COMMENT_COMMENT) == 0)
				psz = comment->szComment;

			if (psz)
			{
#ifdef _UNICODE
				UTF8toUCS2(s + 1, psz, OVD_COMMENT_LEN);
#else
				WCHAR sz[OVD_COMMENT_LEN];
				UTF8toUCS2(s + 1, sz, OVD_COMMENT_LEN);
				WideCharToMultiByte(CP_ACP, 0, sz, -1, psz, OVD_COMMENT_LEN, 0, 0);
#endif	
			}
		}
	}
	return TRUE;
}

BOOL ovd_get_comment_from_file(LPCTSTR pszFile, ovd_comment* comment)
{
	if (!ovd_test_file(pszFile))
		return FALSE;

	FILE* fp = _tfopen(pszFile, _T("rb"));
	if (!fp)
		return FALSE;

	OggVorbis_File	vf;
	if (ov_open(fp, &vf, NULL, 0) < 0)
	{
		fclose(fp);
		return FALSE;
	}

	memset(comment, 0, sizeof(ovd_comment));
	vorbis_comment* p = ov_comment(&vf, -1);
	for (int i = 0; i < p->comments; i++)
	{
		LPTSTR psz = NULL;
		char* s = strchr(p->user_comments[i], '=');
		if (s)
		{
			*s = NULL;
			ovd_strupr(p->user_comments[i]);
			if (strcmp(p->user_comments[i], OVD_COMMENT_DATE) == 0)
				psz = comment->szDate;
			else if (strcmp(p->user_comments[i], OVD_COMMENT_TRACKNUM) == 0)
				psz = comment->szTrackNum;
			else if (strcmp(p->user_comments[i], OVD_COMMENT_TITLE) == 0)
				psz = comment->szTitle;
			else if (strcmp(p->user_comments[i], OVD_COMMENT_ARTIST) == 0)
				psz = comment->szArtist;
			else if (strcmp(p->user_comments[i], OVD_COMMENT_ALBUM) == 0)
				psz = comment->szAlbum;
			else if (strcmp(p->user_comments[i], OVD_COMMENT_GENRE) == 0)
				psz = comment->szGenre;
			else if (strcmp(p->user_comments[i], OVD_COMMENT_COMMENT) == 0)
				psz = comment->szComment;

			if (psz)
			{
#ifdef _UNICODE
				UTF8toUCS2(s + 1, psz, OVD_COMMENT_LEN);
#else
				WCHAR sz[OVD_COMMENT_LEN];
				UTF8toUCS2(s + 1, sz, OVD_COMMENT_LEN);
				WideCharToMultiByte(CP_ACP, 0, sz, -1, psz, OVD_COMMENT_LEN, 0, 0);
#endif	
			}
		}
	}
	fclose(fp);
	return TRUE;
}

// for streaming
typedef struct {
	int init;
	ogg_sync_state oy;
	ogg_stream_state os;
	ogg_page og;
	ogg_packet op;
	vorbis_info vi;
	vorbis_comment vc;
	vorbis_dsp_state vd;
	vorbis_block vb;

	int samples;
	int eof;
	ogg_int32_t **pcm;
} ovd_handle;

ovd_stream_buf* ovd_init_stream()
{
	ovd_handle* handle = new ovd_handle;
	memset(handle, 0, sizeof(ovd_handle));

	ogg_sync_init(&handle->oy);

	ovd_stream_buf* ret = new ovd_stream_buf;
	ret->handle = (HANDLE)handle;
	ret->buf = ogg_sync_buffer(&handle->oy, OVD_STREAM_BUF_LEN);
	ret->len = OVD_STREAM_BUF_LEN;

	return ret;
}

int ovd_header_init(ovd_handle* handle)
{
	if (handle->init < 2) {
		if (handle->init < 0)
			return -1;

		while (handle->init < 2) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -