mirror of
https://git.checksum.fail/alec/TOSamp.git
synced 2026-05-26 17:09:47 +00:00
676 lines
18 KiB
HolyC
676 lines
18 KiB
HolyC
#define IMG_MAIN player.images[0]
|
|
#define IMG_CBUTTONS player.images[1]
|
|
#define IMG_TEXT player.images[2]
|
|
#define IMG_NUMBERS player.images[3]
|
|
#define IMG_PLAYPAUS player.images[4]
|
|
#define IMG_MONOSTER player.images[5]
|
|
#define IMG_POSBAR player.images[6]
|
|
|
|
#define BTN_NULL 0
|
|
#define BTN_PREV 1
|
|
#define BTN_PLAY 2
|
|
#define BTN_PAUSE 3
|
|
#define BTN_STOP 4
|
|
#define BTN_NEXT 5
|
|
#define BTN_EJECT 6
|
|
|
|
#define ACTION_NULL 0
|
|
#define ACTION_PICK_FILE 1
|
|
|
|
#define SRC_TYPE_NULL 0
|
|
#define SRC_TYPE_PCM 1
|
|
#define SRC_TYPE_MP3 2
|
|
|
|
I64 bitrates[16] = {0, 32, 40, 48, 56, 64, 80, 96,
|
|
112, 128, 160, 192, 224, 256, 320, 0};
|
|
I64 samplerates[4] = {44, 48, 32, 0};
|
|
|
|
class @drmp3_config {
|
|
U32 outputChannels;
|
|
U32 outputSampleRate;
|
|
};
|
|
|
|
class @id3v1 {
|
|
U8 header[3];
|
|
U8 title[30];
|
|
U8 artist[30];
|
|
U8 album[30];
|
|
U8 year[4];
|
|
};
|
|
|
|
class @id3v2 {
|
|
U8 header[3];
|
|
U16 version;
|
|
U8 flags;
|
|
U32 size;
|
|
};
|
|
|
|
class @media {
|
|
U8 title[256];
|
|
U8 artist[256];
|
|
U8 album[256];
|
|
U8 year[16];
|
|
U32 channels;
|
|
U32 sampleRate;
|
|
U8 *source_data;
|
|
I64 source_len;
|
|
I64 source_type;
|
|
I64 source_bit_rate;
|
|
I64 source_sample_rate;
|
|
U8 *pcm_data;
|
|
I64 pcm_frames;
|
|
I64 fifo_frame;
|
|
I64 seek_frame;
|
|
I64 seek_to_frame;
|
|
I64 runtime_mins;
|
|
I64 runtime_secs;
|
|
Bool paused;
|
|
Bool stopped;
|
|
Bool loading;
|
|
Bool seeking;
|
|
};
|
|
|
|
class @marquee_char {
|
|
@marquee_char *next;
|
|
U8 char;
|
|
};
|
|
|
|
class @marquee {
|
|
@marquee_char *text;
|
|
@marquee_char *char;
|
|
I64 ticks;
|
|
};
|
|
|
|
class @player {
|
|
@media media;
|
|
CTask *windowTask;
|
|
CDC **images;
|
|
@marquee marquee;
|
|
I64 pressing_button;
|
|
I64 prev_lb_state;
|
|
I64 prev_rb_state;
|
|
U64 decoder_addr;
|
|
I64 audio_stream_id;
|
|
};
|
|
|
|
@player player;
|
|
|
|
U8 *TEXT_5X6_ROW_1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\"@";
|
|
U8 *TEXT_5X6_ROW_2 = "0123456789 :()-'!_+\\/[]^&%.=\d#";
|
|
U8 *TEXT_5X6_ROW_3 = " ?*";
|
|
U8 *TEXT_5X6_ROW_4 = "abcdefghijklmnopqrstuvwxyz";
|
|
|
|
U0 Draw5x6TextChar(CDC *dc, I64 x, I64 y, U8 ch) {
|
|
if (ch == ' ')
|
|
return;
|
|
CDC *char_dc = DCNew(5, 6);
|
|
U8 substr[2];
|
|
substr[0] = ch;
|
|
substr[1] = NULL;
|
|
Bool put_char = FALSE;
|
|
if (StrFind(substr, TEXT_5X6_ROW_1)) {
|
|
GrBlot(char_dc, -(5 * (StrFind(substr, TEXT_5X6_ROW_1) - TEXT_5X6_ROW_1)),
|
|
0, IMG_TEXT);
|
|
put_char = TRUE;
|
|
}
|
|
if (StrFind(substr, TEXT_5X6_ROW_2)) {
|
|
GrBlot(char_dc, -(5 * (StrFind(substr, TEXT_5X6_ROW_2) - TEXT_5X6_ROW_2)),
|
|
-6, IMG_TEXT);
|
|
put_char = TRUE;
|
|
}
|
|
if (StrFind(substr, TEXT_5X6_ROW_3)) {
|
|
GrBlot(char_dc, -(5 * (StrFind(substr, TEXT_5X6_ROW_3) - TEXT_5X6_ROW_3)),
|
|
-12, IMG_TEXT);
|
|
put_char = TRUE;
|
|
}
|
|
if (StrFind(substr, TEXT_5X6_ROW_4)) {
|
|
GrBlot(char_dc, -(5 * (StrFind(substr, TEXT_5X6_ROW_4) - TEXT_5X6_ROW_4)),
|
|
0, IMG_TEXT);
|
|
put_char = TRUE;
|
|
}
|
|
if (put_char)
|
|
GrBlot(dc, x, y, char_dc);
|
|
DCDel(char_dc);
|
|
}
|
|
|
|
U0 Draw5x6Text(CDC *dc, I64 x, I64 y, U8 *str) {
|
|
while (*str) {
|
|
Draw5x6TextChar(dc, x, y, *str);
|
|
str++;
|
|
x += 5;
|
|
}
|
|
}
|
|
|
|
U0 DrawPlayerBitRateSampleRate(CDC *dc, I64 x, I64 y) {
|
|
if (!player.media.source_bit_rate || !player.media.source_sample_rate)
|
|
return;
|
|
U8 buf[16];
|
|
StrPrint(buf, "%03d", player.media.source_bit_rate);
|
|
if (buf[0] == '0')
|
|
buf[0] = ' ';
|
|
Draw5x6Text(dc, x, y, buf);
|
|
StrPrint(buf, "%02d", player.media.source_sample_rate);
|
|
Draw5x6Text(dc, x + 46, y, buf);
|
|
}
|
|
|
|
U0 DrawPlayerMarqueeText(CDC *dc, I64 x, I64 y) {
|
|
I64 pos = 0;
|
|
I64 posX = 0;
|
|
@marquee_char *mchar = player.marquee.char;
|
|
while (pos < 31) {
|
|
Draw5x6TextChar(dc, posX + x, y, mchar->char);
|
|
posX += 5;
|
|
mchar = mchar->next;
|
|
pos++;
|
|
}
|
|
}
|
|
|
|
Bool CheckIfButtonIsHovered(I64 x, I64 y, I64 w, I64 h) {
|
|
if (ms.pos.x >= player.windowTask->pix_left + x &&
|
|
ms.pos.x <= player.windowTask->pix_left + x + w &&
|
|
ms.pos.y >= player.windowTask->pix_top + y &&
|
|
ms.pos.y <= player.windowTask->pix_top + y + h)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
U0 DrawPlayerPositionBar(CDC *dc, I64 x, I64 y) {
|
|
if (!player.media.source_data || !player.media.source_len)
|
|
return;
|
|
CDC *posbar_dc = DCNew(28, 10);
|
|
F64 i;
|
|
if (!player.media.seeking) {
|
|
GrBlot(posbar_dc, -250, 0, IMG_POSBAR);
|
|
i = (220.0 / ToF64(player.media.pcm_frames));
|
|
GrBlot(dc,
|
|
x + (i * (player.media.seek_frame +
|
|
Audio.output_frames[player.audio_stream_id])),
|
|
y, posbar_dc);
|
|
}
|
|
if (player.media.seeking) {
|
|
GrBlot(posbar_dc, -278, 0, IMG_POSBAR);
|
|
I64 j = ms.pos.x - (player.windowTask->pix_left + x) - 14;
|
|
I64 k = 0;
|
|
if (j < 0)
|
|
j = 0;
|
|
if (j > 220)
|
|
j = 220;
|
|
GrBlot(dc, x + j, y, posbar_dc);
|
|
i = (220.0 / ToF64(player.media.pcm_frames));
|
|
player.media.seek_to_frame = 0;
|
|
while ((i * (player.media.seek_to_frame +
|
|
Audio.output_frames[player.audio_stream_id]) <
|
|
j))
|
|
player.media.seek_to_frame++;
|
|
}
|
|
DCDel(posbar_dc);
|
|
}
|
|
|
|
U0 SeekTo(I64 frame) {
|
|
player.media.seek_frame = frame;
|
|
Audio.output_frames[player.audio_stream_id] = 0;
|
|
player.media.fifo_frame = 0;
|
|
}
|
|
|
|
U0 DrawPlayerControlsActive(CDC *dc, I64 x, I64 y) {
|
|
|
|
CDC *control_dc = DCNew(23, 18);
|
|
|
|
if (!ms.lb && player.prev_lb_state) {
|
|
switch (player.pressing_button) {
|
|
case BTN_PREV:
|
|
if (CheckIfButtonIsHovered(x, y, 23, 18)) {
|
|
// player.Prev();
|
|
}
|
|
break;
|
|
case BTN_PLAY:
|
|
if (CheckIfButtonIsHovered(x + (23 * 1), y, 23, 18)) {
|
|
player.media.paused = FALSE;
|
|
player.media.stopped = FALSE;
|
|
}
|
|
break;
|
|
case BTN_PAUSE:
|
|
if (CheckIfButtonIsHovered(x + (23 * 2), y, 23, 18)) {
|
|
player.media.paused = !player.media.paused;
|
|
}
|
|
break;
|
|
case BTN_STOP:
|
|
if (CheckIfButtonIsHovered(x + (23 * 3), y, 23, 18)) {
|
|
player.media.stopped = TRUE;
|
|
}
|
|
break;
|
|
case BTN_NEXT:
|
|
if (CheckIfButtonIsHovered(x + (23 * 4), y, 23, 18)) {
|
|
// player.Next();
|
|
}
|
|
break;
|
|
case BTN_EJECT:
|
|
if (CheckIfButtonIsHovered(x + 121, y + 1, 22, 15)) {
|
|
player.windowTask->user_data = ACTION_PICK_FILE;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
player.pressing_button = BTN_NULL;
|
|
if (player.media.seeking && player.media.seek_to_frame)
|
|
SeekTo(player.media.seek_to_frame);
|
|
player.media.seeking = FALSE;
|
|
}
|
|
|
|
if (ms.lb && !player.prev_lb_state) {
|
|
if (CheckIfButtonIsHovered(x, y, 23, 18))
|
|
player.pressing_button = BTN_PREV;
|
|
if (CheckIfButtonIsHovered(x + (23 * 1), y, 23, 18))
|
|
player.pressing_button = BTN_PLAY;
|
|
if (CheckIfButtonIsHovered(x + (23 * 2), y, 23, 18))
|
|
player.pressing_button = BTN_PAUSE;
|
|
if (CheckIfButtonIsHovered(x + (23 * 3), y, 23, 18))
|
|
player.pressing_button = BTN_STOP;
|
|
if (CheckIfButtonIsHovered(x + (23 * 4), y, 23, 18))
|
|
player.pressing_button = BTN_NEXT;
|
|
if (CheckIfButtonIsHovered(x + 121, y + 1, 22, 15))
|
|
player.pressing_button = BTN_EJECT;
|
|
if (CheckIfButtonIsHovered(21, 74, 248, 10))
|
|
player.media.seeking = TRUE;
|
|
}
|
|
|
|
switch (player.pressing_button) {
|
|
case BTN_PREV:
|
|
if (CheckIfButtonIsHovered(x, y, 23, 18)) {
|
|
DCFill(control_dc);
|
|
GrBlot(control_dc, 0, -17, IMG_CBUTTONS);
|
|
GrBlot(dc, x, y, control_dc);
|
|
}
|
|
break;
|
|
case BTN_PLAY:
|
|
if (CheckIfButtonIsHovered(x + (23 * 1), y, 23, 18)) {
|
|
DCFill(control_dc);
|
|
GrBlot(control_dc, -(23 * 1), -17, IMG_CBUTTONS);
|
|
GrBlot(dc, x + (23 * 1), y, control_dc);
|
|
}
|
|
break;
|
|
case BTN_PAUSE:
|
|
if (CheckIfButtonIsHovered(x + (23 * 2), y, 23, 18)) {
|
|
DCFill(control_dc);
|
|
GrBlot(control_dc, -(23 * 2), -17, IMG_CBUTTONS);
|
|
GrBlot(dc, x + (23 * 2), y, control_dc);
|
|
}
|
|
break;
|
|
case BTN_STOP:
|
|
if (CheckIfButtonIsHovered(x + (23 * 3), y, 23, 18)) {
|
|
DCFill(control_dc);
|
|
GrBlot(control_dc, -(23 * 3), -17, IMG_CBUTTONS);
|
|
GrBlot(dc, x + (23 * 3), y, control_dc);
|
|
}
|
|
break;
|
|
case BTN_NEXT:
|
|
if (CheckIfButtonIsHovered(x + (23 * 4), y, 23, 18)) {
|
|
DCFill(control_dc);
|
|
GrBlot(control_dc, -(23 * 4), -17, IMG_CBUTTONS);
|
|
GrBlot(dc, x + (23 * 4), y, control_dc);
|
|
}
|
|
break;
|
|
case BTN_EJECT:
|
|
if (CheckIfButtonIsHovered(x + 121, y + 1, 22, 15)) {
|
|
DCFill(control_dc);
|
|
GrBlot(control_dc, -113, -16, IMG_CBUTTONS);
|
|
control_dc->color = TRANSPARENT;
|
|
GrRect(control_dc, 0, 16, 32, 32);
|
|
GrBlot(dc, x + 121, y + 1, control_dc);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
player.prev_lb_state = ms.lb;
|
|
player.prev_rb_state = ms.rb;
|
|
|
|
DCDel(control_dc);
|
|
}
|
|
|
|
U0 DrawPlayerControlsIdle(CDC *dc, I64 x, I64 y) {
|
|
CDC *controls_dc = DCNew(114, 17);
|
|
CDC *eject_dc = DCNew(22, 15);
|
|
GrBlot(controls_dc, 0, 0, IMG_CBUTTONS);
|
|
GrBlot(eject_dc, -113, -1, IMG_CBUTTONS);
|
|
GrBlot(dc, x, y, controls_dc);
|
|
GrBlot(dc, x + 121, y + 1, eject_dc);
|
|
DCDel(controls_dc);
|
|
DCDel(eject_dc);
|
|
}
|
|
|
|
U0 DrawPlayerMonoStereo(CDC *dc, I64 x, I64 y) {
|
|
CDC *mono_dc = DCNew(29, 12);
|
|
CDC *stereo_dc = DCNew(29, 12);
|
|
DCFill(mono_dc);
|
|
DCFill(stereo_dc);
|
|
switch (player.media.channels) {
|
|
case 1:
|
|
GrBlot(mono_dc, -29, 0, IMG_MONOSTER);
|
|
GrBlot(stereo_dc, 0, -12, IMG_MONOSTER);
|
|
break;
|
|
case 2:
|
|
GrBlot(mono_dc, -29, -12, IMG_MONOSTER);
|
|
GrBlot(stereo_dc, 0, 0, IMG_MONOSTER);
|
|
break;
|
|
default:
|
|
GrBlot(mono_dc, -29, -12, IMG_MONOSTER);
|
|
GrBlot(stereo_dc, 0, -12, IMG_MONOSTER);
|
|
break;
|
|
}
|
|
GrBlot(dc, x, y, mono_dc);
|
|
GrBlot(dc, x + 29, y, stereo_dc);
|
|
DCDel(mono_dc);
|
|
DCDel(stereo_dc);
|
|
}
|
|
|
|
U0 InsertMarqueeTextChar(U8 ch) {
|
|
@marquee_char *pos = player.marquee.text;
|
|
if (!player.marquee.text) {
|
|
player.marquee.text = CAlloc(sizeof(@marquee_char));
|
|
player.marquee.text->char = ch;
|
|
player.marquee.text->next = player.marquee.text;
|
|
return;
|
|
}
|
|
while (pos->next != player.marquee.text)
|
|
pos = pos->next;
|
|
pos->next = CAlloc(sizeof(@marquee_char));
|
|
pos->next->char = ch;
|
|
pos->next->next = player.marquee.text;
|
|
}
|
|
|
|
U0 SetPlayerMarqueeText(U8 *str) {
|
|
player.marquee.text = NULL;
|
|
while (*str) {
|
|
InsertMarqueeTextChar(*str);
|
|
str++;
|
|
}
|
|
player.marquee.char = player.marquee.text;
|
|
}
|
|
|
|
U0 UpdatePlayerMarqueeTextPos() {
|
|
player.marquee.ticks++;
|
|
if (player.marquee.ticks > 6) {
|
|
player.marquee.ticks = 0;
|
|
player.marquee.char = player.marquee.char->next;
|
|
}
|
|
}
|
|
|
|
@drmp3_config config;
|
|
|
|
U0 DecodeMP3Frames() {
|
|
*GCC_FUN_ADDR(U64 *) = player.decoder_addr;
|
|
config.outputChannels = 2;
|
|
config.outputSampleRate = 48000;
|
|
*HOLYC_ARG1(U64 *) = player.media.source_data;
|
|
*HOLYC_ARG2(I32 *) = player.media.source_len;
|
|
*HOLYC_ARG3(U64 *) = &config;
|
|
*HOLYC_ARG4(U64 *) = &player.media.pcm_frames;
|
|
*HOLYC_ARG5(U64 *) = NULL;
|
|
asm {
|
|
MOV RDI, [HOLYC_ARG1]
|
|
MOV RSI, [HOLYC_ARG2]
|
|
MOV RDX, [HOLYC_ARG3]
|
|
MOV RCX, [HOLYC_ARG4]
|
|
MOV R8, [HOLYC_ARG5]
|
|
MOV RAX, [GCC_FUN_ADDR]
|
|
CLI
|
|
CALL RAX
|
|
MOV [HOLYC_ARG1], RAX
|
|
STI
|
|
}
|
|
player.media.channels = config.outputChannels;
|
|
player.media.sampleRate = config.outputSampleRate;
|
|
player.media.pcm_data = *HOLYC_ARG1(U64 *);
|
|
}
|
|
|
|
U0 CalculateMediaRunTime() {
|
|
player.media.runtime_mins =
|
|
(player.media.pcm_frames / player.media.sampleRate) / 60;
|
|
player.media.runtime_secs =
|
|
(player.media.pcm_frames / player.media.sampleRate) % 60;
|
|
}
|
|
|
|
U0 ParseID3(@id3v1 *tag) {
|
|
MemSet(player.media.title, NULL, 64);
|
|
MemSet(player.media.artist, NULL, 64);
|
|
MemSet(player.media.album, NULL, 64);
|
|
MemSet(player.media.year, NULL, 16);
|
|
if (MemCmp(tag->header, "TAG", 3))
|
|
return;
|
|
MemCpy(player.media.title, tag->title, 30);
|
|
MemCpy(&player.media.artist, tag->artist, 30);
|
|
MemCpy(&player.media.album, tag->album, 30);
|
|
MemCpy(&player.media.year, tag->year, 4);
|
|
}
|
|
|
|
U0 PlayerTask() {
|
|
I64 i;
|
|
while (1) {
|
|
i = 0;
|
|
if (FifoI64Cnt(Audio.output[player.audio_stream_id].data) < BDL_BUF_SIZE &&
|
|
player.media.pcm_data && !player.media.paused && !player.media.stopped)
|
|
while (player.media.seek_frame + player.media.fifo_frame <
|
|
player.media.pcm_frames &&
|
|
i < BDL_BUF_SIZE) {
|
|
FifoI64Ins(Audio.output[player.audio_stream_id].data,
|
|
(player.media.pcm_data)(U32 *)[player.media.seek_frame +
|
|
player.media.fifo_frame]);
|
|
player.media.fifo_frame++;
|
|
i++;
|
|
}
|
|
Sleep(1);
|
|
}
|
|
}
|
|
|
|
U0 GetMP3BitRateAndSampleRate() {
|
|
I64 i = 0;
|
|
@id3v2 *tag = player.media.source_data;
|
|
if (!MemCmp(player.media.source_data, "ID3", 3)) {
|
|
i += tag->size - 10;
|
|
if (tag->flags & 1 << 4)
|
|
i -= 10;
|
|
}
|
|
while (i < player.media.source_len) {
|
|
if (player.media.source_data[i] == 0xFF &&
|
|
player.media.source_data[i + 1] & 0xE0) // Frame Sync
|
|
if (player.media.source_data[i + 1] & 0x1A) // MPEG 1, Layer 3
|
|
{
|
|
player.media.source_bit_rate =
|
|
bitrates[player.media.source_data[i + 2] >> 4 & 0xF];
|
|
player.media.source_sample_rate =
|
|
samplerates[player.media.source_data[i + 2] >> 2 & 0x3];
|
|
return;
|
|
}
|
|
i++;
|
|
Sleep(1);
|
|
}
|
|
}
|
|
|
|
U0 OpenAndPlayFile(U8 *filename) {
|
|
if (!FileFind(filename)) {
|
|
PopUpOk("Error: File not found.");
|
|
return;
|
|
}
|
|
|
|
player.media.loading = TRUE;
|
|
player.media.source_data = FileRead(filename, &player.media.source_len);
|
|
player.media.source_type = SRC_TYPE_MP3;
|
|
|
|
// I shouldn't have to do this, but I get weird memory access/corruption
|
|
// issues if I pass the memory location to ParseID3() if one of the fields is
|
|
// over 20 characters... :/
|
|
U8 id3_buffer[128];
|
|
MemCpy(id3_buffer, player.media.source_data + player.media.source_len - 128,
|
|
128);
|
|
|
|
switch (player.media.source_type) {
|
|
case SRC_TYPE_MP3:
|
|
WinFocus(player.windowTask);
|
|
Sleep(100); // Give WinMgr some time to remove the PopUpPickFile window
|
|
ParseID3(id3_buffer);
|
|
GetMP3BitRateAndSampleRate;
|
|
DecodeMP3Frames;
|
|
CalculateMediaRunTime;
|
|
break;
|
|
default:
|
|
PopUpOk("Error: Unsupported media type.");
|
|
player.media.loading = FALSE;
|
|
return;
|
|
break;
|
|
}
|
|
|
|
U8 marquee_buf[32];
|
|
StrPrint(marquee_buf, "1. %s - %s (%02d:%02d) *** ", player.media.artist,
|
|
player.media.title, player.media.runtime_mins,
|
|
player.media.runtime_secs);
|
|
SetPlayerMarqueeText(marquee_buf);
|
|
|
|
FifoI64Flush(Audio.output[player.audio_stream_id]);
|
|
|
|
player.media.fifo_frame = 0;
|
|
player.media.seek_frame = 0;
|
|
Audio.output_frames[player.audio_stream_id] = 0;
|
|
|
|
player.media.loading = FALSE;
|
|
player.media.stopped = FALSE;
|
|
player.media.paused = FALSE;
|
|
}
|
|
|
|
U0 DrawPlayerTimeElapsed(CDC *dc) {
|
|
if (player.media.stopped)
|
|
return;
|
|
|
|
if (player.media.paused && !Blink(.5))
|
|
return;
|
|
|
|
I64 i;
|
|
|
|
U8 min_buf[3];
|
|
U8 sec_buf[3];
|
|
min_buf[2] = NULL;
|
|
sec_buf[2] = NULL;
|
|
|
|
StrPrint(
|
|
min_buf, "%02d",
|
|
((player.media.seek_frame + Audio.output_frames[player.audio_stream_id]) /
|
|
player.media.sampleRate) /
|
|
60);
|
|
StrPrint(
|
|
sec_buf, "%02d",
|
|
((player.media.seek_frame + Audio.output_frames[player.audio_stream_id]) /
|
|
player.media.sampleRate) %
|
|
60);
|
|
|
|
CDC *num_dc = DCNew(9, 13);
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
DCFill(num_dc);
|
|
GrBlot(num_dc, -(9 * (min_buf[i] - '0')), 0, IMG_NUMBERS);
|
|
GrBlot(dc, 50 + (12 * i), 27, num_dc);
|
|
}
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
DCFill(num_dc);
|
|
GrBlot(num_dc, -(9 * (sec_buf[i] - '0')), 0, IMG_NUMBERS);
|
|
GrBlot(dc, 81 + (12 * i), 27, num_dc);
|
|
}
|
|
|
|
DCDel(num_dc);
|
|
}
|
|
|
|
U0 DrawPlayerPlayPauseStopped(CDC *dc) {
|
|
CDC *state_dc = DCNew(9, 9);
|
|
|
|
if (!player.media.paused && !player.media.stopped) {
|
|
DCFill(state_dc);
|
|
GrBlot(state_dc, 0, 0, IMG_PLAYPAUS);
|
|
GrBlot(dc, 28, 28, state_dc);
|
|
}
|
|
|
|
if (player.media.paused) {
|
|
DCFill(state_dc);
|
|
GrBlot(state_dc, -9, 0, IMG_PLAYPAUS);
|
|
GrBlot(dc, 28, 28, state_dc);
|
|
}
|
|
|
|
if (player.media.stopped) {
|
|
DCFill(state_dc);
|
|
GrBlot(state_dc, -18, 0, IMG_PLAYPAUS);
|
|
GrBlot(dc, 28, 28, state_dc);
|
|
}
|
|
|
|
DCDel(state_dc);
|
|
}
|
|
|
|
U0 DrawPlayer(CTask *, CDC *dc) {
|
|
if (!player.media.loading) {
|
|
GrBlot(dc, 3, 2, IMG_MAIN);
|
|
UpdatePlayerMarqueeTextPos;
|
|
DrawPlayerMarqueeText(dc, 113, 29);
|
|
DrawPlayerBitRateSampleRate(dc, 114, 45);
|
|
DrawPlayerMonoStereo(dc, 212, 43);
|
|
DrawPlayerPlayPauseStopped(dc);
|
|
DrawPlayerTimeElapsed(dc);
|
|
DrawPlayerControlsActive(dc, 22, 91);
|
|
DrawPlayerPositionBar(dc, 21, 74);
|
|
}
|
|
}
|
|
|
|
U0 InitPlayer() {
|
|
MemSet(&player, sizeof(@player), NULL);
|
|
player.windowTask = Fs;
|
|
player.windowTask->win_width = 35;
|
|
WinHorz((TEXT_COLS / 2) - (player.windowTask->win_width / 2),
|
|
(TEXT_COLS / 2) - (player.windowTask->win_width / 2) +
|
|
(player.windowTask->win_width - 1),
|
|
player.windowTask);
|
|
player.windowTask->win_height = 15;
|
|
WinVert((TEXT_ROWS / 2) - (player.windowTask->win_height / 2),
|
|
(TEXT_ROWS / 2) - (player.windowTask->win_height / 2) +
|
|
(player.windowTask->win_height - 1),
|
|
player.windowTask);
|
|
|
|
player.images = CAlloc(sizeof(CDC *) * 32);
|
|
IMG_MAIN = PNGRead("T:/Images/MAIN.png");
|
|
IMG_CBUTTONS = PNGRead("T:/Images/CBUTTONS.png");
|
|
IMG_TEXT = PNGRead("T:/Images/TEXT.png");
|
|
IMG_NUMBERS = PNGRead("T:/Images/NUMBERS.png");
|
|
IMG_PLAYPAUS = PNGRead("T:/Images/PLAYPAUS.png");
|
|
IMG_MONOSTER = PNGRead("T:/Images/MONOSTER.png");
|
|
IMG_POSBAR = PNGRead("T:/Images/POSBAR.png");
|
|
|
|
DrawPlayerControlsIdle(IMG_MAIN, 19, 90);
|
|
// the control buttons are 23x18
|
|
|
|
SetPlayerMarqueeText(
|
|
"Welcome to TosAMP - MP3 Music Player for TempleOS *** ");
|
|
|
|
player.media.stopped = TRUE;
|
|
player.decoder_addr =
|
|
get_symbol_address("drmp3_open_memory_and_read_pcm_frames_s16");
|
|
player.audio_stream_id = @audio_get_available_output_stream;
|
|
player.windowTask->draw_it = &DrawPlayer;
|
|
|
|
Spawn(&PlayerTask, , "TOSamp Player Task", 1);
|
|
|
|
DocClear;
|
|
U8 *res = NULL;
|
|
while (1) {
|
|
StrCpy(player.windowTask->task_title, "...TOSamp...");
|
|
switch (Fs->user_data) {
|
|
case ACTION_PICK_FILE:
|
|
res = PopUpPickFile("T:/Music/");
|
|
Fs->user_data = NULL;
|
|
if (res)
|
|
if (StrCmp(res, ""))
|
|
OpenAndPlayFile(res);
|
|
break;
|
|
default:
|
|
break;
|
|
};
|
|
Sleep(1);
|
|
}
|
|
}
|