init
This commit is contained in:
commit
6a616ebf74
8 changed files with 102549 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
build
|
||||
342
main.c
Normal file
342
main.c
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
#include <Mw/Milsko.h>
|
||||
#include <Mw/Widget/OpenGL.h>
|
||||
|
||||
#include "pl_mpeg.h"
|
||||
#include "miniaudio.h"
|
||||
#include "stb_ds.h"
|
||||
|
||||
#define MULTIPLE_BUFFER
|
||||
#define PERIOD PLM_AUDIO_SAMPLES_PER_FRAME
|
||||
#define BUFFERS 3
|
||||
|
||||
typedef struct buffer {
|
||||
float buffer[PERIOD * 2];
|
||||
} buffer_t;
|
||||
|
||||
static ma_device device;
|
||||
static buffer_t buffers[BUFFERS];
|
||||
static int buf_rseek = 0;
|
||||
static int buf_wseek = 0;
|
||||
static int buf_rframe = 0;
|
||||
static int buf_wframe = 0;
|
||||
static ma_mutex buf_mutex;
|
||||
static MwWidget box, opengl, progress;
|
||||
static plm_t* plm = NULL;
|
||||
static GLuint tex = 0;
|
||||
static unsigned char* vid = NULL;
|
||||
static int vw, vh;
|
||||
static int ww, wh;
|
||||
static double last;
|
||||
static int progress_move = 1;
|
||||
static int paused = 0;
|
||||
static int sample_rate = 0;
|
||||
|
||||
static void camera(int w, int h){
|
||||
MwOpenGLMakeCurrent(opengl);
|
||||
|
||||
glViewport(0, 0, w, h);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, w, h, 0, -1, 1);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
static void MWAPI resize(MwWidget widget, void* user, void* call){
|
||||
ww = MwGetInteger(widget, MwNwidth);
|
||||
wh = MwGetInteger(widget, MwNheight);
|
||||
|
||||
MwVaApply(box,
|
||||
MwNwidth, ww,
|
||||
MwNheight, wh,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void MWAPI opengl_resize(MwWidget widget, void* user, void* call){
|
||||
camera(MwGetInteger(widget, MwNwidth), MwGetInteger(widget, MwNheight));
|
||||
}
|
||||
|
||||
static void MWAPI progress_mouseDown(MwWidget widget, void* user, void* call){
|
||||
MwMouse* m = call;
|
||||
|
||||
if(m->button == MwMOUSE_LEFT) progress_move = 0;
|
||||
}
|
||||
|
||||
static void MWAPI progress_mouseUp(MwWidget widget, void* user, void* call){
|
||||
MwMouse* m = call;
|
||||
|
||||
if(m->button == MwMOUSE_LEFT) progress_move = 1;
|
||||
|
||||
plm_seek(plm, (double)MwGetInteger(widget, MwNvalue) / 1000, 1);
|
||||
}
|
||||
|
||||
static void MWAPI play_activate(MwWidget widget, void* user, void* call){
|
||||
plm_rewind(plm);
|
||||
}
|
||||
|
||||
static void MWAPI pause_activate(MwWidget widget, void* user, void* call){
|
||||
paused = !paused;
|
||||
}
|
||||
|
||||
static void on_audio(plm_t *mpeg, plm_samples_t *samples, void *user) {
|
||||
buffer_t buf;
|
||||
int i;
|
||||
int total;
|
||||
|
||||
total = samples->count;
|
||||
|
||||
for(i = 0; i < total; i++){
|
||||
int b = i * 2;
|
||||
|
||||
buf.buffer[i * 2 + 0] = samples->interleaved[b + 0];
|
||||
buf.buffer[i * 2 + 1] = samples->interleaved[b + 1];
|
||||
}
|
||||
|
||||
ma_mutex_lock(&buf_mutex);
|
||||
buffers[buf_wseek++] = buf;
|
||||
if(buf_wseek == BUFFERS) buf_wseek = 0;
|
||||
buf_wframe++;
|
||||
ma_mutex_unlock(&buf_mutex);
|
||||
}
|
||||
|
||||
static void on_video(plm_t* mpeg, plm_frame_t* frame, void* user){
|
||||
plm_frame_to_rgb(frame, vid, vw * 3);
|
||||
|
||||
MwOpenGLMakeCurrent(opengl);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, vw, vh, GL_RGB, GL_UNSIGNED_BYTE, vid);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
static void MWAPI tick(MwWidget widget, void* user, void* call){
|
||||
double sx = 0;
|
||||
double sy = 0;
|
||||
double sw = 0;
|
||||
double sh = 0;
|
||||
|
||||
if(((double)ww / vw) < ((double)wh / vh)){
|
||||
sw = ww;
|
||||
sh = (double)ww / vw * vh;
|
||||
}else{
|
||||
sh = wh;
|
||||
sw = (double)wh / vh * vw;
|
||||
}
|
||||
|
||||
sx = ((double)MwGetInteger(opengl, MwNwidth) - sw) / 2;
|
||||
sy = ((double)MwGetInteger(opengl, MwNheight) - sh) / 2;
|
||||
|
||||
MwOpenGLMakeCurrent(opengl);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
|
||||
glColor3f(1, 1, 1);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, 0); glVertex2f(sx, sy);
|
||||
glTexCoord2f(0, 1); glVertex2f(sx, sy + sh);
|
||||
glTexCoord2f(1, 1); glVertex2f(sx + sw, sy + sh);
|
||||
glTexCoord2f(1, 0); glVertex2f(sx + sw, sy);
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
MwOpenGLSwapBuffer(opengl);
|
||||
}
|
||||
|
||||
static int load(const char* input){
|
||||
int i;
|
||||
|
||||
buf_wframe = buf_wseek = 0;
|
||||
|
||||
memset(&buffers, 0, sizeof(buffers));
|
||||
|
||||
if(plm != NULL) plm_destroy(plm);
|
||||
|
||||
if((plm = plm_create_with_filename(input)) == NULL || !plm_probe(plm, 5000 * 1024)){
|
||||
if(plm != NULL){
|
||||
plm_destroy(plm);
|
||||
plm = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
plm_set_audio_decode_callback(plm, on_audio, NULL);
|
||||
plm_set_video_decode_callback(plm, on_video, NULL);
|
||||
plm_set_loop(plm, 1);
|
||||
|
||||
sample_rate = plm_get_samplerate(plm);
|
||||
|
||||
MwOpenGLMakeCurrent(opengl);
|
||||
|
||||
vw = plm_get_width(plm);
|
||||
vh = plm_get_height(plm);
|
||||
|
||||
MwVaApply(progress,
|
||||
MwNmaxValue, (int)(plm_get_duration(plm) * 1000),
|
||||
MwNvalue, 0,
|
||||
MwNareaShown, 1000 * 10,
|
||||
NULL);
|
||||
|
||||
if(vid != NULL) free(vid);
|
||||
|
||||
vid = malloc(vw * vh * 3);
|
||||
memset(vid, 0, vw * vh * 3);
|
||||
|
||||
for(i = 0; i < vw * vh; i++){
|
||||
vid[i * 3 + 0] = i / vw * 255 / vh;
|
||||
vid[i * 3 + 2] = (i % vw) * 255 / vw;
|
||||
}
|
||||
|
||||
if(tex != 0) glDeleteTextures(1, &tex);
|
||||
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, vw, vh, 0, GL_RGB, GL_UNSIGNED_BYTE, vid);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
last = (double)MwTimeGetTick() / 1000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void data_callback(ma_device* device, void* output, const void* input, ma_uint32 frame){
|
||||
short* o = output;
|
||||
int i;
|
||||
|
||||
memset(o, 0, frame * sizeof(short) * 2);
|
||||
|
||||
ma_mutex_lock(&buf_mutex);
|
||||
for(i = 0; i < frame * 2; i++){
|
||||
o[i] = buffers[buf_rseek].buffer[i] * 32767;
|
||||
}
|
||||
ma_mutex_unlock(&buf_mutex);
|
||||
|
||||
buf_rseek++;
|
||||
if(buf_rseek == BUFFERS) buf_rseek = 0;
|
||||
buf_rframe++;
|
||||
|
||||
if(buf_rframe > buf_wframe){
|
||||
buf_rframe = buf_wframe;
|
||||
buf_rseek = buf_wseek;
|
||||
}
|
||||
}
|
||||
|
||||
static int init(void){
|
||||
ma_device_config config;
|
||||
|
||||
ma_mutex_init(&buf_mutex);
|
||||
|
||||
config = ma_device_config_init(ma_device_type_playback);
|
||||
config.playback.format = ma_format_s16;
|
||||
config.playback.channels = 2;
|
||||
config.sampleRate = 48000;
|
||||
config.dataCallback = data_callback;
|
||||
config.pUserData = NULL;
|
||||
config.periodSizeInFrames = PERIOD;
|
||||
|
||||
if(ma_device_init(NULL, &config, &device) != MA_SUCCESS){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(ma_device_start(&device) != MA_SUCCESS){
|
||||
ma_device_uninit(&device);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
MwOpenGLMakeCurrent(opengl);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv){
|
||||
MwWidget w, bar, play, pause;
|
||||
int st;
|
||||
|
||||
MwLibraryInit();
|
||||
|
||||
w = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 800, 630,
|
||||
MwNtitle, "poc player",
|
||||
NULL);
|
||||
|
||||
box = MwVaCreateWidget(MwBoxClass, "box", w, 0, 0, 0, 0,
|
||||
MwNorientation, MwVERTICAL,
|
||||
NULL);
|
||||
|
||||
opengl = MwCreateWidget(MwOpenGLClass, "opengl", box, 0, 0, 0, 0);
|
||||
|
||||
bar = MwVaCreateWidget(MwBoxClass, "bar", box, 0, 0, 0, 0,
|
||||
MwNfixedSize, 30,
|
||||
MwNorientation, MwHORIZONTAL,
|
||||
NULL);
|
||||
|
||||
play = MwVaCreateWidget(MwButtonClass, "play", bar, 0, 0, 0, 0,
|
||||
MwNtext, "Play",
|
||||
MwNfixedSize, 60,
|
||||
NULL);
|
||||
|
||||
pause = MwVaCreateWidget(MwButtonClass, "pause", bar, 0, 0, 0, 0,
|
||||
MwNtext, "Pause",
|
||||
MwNfixedSize, 60,
|
||||
NULL);
|
||||
|
||||
progress = MwVaCreateWidget(MwScrollBarClass, "progress", bar, 0, 0, 0, 0,
|
||||
MwNshowArrows, 0,
|
||||
MwNorientation, MwHORIZONTAL,
|
||||
NULL);
|
||||
|
||||
MwAddUserHandler(w, MwNresizeHandler, resize, NULL);
|
||||
MwAddUserHandler(w, MwNtickHandler, tick, NULL);
|
||||
MwAddUserHandler(opengl, MwNresizeHandler, opengl_resize, NULL);
|
||||
MwAddUserHandler(progress, MwNmouseDownHandler, progress_mouseDown, NULL);
|
||||
MwAddUserHandler(progress, MwNmouseUpHandler, progress_mouseUp, NULL);
|
||||
MwAddUserHandler(play, MwNactivateHandler, play_activate, NULL);
|
||||
MwAddUserHandler(pause, MwNactivateHandler, pause_activate, NULL);
|
||||
|
||||
if((st = init()) != 0) return st;
|
||||
|
||||
resize(w, NULL, NULL);
|
||||
|
||||
if((st = load(argv[1])) != 0) return st;
|
||||
|
||||
while(1){
|
||||
double l2, elapsed;
|
||||
|
||||
while(MwPending(w)) MwStep(w);
|
||||
|
||||
elapsed = (l2 = (double)MwTimeGetTick() / 1000) - last;
|
||||
|
||||
if(elapsed > 1.0 / 30) elapsed = 1.0 / 30;
|
||||
|
||||
if(paused){
|
||||
buffer_t buf;
|
||||
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
|
||||
ma_mutex_lock(&buf_mutex);
|
||||
buffers[buf_wseek] = buf;
|
||||
if(buf_wseek == BUFFERS) buf_wseek = 0;
|
||||
ma_mutex_unlock(&buf_mutex);
|
||||
}else{
|
||||
plm_decode(plm, elapsed);
|
||||
last = l2;
|
||||
|
||||
if(progress_move){
|
||||
MwVaApply(progress,
|
||||
MwNvalue, (int)(plm_get_time(plm) * 1000),
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
miniaudio.c
Normal file
2
miniaudio.c
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "miniaudio.h"
|
||||
95864
miniaudio.h
Normal file
95864
miniaudio.h
Normal file
File diff suppressed because it is too large
Load diff
4
pl_mpeg.c
Normal file
4
pl_mpeg.c
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#define PL_MPEG_IMPLEMENTATION
|
||||
#include "pl_mpeg.h"
|
||||
2
stb_ds.c
Normal file
2
stb_ds.c
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#define STB_DS_IMPLEMENTATION
|
||||
#include "stb_ds.h"
|
||||
Loading…
Add table
Add a link
Reference in a new issue