FPlay: ffmpeg-0.11 + rewind

git-svn-id: svn://kolibrios.org@2693 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2012-05-27 10:41:27 +00:00
parent 735d94c630
commit 6a4f6de77e
37 changed files with 2557 additions and 44 deletions

View File

@ -25,6 +25,9 @@ static int snd_format;
int sample_rate; int sample_rate;
static uint32_t samples_written = 0; static uint32_t samples_written = 0;
double audio_base = -1.0;
double get_audio_base();
int init_audio(int format) int init_audio(int format)
{ {
@ -104,6 +107,13 @@ int decode_audio(AVCodecContext *ctx, queue_t *qa)
if(len >= 0) if(len >= 0)
{ {
// if(audio_base == -1.0)
// {
// if (pkt.pts != AV_NOPTS_VALUE)
// audio_base = get_audio_base() * pkt.pts;
// printf("audio base %f\n", audio_base);
// };
pkt_tmp.data += len; pkt_tmp.data += len;
pkt_tmp.size -= len; pkt_tmp.size -= len;
@ -214,19 +224,36 @@ int audio_thread(void *param)
double event_stamp, wait_stamp; double event_stamp, wait_stamp;
int too_late = 0; int too_late = 0;
if(player_state == PAUSE) if((player_state == PAUSE) ||
(player_state == PLAY_INIT) )
{ {
if( active ) if( active )
{ {
StopBuffer(hBuff); StopBuffer(hBuff);
active = 0; active = 0;
} };
delay(1); delay(1);
continue; continue;
} }
else if(player_state == PLAY_RESTART) else if(player_state == REWIND)
{ {
if( active )
{
StopBuffer(hBuff);
active = 0;
};
mutex_lock(&astream.lock);
astream.count = 0;
mutex_unlock(&astream.lock);
delay(1);
continue;
}
else if(player_state == PAUSE_2_PLAY)
{
// SetTimeBase(hBuff, audio_base);
GetTimeStamp(hBuff, &last_time_stamp); GetTimeStamp(hBuff, &last_time_stamp);
// printf("last_time_stamp %f\n", last_time_stamp);
if((err = PlayBuffer(hBuff, 0)) !=0 ) if((err = PlayBuffer(hBuff, 0)) !=0 )
{ {
errstr = "Cannot play buffer\n\r"; errstr = "Cannot play buffer\n\r";
@ -235,7 +262,27 @@ int audio_thread(void *param)
active = 1; active = 1;
sync_audio(hBuff, buffsize); sync_audio(hBuff, buffsize);
player_state = PLAY; player_state = PLAY;
printf("audio delta %f\n", audio_delta); printf("render: set audio latency to %f\n", audio_delta);
}
else if(player_state == REWIND_2_PLAY)
{
while( (astream.count < buffsize*2) &&
(player_state != CLOSED) )
yield();
SetTimeBase(hBuff, audio_base);
GetTimeStamp(hBuff, &last_time_stamp);
printf("last audio time stamp %f\n", last_time_stamp);
if((err = PlayBuffer(hBuff, 0)) !=0 )
{
errstr = "Cannot play buffer\n\r";
goto exit_whith_error;
};
active = 1;
sync_audio(hBuff, buffsize);
player_state = PLAY;
printf("render: set audio latency to %f\n", audio_delta);
}; };
GetNotify(&evnt); GetNotify(&evnt);

View File

@ -36,9 +36,23 @@ uint8_t *decoder_buffer;
extern int sample_rate; extern int sample_rate;
char *movie_file; char *movie_file;
void flush_video();
queue_t q_video; queue_t q_video;
queue_t q_audio; queue_t q_audio;
int64_t rewind_pos;
int64_t stream_duration;
extern double audio_base;
double get_audio_base()
{
return (double)av_q2d(pFormatCtx->streams[audioStream]->time_base)*1000;
};
int main( int argc, char *argv[]) int main( int argc, char *argv[])
{ {
@ -64,7 +78,7 @@ int main( int argc, char *argv[])
return -1; // Couldn't open file return -1; // Couldn't open file
}; };
// printf("%s\n\r", __FUNCTION__); pFormatCtx->flags |= AVFMT_FLAG_GENPTS;
// Retrieve stream information // Retrieve stream information
if(avformat_find_stream_info(pFormatCtx, NULL)<0) if(avformat_find_stream_info(pFormatCtx, NULL)<0)
@ -77,22 +91,39 @@ int main( int argc, char *argv[])
// dump_format(pFormatCtx, 0, argv[1], 0); // dump_format(pFormatCtx, 0, argv[1], 0);
// stream_duration = 1000.0 * pFormatCtx->duration * av_q2d(AV_TIME_BASE_Q);
stream_duration = pFormatCtx->duration;
printf("duration %f\n", (double)stream_duration);
// Find the first video stream // Find the first video stream
videoStream=-1; videoStream=-1;
audioStream=-1; audioStream=-1;
for(i=0; i < pFormatCtx->nb_streams; i++) for(i=0; i < pFormatCtx->nb_streams; i++)
{ {
// pFormatCtx->streams[i]->discard = AVDISCARD_ALL;
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO
&& videoStream < 0) && videoStream < 0)
{ {
videoStream=i; videoStream=i;
video_time_base = pFormatCtx->streams[i]->time_base; video_time_base = pFormatCtx->streams[i]->time_base;
if(stream_duration == 0)
// stream_duration = 1000.0 *
// pFormatCtx->streams[i]->duration *
// av_q2d(pFormatCtx->streams[i]->time_base);
stream_duration = pFormatCtx->streams[i]->duration;
} }
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO && if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO &&
audioStream < 0) audioStream < 0)
{ {
audioStream=i; audioStream=i;
if(stream_duration == 0)
// stream_duration = 1000.0 *
// pFormatCtx->streams[i]->duration *
// av_q2d(pFormatCtx->streams[i]->time_base);
stream_duration = pFormatCtx->streams[i]->duration;
} }
} }
@ -102,7 +133,7 @@ int main( int argc, char *argv[])
return -1; // Didn't find a video stream return -1; // Didn't find a video stream
} }
player_state = PLAY_RESTART; player_state = PLAY_INIT;
// __asm__ __volatile__("int3"); // __asm__ __volatile__("int3");
@ -200,12 +231,64 @@ int main( int argc, char *argv[])
return 0; return 0;
} }
static int fill_queue()
{
int eof = 0;
AVPacket packet;
while( !eof)
{
int err;
// __asm__ __volatile__("int3");
if(q_video.size+q_audio.size < 2*1024*1024)
{
err = av_read_frame(pFormatCtx, &packet);
if( err < 0)
{
eof = 1;
if (err != AVERROR_EOF)
printf("av_read_frame: error %x\n", err);
break;
}
if(packet.stream_index==videoStream)
{
put_packet(&q_video, &packet);
}
else if( (packet.stream_index == audioStream) &&
(have_sound != 0) )
{
put_packet(&q_audio, &packet);
if(audio_base == -1.0)
{
if (packet.dts != AV_NOPTS_VALUE)
audio_base = get_audio_base() * packet.dts;
// printf("audio base %f\n", audio_base);
};
}
else
{
av_free_packet(&packet);
};
}
else break;
};
return eof;
};
void decoder() void decoder()
{ {
int eof = 0; int eof;
AVPacket packet; AVPacket packet;
int ret; int ret;
eof = fill_queue();
while( player_state != CLOSED && !eof) while( player_state != CLOSED && !eof)
{ {
int err; int err;
@ -218,7 +301,55 @@ void decoder()
continue; continue;
}; };
if(q_video.size+q_audio.size < 12*1024*1024) if( player_state == REWIND )
{
// int64_t timestamp = 0;
// int stream_index = av_find_default_stream_index(pFormatCtx);
// __asm__ __volatile__("int3");
if (pFormatCtx->start_time != AV_NOPTS_VALUE)
rewind_pos += pFormatCtx->start_time;
printf("rewind %8"PRId64"\n", rewind_pos);
ret = avformat_seek_file(pFormatCtx, -1, INT64_MIN,
rewind_pos, INT64_MAX, 0);
// ret = avformat_seek_file(pFormatCtx, -1, 0,
// 0, INT64_MAX, 0);
// __asm__ __volatile__("int3");
if (ret < 0)
{
printf("could not seek to position %f\n",
(double)rewind_pos / AV_TIME_BASE);
}
else
{
avcodec_flush_buffers(pCodecCtx);
avcodec_flush_buffers(aCodecCtx);
while( get_packet(&q_video, &packet) != 0)
av_free_packet(&packet);
while( get_packet(&q_audio, &packet)!= 0)
av_free_packet(&packet);
audio_base = -1.0;
// __asm__ __volatile__("int3");
eof = fill_queue();
};
yield();
flush_video();
player_state = REWIND_2_PLAY;
printf("restart\n");
continue;
};
if(q_video.size+q_audio.size < 4*1024*1024)
{ {
err = av_read_frame(pFormatCtx, &packet); err = av_read_frame(pFormatCtx, &packet);
if( err < 0) if( err < 0)

View File

@ -52,10 +52,13 @@ struct render
}; };
enum player_state enum player_state
{ CLOSED=0, STOP, PLAY_RESTART, PLAY, PAUSE, REWIND }; { CLOSED=0,PLAY_INIT,
STOP, PAUSE, PLAY, REWIND,
#define ID_PLAY 100 PAUSE_2_PLAY, REWIND_2_PLAY
};
#define ID_PLAY 100
#define ID_PROGRESS 101
typedef struct typedef struct
{ {
volatile uint32_t lock; volatile uint32_t lock;
@ -156,7 +159,8 @@ static inline void delay(uint32_t time)
{ {
__asm__ __volatile__( __asm__ __volatile__(
"int $0x40" "int $0x40"
::"a"(5), "b"(time)); ::"a"(5), "b"(time)
:"memory");
}; };

View File

@ -307,7 +307,7 @@ int blit_bitmap(bitmap_t *bitmap, int dst_x, int dst_y,
{ {
//bitmap->data = NULL; Not now, Serge //bitmap->data = NULL; Not now, Serge
// printf("blit done\n"); // printf("blit done\n");
delay(1); // delay(1);
return 0; return 0;
}; };
return err; return err;
@ -328,7 +328,8 @@ int blit_bitmap(bitmap_t *bitmap, int dst_x, int dst_y,
__asm__ __volatile__( __asm__ __volatile__(
"int $0x40" "int $0x40"
::"a"(73),"b"(0),"c"(&bc)); ::"a"(73),"b"(0x00),"c"(&bc)
:"memory");
return 0; return 0;
}; };
@ -340,7 +341,7 @@ static inline void* user_realloc(void *mem, size_t size)
__asm__ __volatile__( __asm__ __volatile__(
"int $0x40" "int $0x40"
:"=a"(val) :"=a"(val)
:"a"(68),"b"(12),"c"(size),"d"(mem) :"a"(68),"b"(20),"c"(size),"d"(mem)
:"memory"); :"memory");
return val; return val;

View File

@ -17,6 +17,7 @@ extern int res_pause_btn_pressed[];
extern int res_play_btn[]; extern int res_play_btn[];
extern int res_play_btn_pressed[]; extern int res_play_btn_pressed[];
extern int64_t stream_duration;
typedef struct typedef struct
{ {
@ -44,6 +45,18 @@ volatile uint32_t driver_lock;
void get_client_rect(rect_t *rc); void get_client_rect(rect_t *rc);
void flush_video()
{
int i;
for(i = 0; i < 4; i++)
{
frames[i].pts = 0;
frames[i].ready = 0;
};
vfx = 0;
dfx = 0;
};
int init_video(AVCodecContext *ctx) int init_video(AVCodecContext *ctx)
{ {
@ -113,19 +126,20 @@ int decode_video(AVCodecContext *ctx, queue_t *qv)
if( get_packet(qv, &pkt) == 0 ) if( get_packet(qv, &pkt) == 0 )
return 0; return 0;
current_clock = -80.0 + get_master_clock(); current_clock = -90.0 + get_master_clock();
if( pkt.dts == AV_NOPTS_VALUE && if( pkt.dts == AV_NOPTS_VALUE &&
Frame->reordered_opaque != AV_NOPTS_VALUE) Frame->reordered_opaque != AV_NOPTS_VALUE)
pts = Frame->reordered_opaque; pts = Frame->reordered_opaque;
else if(pkt.dts != AV_NOPTS_VALUE) else if(pkt.dts != AV_NOPTS_VALUE)
pts= pkt.dts; pts= pkt.dts;
else else
pts= 0; pts= 0;
pts *= av_q2d(video_time_base)*1000.0; pts *= av_q2d(video_time_base)*1000.0;
if( pts > current_clock) if( 1 /*pts > current_clock*/)
{ {
frameFinished = 0; frameFinished = 0;
@ -140,7 +154,7 @@ int decode_video(AVCodecContext *ctx, queue_t *qv)
if( pkt.dts == AV_NOPTS_VALUE && if( pkt.dts == AV_NOPTS_VALUE &&
Frame->reordered_opaque != AV_NOPTS_VALUE) Frame->reordered_opaque != AV_NOPTS_VALUE)
pts = Frame->reordered_opaque; pts = Frame->reordered_opaque;
else if(pkt.dts != AV_NOPTS_VALUE) else if(pkt.dts != AV_NOPTS_VALUE)
pts= pkt.dts; pts= pkt.dts;
else else
@ -161,6 +175,8 @@ int decode_video(AVCodecContext *ctx, queue_t *qv)
Frame->linesize, ctx->pix_fmt, ctx->width, ctx->height); Frame->linesize, ctx->pix_fmt, ctx->width, ctx->height);
frames[dfx].pts = pts*1000.0; frames[dfx].pts = pts*1000.0;
// printf("pts %f\n", frames[dfx].pts);
frames[dfx].ready = 1; frames[dfx].ready = 1;
dfx++; dfx++;
@ -175,6 +191,7 @@ int decode_video(AVCodecContext *ctx, queue_t *qv)
extern volatile enum player_state player_state; extern volatile enum player_state player_state;
//rect_t win_rect; //rect_t win_rect;
extern int64_t rewind_pos;
int MainWindowProc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2) int MainWindowProc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
{ {
@ -196,18 +213,18 @@ int MainWindowProc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
case MSG_LBTNDOWN: case MSG_LBTNDOWN:
if(player_state == PAUSE) if(player_state == PAUSE)
{ {
win->panel.play_btn->img_default = res_play_btn; win->panel.play_btn->img_default = res_pause_btn;
win->panel.play_btn->img_hilite = res_play_btn; win->panel.play_btn->img_hilite = res_pause_btn;
win->panel.play_btn->img_pressed = res_play_btn_pressed; win->panel.play_btn->img_pressed = res_pause_btn_pressed;
send_message(win->panel.play_btn, MSG_PAINT, 0, 0); send_message(win->panel.play_btn, MSG_PAINT, 0, 0);
player_state = PLAY_RESTART; player_state = PAUSE_2_PLAY;
} }
else if(player_state == PLAY) else if(player_state == PLAY)
{ {
win->panel.play_btn->img_default = res_pause_btn; win->panel.play_btn->img_default = res_play_btn;
win->panel.play_btn->img_hilite = res_pause_btn; win->panel.play_btn->img_hilite = res_play_btn;
win->panel.play_btn->img_pressed = res_pause_btn_pressed; win->panel.play_btn->img_pressed = res_play_btn_pressed;
send_message(win->panel.play_btn, MSG_PAINT, 0, 0); send_message(win->panel.play_btn, MSG_PAINT, 0, 0);
player_state = PAUSE; player_state = PAUSE;
} }
@ -218,20 +235,36 @@ int MainWindowProc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
{ {
case ID_PLAY: case ID_PLAY:
if(player_state == PAUSE) if(player_state == PAUSE)
{
win->panel.play_btn->img_default = res_play_btn;
win->panel.play_btn->img_hilite = res_play_btn;
win->panel.play_btn->img_pressed = res_play_btn_pressed;
player_state = PLAY_RESTART;
}
else if(player_state == PLAY)
{ {
win->panel.play_btn->img_default = res_pause_btn; win->panel.play_btn->img_default = res_pause_btn;
win->panel.play_btn->img_hilite = res_pause_btn; win->panel.play_btn->img_hilite = res_pause_btn;
win->panel.play_btn->img_pressed = res_pause_btn_pressed; win->panel.play_btn->img_pressed = res_pause_btn_pressed;
player_state = PAUSE_2_PLAY;
}
else if(player_state == PLAY)
{
win->panel.play_btn->img_default = res_play_btn;
win->panel.play_btn->img_hilite = res_play_btn;
win->panel.play_btn->img_pressed = res_play_btn_pressed;
player_state = PAUSE; player_state = PAUSE;
} }
break; break;
case 101: //ID_PROGRESS:
if(player_state != REWIND)
{
progress_t *prg = (progress_t*)arg2;
rewind_pos = (int64_t)prg->pos *
(prg->max - prg->min)/prg->ctrl.w;
// printf("progress action %f\n", (double)rewind_pos);
player_state = REWIND;
main_render->win->panel.prg->current = rewind_pos;
send_message(&main_render->win->panel.ctrl, MSG_PAINT, 0, 0);
};
break;
default: default:
break; break;
} }
@ -243,6 +276,8 @@ int MainWindowProc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
return 0; return 0;
}; };
#define VERSION_A 1
void render_time(render_t *render) void render_time(render_t *render)
{ {
double ctime; /* milliseconds */ double ctime; /* milliseconds */
@ -261,28 +296,103 @@ void render_time(render_t *render)
return; return;
}; };
#ifdef VERSION_A
if(frames[vfx].ready == 1 ) if(frames[vfx].ready == 1 )
{ {
int sys_time;
ctime = get_master_clock(); ctime = get_master_clock();
fdelay = (frames[vfx].pts - ctime); fdelay = (frames[vfx].pts - ctime);
// printf("pts %f time %f delay %f\n", // printf("pts %f time %f delay %f\n",
// frames[vfx].pts, ctime, fdelay); // frames[vfx].pts, ctime, fdelay);
if(fdelay > 20.0) if(fdelay > 15.0)
{ {
delay(2); delay(1);
// yield(); // yield();
return; return;
}; };
ctime = get_master_clock();
fdelay = (frames[vfx].pts - ctime);
sys_time = get_tick_count();
// if(fdelay < 0)
// printf("systime %d pts %f time %f delay %f\n",
// sys_time*10, frames[vfx].pts, ctime, fdelay);
main_render->draw(main_render, &frames[vfx].picture); main_render->draw(main_render, &frames[vfx].picture);
main_render->win->panel.prg->current = frames[vfx].pts*1000;
send_message(&render->win->panel.prg->ctrl, MSG_PAINT, 0, 0);
frames[vfx].ready = 0; frames[vfx].ready = 0;
vfx++; vfx++;
vfx&= 3; vfx&= 3;
} }
else yield(); else yield();
#else
if(frames[vfx].ready == 1 )
{
ctime = get_master_clock();
fdelay = (frames[vfx].pts - ctime);
// printf("pts %f time %f delay %f\n",
// frames[vfx].pts, ctime, fdelay);
if(fdelay < 0.0 )
{
int next_vfx;
fdelay = 0;
next_vfx = (vfx+1) & 3;
if( frames[next_vfx].ready == 1 )
{
if(frames[next_vfx].pts <= ctime)
{
frames[vfx].ready = 0; // skip this frame
vfx++;
vfx&= 3;
}
else
{
if( (frames[next_vfx].pts - ctime) <
( ctime - frames[vfx].pts) )
{
frames[vfx].ready = 0; // skip this frame
vfx++;
vfx&= 3;
fdelay = (frames[next_vfx].pts - ctime);
}
}
};
};
if(fdelay > 10.0)
{
int val = fdelay;
printf("pts %f time %f delay %d\n",
frames[vfx].pts, ctime, val);
delay(val/10);
};
ctime = get_master_clock();
fdelay = (frames[vfx].pts - ctime);
printf("pts %f time %f delay %f\n",
frames[vfx].pts, ctime, fdelay);
main_render->draw(main_render, &frames[vfx].picture);
main_render->win->panel.prg->current = frames[vfx].pts;
// send_message(&render->win->panel.prg->ctrl, MSG_PAINT, 0, 0);
frames[vfx].ready = 0;
vfx++;
vfx&= 3;
}
else yield();
#endif
} }
@ -297,13 +407,18 @@ int video_thread(void *param)
init_winlib(); init_winlib();
MainWindow = create_window(movie_file,0, MainWindow = create_window(movie_file,0,
10,10,width,height+29+75,MainWindowProc); 10,10,width,height+29+55,MainWindowProc);
MainWindow->panel.prg->max = stream_duration;
// printf("MainWindow %x\n", MainWindow); // printf("MainWindow %x\n", MainWindow);
main_render->win = MainWindow; main_render->win = MainWindow;
show_window(MainWindow, NORMAL); show_window(MainWindow, NORMAL);
render_draw_client(main_render);
player_state = PAUSE_2_PLAY;
run_render(MainWindow, main_render); run_render(MainWindow, main_render);
// printf("exit thread\n"); // printf("exit thread\n");
@ -448,7 +563,7 @@ void render_adjust_size(render_t *render, window_t *win)
right = win->w; right = win->w;
bottom = win->h-CAPTION_HEIGHT-75; bottom = win->h-CAPTION_HEIGHT-55;
render->win_state = win->win_state; render->win_state = win->win_state;
if(render->win_state == MINIMIZED) if(render->win_state == MINIMIZED)
@ -482,7 +597,7 @@ void render_adjust_size(render_t *render, window_t *win)
}; };
render->win_width = win->w; render->win_width = win->w;
render->win_height = win->h-CAPTION_HEIGHT-75; render->win_height = win->h-CAPTION_HEIGHT-55;
render_set_size(render, new_w, new_h); render_set_size(render, new_w, new_h);
}; };
@ -600,9 +715,14 @@ void render_draw_client(render_t *render)
render->win_state == ROLLED) render->win_state == ROLLED)
return; return;
if(player_state == PAUSE) if((player_state == PAUSE) ||
(player_state == PLAY_INIT) )
{ {
main_render->draw(main_render, &frames[vfx].picture); if(frames[vfx].ready == 1 )
main_render->draw(main_render, &frames[vfx].picture);
else
draw_bar(0, CAPTION_HEIGHT, render->win_width,
render->rcvideo.b, 0);
}; };
if(render->layout & HAS_TOP) if(render->layout & HAS_TOP)

View File

@ -0,0 +1,337 @@
#include "system.h"
#include <stdlib.h>
#include <string.h>
#include "winlib.h"
extern ctrl_t *mouse_capture;
uint32_t main_cursor;
static int button_proc(ctrl_t *btn, uint32_t msg, uint32_t arg1, uint32_t arg2);
static int spinbtn_proc(ctrl_t *btn, uint32_t msg, uint32_t arg1, uint32_t arg2);
button_t *create_button(char *caption, int id, int x, int y,
int w, int h, ctrl_t *parent)
{
button_t *btn;
int len;
if( !parent )
return NULL;
btn = (button_t*)malloc(sizeof(button_t));
link_initialize(&btn->link);
list_initialize(&btn->child);
btn->handler = button_proc;
btn->parent = parent;
btn->ctx = parent->ctx;
btn->id = id;
btn->style = 0;
btn->rc.l = x;
btn->rc.t = y ;
btn->rc.r = x + w;
btn->rc.b = y + h;
btn->w = w;
btn->h = h;
btn->state = 0;
btn->caption = caption;
if( !caption )
btn->capt_len = 0;
else
{
len = strlen(caption);
btn->capt_len = len;
if( len )
btn->caption = strdup(caption);
else
btn->caption = NULL;
}
btn->img_default = NULL;
btn->img_hilite = NULL;
btn->img_pressed = NULL;
list_append(&btn->link, &parent->child);
return btn;
};
#if 0
int draw_button(button_t *btn)
{
void *bitmap;
bitmap = btn->img_default;
if(btn->state & bPressed)
bitmap = btn->img_pressed;
else if(btn->state & bHighlight)
bitmap = btn->img_hilite;
if( bitmap )
draw_bitmap(bitmap, btn->rc.l, btn->rc.t, btn->w, btn->h);
if( btn->caption && btn->capt_len)
{
int txt_w;
int txt_x, txt_y;
txt_w = btn->capt_len*8-2;
txt_x = btn->rc.l + 1 + (btn->w - txt_w)/2;
txt_y = btn->rc.t + 9;
if(btn->state & bPressed){
txt_x++;
txt_y++;
};
draw_text(btn->caption, txt_x, txt_y, btn->capt_len, 0x10000000);
};
return 0;
};
#endif
int draw_button_cairo(button_t *btn)
{
int *pixmap, *src;
ctx_t *ctx;
int i, j;
int x, y;
ctx = btn->ctx;
x = btn->rc.l - ctx->offset_x;
y = btn->rc.t - ctx->offset_y;
pixmap = ctx->pixmap;
pixmap+= y*ctx->stride/4 + x;
src = btn->img_default;
if(btn->state & bPressed)
src = btn->img_pressed;
else if(btn->state & bHighlight)
src = btn->img_hilite;
for(i=0; i < btn->h ;i++)
{
for(j=0; j<btn->w; j++)
pixmap[j] = src[j];
pixmap+= ctx->stride/4;
src+=btn->w;
};
return 0;
};
int draw_spin_cairo(button_t *btn)
{
void *ctx;
return 0;
};
int button_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
{
int x, y;
int state;
int old_state;
int action=0;
button_t *btn = (button_t*)ctrl;
switch( msg )
{
case MSG_PAINT:
draw_button_cairo(btn);
update_rect((ctrl_t*)btn);
break;
case MSG_MOUSEENTER:
// printf("mouse enter\n");
btn->state|= bHighlight;
send_message(btn, MSG_PAINT, 0, 0);
break;
case MSG_MOUSELEAVE:
// printf("mouse leave\n");
if( (ctrl_t*)btn != mouse_capture) {
btn->state &= ~bHighlight;
send_message(btn, MSG_PAINT, 0, 0);
};
break;
case MSG_LBTNDOWN:
case MSG_LBTNDBLCLK:
// printf("push button\n");
capture_mouse((ctrl_t*)btn);
btn->state|= bPressed;
send_message(btn, MSG_PAINT, 0, 0);
break;
case MSG_LBTNUP:
// printf("button action\n");
if(btn->state & bPressed)
action = MSG_COMMAND;
release_mouse();
x = ((pos_t)arg2).x;
y = ((pos_t)arg2).y;
if( pt_in_rect( &btn->rc, x, y) )
state = bHighlight;
else
state = 0;
if(action)
send_message(btn->parent,MSG_COMMAND,btn->id,(int)btn);
btn->state = state;
send_message(btn, MSG_PAINT, 0, 0);
break;
case MSG_MOUSEMOVE:
if(main_cursor != 0)
{
set_cursor(0);
main_cursor = 0;
}
if( ! (btn->state & bHighlight))
{
btn->state|= bHighlight;
send_message(btn, MSG_PAINT, 0, 0);
};
if( (ctrl_t*)btn != mouse_capture)
return 0;
x = ((pos_t)arg2).x;
y = ((pos_t)arg2).y;
old_state = btn->state;
if( pt_in_rect(&btn->rc, x, y) )
btn->state |= bPressed;
else
btn->state &= ~bPressed;
if( old_state ^ btn->state)
send_message(btn, MSG_PAINT, 0, 0);
}
return 0;
};
int draw_progress(progress_t *prg)
{
int *pixmap, src;
ctx_t *ctx;
int i, j;
int x, y;
int len;
ctx = prg->ctrl.ctx;
x = prg->ctrl.rc.l - ctx->offset_x;
y = prg->ctrl.rc.t - ctx->offset_y;
len = prg->current*prg->ctrl.w/(prg->max - prg->min);
pixmap = ctx->pixmap;
pixmap+= y*ctx->stride/4 + x;
src = 0x32ebfb; //btn->img_default;
for(i=0; i < prg->ctrl.h ;i++)
{
for(j=0; j < len; j++)
pixmap[j] = src;
pixmap+= ctx->stride/4;
};
return 0;
};
int prg_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
{
progress_t *prg = (progress_t*)ctrl;
int pos;
switch( msg )
{
case MSG_PAINT:
draw_progress(prg);
update_rect(ctrl);
break;
case MSG_LBTNDOWN:
prg->pos = ((pos_t)arg2).x - ctrl->rc.l;
send_message(ctrl->parent,MSG_COMMAND,ctrl->id,(int)ctrl);
break;
default:
break;
}
return 0;
};
progress_t *create_progress(char *caption, int id, int x, int y,
int w, int h, ctrl_t *parent)
{
progress_t *prg;
int len;
if( !parent )
return NULL;
prg = (progress_t*)malloc(sizeof(progress_t));
link_initialize(&prg->ctrl.link);
list_initialize(&prg->ctrl.child);
prg->ctrl.handler = prg_proc;
prg->ctrl.parent = parent;
prg->ctrl.ctx = parent->ctx;
prg->ctrl.id = id;
prg->ctrl.rc.l = x;
prg->ctrl.rc.t = y ;
prg->ctrl.rc.r = x + w;
prg->ctrl.rc.b = y + h;
prg->ctrl.w = w;
prg->ctrl.h = h;
prg->min = 0;
prg->max = 1;
prg->current = 0;
prg->pos = 0;
list_append(&prg->ctrl.link, &parent->child);
return prg;
};

View File

@ -0,0 +1,246 @@
#include "system.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "winlib.h"
#define CAPTION_HEIGHT 24
#define CAPTION_CORNER_W 8
extern int res_caption_left[];
extern int res_caption_right[];
extern int res_caption_body[];
extern int res_close_btn[];
extern int res_close_btn_hl[];
extern int res_close_btn_pressed[];
extern int res_minimize_btn[];
extern int res_minimize_btn_hl[];
extern int res_minimize_btn_pressed[];
void update_caption_size(window_t *win);
int caption_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2);
int init_caption(window_t *win)
{
button_t *btn;
caption_t *cpt = &win->caption;
ctx_t *ctx = &cpt->ctx;
link_initialize(&cpt->ctrl.link);
list_initialize(&cpt->ctrl.child);
cpt->ctrl.handler = caption_proc;
cpt->ctrl.parent = (ctrl_t*)win;
ctx->pixmap = user_alloc(1920*CAPTION_HEIGHT*4);
if(!ctx->pixmap)
{
printf("not enough memory for caption bitmap\n");
return 0;
};
// printf("win_w %d win_h %d\n", win->w, win->h);
ctx->stride = win->w*4;
ctx->offset_x = 0;
ctx->offset_y = 0;
cpt->ctrl.ctx = ctx;
btn = create_button(NULL, ID_CLOSE,0,5,16,18,(ctrl_t*)cpt);
cpt->close_btn = btn;
btn->img_default = res_close_btn;
btn->img_hilite = res_close_btn_hl;
btn->img_pressed = res_close_btn_pressed;
btn = create_button(NULL, ID_MINIMIZE,0,5,16,18,(ctrl_t*)cpt);
cpt->minimize_btn = btn;
btn->img_default = res_minimize_btn;
btn->img_hilite = res_minimize_btn_hl;
btn->img_pressed = res_minimize_btn_pressed;
update_caption_size(win);
return 1;
};
void update_caption_size(window_t *win)
{
caption_t *cpt = &win->caption;
int old_size;
int new_size;
int stride;
old_size = cpt->ctx.stride * CAPTION_HEIGHT;
old_size = (old_size+4095) & ~4095;
stride = win->w*4;
new_size = stride * CAPTION_HEIGHT;
new_size = (new_size+4095) & ~4095;
if( new_size < old_size)
user_unmap(cpt->ctx.pixmap, new_size, old_size-new_size);
cpt->ctx.stride = stride;
cpt->ctrl.rc.l = 0;
cpt->ctrl.rc.t = 0;
cpt->ctrl.rc.r = win->w;
cpt->ctrl.rc.b = CAPTION_HEIGHT;
cpt->ctrl.w = win->w;
cpt->ctrl.h = CAPTION_HEIGHT;
win->client.t = CAPTION_HEIGHT;
cpt->close_btn->rc.l = win->w - 25;
cpt->close_btn->rc.r = cpt->close_btn->rc.l +
cpt->close_btn->w;
cpt->minimize_btn->rc.l = win->w - 25 - 16 - 5;
cpt->minimize_btn->rc.r = cpt->minimize_btn->rc.l +
cpt->minimize_btn->w;
};
void draw_caption(caption_t *cpt)
{
int *pixmap, *src;
int i, j, w;
pixmap = cpt->ctx.pixmap;
src = res_caption_left;
for(i=0; i < CAPTION_HEIGHT; i++)
{
for(j=0; j < CAPTION_CORNER_W; j++)
pixmap[j] = src[j];
pixmap+= cpt->ctx.stride/4;
src+= CAPTION_CORNER_W;
};
w = cpt->ctrl.w - (2*CAPTION_CORNER_W);
if( w > 0)
{
pixmap = cpt->ctx.pixmap;
pixmap+= CAPTION_CORNER_W;
src = res_caption_body;
for(i = 0; i < CAPTION_HEIGHT; i++)
{
for(j = 0; j < w; j++)
pixmap[j] = src[i];
pixmap+= cpt->ctx.stride/4;
}
};
pixmap = cpt->ctx.pixmap;
pixmap+= cpt->ctrl.w - CAPTION_CORNER_W;
src = res_caption_right;
for(i = 0; i < CAPTION_HEIGHT; i++)
{
for(j = 0; j < CAPTION_CORNER_W; j++)
pixmap[j] = src[j];
pixmap+= cpt->ctx.stride/4;
src+= CAPTION_CORNER_W;
};
ctrl_t *child;
child = (ctrl_t*)cpt->ctrl.child.next;
while( &child->link != &cpt->ctrl.child)
{
send_message(child, 1, 0, 0);
child = (ctrl_t*)child->link.next;
};
};
int caption_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
{
caption_t *cpt = (caption_t*)ctrl;
window_t *win = (window_t*)ctrl->parent;
ctrl_t *child;
int x, y;
x = ((pos_t)arg2).x;
y = ((pos_t)arg2).y;
switch( msg )
{
case 1:
break;
case MSG_MOUSEMOVE:
child = get_child(ctrl, x, y);
if( win->child_over )
{
if(child == win->child_over)
send_message(child, msg, 0, arg2);
else
send_message(win->child_over, MSG_MOUSELEAVE, 0, arg2);
}
else if( child )
send_message(child, MSG_MOUSEENTER, 0, arg2);
win->child_over = child;
if( child )
send_message(child,msg,0,arg2);
// else if(main_cursor != 0)
// {
// set_cursor(0);
// main_cursor = 0;
// }
break;
case MSG_COMMAND:
switch((short)arg1)
{
case ID_CLOSE:
win = (window_t*)ctrl->parent;
win->win_command = WIN_CLOSED;
break;
case ID_MINIMIZE:
__asm__ __volatile__(
"int $0x40"
::"a"(18),"b"(10));
break;
default:
break;
};
default:
child = get_child(ctrl, x, y);
if(child)
return send_message(child, msg, 0, arg2);
}
return 1;
};
void blit_caption(caption_t *cpt)
{
// printf("%s w:%d h:%d stride: %d\n",__FUNCTION__,
// cpt->ctrl.w, cpt->ctrl.h, cpt->ctx.stride);
Blit(cpt->ctx.pixmap, 0, 0, 0, 0, cpt->ctrl.w, cpt->ctrl.h,
cpt->ctrl.w, cpt->ctrl.h, cpt->ctx.stride);
};

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,191 @@
#ifndef __CONTROL_H__
#define __CONTROL_H_
#include "link.h"
typedef struct
{
int l;
int t;
int r;
int b;
}rect_t;
typedef struct ctx
{
void *pixmap;
int stride;
int offset_x;
int offset_y;
}ctx_t;
ctx_t *get_window_ctx();
typedef struct tag_control ctrl_t;
typedef int (handler_t)(ctrl_t*, uint32_t, uint32_t, uint32_t);
struct tag_control
{
link_t link;
link_t child;
handler_t *handler;
ctrl_t *parent;
ctx_t *ctx;
uint32_t id;
uint32_t style;
rect_t rc;
int w;
int h;
};
typedef struct timer
{
link_t link;
ctrl_t *ctrl;
uint32_t exp_time; /* expiration time */
uint32_t tmr_arg; /* random argument */
} ostimer_t;
typedef struct
{
link_t link;
link_t child;
handler_t *handler;
ctrl_t *parent;
ctx_t *ctx;
uint32_t id;
uint32_t style;
rect_t rc;
int w;
int h;
uint32_t state;
ostimer_t timer;
char *caption;
int capt_len;
void *img_default;
void *img_hilite;
void *img_pressed;
}button_t;
typedef struct
{
ctrl_t ctrl;
float min;
float max;
float current;
int pos;
}progress_t;
typedef struct
{
link_t link;
link_t child;
handler_t *handler;
ctrl_t *parent;
ctx_t *ctx;
uint32_t id;
uint32_t style;
rect_t rc;
int w;
int h;
uint32_t state;
int pix_range;
int min_range;
int max_range;
int page_size;
int thumb_pos;
rect_t tl_rect;
rect_t br_rect;
button_t *btn_up;
button_t *btn_down;
button_t *thumb;
}scroller_t;
#define bPressed 2
#define bHighlight 1
#define MSG_PAINT 0x001
#define MSG_DRAW_CLIENT 0x004
#define MSG_LBTNDOWN 0x010
#define MSG_LBTNUP 0x011
#define MSG_RBTNDOWN 0x012
#define MSG_RBTNUP 0x013
#define MSG_MBTNDOWN 0x014
#define MSG_MBTNUP 0x015
#define MSG_WHEELDOWN 0x016
#define MSG_WHEELUP 0x017
#define MSG_LBTNDBLCLK 0x018
#define MSG_MOUSEMOVE 0x019
#define MSG_MOUSEENTER 0x01A
#define MSG_MOUSELEAVE 0x01B
#define MSG_SIZE 0x020
#define MSG_COMMAND 0x030
#define MSG_TIMER 0x031
#define LBN_DBLCLK 0x100
#define LBOX_READDIR 0x100
#define LBOX_GETFILENAME 0x101
#define ID_CLOSE 1
#define ID_MINIMIZE 2
#define ID_SCROLLER_UP 10
#define ID_SCROLLER_DOWN 11
#define ID_SCROLLER_THUMB 12
#define send_message( ctrl, msg, arg1, arg2) \
(ctrl)->handler( (ctrl_t*)(ctrl), \
(uint32_t)(msg), (uint32_t)(arg1), (uint32_t)(arg2))
static inline handler_t *subclass_control(ctrl_t *ctrl, handler_t *handler)
{
handler_t *old = ctrl->handler;
ctrl->handler = handler;
return old;
};
//int inline send_message(ctrl_t *ctrl, u32_t msg, u32_t arg1, u32_t arg2)
//{
// return ctrl->handler(ctrl, msg, arg1, arg2);
//};
static inline int pt_in_rect(rect_t *rc, int x, int y)
{
if( (x >= rc->l) && (x < rc->r) &&
(y >= rc->t) && (y < rc->b) )
return 1;
return 0;
};
ctrl_t *get_child(ctrl_t *ctrl, int x, int y);
ctrl_t *capture_mouse(ctrl_t *newm);
#endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,289 @@
#include "system.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "winlib.h"
#define CAPTION_HEIGHT 29
#define CAPTION_CORNER_W 8
#define FRAME_WIDTH 7
extern uint32_t main_cursor;
extern uint32_t cursor_ns;
extern uint32_t cursor_we;
extern uint32_t cursor_nwse;
extern uint32_t cursor_nesw;
extern ctrl_t *mouse_capture;
static int frame_proc(ctrl_t *ctrl, uint32_t msg,
uint32_t arg1, uint32_t arg2);
void adjust_frame(window_t *win)
{
frame_t *fr = &win->frame;
fr->left.l = 0;
fr->left.t = win->client.t;
fr->left.r = FRAME_WIDTH;
fr->left.b = win->h-FRAME_WIDTH;
fr->right.l = win->w - FRAME_WIDTH;
fr->right.t = win->client.t;
fr->right.r = win->w;
fr->right.b = win->h-FRAME_WIDTH;
fr->bottom.l = 0;
fr->bottom.t = win->h - FRAME_WIDTH;
fr->bottom.r = win->w;
fr->bottom.b = win->h;
win->client.l = FRAME_WIDTH;
win->client.r = win->w - FRAME_WIDTH;
// win->client.b = win->h - FRAME_WIDTH;
// printf("Left: l:%d t:%d r:%d b:%d\n",
// fr->left.l,fr->left.t,fr->left.r,fr->left.b);
// printf("Left: l:%d t:%d r:%d b:%d\n",
// fr->right.l,fr->right.t,fr->right.r,fr->right.b);
// printf("Left: l:%d t:%d r:%d b:%d\n",
// fr->bottom.l,fr->bottom.t,fr->bottom.r,fr->bottom.b);
};
void init_frame(window_t *win)
{
frame_t *fr = &win->frame;
link_initialize(&fr->link);
list_initialize(&fr->child);
fr->handler = frame_proc;
fr->parent = (ctrl_t*)win;
adjust_frame(win);
};
extern int res_border_left[];
extern int res_border_right[];
int draw_frame(window_t *win)
{
int *pixmap, *src;
int i, j;
int w;
frame_t *fr = &win->frame;
pixmap = win->ctx->pixmap;
pixmap+= CAPTION_HEIGHT*win->w;
src = res_border_left;
for(fr->left.t; i < fr->left.b; i++)
{
for(j = 0; j < FRAME_WIDTH; j++)
pixmap[j] = src[j];
pixmap+= win->ctx->stride/4;
};
pixmap = win->ctx->pixmap;
pixmap+= (CAPTION_HEIGHT+1)*win->w - FRAME_WIDTH;
src = res_border_right;
for(i=fr->right.t; i < fr->right.b; i++)
{
for(j = 0; j < FRAME_WIDTH; j++)
pixmap[j] = src[j];
pixmap+= win->ctx->stride/4;
};
pixmap = win->ctx->pixmap;
pixmap+= fr->bottom.t * win->w;
for(i=0; i < FRAME_WIDTH; i++)
{
for(j = 0; j < win->w; j++)
pixmap[j] = 0x808080;
pixmap+= win->ctx->stride/4;
};
ctrl_t *child;
child = (ctrl_t*)fr->child.next;
while( &child->link != &fr->child)
{
send_message(child, 1, 0, 0);
child = (ctrl_t*)child->link.next;
};
return 0;
};
int frame_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
{
static pos_t spos;
static track_mode;
uint32_t cursor;
ctrl_t *child;
frame_t *fr = (frame_t*)ctrl;
window_t *win = (window_t*)fr->parent;
rect_t *rc = NULL;
int x, y;
x = ((pos_t)arg2).x;
y = ((pos_t)arg2).y;
// child = get_child(ctrl, x, y);
// if(child)
// {
// return send_message(child, msg, 0, arg2);
// };
if( (msg == MSG_LBTNDOWN) ||
(msg == MSG_MOUSEMOVE) )
{
x = ((pos_t)arg2).x;
y = ((pos_t)arg2).y;
if( pt_in_rect(&fr->left, x, y))
{
rc = &fr->left;
if( (y+24) > win->h)
cursor = cursor_nesw;
else
cursor = cursor_we;
set_cursor(cursor);
main_cursor = cursor;
}
else if( pt_in_rect(&fr->right, x, y))
{
// printf("pos x%d y%d\n", x, y);
rc = &fr->right;
if( (y+24) > win->h)
cursor = cursor_nwse;
else
cursor = cursor_we;
// printf("Set cursor %x\n", cursor);
set_cursor(cursor);
main_cursor = cursor;
}
else if( pt_in_rect(&fr->bottom, x, y))
{
rc = &fr->bottom;
cursor = cursor_ns;
if(x+24 > win->w)
cursor = cursor_nwse;
else if(x < rc->l+24)
cursor = cursor_nesw;
set_cursor(cursor);
main_cursor = cursor;
}
};
switch( msg )
{
case MSG_LBTNDOWN:
if( rc != NULL)
{
int relx, rely;
capture_mouse(ctrl);
spos = get_cursor_pos();
fr->track = rc;
relx = spos.x - win->rc.l;
rely = spos.y - win->rc.t;
// printf("relx %d rely %d\n", relx, rely);
if(fr->track == &fr->left ||
fr->track == &fr->right)
{
if(rely+24 > win->h)
track_mode = 1;
};
if(fr->track == &fr->bottom)
{
if(relx < 24)
track_mode = 2;
else if(relx+24 > win->w)
track_mode = 3;
}
break;
};
case MSG_LBTNUP:
release_mouse();
fr->track = NULL;
track_mode = 0;
break;
case MSG_MOUSEMOVE:
if(mouse_capture == ctrl)
{
pos_t npos;
npos = get_cursor_pos();
// printf("cursor pos %dx%d\n", npos.x, npos.y);
if( npos.val != spos.val)
{
int w, h;
rect_t nrc = win->rc;
spos = npos;
if(fr->track == &fr->left)
{
nrc.l = npos.x-2;
if(nrc.l < 0)
nrc.l = 0;
if(track_mode==1)
nrc.b = npos.y+2;
}
else if(fr->track == &fr->right)
{
nrc.r = npos.x+2;
if(track_mode==1)
nrc.b = npos.y+2;
}
else if(fr->track == &fr->bottom)
{
nrc.b = npos.y+2;
if(track_mode==2)
nrc.l = npos.x-2;
else if (track_mode==3)
nrc.r = npos.x+2;
};
w = nrc.r - nrc.l;
h = nrc.b - nrc.t;
if(w < 150)
w = 150;
if(h < 120)
h = 120;
__asm__ __volatile__(
"int $0x40"
::"a"(67), "b"(nrc.l), "c"(nrc.t),
"d"(w-1),"S"(h-1) );
};
}
};
return 1;
}

Binary file not shown.

View File

@ -0,0 +1,60 @@
typedef struct link
{
struct link *prev;
struct link *next;
}link_t;
#define LIST_INITIALIZE(name) \
link_t name = { .prev = &name, .next = &name }
#define list_get_instance(link, type, member) \
((type *)(((u8_t *)(link)) - ((u8_t *)&(((type *)NULL)->member))))
static inline void link_initialize(link_t *link)
{
link->prev = NULL;
link->next = NULL;
}
static inline void list_initialize(link_t *head)
{
head->prev = head;
head->next = head;
}
static inline void list_append(link_t *link, link_t *head)
{
link->prev = head->prev;
link->next = head;
head->prev->next = link;
head->prev = link;
}
static inline void list_remove(link_t *link)
{
link->next->prev = link->prev;
link->prev->next = link->next;
link_initialize(link);
}
static inline int list_empty(link_t *head)
{
return head->next == head ? 1 : 0;
}
static inline void list_prepend(link_t *link, link_t *head)
{
link->next = head->next;
link->prev = head;
head->next->prev = link;
head->next = link;
}
static inline void list_insert(link_t *new, link_t *old)
{
new->prev = old->prev;
new->next = old;
new->prev->next = new;
old->prev = new;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,263 @@
#include "system.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "winlib.h"
#define PANEL_HEIGHT 55
#define PANEL_CORNER_W 16
#define FRAME_WIDTH 7
#define ID_PLAY 100
extern uint32_t main_cursor;
extern int res_panel_left[];
extern int res_panel_right[];
extern int res_panel_body[];
extern int res_play_btn[];
extern int res_play_btn_pressed[];
extern int res_pause_btn[];
extern int res_pause_btn_pressed[];
//extern int res_minimize_btn[];
//extern int res_minimize_btn_hl[];
//extern int res_minimize_btn_pressed[];
void update_panel_size(window_t *win);
int panel_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2);
int init_panel(window_t *win)
{
button_t *btn;
progress_t *prg;
panel_t *panel = &win->panel;
ctx_t *ctx = &panel->ctx;
link_initialize(&panel->ctrl.link);
list_initialize(&panel->ctrl.child);
panel->ctrl.handler = panel_proc;
panel->ctrl.parent = (ctrl_t*)win;
ctx->pixmap = user_alloc(1920*PANEL_HEIGHT*4);
if(!ctx->pixmap)
{
printf("not enough memory for caption bitmap\n");
return 0;
};
// printf("win_w %d win_h %d\n", win->w, win->h);
ctx->stride = win->w*4;
panel->ctrl.ctx = ctx;
btn = create_button(NULL, ID_PLAY,0,19,32,32,&panel->ctrl);
panel->play_btn = btn;
btn->img_default = res_pause_btn;
btn->img_hilite = res_pause_btn;
btn->img_pressed = res_pause_btn_pressed;
prg = create_progress(NULL,101,0,4,0,8,&panel->ctrl);
panel->prg = prg;
// btn = create_button(NULL, ID_MINIMIZE,0,5,16,18,(ctrl_t*)cpt);
// cpt->minimize_btn = btn;
// btn->img_default = res_minimize_btn;
// btn->img_hilite = res_minimize_btn_hl;
// btn->img_pressed = res_minimize_btn_pressed;
update_panel_size(win);
return 1;
};
void update_panel_size(window_t *win)
{
panel_t *panel = &win->panel;
int old_size;
int new_size;
int stride;
old_size = panel->ctx.stride * PANEL_HEIGHT;
old_size = (old_size+4095) & ~4095;
stride = win->w*4;
new_size = stride * PANEL_HEIGHT;
new_size = (new_size+4095) & ~4095;
if( new_size < old_size)
user_unmap(panel->ctx.pixmap, new_size, old_size-new_size);
panel->ctx.stride = stride;
panel->ctx.offset_x = 0;
panel->ctx.offset_y = win->h-PANEL_HEIGHT;
panel->draw.l = 0;
panel->draw.t = win->h-PANEL_HEIGHT;
panel->draw.r = win->w;
panel->draw.b = win->h;
panel->ctrl.rc.l = FRAME_WIDTH;
panel->ctrl.rc.t = win->h-PANEL_HEIGHT;
panel->ctrl.rc.r = win->w-FRAME_WIDTH;
panel->ctrl.rc.b = win->h-FRAME_WIDTH;
panel->ctrl.w = win->w;
panel->ctrl.h = PANEL_HEIGHT;
win->client.b = win->h-PANEL_HEIGHT;
panel->play_btn->rc.l = win->w/2 - 16;
panel->play_btn->rc.t = panel->ctrl.rc.t+19;
panel->play_btn->rc.r = panel->play_btn->rc.l + panel->play_btn->w;
panel->play_btn->rc.b = panel->play_btn->rc.t + panel->play_btn->h;
panel->prg->ctrl.rc.l = 8;
panel->prg->ctrl.rc.t = panel->ctrl.rc.t+7;
panel->prg->ctrl.rc.r = panel->ctrl.rc.r-8;
panel->prg->ctrl.rc.b = panel->prg->ctrl.rc.t+8;
panel->prg->ctrl.w = panel->prg->ctrl.rc.r -
panel->prg->ctrl.rc.l;
panel->prg->ctrl.h = panel->prg->ctrl.rc.b -
panel->prg->ctrl.rc.t;
// cpt->minimize_btn->rc.l = win->w - 25 - 16 - 5;
// cpt->minimize_btn->rc.r = cpt->minimize_btn->rc.l +
// cpt->minimize_btn->w;
};
void draw_panel(panel_t *panel)
{
int *pixmap, *src;
int i, j, w;
pixmap = panel->ctx.pixmap;
src = res_panel_left;
for(i=0; i < PANEL_HEIGHT; i++)
{
for(j=0; j < PANEL_CORNER_W; j++)
pixmap[j] = src[j];
pixmap+= panel->ctx.stride/4;
src+= PANEL_CORNER_W;
};
w = panel->ctrl.w - (2*PANEL_CORNER_W);
if( w > 0)
{
pixmap = panel->ctx.pixmap;
pixmap+= PANEL_CORNER_W;
src = res_panel_body;
for(i = 0; i < PANEL_HEIGHT; i++)
{
for(j = 0; j < w; j++)
pixmap[j] = src[i];
pixmap+= panel->ctx.stride/4;
}
};
pixmap = panel->ctx.pixmap;
pixmap+= panel->ctrl.w - PANEL_CORNER_W;
src = res_panel_right;
for(i = 0; i < PANEL_HEIGHT; i++)
{
for(j = 0; j < PANEL_CORNER_W; j++)
pixmap[j] = src[j];
pixmap+= panel->ctx.stride/4;
src+= PANEL_CORNER_W;
};
ctrl_t *child;
child = (ctrl_t*)panel->ctrl.child.next;
while( &child->link != &panel->ctrl.child)
{
send_message(child, 1, 0, 0);
child = (ctrl_t*)child->link.next;
};
};
int panel_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
{
panel_t *panel = (panel_t*)ctrl;
window_t *win = get_parent_window(ctrl);
ctrl_t *child;
int x, y;
x = ((pos_t)arg2).x;
y = ((pos_t)arg2).y;
switch( msg )
{
case 1:
draw_panel((panel_t*)ctrl);
break;
case MSG_MOUSEMOVE:
child = get_child(ctrl, x, y);
if( win->child_over )
{
if(child == win->child_over)
send_message(child, msg, 0, arg2);
else
send_message(win->child_over, MSG_MOUSELEAVE, 0, arg2);
}
else if( child )
send_message(child, MSG_MOUSEENTER, 0, arg2);
win->child_over = child;
if( child )
send_message(child,msg,0,arg2);
else if(main_cursor != 0)
{
set_cursor(0);
main_cursor = 0;
}
break;
case MSG_COMMAND:
switch((short)arg1)
{
case ID_PLAY:
case 101:
win = get_parent_window(ctrl);
send_message(win, msg, arg1, arg2);
break;
default:
break;
};
default:
child = get_child(ctrl, x, y);
if(child)
return send_message(child, msg, 0, arg2);
}
return 1;
};
void blit_panel(panel_t *panel)
{
// printf("%s w:%d h:%d stride: %d\n",__FUNCTION__,
// cpt->ctrl.w, cpt->ctrl.h, cpt->ctx.stride);
Blit(panel->ctx.pixmap, panel->draw.l, panel->draw.t,
0, 0, panel->ctrl.w, panel->ctrl.h,
panel->ctrl.w, panel->ctrl.h, panel->ctx.stride);
};

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,65 @@
format MS COFF
public _res_caption_left
public _res_caption_right
public _res_caption_body
public _res_panel_left
public _res_panel_right
public _res_panel_body
public _res_border_left
public _res_border_right
public _res_close_btn
public _res_close_btn_hl
public _res_close_btn_pressed
public _res_minimize_btn
public _res_minimize_btn_hl
public _res_minimize_btn_pressed
public _res_play_btn
public _res_play_btn_pressed
public _res_pause_btn
public _res_pause_btn_pressed
public _res_cursor_ns
public _res_cursor_we
public _res_cursor_nwse
public _res_cursor_nesw
section '.rdata' data readable align 16
_res_caption_left: file 'cptleft.raw'
_res_caption_right: file 'cptright.raw'
_res_caption_body: file 'cptbody.raw'
_res_panel_left: file 'panelleft.raw'
_res_panel_right: file 'panelright.raw'
_res_panel_body: file 'panel.raw'
_res_border_left: file 'lborder.raw'
_res_border_right: file 'rborder.raw'
_res_close_btn: file 'clbn.raw'
_res_close_btn_hl: file 'clbhl.raw'
_res_close_btn_pressed: file 'clbp.raw'
_res_play_btn: file 'playbtn.raw'
_res_play_btn_pressed: file 'playbp.raw'
_res_pause_btn: file 'pausebtn.raw'
_res_pause_btn_pressed: file 'pausebp.raw'
_res_minimize_btn: file 'minbn.raw'
_res_minimize_btn_hl: file 'minbhl.raw'
_res_minimize_btn_pressed: file 'minbp.raw'
_res_cursor_ns: file 'size_ns.cur'
_res_cursor_we: file 'size_we.cur'
_res_cursor_nwse: file 'size_nwse.cur'
_res_cursor_nesw: file 'size_nesw.cur'

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

View File

@ -0,0 +1,21 @@
typedef unsigned char u8_t;
typedef unsigned short int u16_t;
typedef unsigned int u32_t;
typedef unsigned long long u64_t;
typedef unsigned int addr_t;
typedef unsigned int size_t;
typedef unsigned int count_t;
typedef unsigned int eflags_t;
typedef unsigned int color_t;
typedef unsigned int Bool;
#define TRUE (Bool)1
#define FALSE (Bool)0

View File

@ -0,0 +1,613 @@
#include "system.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include "winlib.h"
int draw_frame(window_t *win);
static int draw_window(window_t *win);
uint32_t main_cursor;
uint32_t cursor_ns;
uint32_t cursor_we;
uint32_t cursor_nwse;
uint32_t cursor_nesw;
static pos_t old_pos;
ctrl_t *mouse_capture = NULL;
static link_t timers;
static uint32_t realtime;
static uint32_t wait_time;
static uint32_t exp_time;
static int need_update;
#define LOAD_FROM_MEM 1
void adjust_frame(window_t *win);
#include "control.inc"
//#include "io.inc"
#include "timer.inc"
//#include "button.inc"
//#include "scroller.inc"
static window_t Window;
void init_frame(window_t *win);
window_t *create_window(char *caption, int style, int x, int y,
int w, int h, handler_t handler)
{
int stride;
ctx_t *ctx = &Window.client_ctx;
if(handler==0) return 0;
Window.handler = handler;
Window.ctx = ctx;
list_initialize(&Window.link);
list_initialize(&Window.child);
ctx->pixmap = user_alloc(1280*1024*4);
if(!ctx->pixmap)
{
printf("not enough memory for context bitmap\n");
return NULL;
};
stride = w*4;
ctx->stride = stride;
Window.rc.l = x;
Window.rc.t = y;
Window.rc.r = x + w;
Window.rc.b = y + h;
Window.w = w;
Window.h = h;
Window.caption_txt = caption;
Window.style = style;
Window.child_over = NULL;
Window.child_focus = NULL;
init_caption(&Window);
init_panel(&Window);
init_frame(&Window);
send_message((ctrl_t*)&Window, MSG_SIZE, 0, 0);
return &Window;
};
int def_window_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
{
ctrl_t *child;
window_t *win = (window_t*)ctrl;
switch(msg)
{
case MSG_PAINT:
draw_window(win);
break;
case 2:
child = (ctrl_t*)win->child.next;
while( &child->link != &win->child)
{
send_message(child, 2, arg1, arg2);
child = (ctrl_t*)child->link.next;
};
break;
case MSG_MOUSEMOVE:
child = win_get_child(win, arg2 & 0xFFFF, (arg2>>16));
if( win->child_over )
{
if(child == win->child_over)
send_message(child, msg, 0, arg2);
else
send_message(win->child_over, MSG_MOUSELEAVE, 0, arg2);
}
else if( child )
send_message(child, MSG_MOUSEENTER, 0, arg2);
win->child_over = child;
if( child )
send_message(child,msg,0,arg2);
else if(main_cursor != 0)
{
set_cursor(0);
main_cursor = 0;
}
break;
case MSG_SIZE:
break;
default:
child = win_get_child(win, arg2 & 0xFFFF, (arg2>>16));
win->child_over = child;
if(child) send_message(child, msg, 0, arg2);
};
return 0;
}
static int draw_window(window_t *win)
{
ctrl_t *child;
void *ctx;
rect_t *rc = &win->client;
draw_caption(&win->caption);
draw_panel(&win->panel);
// draw_frame(win);
// child = (ctrl_t*)win->child.next;
// while( &child->link != &win->child)
// {
// send_message(child, 1, 0, 0);
// child = (ctrl_t*)child->link.next;
// };
return 0;
};
void blit_client(window_t *win)
{
int w, h;
w = win->client.r - win->client.l;
h = win->client.b - win->client.t;
Blit(win->ctx->pixmap, win->client.l, win->client.t,
0, 0, w, h, w, h,win->ctx->stride);
};
int show_window(window_t *win, int state)
{
win->win_state = state;
draw_window(win);
BeginDraw();
DrawWindow(win->rc.l, win->rc.t, win->w-1, win->h-1,
NULL,0,0x41);
EndDraw();
blit_caption(&win->caption);
blit_panel(&win->panel);
// blit_client(win);
return 0;
}
void window_update_layout(window_t *win)
{
char proc_info[1024];
int new_w, new_h;
uint8_t state;
int winx, winy, winw, winh;
// __asm__ __volatile__("int3");
get_proc_info(proc_info);
winx = *(uint32_t*)(proc_info+34);
winy = *(uint32_t*)(proc_info+38);
winw = *(uint32_t*)(proc_info+42)+1;
winh = *(uint32_t*)(proc_info+46)+1;
state = *(uint8_t*)(proc_info+70);
if(state & 2)
{ win->win_state = MINIMIZED;
return;
}
if(state & 4)
{
win->win_state = ROLLED;
return;
};
if(state & 1)
win->win_state = MAXIMIZED;
else
win->win_state = NORMAL;
if( (winx != win->rc.l) || (winy != win->rc.t) )
{
win->rc.l = winx;
win->rc.t = winy;
win->rc.r = winx + win->w;
win->rc.b = winy + win->h;
};
if( winw == win->w &&
winh == win->h)
return;
int old_size;
int new_size;
int stride;
old_size = win->ctx->stride * win->h;
old_size = (old_size+4095) & ~4095;
new_size = winw*winh*4;
new_size = (new_size+4095) & ~4095;
stride = winw*4;
// printf("update win size %d %d\n", winw, winh);
if( new_size < old_size)
user_unmap(win->ctx->pixmap, new_size, old_size-new_size);
win->ctx->stride = stride;
win->rc.r = winx + winw;
win->rc.b = winy + winh;
win->w = winw;
win->h = winh;
update_caption_size(win);
update_panel_size(win);
adjust_frame(win);
send_message((ctrl_t*)win, MSG_SIZE, 0, 0);
draw_window(win);
};
int send_mouse_message(window_t *win, uint32_t msg)
{
ctrl_t *child;
if(mouse_capture)
return send_message(mouse_capture, msg, 0, old_pos.val);
if(pt_in_rect(&win->caption.ctrl.rc, old_pos.x, old_pos.y))
{
return send_message(&win->caption.ctrl, msg, 0, old_pos.val);
}
if(pt_in_rect(&win->panel.ctrl.rc, old_pos.x, old_pos.y))
{
// old_pos.x-= win->panel.ctrl.rc.l;
// old_pos.y-= win->panel.ctrl.rc.t;
return send_message(&win->panel.ctrl, msg, 0, old_pos.val);
}
if(pt_in_rect(&win->client, old_pos.x, old_pos.y))
return send_message((ctrl_t*)win, msg, 0, old_pos.val);
return send_message(&win->frame, msg, 0, old_pos .val);
// if( ( old_pos.x < win->rc.r) && ( old_pos.y < win->rc.b))
// send_message((ctrl_t*)win, msg, 0, old_pos.val);
};
void do_sys_draw(window_t *win)
{
// printf("%s win:%x\n", __FUNCTION__, win);
window_update_layout(win);
BeginDraw();
DrawWindow(0,0,0,0, NULL, 0x000000,0x41);
EndDraw();
blit_caption(&win->caption);
blit_panel(&win->panel);
// blit_client(win);
send_message((ctrl_t*)win, MSG_DRAW_CLIENT, 0, 0);
need_update=0;
};
static void do_sys_mouse(window_t *win)
{
static uint32_t mouse_click_time;
static int mouse_action;
static int old_buttons;
int buttons;
uint32_t wheels;
uint32_t click_time;
int action;
pos_t pos;
mouse_action = 0;
pos = get_mouse_pos();
if(pos.val != old_pos.val)
{
mouse_action = 0x80000000;
old_pos = pos;
};
// printf("pos x%d y%d\n", pos.x, pos.y);
buttons = get_mouse_buttons();
wheels = get_mouse_wheels();
if( wheels & 0xFFFF){
wheels = (short)wheels>0 ? MSG_WHEELDOWN : MSG_WHEELUP;
send_mouse_message(win, wheels);
}
if((action = (buttons ^ old_buttons))!=0)
{
mouse_action|= action<<3;
mouse_action|= buttons & ~old_buttons;
}
old_buttons = buttons;
if(mouse_action & 0x80000000) {
DBG("mouse move \n\r");
send_mouse_message(win, MSG_MOUSEMOVE);
};
if(mouse_action & 0x09)
{
if((mouse_action & 0x09)==0x09)
{
// printf("left button down x= %d y= %d\n\r", old_x.x, old_x.y);
click_time = get_tick_count();
if(click_time < mouse_click_time+35) {
mouse_click_time = click_time;
send_mouse_message(win,MSG_LBTNDBLCLK);
}
else {
mouse_click_time = click_time;
send_mouse_message(win,MSG_LBTNDOWN);
};
}
else {
// printf("left button up \n\r");
send_mouse_message(win,MSG_LBTNUP);
}
};
if(mouse_action & 0x12)
{
if((mouse_action & 0x12)==0x12) {
DBG("right button down \n\r");
send_mouse_message(win,MSG_RBTNDOWN);
}
else {
DBG("right button up \n\r");
send_mouse_message(win,MSG_RBTNUP);
};
};
if(mouse_action & 0x24)
{
if((mouse_action & 0x24)==0x24){
DBG("middle button down \n\r");
send_mouse_message(win,MSG_MBTNDOWN);
}
else {
DBG("middle button up \n\r");
send_mouse_message(win,MSG_MBTNUP);
};
};
};
void run_window(window_t *win)
{
int ev;
oskey_t key;
// buttons = get_mouse_buttons();
// wheels = get_mouse_wheels();
realtime = get_tick_count();
exp_time = -1;
while(1)
{
wait_time = exp_time - realtime;
ev = wait_for_event(wait_time);
realtime = get_tick_count();
// if(exp_time < realtime)
// exp_time = update_timers(realtime);
switch(ev)
{
case MSG_PAINT:
do_sys_draw(win);
continue;
case 2:
key = get_key();
if( key.state == 0)
send_message((ctrl_t*)win, ev, 0, key.code);
continue;
case 6:
do_sys_mouse(win);
continue;
default:
continue;
};
};
}
void render_time(void *render);
void run_render(window_t *win, void *render)
{
int ev;
oskey_t key;
realtime = get_tick_count();
exp_time = -1;
while(win->win_command != WIN_CLOSED)
{
wait_time = exp_time - realtime;
ev = check_os_event();
realtime = get_tick_count();
// if(exp_time < realtime)
// exp_time = update_timers(realtime);
switch(ev)
{
case MSG_PAINT:
do_sys_draw(win);
break;
case 2:
key = get_key();
if( key.state == 0)
send_message((ctrl_t*)win, ev, 0, key.code);
break;
case 6:
do_sys_mouse(win);
break;
default:
break;
};
render_time(render);
};
};
extern unsigned char res_cursor_ns[];
extern unsigned char res_cursor_we[];
extern unsigned char res_cursor_nwse[];
extern unsigned char res_cursor_nesw[];
int init_resources()
{
cursor_ns = load_cursor(res_cursor_ns, LOAD_FROM_MEM);
cursor_we = load_cursor(res_cursor_we, LOAD_FROM_MEM);
cursor_nwse = load_cursor(res_cursor_nwse, LOAD_FROM_MEM);
cursor_nesw = load_cursor(res_cursor_nesw, LOAD_FROM_MEM);
return 1;
}
void init_winlib(void)
{
__asm__ __volatile__(
"int $0x40"
::"a"(40), "b"(0xC0000027));
init_resources();
list_initialize(&timers);
};
ctx_t *get_window_ctx()
{
return &Window.client_ctx;
};
void update_rect(ctrl_t *ctrl)
{
int ctx_w, ctx_h;
int src_x, src_y;
src_x = ctrl->rc.l - ctrl->ctx->offset_x;
src_y = ctrl->rc.t - ctrl->ctx->offset_y;
ctx_w = ctrl->parent->w;
ctx_h = ctrl->parent->h;
Blit(ctrl->ctx->pixmap, ctrl->rc.l, ctrl->rc.t, src_x, src_y,
ctrl->w, ctrl->h, ctx_w, ctx_h, ctrl->ctx->stride);
// need_update++;
};
void Blit(void *bitmap, int dst_x, int dst_y,
int src_x, int src_y, int w, int h,
int src_w, int src_h, int stride)
{
volatile struct blit_call bc;
bc.dstx = dst_x;
bc.dsty = dst_y;
bc.w = w;
bc.h = h;
bc.srcx = src_x;
bc.srcy = src_y;
bc.srcw = src_w;
bc.srch = src_h;
bc.stride = stride;
bc.bitmap = bitmap;
__asm__ __volatile__(
"int $0x40"
::"a"(73),"b"(0),"c"(&bc.dstx));
};
ctrl_t *get_child(ctrl_t *ctrl, int x, int y)
{
ctrl_t *child = NULL;
ctrl_t *tmp = (ctrl_t*)ctrl->child.next;
while( &tmp->link != &ctrl->child )
{
if(pt_in_rect(&tmp->rc, x, y))
{
child = get_child(tmp, x, y);
return child == NULL ? tmp : child;
};
tmp = (ctrl_t*)tmp->link.next;
};
return child;
};
ctrl_t *capture_mouse(ctrl_t *newm)
{
ctrl_t *old = mouse_capture;
mouse_capture = newm;
__asm__ __volatile__(
"int $0x40"
::"a"(40), "b"(0x80000027));
return old;
}
void release_mouse(void)
{
mouse_capture = NULL;
__asm__ __volatile__(
"int $0x40"
::"a"(40), "b"(0xC0000027));
}

View File

@ -0,0 +1,125 @@
#ifndef __WINLIB_H__
#define __WINLIB_H__
#include "control.h"
typedef struct
{
link_t link;
link_t child;
handler_t *handler;
ctrl_t *parent;
ctx_t *ctx;
uint32_t id;
uint32_t style;
rect_t rc;
int w;
int h;
rect_t left; /* left border */
rect_t right; /* right border */
rect_t bottom; /* bottom border */
button_t *close_btn;
rect_t *track;
}frame_t;
typedef struct
{
ctrl_t ctrl;
ctx_t ctx;
ctrl_t *child_over;
button_t *close_btn;
button_t *minimize_btn;
}caption_t;
typedef struct
{
ctrl_t ctrl;
ctx_t ctx;
rect_t draw;
ctrl_t *child_over;
progress_t *prg;
button_t *play_btn;
}panel_t;
typedef struct
{
link_t link;
link_t child;
handler_t *handler;
ctrl_t *parent;
ctx_t *ctx;
uint32_t id;
uint32_t style;
rect_t rc;
int w;
int h;
rect_t client;
ctx_t client_ctx;
char *caption_txt;
ctrl_t *child_over;
ctrl_t *child_focus;
caption_t caption;
panel_t panel;
frame_t frame;
enum win_state{
NORMAL, MINIMIZED, ROLLED, MAXIMIZED
}win_state;
enum win_command{
WIN_CLOSED=1
}win_command;
}window_t;
#define get_parent_window(x) ((window_t*)((x)->parent))
ctrl_t *win_get_child(window_t *win, int x, int y);
void init_winlib(void);
void draw_caption(caption_t *cpt);
void draw_panel(panel_t *panel);
void blit_caption(caption_t *cpt);
int init_caption(window_t *win);
int init_panel(window_t *win);
window_t *create_window(char *caption, int style, int x, int y,
int w, int h, handler_t handler);
int show_window(window_t *win, int state);
int def_window_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2);
void frame_run(window_t *win);
button_t *create_button(char *caption, int id, int x, int y,
int w, int h, ctrl_t *parent);
progress_t *create_progress(char *caption, int id, int x, int y,
int w, int h, ctrl_t *parent);
scroller_t *create_scroller(uint32_t style, int id, int x, int y,
int w, int h, ctrl_t *parent);
//static uint32_t update_timers(uint32_t realtime);
int set_timer(ctrl_t *ctrl, ostimer_t *timer, uint32_t delay);
void update_rect(ctrl_t *ctrl);
#endif