-
Notifications
You must be signed in to change notification settings - Fork 0
/
player_win32.c
177 lines (154 loc) · 4.99 KB
/
player_win32.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// minimp3 example player application for Win32
// this file is public domain -- do with it whatever you want!
#define MAIN_PROGRAM
#include "libc.h"
#include "minimp3.h"
#define BUFFER_COUNT 8
static WAVEFORMATEX wf = {
1, // wFormatTag
0, // nChannels
0, // nSamplesPerSec
0, // nAvgBytesPerSec
4, // nBlockAlign
16, // wBitsPerSample
sizeof(WAVEFORMATEX) // cbSize
};
static const WAVEHDR wh_template = {
NULL, // lpData
0, // dwBufferLength
0, // dwBytesRecorded
0, // dwUser
0, // dwFlags
1, // dwLoops
NULL, // lpNext
0 // reserved
};
static mp3_decoder_t mp3;
static mp3_info_t info;
static unsigned char *stream_pos;
static int bytes_left;
static int byte_count;
static WAVEHDR wh[BUFFER_COUNT];
static signed short sample_buffer[MP3_MAX_SAMPLES_PER_FRAME * BUFFER_COUNT];
static HANDLE local_stdout;
#define out(text) WriteFile(local_stdout, (LPCVOID) text, strlen(text), NULL, NULL)
void CALLBACK AudioCallback(
HWAVEOUT hwo,
UINT uMsg,
DWORD_PTR dwInstance,
DWORD dwParam1,
DWORD dwParam2
) {
LPWAVEHDR wh = (LPWAVEHDR) dwParam1;
if (!wh) return;
if (byte_count) {
stream_pos += byte_count;
bytes_left -= byte_count;
waveOutUnprepareHeader(hwo, wh, sizeof(WAVEHDR));
waveOutPrepareHeader(hwo, wh, sizeof(WAVEHDR));
waveOutWrite(hwo, wh, sizeof(WAVEHDR));
}
byte_count = mp3_decode(mp3, stream_pos, bytes_left, (signed short *) wh->lpData, &info);
}
void ShowTag(const char *caption, const unsigned char *src, int max_length) {
static char tagbuf[32];
char *tagpos = tagbuf;
tagbuf[max_length] = '\0';
__asm {
cld
mov esi, src
mov edi, tagpos
mov ecx, max_length
rep movsb
}
if (!*tagbuf)
return;
out(caption);
out(tagbuf);
}
int main(void) {
char input_file_name[256];
char *inptr, *outptr = input_file_name;
HANDLE hFile, hMap;
HWAVEOUT hwo;
int i;
// init stdout and write banner
local_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
out("minimp3 -- a small MPEG Audio Layer III player based on ffmpeg\n\n");
// read arguments, but skip the program name
for (inptr = GetCommandLine(); (*inptr) && (*inptr != ' '); ++inptr) {
if (*inptr == '"') // skip "quoted arguments"
do { ++inptr; } while (*inptr != '"');
}
// skip whitespace
while (*inptr == ' ') ++inptr;
// check for a parameter
if (!*inptr) {
// no parameter -> quit
out("Error: no input file specified!\n");
return 1;
} else if (*inptr == '"') {
// "quoted parameter"
++inptr;
while (*inptr != '"')
*outptr++ = *inptr++;
} else {
// unquoted parameter
do {
*outptr++ = *inptr++;
} while(*inptr);
}
*outptr = '\0';
// open and mmap() the file
hFile = CreateFile(input_file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
bytes_left = GetFileSize(hFile, NULL) - 128;
hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
stream_pos = (unsigned char*) MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
// check if the result is valid
if (!stream_pos) {
out("Error: cannot open `");
out(input_file_name);
out("'!\n");
return 1;
} else {
out("Now Playing: ");
out(input_file_name);
}
// check for a ID3 tag
inptr = stream_pos + bytes_left;
if (((*(unsigned long *)inptr) & 0xFFFFFF) == 0x474154) {
ShowTag("\nTitle: ", inptr + 3, 30);
ShowTag("\nArtist: ", inptr + 33, 30);
ShowTag("\nAlbum: ", inptr + 63, 30);
ShowTag("\nYear: ", inptr + 93, 4);
ShowTag("\nComment: ", inptr + 97, 30);
}
// set up minimp3 and decode the first frame
mp3 = mp3_create();
byte_count = mp3_decode(mp3, stream_pos, bytes_left, sample_buffer, &info);
if (!byte_count) {
out("\nError: not a valid MP2 audio file!\n");
return 1;
}
// set up wave output
wf.nSamplesPerSec = info.sample_rate;
wf.nChannels = info.channels;
if(waveOutOpen(&hwo, WAVE_MAPPER, &wf, (INT_PTR) AudioCallback, (INT_PTR) NULL, CALLBACK_FUNCTION)
!= MMSYSERR_NOERROR) {
out("\nError: cannot open wave output!\n");
return 1;
}
// allocate buffers
out("\n\nPress Ctrl+C or close the console window to stop playback.\n");
inptr = (char*) sample_buffer;
for (i = 0; i < BUFFER_COUNT; ++i) {
wh[i] = wh_template;
wh[i].lpData = inptr;
wh[i].dwBufferLength = info.audio_bytes;
AudioCallback(hwo, 0, 0, (DWORD) &wh[i], 0);
inptr += MP3_MAX_SAMPLES_PER_FRAME * 2;
}
// endless loop
while (1) Sleep(10);
return 0;
}