mirror of
https://gitea.nishi.boats/pyrite-dev/milsko
synced 2026-01-09 10:53:27 +00:00
working mpegplayer example
git-svn-id: http://svn2.nishi.boats/svn/milsko/trunk@506 b9cfdab3-6d41-4d17-bbe4-086880011989
This commit is contained in:
@@ -161,10 +161,10 @@ EXAMPLES = examples/basic/example$(EXEC) examples/basic/rotate$(EXEC) examples/b
|
||||
ifeq ($(OPENGL),1)
|
||||
L_OBJS += src/widget/opengl.o
|
||||
|
||||
MP_OBJS = examples/mpegplayer/main.o
|
||||
MP_OBJS = examples/mpegplayer/mpegplayer.o
|
||||
MP_OBJS += external/pl_mpeg.o external/stb_ds.o external/miniaudio.o
|
||||
|
||||
EXAMPLES += examples/gldemos/clock$(EXEC) examples/gldemos/triangle$(EXEC) examples/gldemos/gears$(EXEC) examples/gldemos/boing$(EXEC) examples/gldemos/cube$(EXEC) examples/gldemos/tripaint$(EXEC) examples/mpegplayer/mpegplayer$(EXEC)
|
||||
EXAMPLES += examples/gldemos/clock$(EXEC) examples/gldemos/triangle$(EXEC) examples/gldemos/gears$(EXEC) examples/gldemos/boing$(EXEC) examples/gldemos/cube$(EXEC) examples/gldemos/tripaint$(EXEC)
|
||||
endif
|
||||
|
||||
ifeq ($(VULKAN),1)
|
||||
@@ -211,7 +211,7 @@ src/%.o: src/%.c
|
||||
$(CC) $(L_CFLAGS) -c -o $@ $<
|
||||
|
||||
external/%.o: external/%.c
|
||||
$(CC) $(L_CFLAGS) -Wno-unused-value -Wno-unused-parameter -Wno-unused-function -c -o $@ $<
|
||||
$(CC) $(L_CFLAGS) -Wno-unused-value -Wno-unused-parameter -Wno-unused-function -Wno-stringop-overflow -c -o $@ $<
|
||||
|
||||
examples/%.o: examples/%.c
|
||||
$(CC) $(E_CFLAGS) -c -o $@ $<
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
/* $Id$ */
|
||||
#include <Mw/Milsko.h>
|
||||
|
||||
extern MwWidget wWindow, wOpengl;
|
||||
extern MwWidget bPlay, bPause;
|
||||
@@ -1,24 +1,311 @@
|
||||
/* $Id$ */
|
||||
#include "common.h"
|
||||
|
||||
#include <Mw/Milsko.h>
|
||||
#include <Mw/Widget/OpenGL.h>
|
||||
|
||||
#include "../../external/pl_mpeg.h"
|
||||
#include "../../external/miniaudio.h"
|
||||
#include "../../external/stb_ds.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
typedef struct buffer {
|
||||
unsigned char* buffer;
|
||||
int seek;
|
||||
int size;
|
||||
} buffer_t;
|
||||
|
||||
typedef struct frame {
|
||||
unsigned char* buffer;
|
||||
int width;
|
||||
int height;
|
||||
int count;
|
||||
} frame_t;
|
||||
|
||||
MwWidget wWindow, wOpengl;
|
||||
MwWidget bPlay, bPause;
|
||||
plm_t* plm;
|
||||
GLuint tex;
|
||||
buffer_t* buffers = NULL;
|
||||
frame_t* frames = NULL;
|
||||
ma_mutex mutex;
|
||||
ma_event event;
|
||||
ma_device device;
|
||||
ma_device_config config;
|
||||
int paused = 0;
|
||||
int quit = 0;
|
||||
int wait = 16;
|
||||
int v = 0, r = 1;
|
||||
#ifdef _WIN32
|
||||
HANDLE thread;
|
||||
#else
|
||||
pthread_t thread;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
static DWORD WINAPI thread_routine(void* arg){
|
||||
#else
|
||||
static void* thread_routine(void* arg){
|
||||
#endif
|
||||
(void)arg;
|
||||
|
||||
ma_event_wait(&event);
|
||||
|
||||
while(!plm_has_ended(plm) && !quit){
|
||||
ma_mutex_lock(&mutex);
|
||||
if(arrlen(frames) > 10 || paused){
|
||||
ma_mutex_unlock(&mutex);
|
||||
#ifdef _WIN32
|
||||
Sleep(1);
|
||||
#else
|
||||
usleep(1000);
|
||||
#endif
|
||||
}else{
|
||||
ma_mutex_unlock(&mutex);
|
||||
v = 0;
|
||||
plm_decode(plm, wait / 1000.0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
return 0;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void data_callback(ma_device* device, void* out, const void* in, ma_uint32 frame){
|
||||
int fsz = sizeof(float) * frame * 2;
|
||||
int bsz = 0;
|
||||
|
||||
(void)device;
|
||||
(void)in;
|
||||
|
||||
memset(out, 0, sizeof(float) * frame * 2);
|
||||
|
||||
ma_mutex_lock(&mutex);
|
||||
while(fsz > 0 && arrlen(buffers) > 0){
|
||||
int sz = 0;
|
||||
if(fsz > (buffers[0].size - buffers[0].seek)){
|
||||
sz = buffers[0].size - buffers[0].seek;
|
||||
}else{
|
||||
sz = fsz;
|
||||
}
|
||||
memcpy(bsz + (unsigned char*)out, buffers[0].buffer + buffers[0].seek, sz);
|
||||
|
||||
buffers[0].seek += sz;
|
||||
fsz -= sz;
|
||||
bsz += sz;
|
||||
if(buffers[0].seek >= buffers[0].size){
|
||||
free(buffers[0].buffer);
|
||||
arrdel(buffers, 0);
|
||||
}
|
||||
}
|
||||
ma_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
double a = 0;
|
||||
static void tick(MwWidget handle, void* user, void* call){
|
||||
(void)handle;
|
||||
(void)user;
|
||||
(void)call;
|
||||
|
||||
ma_mutex_lock(&mutex);
|
||||
if(arrlen(frames) > 0){
|
||||
double f = (1000.0 / wait) / plm_get_framerate(plm);
|
||||
|
||||
if(frames[0].count == 0){
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, frames[0].width, frames[0].height, 0, GL_RGB, GL_UNSIGNED_BYTE, frames[0].buffer);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
frames[0].count++;
|
||||
if(f >= 1 && frames[0].count >= (int)f + (int)a){
|
||||
a += f - (int)f;
|
||||
if(a > 1) a--;
|
||||
free(frames[0].buffer);
|
||||
arrdel(frames, 0);
|
||||
}else if(f < 1){
|
||||
free(frames[0].buffer);
|
||||
arrdel(frames, 0);
|
||||
}
|
||||
}
|
||||
ma_mutex_unlock(&mutex);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, 1, 1, 0, -1, 1);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, 0); glVertex2f(0, 0);
|
||||
glTexCoord2f(0, 1); glVertex2f(0, 1);
|
||||
glTexCoord2f(1, 1); glVertex2f(1, 1);
|
||||
glTexCoord2f(1, 0); glVertex2f(1, 0);
|
||||
glEnd();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
MwOpenGLSwapBuffer(wOpengl);
|
||||
|
||||
if(r){
|
||||
ma_event_signal(&event);
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void video_cb(plm_t* self, plm_frame_t* frame, void* user){
|
||||
unsigned char* data = malloc(frame->width * frame->height * 3);
|
||||
frame_t f;
|
||||
|
||||
(void)self;
|
||||
(void)user;
|
||||
|
||||
if(v){
|
||||
free(data);
|
||||
return;
|
||||
}else{
|
||||
v = 1;
|
||||
}
|
||||
|
||||
plm_frame_to_rgb(frame, data, frame->width * 3);
|
||||
f.buffer = data;
|
||||
f.width = frame->width;
|
||||
f.height = frame->height;
|
||||
f.count = 0;
|
||||
|
||||
ma_mutex_lock(&mutex);
|
||||
arrput(frames, f);
|
||||
ma_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
static void audio_cb(plm_t* self, plm_samples_t* samples, void* user){
|
||||
buffer_t buf;
|
||||
|
||||
(void)self;
|
||||
(void)user;
|
||||
|
||||
buf.size = sizeof(float) * samples->count * 2;
|
||||
buf.seek = 0;
|
||||
buf.buffer = malloc(sizeof(float) * samples->count * 2);
|
||||
memcpy(buf.buffer, samples->interleaved, sizeof(float) * samples->count * 2);
|
||||
|
||||
ma_mutex_lock(&mutex);
|
||||
arrput(buffers, buf);
|
||||
ma_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
static void button_play(MwWidget handle, void* user, void* call){
|
||||
(void)handle;
|
||||
(void)user;
|
||||
(void)call;
|
||||
|
||||
ma_mutex_lock(&mutex);
|
||||
paused = 0;
|
||||
ma_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
static void button_pause(MwWidget handle, void* user, void* call){
|
||||
(void)handle;
|
||||
(void)user;
|
||||
(void)call;
|
||||
|
||||
ma_mutex_lock(&mutex);
|
||||
paused = 1;
|
||||
ma_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
MwSizeHints sh;
|
||||
#ifdef _WIN32
|
||||
DWORD thid;
|
||||
#else
|
||||
void* ret;
|
||||
#endif
|
||||
int scw = 640, sch = 480;
|
||||
|
||||
if(argc != 2) return 1;
|
||||
|
||||
wWindow = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 5 + 640 + 5 + 64 + 5, 5 + 480 + 5,
|
||||
plm = plm_create_with_filename(argv[1]);
|
||||
if(plm == NULL) return 1;
|
||||
|
||||
wait = 1000.0 / plm_get_framerate(plm);
|
||||
|
||||
sh.min_width = sh.max_width = 5 + scw + 5 + 64 + 5;
|
||||
sh.min_height = sh.max_height = 5 + sch + 5;
|
||||
|
||||
wWindow = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, sh.min_width, sh.min_height,
|
||||
MwNtitle, "mpeg player",
|
||||
MwNsizeHints, &sh,
|
||||
MwNwaitMS, wait,
|
||||
NULL);
|
||||
wOpengl = MwCreateWidget(MwOpenGLClass, "opengl", wWindow, 5, 5, 640, 480);
|
||||
bPlay = MwVaCreateWidget(MwButtonClass, "play", wWindow, 5 + 640 + 5, 5, 64, 24,
|
||||
wOpengl = MwCreateWidget(MwOpenGLClass, "opengl", wWindow, 5, 5, scw, sch);
|
||||
bPlay = MwVaCreateWidget(MwButtonClass, "play", wWindow, 5 + scw + 5, 5, 64, 24,
|
||||
MwNtext, "Play",
|
||||
NULL);
|
||||
bPause = MwVaCreateWidget(MwButtonClass, "pause", wWindow, 5 + 640 + 5, 5 + 24 + 5, 64, 24,
|
||||
bPause = MwVaCreateWidget(MwButtonClass, "pause", wWindow, 5 + scw + 5, 5 + 24 + 5, 64, 24,
|
||||
MwNtext, "Pause",
|
||||
NULL);
|
||||
|
||||
MwAddUserHandler(bPlay, MwNactivateHandler, button_play, NULL);
|
||||
MwAddUserHandler(bPause, MwNactivateHandler, button_pause, NULL);
|
||||
|
||||
plm_set_loop(plm, 1);
|
||||
plm_set_audio_enabled(plm, 1);
|
||||
plm_set_audio_stream(plm, 0);
|
||||
|
||||
plm_set_video_decode_callback(plm, video_cb, NULL);
|
||||
plm_set_audio_decode_callback(plm, audio_cb, NULL);
|
||||
|
||||
MwOpenGLMakeCurrent(wOpengl);
|
||||
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
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);
|
||||
|
||||
ma_event_init(&event);
|
||||
ma_mutex_init(&mutex);
|
||||
config = ma_device_config_init(ma_device_type_playback);
|
||||
config.playback.format = ma_format_f32;
|
||||
config.playback.channels = 2;
|
||||
config.sampleRate = plm_get_samplerate(plm);
|
||||
config.dataCallback = data_callback;
|
||||
ma_device_init(NULL, &config, &device);
|
||||
ma_device_start(&device);
|
||||
|
||||
#ifdef _WIN32
|
||||
thread = CreateThread(NULL, 0, thread_routine, NULL, 0, &thid);
|
||||
#else
|
||||
pthread_create(&thread, NULL, thread_routine, NULL);
|
||||
#endif
|
||||
|
||||
MwAddUserHandler(wWindow, MwNtickHandler, tick, NULL);
|
||||
|
||||
MwLoop(wWindow);
|
||||
|
||||
ma_mutex_lock(&mutex);
|
||||
quit = 1;
|
||||
ma_mutex_unlock(&mutex);
|
||||
|
||||
#ifdef _WIN32
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
CloseHandle(thread);
|
||||
#else
|
||||
pthread_join(thread, &ret);
|
||||
#endif
|
||||
plm_destroy(plm);
|
||||
ma_device_uninit(&device);
|
||||
ma_mutex_uninit(&mutex);
|
||||
ma_event_uninit(&event);
|
||||
}
|
||||
|
||||
311
examples/mpegplayer/mpegplayer.c
Normal file
311
examples/mpegplayer/mpegplayer.c
Normal file
@@ -0,0 +1,311 @@
|
||||
/* $Id$ */
|
||||
#include <Mw/Milsko.h>
|
||||
#include <Mw/Widget/OpenGL.h>
|
||||
|
||||
#include "../../external/pl_mpeg.h"
|
||||
#include "../../external/miniaudio.h"
|
||||
#include "../../external/stb_ds.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
typedef struct buffer {
|
||||
unsigned char* buffer;
|
||||
int seek;
|
||||
int size;
|
||||
} buffer_t;
|
||||
|
||||
typedef struct frame {
|
||||
unsigned char* buffer;
|
||||
int width;
|
||||
int height;
|
||||
int count;
|
||||
} frame_t;
|
||||
|
||||
MwWidget wWindow, wOpengl;
|
||||
MwWidget bPlay, bPause;
|
||||
plm_t* plm;
|
||||
GLuint tex;
|
||||
buffer_t* buffers = NULL;
|
||||
frame_t* frames = NULL;
|
||||
ma_mutex mutex;
|
||||
ma_event event;
|
||||
ma_device device;
|
||||
ma_device_config config;
|
||||
int paused = 0;
|
||||
int quit = 0;
|
||||
int wait = 16;
|
||||
int v = 0, r = 1;
|
||||
#ifdef _WIN32
|
||||
HANDLE thread;
|
||||
#else
|
||||
pthread_t thread;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
static DWORD WINAPI thread_routine(void* arg){
|
||||
#else
|
||||
static void* thread_routine(void* arg){
|
||||
#endif
|
||||
(void)arg;
|
||||
|
||||
ma_event_wait(&event);
|
||||
|
||||
while(!plm_has_ended(plm) && !quit){
|
||||
ma_mutex_lock(&mutex);
|
||||
if(arrlen(frames) > 10 || paused){
|
||||
ma_mutex_unlock(&mutex);
|
||||
#ifdef _WIN32
|
||||
Sleep(1);
|
||||
#else
|
||||
usleep(1000);
|
||||
#endif
|
||||
}else{
|
||||
ma_mutex_unlock(&mutex);
|
||||
v = 0;
|
||||
plm_decode(plm, wait / 1000.0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
return 0;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void data_callback(ma_device* device, void* out, const void* in, ma_uint32 frame){
|
||||
int fsz = sizeof(float) * frame * 2;
|
||||
int bsz = 0;
|
||||
|
||||
(void)device;
|
||||
(void)in;
|
||||
|
||||
memset(out, 0, sizeof(float) * frame * 2);
|
||||
|
||||
ma_mutex_lock(&mutex);
|
||||
while(fsz > 0 && arrlen(buffers) > 0){
|
||||
int sz = 0;
|
||||
if(fsz > (buffers[0].size - buffers[0].seek)){
|
||||
sz = buffers[0].size - buffers[0].seek;
|
||||
}else{
|
||||
sz = fsz;
|
||||
}
|
||||
memcpy(bsz + (unsigned char*)out, buffers[0].buffer + buffers[0].seek, sz);
|
||||
|
||||
buffers[0].seek += sz;
|
||||
fsz -= sz;
|
||||
bsz += sz;
|
||||
if(buffers[0].seek >= buffers[0].size){
|
||||
free(buffers[0].buffer);
|
||||
arrdel(buffers, 0);
|
||||
}
|
||||
}
|
||||
ma_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
double a = 0;
|
||||
static void tick(MwWidget handle, void* user, void* call){
|
||||
(void)handle;
|
||||
(void)user;
|
||||
(void)call;
|
||||
|
||||
ma_mutex_lock(&mutex);
|
||||
if(arrlen(frames) > 0){
|
||||
double f = (1000.0 / wait) / plm_get_framerate(plm);
|
||||
|
||||
if(frames[0].count == 0){
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, frames[0].width, frames[0].height, 0, GL_RGB, GL_UNSIGNED_BYTE, frames[0].buffer);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
frames[0].count++;
|
||||
if(f >= 1 && frames[0].count >= (int)f + (int)a){
|
||||
a += f - (int)f;
|
||||
if(a > 1) a--;
|
||||
free(frames[0].buffer);
|
||||
arrdel(frames, 0);
|
||||
}else if(f < 1){
|
||||
free(frames[0].buffer);
|
||||
arrdel(frames, 0);
|
||||
}
|
||||
}
|
||||
ma_mutex_unlock(&mutex);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, 1, 1, 0, -1, 1);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, 0); glVertex2f(0, 0);
|
||||
glTexCoord2f(0, 1); glVertex2f(0, 1);
|
||||
glTexCoord2f(1, 1); glVertex2f(1, 1);
|
||||
glTexCoord2f(1, 0); glVertex2f(1, 0);
|
||||
glEnd();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
MwOpenGLSwapBuffer(wOpengl);
|
||||
|
||||
if(r){
|
||||
ma_event_signal(&event);
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void video_cb(plm_t* self, plm_frame_t* frame, void* user){
|
||||
unsigned char* data = malloc(frame->width * frame->height * 3);
|
||||
frame_t f;
|
||||
|
||||
(void)self;
|
||||
(void)user;
|
||||
|
||||
if(v){
|
||||
free(data);
|
||||
return;
|
||||
}else{
|
||||
v = 1;
|
||||
}
|
||||
|
||||
plm_frame_to_rgb(frame, data, frame->width * 3);
|
||||
f.buffer = data;
|
||||
f.width = frame->width;
|
||||
f.height = frame->height;
|
||||
f.count = 0;
|
||||
|
||||
ma_mutex_lock(&mutex);
|
||||
arrput(frames, f);
|
||||
ma_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
static void audio_cb(plm_t* self, plm_samples_t* samples, void* user){
|
||||
buffer_t buf;
|
||||
|
||||
(void)self;
|
||||
(void)user;
|
||||
|
||||
buf.size = sizeof(float) * samples->count * 2;
|
||||
buf.seek = 0;
|
||||
buf.buffer = malloc(sizeof(float) * samples->count * 2);
|
||||
memcpy(buf.buffer, samples->interleaved, sizeof(float) * samples->count * 2);
|
||||
|
||||
ma_mutex_lock(&mutex);
|
||||
arrput(buffers, buf);
|
||||
ma_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
static void button_play(MwWidget handle, void* user, void* call){
|
||||
(void)handle;
|
||||
(void)user;
|
||||
(void)call;
|
||||
|
||||
ma_mutex_lock(&mutex);
|
||||
paused = 0;
|
||||
ma_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
static void button_pause(MwWidget handle, void* user, void* call){
|
||||
(void)handle;
|
||||
(void)user;
|
||||
(void)call;
|
||||
|
||||
ma_mutex_lock(&mutex);
|
||||
paused = 1;
|
||||
ma_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
MwSizeHints sh;
|
||||
#ifdef _WIN32
|
||||
DWORD thid;
|
||||
#else
|
||||
void* ret;
|
||||
#endif
|
||||
int scw = 640, sch = 480;
|
||||
|
||||
if(argc != 2) return 1;
|
||||
|
||||
plm = plm_create_with_filename(argv[1]);
|
||||
if(plm == NULL) return 1;
|
||||
|
||||
wait = 1000.0 / plm_get_framerate(plm);
|
||||
|
||||
sh.min_width = sh.max_width = 5 + scw + 5 + 64 + 5;
|
||||
sh.min_height = sh.max_height = 5 + sch + 5;
|
||||
|
||||
wWindow = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, sh.min_width, sh.min_height,
|
||||
MwNtitle, "mpeg player",
|
||||
MwNsizeHints, &sh,
|
||||
MwNwaitMS, wait,
|
||||
NULL);
|
||||
wOpengl = MwCreateWidget(MwOpenGLClass, "opengl", wWindow, 5, 5, scw, sch);
|
||||
bPlay = MwVaCreateWidget(MwButtonClass, "play", wWindow, 5 + scw + 5, 5, 64, 24,
|
||||
MwNtext, "Play",
|
||||
NULL);
|
||||
bPause = MwVaCreateWidget(MwButtonClass, "pause", wWindow, 5 + scw + 5, 5 + 24 + 5, 64, 24,
|
||||
MwNtext, "Pause",
|
||||
NULL);
|
||||
|
||||
MwAddUserHandler(bPlay, MwNactivateHandler, button_play, NULL);
|
||||
MwAddUserHandler(bPause, MwNactivateHandler, button_pause, NULL);
|
||||
|
||||
plm_set_loop(plm, 1);
|
||||
plm_set_audio_enabled(plm, 1);
|
||||
plm_set_audio_stream(plm, 0);
|
||||
|
||||
plm_set_video_decode_callback(plm, video_cb, NULL);
|
||||
plm_set_audio_decode_callback(plm, audio_cb, NULL);
|
||||
|
||||
MwOpenGLMakeCurrent(wOpengl);
|
||||
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
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);
|
||||
|
||||
ma_event_init(&event);
|
||||
ma_mutex_init(&mutex);
|
||||
config = ma_device_config_init(ma_device_type_playback);
|
||||
config.playback.format = ma_format_f32;
|
||||
config.playback.channels = 2;
|
||||
config.sampleRate = plm_get_samplerate(plm);
|
||||
config.dataCallback = data_callback;
|
||||
ma_device_init(NULL, &config, &device);
|
||||
ma_device_start(&device);
|
||||
|
||||
#ifdef _WIN32
|
||||
thread = CreateThread(NULL, 0, thread_routine, NULL, 0, &thid);
|
||||
#else
|
||||
pthread_create(&thread, NULL, thread_routine, NULL);
|
||||
#endif
|
||||
|
||||
MwAddUserHandler(wWindow, MwNtickHandler, tick, NULL);
|
||||
|
||||
MwLoop(wWindow);
|
||||
|
||||
ma_mutex_lock(&mutex);
|
||||
quit = 1;
|
||||
ma_mutex_unlock(&mutex);
|
||||
|
||||
#ifdef _WIN32
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
CloseHandle(thread);
|
||||
#else
|
||||
pthread_join(thread, &ret);
|
||||
#endif
|
||||
plm_destroy(plm);
|
||||
ma_device_uninit(&device);
|
||||
ma_mutex_uninit(&mutex);
|
||||
ma_event_uninit(&event);
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
#define MwnhasBorder "IhasBorder"
|
||||
#define MwNinverted "Iinverted"
|
||||
#define MwNmodernLook "ImodernLook"
|
||||
#define MwNwaitMS "IwaitMS"
|
||||
|
||||
#define MwNtitle "Stitle"
|
||||
#define MwNtext "Stext"
|
||||
|
||||
@@ -412,7 +412,12 @@ void MwLLNextEvent(MwLL handle) {
|
||||
}
|
||||
|
||||
void MwLLSleep(int ms) {
|
||||
usleep(ms * 1000);
|
||||
struct timespec ts;
|
||||
|
||||
ts.tv_sec = ms / 1000;
|
||||
ts.tv_nsec = (ms % 1000) * 1000 * 1000;
|
||||
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
void MwLLSetTitle(MwLL handle, const char* title) {
|
||||
|
||||
13
src/core.c
13
src/core.c
@@ -289,8 +289,11 @@ int MwPending(MwWidget handle) {
|
||||
void MwLoop(MwWidget handle) {
|
||||
long tick = MwLLGetTick();
|
||||
int i;
|
||||
long wait = MwGetInteger(handle, MwNwaitMS);
|
||||
if(wait == MwDEFAULT) wait = MwWaitMS;
|
||||
while(!handle->close) {
|
||||
int v = 0;
|
||||
long t, t2;
|
||||
while(MwPending(handle)) {
|
||||
if((v = MwStep(handle)) != 0) break;
|
||||
}
|
||||
@@ -300,9 +303,13 @@ void MwLoop(MwWidget handle) {
|
||||
MwDispatchUserHandler(handle->tick_list[i], MwNtickHandler, NULL);
|
||||
}
|
||||
|
||||
tick = MwWaitMS - (MwLLGetTick() - tick);
|
||||
if(tick > 0) MwLLSleep(tick);
|
||||
tick = MwLLGetTick();
|
||||
t = (tick + wait) - (t2 = MwLLGetTick());
|
||||
if(t > 0){
|
||||
MwLLSleep(t);
|
||||
tick += wait;
|
||||
}else{
|
||||
tick = t2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user