From 4ebbeeff95f38a7d3673c9ac4364ad9da08d9e15 Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Fri, 10 Jan 2014 13:47:21 +0000 Subject: [PATCH] Fplay source code git-svn-id: svn://kolibrios.org@4438 a494cfbc-eb01-0410-851d-a64ba20cac60 --- contrib/media/fplay/audio.c | 442 ++++++++++ contrib/media/fplay/fplay.c | 530 ++++++++++++ contrib/media/fplay/fplay.h | 143 ++++ contrib/media/fplay/opendial.asm | 149 ++++ contrib/media/fplay/skin/clbhl.raw | Bin 0 -> 1296 bytes contrib/media/fplay/skin/clbn.raw | Bin 0 -> 1296 bytes contrib/media/fplay/skin/clbp.raw | Bin 0 -> 1296 bytes contrib/media/fplay/skin/cptbody.raw | Bin 0 -> 96 bytes contrib/media/fplay/skin/cptleft.raw | Bin 0 -> 768 bytes contrib/media/fplay/skin/cptright.raw | Bin 0 -> 768 bytes contrib/media/fplay/skin/fullbhl.raw | 10 + contrib/media/fplay/skin/fullbn.raw | Bin 0 -> 1296 bytes contrib/media/fplay/skin/fullbp.raw | 10 + contrib/media/fplay/skin/istokweb.ttf | Bin 0 -> 277996 bytes contrib/media/fplay/skin/lborder.raw | Bin 0 -> 28 bytes contrib/media/fplay/skin/minbhl.raw | Bin 0 -> 1296 bytes contrib/media/fplay/skin/minbn.raw | Bin 0 -> 1296 bytes contrib/media/fplay/skin/minbp.raw | Bin 0 -> 1296 bytes contrib/media/fplay/skin/panel.raw | 1 + contrib/media/fplay/skin/panelleft.raw | 1 + contrib/media/fplay/skin/panelright.raw | 1 + contrib/media/fplay/skin/pausebp.raw | Bin 0 -> 4096 bytes contrib/media/fplay/skin/pausebtn.raw | Bin 0 -> 4096 bytes contrib/media/fplay/skin/pbar.raw | Bin 0 -> 40 bytes contrib/media/fplay/skin/playbp.raw | Bin 0 -> 4096 bytes contrib/media/fplay/skin/playbtn.raw | Bin 0 -> 4096 bytes contrib/media/fplay/skin/prg_level.raw | Bin 0 -> 40 bytes contrib/media/fplay/skin/rborder.raw | Bin 0 -> 28 bytes contrib/media/fplay/skin/size_nesw.cur | Bin 0 -> 766 bytes contrib/media/fplay/skin/size_ns.cur | Bin 0 -> 766 bytes contrib/media/fplay/skin/size_nwse.cur | Bin 0 -> 766 bytes contrib/media/fplay/skin/size_we.cur | Bin 0 -> 766 bytes contrib/media/fplay/skin/skin.asm | 103 +++ contrib/media/fplay/skin/slider.raw | 1 + contrib/media/fplay/skin/stopbtn.raw | Bin 0 -> 2304 bytes contrib/media/fplay/skin/stopbtnp.raw | Bin 0 -> 2304 bytes contrib/media/fplay/skin/vol_level.raw | Bin 0 -> 3840 bytes contrib/media/fplay/skin/vol_slider.raw | Bin 0 -> 1920 bytes contrib/media/fplay/utils.c | 117 +++ contrib/media/fplay/video.c | 1022 +++++++++++++++++++++++ contrib/media/fplay/winlib/button.c | 574 +++++++++++++ contrib/media/fplay/winlib/caption.c | 272 ++++++ contrib/media/fplay/winlib/control.h | 212 +++++ contrib/media/fplay/winlib/fontlib.c | 184 ++++ contrib/media/fplay/winlib/frame.c | 289 +++++++ contrib/media/fplay/winlib/panel.c | 314 +++++++ contrib/media/fplay/winlib/window.c | 691 +++++++++++++++ contrib/media/fplay/winlib/winlib.h | 150 ++++ 48 files changed, 5216 insertions(+) create mode 100644 contrib/media/fplay/audio.c create mode 100644 contrib/media/fplay/fplay.c create mode 100644 contrib/media/fplay/fplay.h create mode 100644 contrib/media/fplay/opendial.asm create mode 100644 contrib/media/fplay/skin/clbhl.raw create mode 100644 contrib/media/fplay/skin/clbn.raw create mode 100644 contrib/media/fplay/skin/clbp.raw create mode 100644 contrib/media/fplay/skin/cptbody.raw create mode 100644 contrib/media/fplay/skin/cptleft.raw create mode 100644 contrib/media/fplay/skin/cptright.raw create mode 100644 contrib/media/fplay/skin/fullbhl.raw create mode 100644 contrib/media/fplay/skin/fullbn.raw create mode 100644 contrib/media/fplay/skin/fullbp.raw create mode 100644 contrib/media/fplay/skin/istokweb.ttf create mode 100644 contrib/media/fplay/skin/lborder.raw create mode 100644 contrib/media/fplay/skin/minbhl.raw create mode 100644 contrib/media/fplay/skin/minbn.raw create mode 100644 contrib/media/fplay/skin/minbp.raw create mode 100644 contrib/media/fplay/skin/panel.raw create mode 100644 contrib/media/fplay/skin/panelleft.raw create mode 100644 contrib/media/fplay/skin/panelright.raw create mode 100644 contrib/media/fplay/skin/pausebp.raw create mode 100644 contrib/media/fplay/skin/pausebtn.raw create mode 100644 contrib/media/fplay/skin/pbar.raw create mode 100644 contrib/media/fplay/skin/playbp.raw create mode 100644 contrib/media/fplay/skin/playbtn.raw create mode 100644 contrib/media/fplay/skin/prg_level.raw create mode 100644 contrib/media/fplay/skin/rborder.raw create mode 100644 contrib/media/fplay/skin/size_nesw.cur create mode 100644 contrib/media/fplay/skin/size_ns.cur create mode 100644 contrib/media/fplay/skin/size_nwse.cur create mode 100644 contrib/media/fplay/skin/size_we.cur create mode 100644 contrib/media/fplay/skin/skin.asm create mode 100644 contrib/media/fplay/skin/slider.raw create mode 100644 contrib/media/fplay/skin/stopbtn.raw create mode 100644 contrib/media/fplay/skin/stopbtnp.raw create mode 100644 contrib/media/fplay/skin/vol_level.raw create mode 100644 contrib/media/fplay/skin/vol_slider.raw create mode 100644 contrib/media/fplay/utils.c create mode 100644 contrib/media/fplay/video.c create mode 100644 contrib/media/fplay/winlib/button.c create mode 100644 contrib/media/fplay/winlib/caption.c create mode 100644 contrib/media/fplay/winlib/control.h create mode 100644 contrib/media/fplay/winlib/fontlib.c create mode 100644 contrib/media/fplay/winlib/frame.c create mode 100644 contrib/media/fplay/winlib/panel.c create mode 100644 contrib/media/fplay/winlib/window.c create mode 100644 contrib/media/fplay/winlib/winlib.h diff --git a/contrib/media/fplay/audio.c b/contrib/media/fplay/audio.c new file mode 100644 index 0000000000..90dc94168c --- /dev/null +++ b/contrib/media/fplay/audio.c @@ -0,0 +1,442 @@ + +#include +#include +#include +#include "libswresample/swresample.h" + +#include +#include +#include "../winlib/winlib.h" +#include "sound.h" +#include "fplay.h" + + +astream_t astream; + +extern uint8_t *decoder_buffer; +int resampler_size; +volatile int sound_level_0; +volatile int sound_level_1; + +volatile enum player_state player_state; +volatile enum player_state decoder_state; +volatile enum player_state sound_state; + +extern volatile uint32_t driver_lock; + +static SNDBUF hBuff; + +static int snd_format; +int sample_rate; + +static uint32_t samples_written = 0; +double audio_base = -1.0; + +double get_audio_base(); + +int init_audio(int format) +{ + int err; + int version =-1; + char *errstr; + + mutex_lock(&driver_lock); + + if((err = InitSound(&version)) !=0 ) + { + mutex_unlock(&driver_lock); + errstr = "Sound service not installed\n\r"; + goto exit_whith_error; + }; + + mutex_unlock(&driver_lock); + +// printf("sound version 0x%x\n", version); + + if( (SOUND_VERSION>(version&0xFFFF)) || + (SOUND_VERSION<(version >> 16))) + { + errstr = "Sound service version mismatch\n\r"; + goto exit_whith_error; + } + + snd_format = format; + + create_thread(audio_thread, 0, 163840); + + return 1; + +exit_whith_error: + + printf(errstr); + return 0; +}; + +void set_audio_volume(int left, int right) +{ + SetVolume(hBuff, left, right); +}; + +static uint64_t samples_lost; +static double audio_delta; +static double last_time_stamp; + + +double get_master_clock(void) +{ + double tstamp; + + GetTimeStamp(hBuff, &tstamp); + return tstamp - audio_delta; +}; + +int decode_audio(AVCodecContext *ctx, queue_t *qa) +{ + static struct SwrContext *swr_ctx; + static int64_t src_layout; + static int src_freq; + static int src_channels; + static enum AVSampleFormat src_fmt = -1; + static AVFrame *aFrame; + + AVPacket pkt; + AVPacket pkt_tmp; + int64_t dec_channel_layout; + int len, len2; + int got_frame; + int data_size; + + + if( astream.count > 192000*2) + return -1; + + if( get_packet(qa, &pkt) == 0 ) + return 0; + + // __asm__("int3"); + + if (!aFrame) + { + if (!(aFrame = avcodec_alloc_frame())) + return -1; + } else + avcodec_get_frame_defaults(aFrame); + + pkt_tmp = pkt; + + while(pkt_tmp.size > 0) + { + data_size = 192000; + +// len = avcodec_decode_audio3(ctx,(int16_t*)decoder_buffer, +// &data_size, &pkt_tmp); + got_frame = 0; + len = avcodec_decode_audio4(ctx, aFrame, &got_frame, &pkt_tmp); + + if(len >= 0 && got_frame) + { + char *samples; + int ch, plane_size; + int planar = av_sample_fmt_is_planar(ctx->sample_fmt); + int data_size = av_samples_get_buffer_size(&plane_size, ctx->channels, + aFrame->nb_samples, + ctx->sample_fmt, 1); + +// 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.size -= len; + + dec_channel_layout = + (aFrame->channel_layout && aFrame->channels == av_get_channel_layout_nb_channels(aFrame->channel_layout)) ? + aFrame->channel_layout : av_get_default_channel_layout(aFrame->channels); + + if (aFrame->format != src_fmt || + dec_channel_layout != src_layout || + aFrame->sample_rate != src_freq || + !swr_ctx) + { + swr_free(&swr_ctx); + swr_ctx = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, + aFrame->sample_rate, dec_channel_layout,aFrame->format, + aFrame->sample_rate, 0, NULL); + if (!swr_ctx || swr_init(swr_ctx) < 0) + { + printf("Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n", + aFrame->sample_rate, av_get_sample_fmt_name(aFrame->format), (int)aFrame->channels, + aFrame->sample_rate, av_get_sample_fmt_name(AV_SAMPLE_FMT_S16), 2); + break; + } + + src_layout = dec_channel_layout; + src_channels = aFrame->channels; + src_freq = aFrame->sample_rate; + src_fmt = aFrame->format; + }; + + if (swr_ctx) + { + const uint8_t **in = (const uint8_t **)aFrame->extended_data; + uint8_t *out[] = {decoder_buffer}; + int out_count = 192000 * 3 / 2 / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16); + len2 = swr_convert(swr_ctx, out, out_count, in, aFrame->nb_samples); + if (len2 < 0) { + printf("swr_convert() failed\n"); + break; + } + if (len2 == out_count) { + printf("warning: audio buffer is probably too small\n"); + swr_init(swr_ctx); + } + data_size = len2 * 2 * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16); + + mutex_lock(&astream.lock); + + samples = astream.buffer+astream.count; + + memcpy(samples, decoder_buffer, data_size); +/* + memcpy(samples, aFrame->extended_data[0], plane_size); + + if (planar && ctx->channels > 1) + { + uint8_t *out = ((uint8_t *)samples) + plane_size; + for (ch = 1; ch < ctx->channels; ch++) + { + memcpy(out, aFrame->extended_data[ch], plane_size); + out += plane_size; + } + } +*/ + astream.count += data_size; + mutex_unlock(&astream.lock); + }; + } + else pkt_tmp.size = 0; + } + av_free_packet(&pkt); + return 1; +}; + + +static void sync_audio(SNDBUF hbuff, int buffsize) +{ + SND_EVENT evnt; + uint32_t offset; + double time_stamp; + +#ifdef BLACK_MAGIC_SOUND + + while( player_state != CLOSED) + { + GetNotify(&evnt); + + if(evnt.code != 0xFF000001) + { + printf("invalid event code %d\n\r", evnt.code); + continue; + } + + if(evnt.stream != hbuff) + { + printf("invalid stream %x hBuff= %x\n\r", + evnt.stream, hbuff); + continue; + } + + GetTimeStamp(hbuff, &time_stamp); + audio_delta = time_stamp - last_time_stamp; + + offset = evnt.offset; + + mutex_lock(&astream.lock); + { + if(astream.count < buffsize) + { + memset(astream.buffer+astream.count, + 0, buffsize-astream.count); + astream.count = buffsize; + }; + + SetBuffer(hbuff, astream.buffer, offset, buffsize); + samples_written+= buffsize/4; + + astream.count -= buffsize; + if(astream.count) + memcpy(astream.buffer, astream.buffer+buffsize, astream.count); + mutex_unlock(&astream.lock); + }; + break; + }; +#endif + +}; + +int audio_thread(void *param) +{ + SND_EVENT evnt; + + int buffsize; + int samples; + int err; + char *errstr; + int active; + + + if((err = CreateBuffer(snd_format|PCM_RING,0, &hBuff)) != 0) + { + errstr = "Cannot create sound buffer\n\r"; + goto exit_whith_error; + }; + + SetVolume(hBuff,-1875,-1875); + + if((err = GetBufferSize(hBuff, &buffsize)) != 0) + { + errstr = "Cannot get buffer size\n\r"; + goto exit_whith_error; + }; + + resampler_size = buffsize = buffsize/2; + + samples = buffsize/4; + + while( player_state != CLOSED) + { + uint32_t offset; + double event_stamp, wait_stamp; + int too_late = 0; + + switch(sound_state) + { + case PREPARE: + + mutex_lock(&astream.lock); + if(astream.count < buffsize*2) + { + memset(astream.buffer+astream.count, + 0, buffsize*2-astream.count); + astream.count = buffsize*2; + }; + + SetBuffer(hBuff, astream.buffer, 0, buffsize*2); + astream.count -= buffsize*2; + if(astream.count) + memcpy(astream.buffer, astream.buffer+buffsize*2, astream.count); + mutex_unlock(&astream.lock); + + SetTimeBase(hBuff, audio_base); + + case PAUSE_2_PLAY: + 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); + sound_state = PLAY; +// printf("render: set audio latency to %f\n", audio_delta); + + /* breaktrough */ + + case PLAY: + GetNotify(&evnt); + + if(evnt.code != 0xFF000001) + { + printf("invalid event code %d\n\r", evnt.code); + continue; + } + + if(evnt.stream != hBuff) + { + printf("invalid stream %x hBuff= %x\n\r", + evnt.stream, hBuff); + continue; + }; + + offset = evnt.offset; + + mutex_lock(&astream.lock); + if(astream.count < buffsize) + { + memset(astream.buffer+astream.count, + 0, buffsize-astream.count); + astream.count = buffsize; + }; + + SetBuffer(hBuff, astream.buffer, offset, buffsize); + + { + double val = 0; + int16_t *src = (int16_t*)astream.buffer; + int samples = buffsize/2; + int i; + + for(i = 0, val = 0; i < samples/2; i++, src++) + if(val < abs(*src)) + val= abs(*src); // * *src; + + sound_level_0 = val; //sqrt(val / (samples/2)); + + for(i = 0, val = 0; i < samples/2; i++, src++) + if(val < abs(*src)) + val= abs(*src); // * *src; + + sound_level_1 = val; //sqrt(val / (samples/2)); + + // printf("%d\n", sound_level); + }; + + samples_written+= buffsize/4; + + astream.count -= buffsize; + if(astream.count) + memcpy(astream.buffer, astream.buffer+buffsize, astream.count); + mutex_unlock(&astream.lock); + break; + + case PLAY_2_STOP: + if( active ) + { + ResetBuffer(hBuff, SND_RESET_ALL); + audio_base = -1.0; + active = 0; + } + sound_state = STOP; + break; + + case PLAY_2_PAUSE: + if( active ) + { + StopBuffer(hBuff); + }; + sound_state = PAUSE; + + case PAUSE: + case STOP: + delay(1); + }; + } + + StopBuffer(hBuff); + DestroyBuffer(hBuff); + + return 0; + +exit_whith_error: + + printf(errstr); + return -1; + +}; + diff --git a/contrib/media/fplay/fplay.c b/contrib/media/fplay/fplay.c new file mode 100644 index 0000000000..b9569d8807 --- /dev/null +++ b/contrib/media/fplay/fplay.c @@ -0,0 +1,530 @@ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "../winlib/winlib.h" + +#include "sound.h" +#include "fplay.h" + +volatile enum player_state player_state = STOP; +volatile enum player_state decoder_state = PREPARE; +volatile enum player_state sound_state = STOP; + +uint32_t win_width, win_height; + +void decoder(); + +AVFormatContext *pFormatCtx; +AVCodecContext *pCodecCtx; +AVCodecContext *aCodecCtx; +AVCodec *pCodec; +AVCodec *aCodec; +AVFrame *pFrame; +int videoStream; +int audioStream; + +int have_sound = 0; + +uint8_t *decoder_buffer; +extern int resampler_size; + +extern int sample_rate; +char *movie_file; + +void flush_video(); + +queue_t q_video; +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 i; + char *file_name, *dot; + + if(argc < 2) + { + movie_file = get_moviefile(); + if(movie_file == NULL) + { + printf("Please provide a movie file\n"); + return -1; + } + } + else movie_file = argv[1]; + + /* register all codecs, demux and protocols */ + +#if 0 + { + int fd, i; + char *buff; + uint32_t start, stop; + + fd = open(movie_file,O_RDONLY); + + if(fd < 0) + return 0; + + buff = user_alloc(65536); + memset(buff, 0, 65536); + + start = get_tick_count(); + + for(i = 0; i < 1024*1024*1024; i+=65536) + { + if(read(fd, buff, 65536) < 0) + break; + + }; + stop = get_tick_count(); + + printf("average speed %d Kbytes/c\n", ((i/1024)*100)/(stop-start)); + }; + return 0; +}; + +#else + + av_log_set_level(AV_LOG_FATAL); + + avcodec_register_all(); + avdevice_register_all(); + av_register_all(); + +// init_pixlib(HW_BIT_BLIT|HW_TEX_BLIT); + + if( avformat_open_input(&pFormatCtx, movie_file, NULL, NULL) < 0) + { + printf("Cannot open file %s\n\r", movie_file); + return -1; // Couldn't open file + }; + + pFormatCtx->flags |= AVFMT_FLAG_GENPTS; + + // Retrieve stream information + if(avformat_find_stream_info(pFormatCtx, NULL)<0) + { + printf("Cannot find streams\n\r"); + return -1; + }; + + file_name = strrchr(movie_file,'/')+1; + dot = strrchr(file_name,'.'); + if(dot) + { + movie_file = malloc(dot-file_name+1); + memcpy(movie_file, file_name, dot-file_name); + movie_file[dot-file_name] = 0; + } + else movie_file = file_name; + + +// __asm__ __volatile__("int3"); + +// 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 + videoStream=-1; + audioStream=-1; + for(i=0; i < pFormatCtx->nb_streams; i++) + { +// pFormatCtx->streams[i]->discard = AVDISCARD_ALL; + + if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO + && videoStream < 0) + { + videoStream=i; + 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 && + audioStream < 0) + { + 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; + + } + } + + if(videoStream==-1) + { + printf("Video stream not detected\n\r"); + return -1; // Didn't find a video stream + }; + +#if 0 + { + AVPacket packet; + int psize = 0; + uint32_t start, stop; + + int err; + start = get_tick_count(); + + while(psize < 1024*1024*1024) + { + err = av_read_frame(pFormatCtx, &packet); + if(err != 0) + break; + psize+= packet.size; + av_free_packet(&packet); + }; + + stop = get_tick_count(); + + printf("average speed %d Kbytes/c\n", ((psize/1024)*100)/(stop-start)); + + return 1; + }; +}; +#else + + + // __asm__ __volatile__("int3"); + + // Get a pointer to the codec context for the video stream + pCodecCtx=pFormatCtx->streams[videoStream]->codec; + aCodecCtx=pFormatCtx->streams[audioStream]->codec; + + // Find the decoder for the video stream + +// init_hw_context(pCodecCtx); + + pCodec=avcodec_find_decoder(pCodecCtx->codec_id); + +// printf("ctx->pix_fmt %d\n", pCodecCtx->pix_fmt); + + if(pCodec==NULL) { + printf("Unsupported codec with id %d for input stream %d\n", + pCodecCtx->codec_id, videoStream); + return -1; // Codec not found + } + + if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0) + { + printf("Error while opening codec for input stream %d\n", + videoStream); + return -1; // Could not open codec + }; + +// printf("ctx->pix_fmt %d\n", pCodecCtx->pix_fmt); + + + if (aCodecCtx->channels > 0) + aCodecCtx->request_channels = FFMIN(2, aCodecCtx->channels); + else + aCodecCtx->request_channels = 2; + + aCodec = avcodec_find_decoder(aCodecCtx->codec_id); + + if(aCodec) + { + if(avcodec_open2(aCodecCtx, aCodec, NULL) >= 0 ) + { + WAVEHEADER whdr; + int fmt; + int channels; + + printf("audio stream rate %d channels %d format %d\n", + aCodecCtx->sample_rate, aCodecCtx->channels, aCodecCtx->sample_fmt ); + whdr.riff_id = 0x46464952; + whdr.riff_format = 0x45564157; + whdr.wFormatTag = 0x01; + whdr.nSamplesPerSec = aCodecCtx->sample_rate; + whdr.nChannels = 2; + whdr.wBitsPerSample = 16; + + sample_rate = aCodecCtx->sample_rate; + + fmt = test_wav(&whdr); + + if( init_audio(fmt) ) + { + decoder_buffer = (uint8_t*)av_mallocz(192000*2+64); + if( decoder_buffer != NULL ) + { + astream.lock = 0; + astream.count = 0; + astream.buffer = (char *)av_mallocz(192000*3); + if( astream.buffer != NULL ) + have_sound = 1; + else + av_free(decoder_buffer); + } + if( have_sound == 0) + { + printf("Not enough memory for audio buffers\n"); + } + } + } + else printf("Cannot open audio codec\n\r"); + } + else printf("Unsupported audio codec!\n"); + + if( !init_video(pCodecCtx)) + return 0; + +// __asm__ __volatile__("int3"); + + decoder(); + + // Free the YUV frame + av_free(pFrame); + + +//__asm__ __volatile__("int3"); + + // Close the codec + // avcodec_close(pCodecCtx); + + // Close the video file + // av_close_input_file(pFormatCtx); + +//__asm__ __volatile__("int3"); + + return 0; +} + + +static int load_frame() +{ + AVPacket packet; + int err; + + err = av_read_frame(pFormatCtx, &packet); + if( err == 0) + { + 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.pts != AV_NOPTS_VALUE) + audio_base = get_audio_base() * packet.pts; +// printf("audio base %f\n", audio_base); + }; + } + else av_free_packet(&packet); + } + else if (err != AVERROR_EOF) + printf("av_read_frame: error %x\n", err); + + return err; +} + + + +static int fill_queue() +{ + int err = 0; + AVPacket packet; + +// __asm__ __volatile__("int3"); + + while( (q_video.size < 4*1024*1024) && + !err ) + err = load_frame(); + + return err; + +}; + + +static void flush_all() +{ + AVPacket packet; + + 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); + + flush_video(); + + astream.count = 0; +}; + +void decoder() +{ + int eof; + AVPacket packet; + int ret, vret, aret; + + int64_t min_pos, max_pos; + + while( player_state != CLOSED ) + { + int err; + +// __asm__ __volatile__("int3"); + + switch(decoder_state) + { + case PREPARE: + eof = fill_queue(); + + do + { + if( (q_video.size < 4*1024*1024) && + (eof == 0) ) + { + eof = load_frame(); + } + decode_video(pCodecCtx, &q_video); + ret = decode_audio(aCodecCtx, &q_audio); + }while(astream.count < resampler_size*2 && + ret == 1); + + sound_state = PREPARE; + decoder_state = PLAY; + player_state = PLAY; + + case PLAY: + if( (q_video.size < 4*1024*1024) && + (eof == 0) ) + { + eof = load_frame(); + } + vret = decode_video(pCodecCtx, &q_video); + aret = decode_audio(aCodecCtx, &q_audio); + ret = vret | aret; + + if( eof && !ret) + { + decoder_state = STOP; + continue; + }; + + if( (vret & aret) == -1) + { + if( (q_video.size < 4*1024*1024) && + (eof == 0) ) + { + eof = load_frame(); + yield(); + continue; + }; + delay(1); + continue; + } + + yield(); + continue; + + case STOP: + delay(1); + continue; + + + case PLAY_2_STOP: + while(sound_state != STOP) + delay(1); + + flush_all(); + + if (pFormatCtx->start_time != AV_NOPTS_VALUE) + rewind_pos = pFormatCtx->start_time; + else + rewind_pos = 0; + + ret = avformat_seek_file(pFormatCtx, -1, INT64_MIN, + rewind_pos, INT64_MAX, 0); + + decoder_state = STOP; + break; + + case REWIND: + while(sound_state != STOP) + yield(); + + flush_all(); + int opts = 0; + if(rewind_pos < 0) + { + rewind_pos = -rewind_pos; + opts = AVSEEK_FLAG_BACKWARD; + }; + + if (pFormatCtx->start_time != AV_NOPTS_VALUE) + rewind_pos += pFormatCtx->start_time; + +// printf("rewind %8"PRId64"\n", rewind_pos); + min_pos = rewind_pos - 1000000; + max_pos = rewind_pos + 1000000; + + ret = avformat_seek_file(pFormatCtx, -1, INT64_MIN, + rewind_pos, INT64_MAX, 0); + +// ret = avformat_seek_file(pFormatCtx, -1, min_pos, +// rewind_pos, max_pos, opts); +// __asm__ __volatile__("int3"); + + if (ret < 0) + { + printf("could not seek to position %f\n", + (double)rewind_pos / AV_TIME_BASE); + } + +// printf("restart\n"); + decoder_state = PREPARE; + break; + } + }; + + ret = 1; + + while( (player_state != CLOSED) && ret) + { + ret = decode_video(pCodecCtx, &q_video); + ret |= decode_audio(aCodecCtx, &q_audio); + delay(1); + }; + delay(50); + player_state = CLOSED; + delay(300); +}; +#endif +#endif diff --git a/contrib/media/fplay/fplay.h b/contrib/media/fplay/fplay.h new file mode 100644 index 0000000000..b60e52bdf2 --- /dev/null +++ b/contrib/media/fplay/fplay.h @@ -0,0 +1,143 @@ + +#include "pixlib2.h" + +#define BLACK_MAGIC_SOUND +#define BLACK_MAGIC_VIDEO + +typedef unsigned int color_t; +typedef unsigned int count_t; + +typedef struct render render_t; + +#define HAS_LEFT (1<<0) +#define HAS_TOP (1<<1) +#define HAS_RIGHT (1<<2) +#define HAS_BOTTOM (1<<3) + +struct render +{ + uint32_t caps; + uint32_t ctx_width; + uint32_t ctx_height; + uint32_t win_width; + uint32_t win_height; + + rect_t rc_client; + rect_t rcvideo; + rect_t rcleft; + rect_t rctop; + rect_t rcright; + rect_t rcbottom; + + uint32_t layout; + bitmap_t bitmap[4]; + bitmap_t *last_bitmap; + + uint32_t ctx_format; + int target; + + window_t *win; + enum{ + EMPTY, INIT }state; + enum win_state win_state; + + void (*draw)(render_t *render, AVPicture *picture); +}; + +enum player_state +{ + CLOSED = 0, + PREPARE, + STOP, + PAUSE, + PLAY, + REWIND, + PLAY_2_STOP, + PLAY_2_PAUSE, + PAUSE_2_PLAY, + REWIND_2_PLAY, +}; + +#define ID_PLAY 100 +#define ID_STOP 101 +#define ID_PROGRESS 102 +#define ID_VOL_LEVEL 103 +#define ID_VOL_CTRL 104 + +typedef struct +{ + volatile uint32_t lock; + char *buffer; + volatile uint32_t count; +}astream_t; + +typedef struct +{ + unsigned int code; + unsigned int sender; + unsigned int stream; + unsigned int offset; + unsigned int size; + unsigned int unused[2]; +}SND_EVENT; + + +typedef struct { + AVPacketList *first_pkt; + AVPacketList *last_pkt; + int size; + int count; + volatile uint32_t lock; +} queue_t; + +int put_packet(queue_t *q, AVPacket *pkt); +int get_packet(queue_t *q, AVPacket *pkt); + + +extern astream_t astream; +extern AVRational video_time_base; + +render_t *create_render(window_t *win, AVCodecContext *ctx, uint32_t flags); +void destroy_render(render_t *render); +int init_render(render_t *render, int width, int height); +void render_adjust_size(render_t *render, window_t *win); +void render_set_size(render_t *render, int width, int height); +void render_draw_client(render_t *render); + + +int init_audio(int format); +int audio_thread(void *param); +void set_audio_volume(int left, int right); + +int init_video(AVCodecContext *ctx); +int video_thread(void *param); + +int decode_video(AVCodecContext *ctx, queue_t *qv); +int decode_audio(AVCodecContext *ctx, queue_t *qa); + +double get_master_clock(void); + + +int create_thread(int (*proc)(void *param), void *param, int stack_size); + +void mutex_lock(volatile uint32_t *val); + +static inline void mutex_unlock(volatile uint32_t *val) +{ + *val = 0; +} + +static inline void GetNotify(void *event) +{ + __asm__ __volatile__ ( + "int $0x40" + ::"a"(68),"b"(14),"c"(event)); +} + + + +int init_fontlib(); +int draw_text(bitmap_t *winbitmap, int face, char *text, int x, int y, int color); +int draw_text_ext(bitmap_t *winbitmap, int face, char *text, rect_t *rc, int color); +char *get_moviefile(); + diff --git a/contrib/media/fplay/opendial.asm b/contrib/media/fplay/opendial.asm new file mode 100644 index 0000000000..416c1413d7 --- /dev/null +++ b/contrib/media/fplay/opendial.asm @@ -0,0 +1,149 @@ +format MS COFF + +public _get_moviefile + +section '.text' align 16 + +align 4 +getprocaddress: + mov edx, [esp + 8] ; hlib + xor eax, eax + test edx, edx ; If hlib = 0 then goto .end + jz .end + +.next: + cmp [edx], dword 0 ; If end of export table then goto .end + jz .end + + xor eax, eax + mov esi, [edx] + mov edi, [esp + 4] ; name + +.next_: + lodsb + scasb + jne .fail + or al, al + jnz .next_ + jmp .ok +.fail: + add edx, 8 + jmp .next + +.ok: ; return address + mov eax, [edx + 4] +.end: + ret 8 + + + +align 8 +_get_moviefile: + + pushad + mov eax, 68 + mov ebx, 19 + mov ecx, sz_proc_lib + int 0x40 + mov [proclib], eax + test eax, eax + jz .fail + + push [proclib] + push sz_OpenDialog_init + call getprocaddress + mov [opendialog_init], eax + + push dword[proclib] + push sz_OpenDialog_start + call getprocaddress + mov [opendialog_start], eax + + mov eax, 68 + mov ebx, 12 + mov ecx, 4096*3 + int 0x40 + + mov [od.procinfo], eax + + add eax, 1024 + mov [od.filename_area], eax + + add eax, 3072 + mov [od.opendir_path], eax + + add eax, 4096 + mov [od.openfile_path], eax + + push od + call [opendialog_init] + + mov eax, [od.openfile_path] + mov [eax], byte 0 ; end of ASCIIZ-string(may be don't need?) + + push od + call [opendialog_start] + + popad + mov eax, [od.openfile_path]; selected filePath + + ret +.fail: + xor eax, eax + ret + +align 4 +fake_on_redraw: + ret + +section '.rdata' align 16 + +sz_proc_lib db "/rd/1/lib/proc_lib.obj",0 +sz_OpenDialog_init db "OpenDialog_init",0 +sz_OpenDialog_start db "OpenDialog_start",0 +sz_com_area_name db "FFFFFFFF_open_dialog",0 +sz_dir_default_path db "/rd/1",0 +sz_start_path db "/rd/1/File managers/opendial",0 + + +section '.data' align 16 + +od: + .mode dd 0 + .procinfo dd 0 + .com_area_name dd sz_com_area_name + .com_area dd 0 + .opendir_path dd 0 + .dir_default_path dd sz_dir_default_path + .start_path dd sz_start_path + .draw_window dd fake_on_redraw + .status dd 0 + .openfile_path dd 0 + .filename_area dd 0 + .filter_area dd filefilter + .x_size dw 512 + .x_start dw 512 + .y_size dw 512 + .y_start dw 512 + +filefilter: +dd filefilter.end - filefilter + db 'avi',0 + db 'flv',0 + db 'mov',0 + db 'mpg',0 + db 'mpeg',0 + db 'mkv',0 + db 'mp4',0 + db 'webm',0 + db 'wmv',0 +.end: + db 0 + + +section '.bss' align 16 + +proclib dd ? +opendialog_init dd ? +opendialog_start dd ? + diff --git a/contrib/media/fplay/skin/clbhl.raw b/contrib/media/fplay/skin/clbhl.raw new file mode 100644 index 0000000000000000000000000000000000000000..401d6543ed64196798d85af98f161853c264aa45 GIT binary patch literal 1296 zcmZWpOKcle6eY3qX`9w|{2SXd9?y)&_KZDWkH>c6IPou}X;PK8LV%Mdq_9A25DPX) zAaz%Di_|S3u|#6U1{O#lRb3!~Kmvh;U_;fiVTTZl!+pzKEN^M98vD!;S`g}i1%l642N3?0vBQEqTBJ%TlcZq_c7RN zV#sVT`?7U^!^irXhfdo=tL0)uwad$k9IM+6;dynmf(GGO*y!1W;b1ayuswFUF@HRC zu+_H-$3i=_(DWPRhr}()^=OAaT&IShX<)5uQm%=>%V5w~u)k~L>J=MTb{c59N%*dS zey@&BXcCS=eVaJ99Oaq?fepvjX`Tu;)~ndsknr(`D&Brmz}}96o7YV2PEz>t(<(l= zuVAoQBVHBwo=$T)IDan6|BX+aY)e6_sbaHN#@#z6{`tel-;aIVeYb$?dkK91U>5uR zM;GIPj&56n=c?4Zeu~rd>u{_R+AWp1lyPmZf`^|w9E;)o^~mG?lb=1j{;GlPk&gAQ zM)N2LTMb+||8yP$c0)!Oln6&7E;?R%UdIm)>!(-@?~T_KJhxvV91Uw7h31h-QG{Anil!Lc{-0}=`d;qc#eo( zw}{K*EWZ6}rpKSZdid=-m*X+L-g!%;nPuuJph-#ap4;sftJO+s{eB;Z!vR4MNR13x z?bGdcQLR=*>-8G%_ZzR*3tV?P9h}c+Rl8oV(np3Y&x+^Gb)`}fIgW$~{hOsy3A^1+)sDxb z^pPQ}eV7IBh!*!8h9L%nfzx{pt?+K0L4^LZnY)jrHUo6Q=DtoGpYbg literal 0 HcmV?d00001 diff --git a/contrib/media/fplay/skin/clbp.raw b/contrib/media/fplay/skin/clbp.raw new file mode 100644 index 0000000000000000000000000000000000000000..b71cf5a92418ba5fcac7079e2ca3d1cc3c24ce5e GIT binary patch literal 1296 zcmZWpIcQX25H`EXZjLqk-tOCd_uF^ueP(l*!+6A)%XmNp5vw$&5gQ8|A%b8b+Ny03 zECnkIZ3Knb2r8mrAzFw88#@t;&zb+}#>8TH|C@j2o0)HBenm+m7VAMIvIo&<7rMK< z=)VhblHPdaKVf}OPiV*Xu~;`0!iYvANF@4^PD#jSWT>hPT~EO>Q?RWx9D7^%-!xLt zv=r2=3?(gL@7@6spYyOxo%AX4Pt!RKH>V))XHdvzP%LCnDu!SF_gw`!MRt5tO2->fAuKAOd$X&Z+R*f_Y~LaRQAdPNd37%T88W+fmFqk^+aIS{%E<-sv0 z$Fg{E&&QQZ8s=s+EHC7+I4k4XqY^gmc-S`*=2a|E+**LX-l*tJts01WIOp+E3)j~R z`1NfVKevW)} zgdgMm_}Uidtq((3TMa~=%o}siYUVM}AL7&rhwB|89FDbcG>0=QF5bPUb+8!k;+lgK zOD<*(IvAtc>Q$qI!*jJ8XMWbf%5eoBU)6Wu+`MLC{)pbe*_{t_^>1B^vst`;9`f=1 zQyZV(3<*5uYyGk%ddPFY^U-W<*R`AHjk~1|9~aICID6W|=97@Gmrom*8n*-o%*9`x zc~>fBAHJs&M;hJhIJsow;r%LB&w0d^gT*-q#}*vizE#AjWrya=5FF=ymFCA6^TT^t zEP6DXS=t5Cml?|tGqRt0H$52&pC`u54n`rb((Go54-avgL*ChZ-h*XjJ6ILMYSg%Y zVGr9aL!6s+UBqDw-XZoW6g-;csCX}Y--YMdv@;IjJ5*dw*pyVTb|LTA=hD>FXDvII-TZUnvJkKf1vKQ>^x{i`0VWDFWwsX+22^%@+IGgYLEOcyhU6+NPrYSj& z!+N@H+r&Y~Zp*S*=us4rX__qbFbv5s3>G@ht?N1q9cR}xjrC9WJdadWW#N0=ouVi# QbljaR%dCGocdyU84^Hp_ssI20 literal 0 HcmV?d00001 diff --git a/contrib/media/fplay/skin/cptright.raw b/contrib/media/fplay/skin/cptright.raw new file mode 100644 index 0000000000000000000000000000000000000000..f8a81df431a3d7861fd4838e068089e7fd4b9140 GIT binary patch literal 768 zcma*jIc|nP3TlaND@hWWTb2b*9LF*@O%oit3H3J&gGG1wB-eEvoFE8f Zy{2j4&|Rs&s;Vry>nAyP+xHvQe*yEr0jdB1 literal 0 HcmV?d00001 diff --git a/contrib/media/fplay/skin/fullbhl.raw b/contrib/media/fplay/skin/fullbhl.raw new file mode 100644 index 0000000000..5f307a58a5 --- /dev/null +++ b/contrib/media/fplay/skin/fullbhl.raw @@ -0,0 +1,10 @@ + + +       GFBaa[cb\fe\gf]hg]ih]ji]ji]ih]ih]hg]fe\dd\bb\GGA + GGA;:1>=2B@3CB3EC3GF4HF4HF4GF4GE4DC3BA3@?2?>4ED= + + @?7:9-97(/.20537496968564311/0/=5  ?>498*PL#}u><,>=1>=098'lf$2222222222ĸ)><)><.;:-75#ke"Ÿ)EB&FC&IF&KG'KG'JG'HE&FC&pi#ĸ);9%<;+<;-75"kd!Ź)DA%FC%HE%IF&IF&HE%FC%EB%oh#ĸ);9%<;+:9+53 jd Ÿ)A>#B?#EB#FC#GC$FC#DA#A>#nh"ĸ(97#:9)97*31hb ĸ)?"?;>;=:<9:8icö(3164%10$+)b]µ',*-+/-0-0-/-.,,*b[¶(/-21# .-"&%b\.""""""""&÷**(.,  + ((! 30`[`[`[b\b]b]b\a[`[`[QM%#(' %$!" #!$"%#%#%#$"#!"  $# +!! #"%$%$&%'&'&(''&&%%$%$$#!    + +                 \ No newline at end of file diff --git a/contrib/media/fplay/skin/fullbn.raw b/contrib/media/fplay/skin/fullbn.raw new file mode 100644 index 0000000000000000000000000000000000000000..4012d94299867a1724c74fead2097970b6d68068 GIT binary patch literal 1296 zcmbW0Ny@@N5QRn2fPw>2oTq4{LFAT#B@59 zUO3NqJVvL}`I&CFi_vIg`_Q-1Xka#*;c~fr#p!fHtJOlk-?x2wy&eq1z~OMf`~Cik z=ktkry)H9w$DFI(ZlhExVZYzw@py=4?1ajzR4QmTn|43+DHe<3bHCq3Gj@VL%qy46 z|9t3~&*!n*?c|)=4VA|_rfJ&!aL2h^PJC{+n`p*P(1&@2LP2(<_EW3XkWQzu-EQTa z+6|SL&1O-pR_%VMQ>hd-n++_>63y5NmB(7#k?Mz9|NGC@>os1l7tZIiE7$AQuE!lI zAL>LRA@96et?&(#$wX@NJ(Lf1EEfA2*5;0s58uUYuWo0VOh$Y{p%B91Frv|@CwN!W SH2Fs2@i-!ph$ncL^Lzj_8TA>;keķ(1/75%53%/.g`Ÿ(=:?<B?C?C?B?@=>;keķ(2075%53%/.g`ĸ(<9=:@=A>B?A>?<<9kdķ(2075%43%/-e_ĸ(:8;9>;?<?<>;=::8jdķ(1/75%32%-+d^÷(8596;9<9<9;9:896hbö(/.64%10$+)b]µ',*-+/-0-0-/-.,,*b[¶(-+43% /.#'&b].########&÷*)(1/# + ++"$"53b\b] b] d^ e_ e_ d^ c] b] b] SO%$-,#*)" $"%$&%'&(')()()((''&&%%#"!**" &% %$(')(*)+*,+,+-,,++**))(('&%'&! +  + +                    \ No newline at end of file diff --git a/contrib/media/fplay/skin/istokweb.ttf b/contrib/media/fplay/skin/istokweb.ttf new file mode 100644 index 0000000000000000000000000000000000000000..566c7da670087317ba90a3608b51e7197853e755 GIT binary patch literal 277996 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

EH?dg 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 z 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

gx;PR?L^sh- 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 literal 0 HcmV?d00001 diff --git a/contrib/media/fplay/skin/minbn.raw b/contrib/media/fplay/skin/minbn.raw new file mode 100644 index 0000000000000000000000000000000000000000..ee0f228c6fae0efdfdab43e9270341f5b8eb2655 GIT binary patch literal 1296 zcmbW0&#FdH6i1~Pkbg;v5Q-?tfT>KG8}I<0#QS-peedtosc&-g-91<%)@q-#@qM2( zO(R87Sitpv8>*_(vMh8Q2Mf4pV2*j7sqcFhaOGLXaiq3wS-_Q@VHl{YDi&~Mr|UW@ zih>1P*=d@F(lliO_p_5E332%B)OAg99J7Ec=fNFEQN#kS?386mVHmQ2D?53fQxF6+ zO%vVs{T1uF3J0$2WLYNuk!{=Pd7iJhu8SPUA-J-GJ$ar-xU=&-Y2Wu(@co;nDRwM7 z*cIBqwr%ko@4R7Ime{fEU{~CGhKr7_>tq;)m;i@f4E~nq`qgt(^R4QEwUDwg;^-wOCQLoq0Znx3tbp8w0 zG#U+Pnx^hx+cvu0?v-HexsUJrFbv~L1VM1&BZPoy8oyy#2L8sMeXQl#Xj%zjC}7(r z9Kv-7*M#R43nYXL{}*g*L_`8ffW07~ToE31Kr)?xui)0g{s886)NZY9Ec2ObV+=Bow2N8SbA0gGlU)qMDUO=3X|X=Xka z^8kBGfy1@H(SgLtQNi({RJr|?z;Y2F&wTP?1hzIS>E#2K{%`Hz@Wf?xNpo()ZqkWj5*iX<^{8cbn>$aE@!X N)l$7mv(r%?zW{`N%R>MF literal 0 HcmV?d00001 diff --git a/contrib/media/fplay/skin/panel.raw b/contrib/media/fplay/skin/panel.raw new file mode 100644 index 0000000000..de8555c941 --- /dev/null +++ b/contrib/media/fplay/skin/panel.raw @@ -0,0 +1 @@ +QQQQQQ333333 \ No newline at end of file diff --git a/contrib/media/fplay/skin/panelleft.raw b/contrib/media/fplay/skin/panelleft.raw new file mode 100644 index 0000000000..aa7463709d --- /dev/null +++ b/contrib/media/fplay/skin/panelleft.raw @@ -0,0 +1 @@ +QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333333333333333333333333333333333333333333333333 \ No newline at end of file diff --git a/contrib/media/fplay/skin/panelright.raw b/contrib/media/fplay/skin/panelright.raw new file mode 100644 index 0000000000..3d8a2ff3de --- /dev/null +++ b/contrib/media/fplay/skin/panelright.raw @@ -0,0 +1 @@ +QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333,,,333333333333333333333333333333333333333333333333333 \ No newline at end of file diff --git a/contrib/media/fplay/skin/pausebp.raw b/contrib/media/fplay/skin/pausebp.raw new file mode 100644 index 0000000000000000000000000000000000000000..9d2aa2e70d6a99ba50af6e00639dd45149bd55d3 GIT binary patch literal 4096 zcmb`J*^d-e6vi1ChMn%|rK-BRx~rG!>1DQ_VGv_f2op7NBf}uVgCUM6gKP#8jSu1$ z0wKnz{{l}&BTq*E74%JCP~Uj<;dp;{a*FC@mJlCK>fT$o?)RPVEVqInkYEc|EEXl3 z&B~rVdt_{EOm^(pA=|cXv$k{RPP=yS;6ZU5XG`a81(Q96LP7TJ+b1IS^7*{{Bj#_wJ23FjkE9 zp1$wLyzw86lemfp$9~gy%13$NyXMYjIuJiJ)3|X4K6##N^3XN;RFG2OTMLT5owLT6 z^}vjov)6Ukbm9y&)L5*S53I9i`}XZJK0Y4%?RnIbC)J8C6OBMxO{`?cQ9Tf>Iq}#U zkuPCrc=(>>pgNGZoKI~Gs|(E+_G!HFAt-tV!2eNpqE-xZriVy#&Ua;qV z_HiWt{xcuj{d+Arz0{PmZ#3o6AKiHU;e#1@;ds?@E|+`plNx}52JnCrmc)j)Z(@ia zN1v_8-7gw320VWGp)KdnwPkgsBai-kjQ{uVv$FJBB!}ioHfNIc!1-E}^a$|5QSGU> zBnRL4Pb?RYRpgu7%^v(;e{9R8cRTXI#mNEu(3W6Kl=| z3w&xEpXqm+`{dyN?Z4t{4;Y3IH@K+(Ne)T>zr8at5dW*I9l3FNF#czjBYA2eFtt0} z|D^upC;0RRv`FH6ZrOgXb&DUCU0cgZ?YXPLgG0GowmHaL z{~3}TTqkGxtS85hmWSeBxzLj9m)ZmQ_vXo(96nT(a>?n5JJ|d8?~nB+|HCkh|E1_p z{rHW@m1ED9On>XGf9mhzJ57N@fBi3?sLFiTABwO4721E`pgE}j8O*VKJ}dRABhMTu z%I%xAp7{U#eM`=rjb!DmMi2g9zs<@kFNHEY?U~+|k8>X1seS!#RPDiMtTCZ4u@}o` z$Bhp;nVa$C=7;qj{GaZ1`4+Qq6|d9Nm?PL$>8!@kvKb){<7YjSn9YV-(Y zdeW7!Z2p;Ye8uumm!6BVaN!D=i3mFrKoISTY?V7vA^yQ`_ zjmRBv;aF?X=JlZ|y+j=|2FyPp`QtRI|3zr}a%IIt8~pTvNE#2$=1UCYNc4xCr? zGv-dkvSx4AYJk3>JNZ_r zRMz!9$zft*!su9t^MUWFTVev2jVy_){G%uu8uKJ(|Cm_to%Sn@3H6I6@S&bC#;j?6 zvzIaVPOH`GskMHbjpk^^_rwiNwRb3&VNbXyF0mX|Ya3w>dq>=w&8BoZ9UDXHg#Jmc iV%%Y@fyW-6o8{RsoUN>(MXgq|7~}~?oLGAj%>MunxX&B_ literal 0 HcmV?d00001 diff --git a/contrib/media/fplay/skin/pausebtn.raw b/contrib/media/fplay/skin/pausebtn.raw new file mode 100644 index 0000000000000000000000000000000000000000..5e22c5d92b38dd4d3fe7a45f70d42fa001942b77 GIT binary patch literal 4096 zcmbW4Nsm-j6vvrodZ@8$o`?5p=&J7ONwAsJh@y;Pa3F!8jX-OFL>Gn_g9vd7`W19z zB*ujcz6!e24eHLVi{t&>%6Yu5>Y_Rql<{%3f%lF6hb*C2^RLW04dY~Q|J zwrtrV8#iv0b?eqy*}QqP)s2jdNF)+jlfAWIawZmw$$N@XH!;Jp#1nCeY7!2I1z+`j@-hrl_a`PML}OsZmu9mmQ&Uq`z)%5GaaG5; zcDrqP0atz4v17+jAL8-2=Qr_ZvsoK6akpA6YZu$YgtNR;uh%UXT06sdptkXsxO2Ij zb@g>=w`vC4H94qS8>Lc7G#B*7YJH*g!ns1B zAjM))N~NN)Q8xCfGB;C}xlT%+n@`L9Y}%|Pd45k_7WdX=ekLP(7BaFhmzLR1#`xw) zqi*~!m#iIZWilBrx1*z@D{5hUeB9%mI^-<5FBD7;+@is&$m!z+`Qp=rd~+u$U)@g1 z)k|49a=0l+k2K}Zt)$hn_sK^I*}v$>RJ$zYa>3>iTi6T)0v^YH4m9udyXxujTsC9y zbF#RnEVnb0yK+Fz0{Z?D9E_`sE=3k|t)$>9I_1pn{fC*{;J$K)$- z@G~9;HtB6f#x-{p{DP^!grrju zi%%@r#6JA{@!7){;%CqAgT@d3{kx^U_?MTea^tGghkxco-s1b?*Vw`E^G{uXuisWb zel!v?H9R5DickE+?Z;;JfQJu!Q>j6IGZ)$Oa}Ws!rBsZ{fyGpR{6AIY+Pf9Gex=$M z|LNm7=}g5Xl??Y`@7lG?;~Q+|lHR45y?ywFi0s>&l&?Q4uH@g~U%ptjKJ@ngiPy8z zo{X)EulEY_4n6|sa6k_#2lx>R1xycxWnnfhpWn)_!2k8fikv@Jkc)2>SH%C^b_%v4K9(t%Eh-c(x^pE@0&Rm>h>G9h)erUzXyuX%6&uo0{^0^IbvI%;V$ZEc40h1Wy>Y{Rmq%tJrW$-2S>#T>r{lN&5jmcpp1(p`!KFyXrnG z_g&?jyi;S`L;P5Sp3CL3y$5JL@IHM@PVnVv;>T70xqq#e^FjFN^$w`>N^?U0!U_J+ zPYBQGw7xmZGvC~5wQ6I38rGmaIOBbMhf|#$>dR^?z9=raT&>pz;SJK0x9(lswK=3u kn4i=t!Z!>Zc-;3{ht=62tYLb%;J+sr)Cod<(LD?1|J4QU7ytkO literal 0 HcmV?d00001 diff --git a/contrib/media/fplay/skin/pbar.raw b/contrib/media/fplay/skin/pbar.raw new file mode 100644 index 0000000000000000000000000000000000000000..673aadd3ea9d75735fa8d0783b1af4bc8687f02a GIT binary patch literal 40 gcmZQzVE8X8DvE(cL`42`b94U}78d@mp`q~~0OpAdKmY&$ literal 0 HcmV?d00001 diff --git a/contrib/media/fplay/skin/playbp.raw b/contrib/media/fplay/skin/playbp.raw new file mode 100644 index 0000000000000000000000000000000000000000..420cdc73d2caf890aa55c53a752b5c86f5d940d9 GIT binary patch literal 4096 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 QxYvR~ogn0wz5j#xFUV+#lK=n! literal 0 HcmV?d00001 diff --git a/contrib/media/fplay/skin/prg_level.raw b/contrib/media/fplay/skin/prg_level.raw new file mode 100644 index 0000000000000000000000000000000000000000..64a9bea2f1f2490d80357fc10495abdf20e19259 GIT binary patch literal 40 pcmZQzVEBLbfX@HluZ`gN-bs%C*SE3$zqo|;|Bhzn|JgnQ{{j507`Olc literal 0 HcmV?d00001 diff --git a/contrib/media/fplay/skin/rborder.raw b/contrib/media/fplay/skin/rborder.raw new file mode 100644 index 0000000000000000000000000000000000000000..897339e8d9ceb19c3f5783821d01a94468f2a4f9 GIT binary patch literal 28 kcmXri(fsdXXZhdF!REi8yVL)uAn*Sfu_6B%7#RKo0H;R_5>;kpW?zTNoS(CM5Wr=bzYBU8z#5 zMtv`J*rk=$l6JtA4$x?cNAzCmNSs+&;wa}i;7L_VA$r56BQwtc^DB3MAhR)SQLk0C zWhsnn#Gvj{gH9upH=(=Z*^aoO{|CsJZ@p&kt^Je6nl~loS?w@ J88gxOtOvUepxpof literal 0 HcmV?d00001 diff --git a/contrib/media/fplay/skin/size_ns.cur b/contrib/media/fplay/skin/size_ns.cur new file mode 100644 index 0000000000000000000000000000000000000000..1b50dd7d46c74964149f44be0dbf6bcf8f3ed17f GIT binary patch literal 766 zcmd6ku@1s83`Ae6?(M`%NB#o-jC@)?g^`i51H#-ulc(=%~f34N+Wm8F1H yIOKePzR&&Seo5_a`b+J9Z>!3-cu2aRBc`MNVIOf(y{5HKxWxOebNG&PzQGeFl9-(U literal 0 HcmV?d00001 diff --git a/contrib/media/fplay/skin/size_nwse.cur b/contrib/media/fplay/skin/size_nwse.cur new file mode 100644 index 0000000000000000000000000000000000000000..fb20e7f05fb475a9afe57a382342ddc91b26966a GIT binary patch literal 766 zcmd5)F%H5o47?U3Ml&%nRAS*5@FiYAMxK?YFfw*zKpf|`NVNwT;ga*&xyDMP04*AH z9bg)_7T5sTi(0}_Y_L=mk3KlF~b?S zDm3Dzm{^nrX@QdpkB$QRl+sCACAC(u3-t*l-tad%@7b>E zX0s{H7gniMB%Mx6I2;zg-!C5@A8PCqiG&mi1!*)IFXP|gMx)Uu9=Pny0)fEuTQC@u zd_Mo{9JyRhd_JGX!?Dxp$ZEBc&1NIp?N)8QUdwPeRQ_JypR{B$8O5a*_%4@A#RmVC zk;k;MzRE!@sRP>KJe$pAKA)>C77KCBzTr0>kF_7fquH%HIl)D1xm;H5qtQq(V$CL# ziD0&8#Rm;=q8H>Sl}ev-SY49Iq_o>@_3d`Mg7td6mu5a-6K6GGzPuX93-@BNDD`?> zYiM<3KFRAEb;xG3Pha9{wVKW{8mI#~m~r-@P)K$0o_E!1RsGNBv)pdCZ|!h6s2~2s zVexoe@u&&-rYRDM=p3_02Q|e1e!t7(@%YxR*Q@&BPaNkUl}af-dBA7h;SWAJ(abx1 ziFt>Axm?r_f8sF1XI5Q&^Z6@2Tr3BDGQQxWjXgc5m#&7N_!}J2^O);A1@7JxJZGPL|6!x~qN1AMI8LxWn7@wK`z zm;HYKiETN!r);*+f>v)1!*W+*44aj^&M@7T`_RsZ%@p5JZ{hc^2~wf?II`_N-a5g)6{@yKp17o~0-mQ^o(?>P4z>*?tk3&N9Q{ z&n0wLTQ;82AqU>WAs8151p`}}E}c%>`bP0xF2CIzI2ZK< z{pIp?PNh=mjSqu-^ZEQoz+%1p!>0#S2l7ON9;fcSSC7a){LAHH9*@UI-0ydDI-TD5 zXi#5x)C4{(#^e;ne?Fh)^?HTI?RIfl!G*m$D=u)&!KTR90EV=lXo;`vzg_S1HW}g z(O2A$tXC)}|EYP_^R4OI!aKfU6XWqXIA`u;&WKvE&)0I9nrE%*LLbiO^MEal)oNuu zP$zOBS64$U|A}w0c`ldB54JSc>viybpu>9Vg^nNO$a$%*{9Y^;wie>~PinT=Z0w!n z{@=o2j2<<1=kP&Jc%v76X4seS!C@_D a$M5}q|5u))ba;<9a)&*gPJdko_Wl7eA21C7 literal 0 HcmV?d00001 diff --git a/contrib/media/fplay/skin/vol_level.raw b/contrib/media/fplay/skin/vol_level.raw new file mode 100644 index 0000000000000000000000000000000000000000..4752a5ac67a0c72ac062b555af5118c7eff1a27d GIT binary patch literal 3840 zcmeH}F$%*l3`KQ<4#jjRGPql^h29~9=L|`qz5kFSbWke`57AT;=#oEt$V1!X6MrHS z`X+=R%v`>~|MT%)@1j|zSp0+Ae9$VQIZY4iuj645(JPV`KbS&^ZeTE&&qXgret@|c}$||JKO)@HXoNUi{{$( O#lPp2vS?zoyXOy=57iO? literal 0 HcmV?d00001 diff --git a/contrib/media/fplay/skin/vol_slider.raw b/contrib/media/fplay/skin/vol_slider.raw new file mode 100644 index 0000000000000000000000000000000000000000..990d1fbb0914daa120d682fc7222e360dd056e7d GIT binary patch literal 1920 zcmeIyI|=|H3`J4Dhzf!z*aU3tbpM-sGm|}xRf=0A +#include +#include +#include +#include +#include +#include "../winlib/winlib.h" +#include "fplay.h" + +extern uint32_t hw2d ; + +void mutex_lock(volatile uint32_t *val) +{ + uint32_t tmp; + + __asm__ __volatile__ ( +"0:\n\t" + "mov %0, %1\n\t" + "testl %1, %1\n\t" + "jz 1f\n\t" + + "movl $68, %%eax\n\t" + "movl $1, %%ebx\n\t" + "int $0x40\n\t" + "jmp 0b\n\t" +"1:\n\t" + "incl %1\n\t" + "xchgl %0, %1\n\t" + "testl %1, %1\n\t" + "jnz 0b\n" + : "+m" (*val), "=&r"(tmp) + ::"eax","ebx" ); +} + + +int64_t _lseeki64(int fd, int64_t offset, int origin ) +{ + int off = offset; + return lseek(fd, off, origin); +} + + +int put_packet(queue_t *q, AVPacket *pkt) +{ + AVPacketList *q_pkt; + + /* duplicate the packet */ +// if (av_dup_packet(pkt) < 0) +// return -1; + + q_pkt = av_malloc(sizeof(AVPacketList)); + if (!q_pkt) + return -1; + + q_pkt->pkt = *pkt; + q_pkt->next = NULL; + + mutex_lock(&q->lock); + + if (!q->last_pkt) + q->first_pkt = q_pkt; + else + q->last_pkt->next = q_pkt; + + q->last_pkt = q_pkt; + q->size += q_pkt->pkt.size + sizeof(*q_pkt); + q->count++; + + mutex_unlock(&q->lock); + + return 0; +} + +int get_packet(queue_t *q, AVPacket *pkt) +{ + AVPacketList *q_pkt; + int ret = 0; + + mutex_lock(&q->lock); + + q_pkt = q->first_pkt; + if (q_pkt) + { + q->first_pkt = q_pkt->next; + if (!q->first_pkt) + q->last_pkt = NULL; + + q->count--; + q->size -= q_pkt->pkt.size + sizeof(*q_pkt); + *pkt = q_pkt->pkt; + av_free(q_pkt); + ret = 1; + }; + + mutex_unlock(&q->lock); + + return ret; +} + +void blit_raw(ctx_t *ctx, void *raw, int x, int y, int w, int h, int pitch) +{ + int *dst = (int*)ctx->pixmap->data; + int *src = raw; + int i, j; + + dst+= y * ctx->pixmap->pitch/4 + x; + + + for(i=0; i < h; i++) + { + for(j = 0; j < w; j++) + dst[j] = src[j]; + dst+= ctx->pixmap->pitch/4; + src+= pitch/4; + }; +}; diff --git a/contrib/media/fplay/video.c b/contrib/media/fplay/video.c new file mode 100644 index 0000000000..33d36b4058 --- /dev/null +++ b/contrib/media/fplay/video.c @@ -0,0 +1,1022 @@ + +#include +#include +#include +#include +#include +#include +#include "../winlib/winlib.h" +#include +#include "fplay.h" +#include + +int fplay_blit_bitmap(bitmap_t *bitmap, int dst_x, int dst_y,int w, int h); + +extern int res_pause_btn[]; +extern int res_pause_btn_pressed[]; + +extern int res_play_btn[]; +extern int res_play_btn_pressed[]; + +extern int64_t stream_duration; +extern volatile int sound_level_0; +extern volatile int sound_level_1; + +typedef struct +{ + AVPicture picture; + double pts; + volatile int ready; +}vframe_t; + +vframe_t frames[4]; +volatile int frames_count = 0; + +struct SwsContext *cvt_ctx = NULL; + +int vfx = 0; +int dfx = 0; + +render_t *main_render; + +int width; +int height; + +AVRational video_time_base; +AVFrame *Frame; + +volatile uint32_t driver_lock; + +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; + }; + frames_count = 0; + vfx = 0; + dfx = 0; +}; + +int init_video(AVCodecContext *ctx) +{ + int i; + + width = ctx->width; + height = ctx->height; + + + Frame = avcodec_alloc_frame(); + if ( Frame == NULL ) + { + printf("Cannot alloc video frame\n\r"); + return 0; + }; + + for( i=0; i < 4; i++) + { + int ret; + +// printf("alloc picture %d %d %x\n", +// ctx->width, ctx->height, ctx->pix_fmt ); + + ret = avpicture_alloc(&frames[i].picture, ctx->pix_fmt, + ctx->width, ctx->height); + if ( ret != 0 ) + { + printf("Cannot alloc video buffer\n\r"); + return 0; + }; + + frames[i].pts = 0; + frames[i].ready = 0; + }; + + create_thread(video_thread, ctx, 1024*1024); + + delay(50); + return 1; +}; + +int decode_video(AVCodecContext *ctx, queue_t *qv) +{ + AVPacket pkt; + double pts; + int frameFinished; + double current_clock; + + if(frames[dfx].ready != 0 ) + return -1; + + if( get_packet(qv, &pkt) == 0 ) + return 0; + +/* + current_clock = -90.0 + get_master_clock(); + + if( pkt.dts == AV_NOPTS_VALUE && + Frame->reordered_opaque != AV_NOPTS_VALUE) + pts = Frame->reordered_opaque; + else if(pkt.dts != AV_NOPTS_VALUE) + pts= pkt.dts; + else + pts= 0; + + + pts *= av_q2d(video_time_base)*1000.0; +*/ + if( 1 /*pts > current_clock*/) + { + frameFinished = 0; + + ctx->reordered_opaque = pkt.pts; + + if(avcodec_decode_video2(ctx, Frame, &frameFinished, &pkt) <= 0) + printf("video decoder error\n"); + + if(frameFinished) + { + AVPicture *dst_pic; + + if( pkt.dts == AV_NOPTS_VALUE && + Frame->reordered_opaque != AV_NOPTS_VALUE) + pts = Frame->reordered_opaque; + else if(pkt.dts != AV_NOPTS_VALUE) + pts= pkt.dts; + else + pts= 0; + +// pts = *(int64_t*)av_opt_ptr(avcodec_get_frame_class(), +// Frame, "best_effort_timestamp"); + +// if (pts == AV_NOPTS_VALUE) +// pts = 0; + + pts *= av_q2d(video_time_base); + + dst_pic = &frames[dfx].picture; + + av_image_copy(dst_pic->data, dst_pic->linesize, + (const uint8_t**)Frame->data, + Frame->linesize, ctx->pix_fmt, ctx->width, ctx->height); + + frames[dfx].pts = pts*1000.0; +// printf("pts %f\n", frames[dfx].pts); + + frames[dfx].ready = 1; + + dfx++; + dfx&= 3; + frames_count++; + }; + }; + av_free_packet(&pkt); + + return 1; +} + +extern volatile enum player_state player_state; +extern volatile enum player_state decoder_state; +extern volatile enum player_state sound_state; + +//rect_t win_rect; + +extern int64_t rewind_pos; + +static void player_stop() +{ + window_t *win; + + win = main_render->win; + + rewind_pos = 0; + + 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; + win->panel.prg->current = rewind_pos; + + send_message(&win->panel.ctrl, MSG_PAINT, 0, 0); + player_state = STOP; + decoder_state = PLAY_2_STOP; + sound_state = PLAY_2_STOP; + render_draw_client(main_render); +// printf("stop player\n"); + +}; + +int MainWindowProc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2) +{ + window_t *win = (window_t*)ctrl; + static int spc_down = 0; + static int ent_down = 0; + + switch(msg) + { + case MSG_SIZE: + //printf("MSG_SIZE\n"); + if(main_render) + { + render_adjust_size(main_render, win); + render_draw_client(main_render); + }; + break; + + case MSG_KEY: + switch((short)arg2) + { + case 0x39: + if(spc_down == 0) + { + spc_down = 1; + send_message(win, MSG_LBTNDOWN, 0, 0); + } + break; + + case 0xB9: + spc_down = 0; + break; + + case 0x1C: + if(ent_down == 0) + { + int screensize; + if(win->win_state == NORMAL) + { + win->saved = win->rc; + win->saved_state = win->win_state; + + screensize = GetScreenSize(); + __asm__ __volatile__( + "int $0x40" + ::"a"(67), "b"(0), "c"(0), + "d"((screensize >> 16)-1),"S"((screensize & 0xFFFF)-1) ); + win->win_state = FULLSCREEN; + window_update_layout(win); + } + else if(win->win_state == FULLSCREEN) + { + __asm__ __volatile__( + "int $0x40" + ::"a"(67), "b"(win->saved.l), "c"(win->saved.t), + "d"(win->saved.r-win->saved.l-1),"S"(win->saved.b-win->saved.t-1)); + win->win_state = win->saved_state; + window_update_layout(win); +// if(win->saved_state == MAXIMIZED) + { + blit_caption(&win->caption); + blit_panel(&win->panel); + } + } + ent_down = 1; + }; + break; + + case 0x9C: + ent_down = 0; + break; + }; + + case MSG_DRAW_CLIENT: + if(main_render) + { + render_draw_client(main_render); + }; + break; + + case MSG_LBTNDOWN: + + if(player_state == PAUSE) + { + win->panel.play_btn->img_default = res_pause_btn; + win->panel.play_btn->img_hilite = res_pause_btn; + win->panel.play_btn->img_pressed = res_pause_btn_pressed; + send_message(&win->panel.play_btn->ctrl, MSG_PAINT, 0, 0); + player_state = PLAY; + sound_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; + send_message(&win->panel.play_btn->ctrl, MSG_PAINT, 0, 0); + player_state = PAUSE; + sound_state = PLAY_2_PAUSE; + } + break; + + case MSG_COMMAND: + switch((short)arg1) + { + case ID_PLAY: + if(player_state == PAUSE) + { + win->panel.play_btn->img_default = res_pause_btn; + win->panel.play_btn->img_hilite = res_pause_btn; + win->panel.play_btn->img_pressed = res_pause_btn_pressed; + player_state = PLAY; + sound_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; + sound_state = PLAY_2_PAUSE; + } + else if(player_state == STOP) + { + win->panel.play_btn->img_default = res_pause_btn; + win->panel.play_btn->img_hilite = res_pause_btn; + win->panel.play_btn->img_pressed = res_pause_btn_pressed; + rewind_pos = 0; + send_message(&win->panel.ctrl, MSG_PAINT, 0, 0); + player_state = PLAY; + decoder_state = PREPARE; + } + break; + + case ID_STOP: + player_stop(); + break; + + case ID_PROGRESS: + if(player_state != REWIND) + { + progress_t *prg = (progress_t*)arg2; + + rewind_pos = (prg->max - prg->min)*prg->pos/prg->ctrl.w; + +// printf("progress action pos: %d time: %f\n", prg->pos, (double)rewind_pos); + player_state = REWIND; + decoder_state = REWIND; + sound_state = PLAY_2_STOP; + if(rewind_pos < prg->current) + { + prg->current = rewind_pos; + rewind_pos = -rewind_pos; + } + else + prg->current = rewind_pos; + + win->panel.play_btn->img_default = res_pause_btn; + win->panel.play_btn->img_hilite = res_pause_btn; + win->panel.play_btn->img_pressed = res_pause_btn_pressed; + send_message(&prg->ctrl, MSG_PAINT, 0, 0); + }; + break; + + case ID_VOL_CTRL: + { + slider_t *sld = (slider_t*)arg2; + int peak; + int level; + + peak = sld->min + sld->pos * (sld->max - sld->min)/(96); +// level = (log2(peak+16384)*10000.0)/15 - 10000; + level = peak; + +// printf("level %d\n", level); + set_audio_volume(level, level); + send_message(&sld->ctrl, MSG_PAINT, 0, 0); + win->panel.lvl->vol = level; + } + + default: + break; + } + break; + + default: + def_window_proc(ctrl,msg,arg1,arg2); + }; + return 0; +}; + +#define VERSION_A 1 + +extern queue_t q_video; +extern queue_t q_audio; + +void render_time(render_t *render) +{ + progress_t *prg = main_render->win->panel.prg; + level_t *lvl = main_render->win->panel.lvl; + + double ctime; /* milliseconds */ + double fdelay; /* milliseconds */ + +//again: + + if(player_state == CLOSED) + { + render->win->win_command = WIN_CLOSED; + return; + } + else if((player_state == PAUSE) || (player_state == REWIND)) + { + delay(1); + return; + } + else if (decoder_state == STOP && frames_count == 0 && + player_state != STOP) + { + player_stop(); + } + else if(player_state != PLAY) + { + delay(1); + return; + }; + + +#ifdef VERSION_A + if(frames[vfx].ready == 1 ) + { + int sys_time; + + ctime = get_master_clock(); + fdelay = (frames[vfx].pts - ctime); + +// printf("pts %f time %f delay %f\n", +// frames[vfx].pts, ctime, fdelay); + + if(fdelay > 15.0) + { + delay((int)fdelay/10); + // return; + }; +#if 0 + ctime = get_master_clock(); + fdelay = (frames[vfx].pts - ctime); + +// while(fdelay > 0) +// { +// yield(); +// 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); + + printf("pts %f time %f delay %f\n", + frames[vfx].pts, ctime, fdelay); + printf("video cache %d audio cache %d\n", q_video.size/1024, q_audio.size/1024); +#endif + + main_render->draw(main_render, &frames[vfx].picture); + if(main_render->win->win_state != FULLSCREEN) + { + prg->current = frames[vfx].pts*1000; +// printf("current %f\n", prg->current); + lvl->current = vfx & 1 ? sound_level_1 : sound_level_0; + + send_message(&prg->ctrl, PRG_PROGRESS, 0, 0); + + if(main_render->win->panel.layout) + send_message(&lvl->ctrl, MSG_PAINT, 0, 0); + } + + frames_count--; + frames[vfx].ready = 0; + vfx++; + vfx&= 3; + } + else delay(1); + +#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 + +} + + +extern char *movie_file; + +int video_thread(void *param) +{ + AVCodecContext *ctx = param; + window_t *MainWindow; + + init_winlib(); + + MainWindow = create_window(movie_file,0, + 10,10,width,height+CAPTION_HEIGHT+PANEL_HEIGHT,MainWindowProc); + + MainWindow->panel.prg->max = stream_duration; +// printf("MainWindow %x\n", MainWindow); + + show_window(MainWindow, NORMAL); + +// __asm__ __volatile__("int3"); + + main_render = create_render(MainWindow, ctx, HW_TEX_BLIT|HW_BIT_BLIT); + if( main_render == NULL) + { + printf("Cannot create render\n\r"); + return 0; + }; + + render_draw_client(main_render); + player_state = PLAY; + + run_render(MainWindow, main_render); + + destroy_render(main_render); + fini_winlib(); + + player_state = CLOSED; + return 0; +}; + + +void draw_hw_picture(render_t *render, AVPicture *picture); +void draw_sw_picture(render_t *render, AVPicture *picture); + +render_t *create_render(window_t *win, AVCodecContext *ctx, uint32_t flags) +{ + render_t *render; + + uint32_t right, bottom, draw_w, draw_h; + uint32_t s, sw, sh; + uint8_t state; + +// __asm__ __volatile__("int3"); + + render = (render_t*)malloc(sizeof(render_t)); + memset(render, 0, sizeof(render_t)); + + render->win = win; + + render->ctx_width = ctx->width; + render->ctx_height = ctx->height; + render->ctx_format = ctx->pix_fmt; + + mutex_lock(&driver_lock); + render->caps = init_pixlib(flags); + mutex_unlock(&driver_lock); + + right = win->w; + bottom = win->h-CAPTION_HEIGHT-PANEL_HEIGHT; + + // printf("window width %d height %d\n", + // right, bottom); + + render->win_state = win->win_state; + + draw_w = bottom*render->ctx_width/render->ctx_height; + draw_h = right*render->ctx_height/render->ctx_width; + + if(draw_w > right) + { + draw_w = right; + draw_h = right*render->ctx_height/render->ctx_width; + }; + + if(draw_h > bottom) + { + draw_h = bottom; + draw_w = bottom*render->ctx_width/render->ctx_height; + }; + + render->win_width = win->w; + render->win_height = win->h-CAPTION_HEIGHT-PANEL_HEIGHT; + + render_set_size(render, draw_w, draw_h); + + + if(render->caps==0) + { + render->bitmap[0].width = draw_w; + render->bitmap[0].height = draw_h; + + if( create_bitmap(&render->bitmap[0]) != 0 ) + { + free(render); + return NULL; + } + render->draw = draw_sw_picture; + } + else + { + int width, height, flags; + int i; + + if(render->caps & HW_TEX_BLIT) + { + sna_create_mask(); + + width = render->ctx_width; + height = render->ctx_height; + flags = HW_TEX_BLIT; + } + else + { + width = draw_w; + height = draw_h;; + flags = HW_BIT_BLIT; + } + + for( i=0; i < 2; i++) + { + render->bitmap[i].width = width; + render->bitmap[i].height = height; + render->bitmap[i].flags = flags; + + if( create_bitmap(&render->bitmap[i]) != 0 ) + { + player_state = CLOSED; + free(render); + return NULL; + }; + } + + render->state = INIT; + render->target = 0; + render->draw = draw_hw_picture; + }; + + + printf("FPlay %s render engine: context %dx%d picture %dx%d\n", + render->caps & HW_TEX_BLIT ? "hw_tex_blit": + render->caps & HW_BIT_BLIT ? "hw_bit_blit":"software", + render->ctx_width, render->ctx_height, + draw_w, draw_h); + +// if(init_hw_context(ctx) == 0) +// printf("create hardware decoder context\n"); + + return render; +}; + +void destroy_render(render_t *render) +{ + + destroy_bitmap(&render->bitmap[0]); + + if(render->caps & (HW_BIT_BLIT|HW_TEX_BLIT)) /* hw blitter */ + destroy_bitmap(&render->bitmap[1]); + + done_pixlib(); +}; + +void render_set_size(render_t *render, int width, int height) +{ + int i; + + render->layout = 0; + render->rcvideo.l = 0; + render->rcvideo.t = 0; + render->rcvideo.r = width; + render->rcvideo.b = height; + +// printf("render width %d height %d\n",width, height); + + if( render->win_height > height ) + { + int yoffs; + yoffs = (render->win_height-height)/2; + if(yoffs) + { + render->rctop.t = 0; + render->rctop.b = yoffs; + render->rcvideo.t = yoffs; + render->layout |= HAS_TOP; + } + + yoffs = render->win_height-(render->rcvideo.t+render->rcvideo.b); + if(yoffs) + { + render->rcbottom.t = render->rcvideo.t+render->rcvideo.b; + render->rcbottom.b = yoffs; + render->layout |= HAS_BOTTOM; + } + } + + if( render->win_width > width ) + { + int xoffs; + xoffs = (render->win_width-width)/2; + if(xoffs) + { + render->rcleft.r = xoffs; + render->rcvideo.l = xoffs; + render->layout |= HAS_LEFT; + } + xoffs = render->win_width-(render->rcvideo.l+render->rcvideo.r); + if(xoffs) + { + render->rcright.l = render->rcvideo.l+render->rcvideo.r; + render->rcright.r = xoffs; + render->layout |= HAS_RIGHT; + } + }; +}; + +void render_adjust_size(render_t *render, window_t *win) +{ + uint32_t right, bottom, new_w, new_h; + uint32_t s, sw, sh; + uint8_t state; + + right = win->w; + bottom = win->h; + + if(win->win_state != FULLSCREEN) + bottom-= CAPTION_HEIGHT+PANEL_HEIGHT; + + // printf("window width %d height %d\n", + // right, bottom); + + render->win_state = win->win_state; + + if(render->win_state == MINIMIZED) + return; + + if(render->win_state == ROLLED) + return; + + if( right == render->win_width && + bottom == render->win_height) + return; + +// printf("%s r: %d b: %d\n", __FUNCTION__, right, bottom); + + new_w = bottom*render->ctx_width/render->ctx_height; + new_h = right*render->ctx_height/render->ctx_width; + + if(new_w > right) + { + new_w = right; + new_h = right*render->ctx_height/render->ctx_width; + }; + if(new_h > bottom) + { + new_h = bottom; + new_w = bottom*render->ctx_width/render->ctx_height; + }; + + render->win_width = right; + render->win_height = bottom; + render_set_size(render, new_w, new_h); + + if(render->caps & HW_TEX_BLIT) /* hw scaler */ + return; + + render->bitmap[0].width = new_w; + render->bitmap[0].height = new_h; + resize_bitmap(&render->bitmap[0]); + + if(render->caps & HW_BIT_BLIT) /* hw blitter */ + { + render->bitmap[1].width = new_w; + render->bitmap[1].height = new_h; + resize_bitmap(&render->bitmap[1]); + }; + return; +}; + +void draw_hw_picture(render_t *render, AVPicture *picture) +{ + int dst_width, dst_height; + bitmap_t *bitmap; + uint8_t *data[4]; + int linesize[4]; + int ret; + + if(render->win->win_state == MINIMIZED || + render->win->win_state == ROLLED) + return; + + if(render->caps & HW_TEX_BLIT) + { + dst_width = render->ctx_width; + dst_height = render->ctx_height; + } + else + { + dst_width = render->rcvideo.r; + dst_height = render->rcvideo.b; + }; + + cvt_ctx = sws_getCachedContext(cvt_ctx, + render->ctx_width, render->ctx_height, render->ctx_format, + dst_width, dst_height, PIX_FMT_BGRA, + SWS_FAST_BILINEAR, NULL, NULL, NULL); + if(cvt_ctx == NULL) + { + printf("Cannot initialize the conversion context!\n"); + return ; + }; + + bitmap = &render->bitmap[render->target]; + + ret = lock_bitmap(bitmap); + if( ret != 0) + { + printf("Cannot lock bitmap!\n"); + return ; + } + +// printf("sws_getCachedContext\n"); + data[0] = bitmap->data; + data[1] = bitmap->data+1; + data[2] = bitmap->data+2; + data[3] = bitmap->data+3; + + linesize[0] = bitmap->pitch; + linesize[1] = bitmap->pitch; + linesize[2] = bitmap->pitch; + linesize[3] = bitmap->pitch; + + sws_scale(cvt_ctx, (const uint8_t* const *)picture->data, + picture->linesize, 0, render->ctx_height, data, linesize); +// printf("sws_scale\n"); + + + if(render->caps & HW_TEX_BLIT) + { + + if(render->win->win_state == FULLSCREEN) + fplay_blit_bitmap(bitmap,render->rcvideo.l,render->rcvideo.t, + render->rcvideo.r, render->rcvideo.b); + else + fplay_blit_bitmap(bitmap, render->rcvideo.l, + CAPTION_HEIGHT+render->rcvideo.t, + render->rcvideo.r, render->rcvideo.b); + } + else + { + if(render->win->win_state == FULLSCREEN) + blit_bitmap(bitmap,render->rcvideo.l,render->rcvideo.t, + render->rcvideo.r, render->rcvideo.b, 0,0); + else + blit_bitmap(bitmap, render->rcvideo.l, + CAPTION_HEIGHT+render->rcvideo.t, + render->rcvideo.r, render->rcvideo.b, 0, 0); + }; + + render->last_bitmap = bitmap; + render->target++; + render->target&= 1; +} + +void draw_sw_picture(render_t *render, AVPicture *picture) +{ + uint8_t *data[4]; + int linesize[4]; + + if(render->win->win_state == MINIMIZED || + render->win->win_state == ROLLED) + return; + + cvt_ctx = sws_getCachedContext(cvt_ctx, + render->ctx_width, render->ctx_height, + render->ctx_format, + render->rcvideo.r, render->rcvideo.b, + PIX_FMT_BGRA, SWS_FAST_BILINEAR, NULL, NULL, NULL); + if(cvt_ctx == NULL) + { + printf("Cannot initialize the conversion context!\n"); + return ; + } + + lock_bitmap(&render->bitmap[0]); + + data[0] = render->bitmap[0].data; + data[1] = render->bitmap[0].data+1; + data[2] = render->bitmap[0].data+2; + data[3] = render->bitmap[0].data+3; + + linesize[0] = render->bitmap[0].pitch; + linesize[1] = render->bitmap[0].pitch; + linesize[2] = render->bitmap[0].pitch; + linesize[3] = render->bitmap[0].pitch; + + sws_scale(cvt_ctx, (const uint8_t* const *)picture->data, + picture->linesize, 0, render->ctx_height, data, linesize); + + if(render->win->win_state == FULLSCREEN) + fplay_blit_bitmap(&render->bitmap[0],render->rcvideo.l,render->rcvideo.t, + render->rcvideo.r, render->rcvideo.b); + else + fplay_blit_bitmap(&render->bitmap[0], render->rcvideo.l, + CAPTION_HEIGHT+render->rcvideo.t, + render->rcvideo.r, render->rcvideo.b); + + render->last_bitmap = &render->bitmap[0]; +} + +void render_draw_client(render_t *render) +{ + int y; + + if(render->win_state == MINIMIZED || + render->win_state == ROLLED ) + return; + if(render->win_state == FULLSCREEN) + y = 0; + else + y = CAPTION_HEIGHT; + + if(player_state == PAUSE) + { + if(frames[vfx].ready == 1 ) + main_render->draw(main_render, &frames[vfx].picture); + else + draw_bar(0, y, render->win_width, + render->rcvideo.b, 0); + } + else if( player_state == STOP ) + { + draw_bar(0,y, render->win_width, + render->rcvideo.b, 0); + }; + + if(render->layout & HAS_TOP) + draw_bar(0, y, render->win_width, + render->rctop.b, 0); + if(render->layout & HAS_LEFT) + draw_bar(0, render->rcvideo.t+y, render->rcleft.r, + render->rcvideo.b, 0); + if(render->layout & HAS_RIGHT) + draw_bar(render->rcright.l, render->rcvideo.t+y, + render->rcright.r, render->rcvideo.b, 0); + if(render->layout & HAS_BOTTOM) + draw_bar(0, render->rcbottom.t+y, + render->win_width, render->rcbottom.b, 0); +} + + + + + diff --git a/contrib/media/fplay/winlib/button.c b/contrib/media/fplay/winlib/button.c new file mode 100644 index 0000000000..bed33db805 --- /dev/null +++ b/contrib/media/fplay/winlib/button.c @@ -0,0 +1,574 @@ + +#include +#include +#include +#include +#include "winlib.h" + +extern int res_level[]; +extern int res_slider[]; +extern int res_vol_slider[]; +extern int res_progress_bar[]; +extern int res_prg_level[]; + +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); + +ctrl_t *create_control(size_t size, int id, int x, int y, + int w, int h, ctrl_t *parent) +{ + + ctrl_t *ctrl; + + if( !parent ) + return NULL; + + ctrl = (ctrl_t*)malloc(size); + + link_initialize(&ctrl->link); + list_initialize(&ctrl->child); + + ctrl->parent = parent; + + ctrl->ctx = parent->ctx; + ctrl->id = id; + + ctrl->rc.l = x; + ctrl->rc.t = y ; + + ctrl->rc.r = x + w; + ctrl->rc.b = y + h; + + ctrl->w = w; + ctrl->h = h; + + list_append(&ctrl->link, &parent->child); + + return ctrl; +}; + + +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*)create_control(sizeof(button_t), id, x, y, w, h, parent); + btn->ctrl.handler = button_proc; + 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; + + 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 *src; + ctx_t *ctx; + int x, y; + + ctx = btn->ctrl.ctx; + + lock_bitmap(ctx->pixmap); + + x = btn->ctrl.rc.l - ctx->offset_x; + y = btn->ctrl.rc.t - ctx->offset_y; + + src = btn->img_default; + + if(btn->state & bPressed) + src = btn->img_pressed; + else if(btn->state & bHighlight) + src = btn->img_hilite; + + blit_raw(ctx, src, x, y, btn->ctrl.w, btn->ctrl.h, btn->ctrl.w*4); + + 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->ctrl, MSG_PAINT, 0, 0); + break; + + case MSG_MOUSELEAVE: +// printf("mouse leave\n"); + if( (ctrl_t*)btn != mouse_capture) { + btn->state &= ~bHighlight; + send_message(&btn->ctrl, 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->ctrl, 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->ctrl.rc, x, y) ) + state = bHighlight; + else + state = 0; + + if(action) + send_message(btn->ctrl.parent,MSG_COMMAND,btn->ctrl.id,(int)btn); + + btn->state = state; + send_message(&btn->ctrl, 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->ctrl, 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->ctrl.rc, x, y) ) + btn->state |= bPressed; + else + btn->state &= ~bPressed; + + if( old_state ^ btn->state) + send_message(&btn->ctrl, MSG_PAINT, 0, 0); + } + return 0; +}; + + +int draw_progress(progress_t *prg, int background) +{ + int *pixmap, *src; + ctx_t *ctx; + int i, j; + int x, y; + rect_t rc = prg->ctrl.rc; + + int len = prg->ctrl.w; + + ctx = prg->ctrl.ctx; + + lock_bitmap(ctx->pixmap); + + x = prg->ctrl.rc.l - ctx->offset_x; + y = prg->ctrl.rc.t - ctx->offset_y; + + if( background ) + { + src = res_progress_bar; + + pixmap = (int*)ctx->pixmap->data; + pixmap+= y * ctx->pixmap->pitch/4 + x; + + for(i=0; i < 10; i++) + { + for(j = 0; j < len; j++) + pixmap[j] = *src; + + pixmap+= ctx->pixmap->pitch/4; + src++; + }; + }; + + + len = prg->current*prg->ctrl.w/(prg->max - prg->min); + + src = res_prg_level; + + pixmap = (int*)ctx->pixmap->data; + pixmap+= y*ctx->pixmap->pitch/4 + x; + + for(i=0; i < prg->ctrl.h ;i++) + { + for(j=0; j < len; j++) + pixmap[j] = *src; + pixmap+= ctx->pixmap->pitch/4; + src++; + }; + + 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, 1); + 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; + + case PRG_PROGRESS: + draw_progress(prg, 0); + update_rect(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*)create_control(sizeof(progress_t), id, x, y, w, h, parent); + + prg->ctrl.handler = prg_proc; + + prg->min = 0; + prg->max = 1; + prg->current = 0; + prg->pos = 0; + + return prg; +}; + +int draw_level(level_t *lvl) +{ + int *pixmap; + ctx_t *ctx; + int i, j; + int x, y; + + int len; + double level; + + ctx = lvl->ctrl.ctx; + + lock_bitmap(ctx->pixmap); + + x = lvl->ctrl.rc.l - ctx->offset_x; + y = lvl->ctrl.rc.t - ctx->offset_y; + + level = (log2(lvl->current+1)-7)*12 + lvl->vol/50 ; + + len = level; + + if(len < 0) + len = 0; + if(len > 96) + len = 96; + + pixmap = (int*)ctx->pixmap->data; + + pixmap+= y*ctx->pixmap->pitch/4 + x; + + for(i=0; i < 10; i++) + { + for(j = 0; j < 96; j++) + pixmap[j] = 0xFF1C1C1C; + pixmap+= ctx->pixmap->pitch/4; + }; + + blit_raw(ctx, lvl->img_level, x, y, len, 10, 96*4); + + return 0; +}; + + +int lvl_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2) +{ + level_t *lvl = (level_t*)ctrl; +// int pos; + + switch( msg ) + { + case MSG_PAINT: + if(lvl->visible) + { + draw_level(lvl); + 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; +}; + +level_t *create_level(char *caption, int id, int x, int y, + int w, int h, ctrl_t *parent) +{ + level_t *lvl; + + if( !parent ) + return NULL; + + lvl = (level_t*)create_control(sizeof(level_t), id, x, y, w, h, parent); + lvl->ctrl.handler = lvl_proc; + + lvl->min = 0; + lvl->max = 1; + lvl->current = 0; + lvl->pos = 0; + lvl->visible = 0; + lvl->img_level = res_level; + + return lvl; +}; + + +int draw_slider(slider_t *sld) +{ + int *pixmap; + ctx_t *ctx; + int i, j; + int x, y; + + int32_t len; + double level; + + ctx = sld->ctrl.ctx; + + lock_bitmap(ctx->pixmap); + + x = sld->ctrl.rc.l - ctx->offset_x; + y = sld->ctrl.rc.t - ctx->offset_y; + + len = 96 + 12; + + pixmap = (int*)ctx->pixmap->data; + pixmap+= y*ctx->pixmap->pitch/4 + x; + + for(i=0; i < 11; i++) + { + for(j = 0; j < len; j++) + pixmap[j] = 0xFF1C1C1C; + pixmap+= ctx->pixmap->pitch/4; + }; + + blit_raw(ctx, sld->img_vol_slider, x+6, y+4, 96, 4, 96*4); + + blit_raw(ctx, res_slider, x+sld->pos, y, 12, 11, 12*4); + + return 0; +}; + + +int sld_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2) +{ + slider_t *sld = (slider_t*)ctrl; + int pos; + + switch( msg ) + { + case MSG_PAINT: + draw_slider(sld); + update_rect(ctrl); + break; + + case MSG_LBTNDOWN: + capture_mouse(ctrl); + sld->mode = 1; + + pos = ((pos_t)arg2).x - ctrl->rc.l - 6; + if( pos < 0 ) + pos = 0; + else if(pos > 96) + pos = 96; + if( sld->pos != pos) + { + sld->pos = pos; + send_message(ctrl->parent,MSG_COMMAND,ctrl->id,(int)ctrl); + }; + break; + + case MSG_LBTNUP: + if(sld->mode) + { + release_mouse(); + sld->mode = 0; + }; + break; + + case MSG_MOUSEMOVE: + if(sld->mode) + { + pos = ((pos_t)arg2).x - ctrl->rc.l - 6; + if( pos < 0 ) + pos = 0; + else if(pos > 96) + pos = 96; + if( sld->pos != pos) + { + sld->pos = pos; +// printf("slider pos %d\n", sld->pos); + send_message(ctrl->parent,MSG_COMMAND,ctrl->id,(int)ctrl); + } + }; + break; + + case MSG_MOUSEENTER: + panel_set_layout(ctrl->parent, 1); +// printf("level on\n"); + break; + + case MSG_MOUSELEAVE: + panel_set_layout(ctrl->parent, 0); +// printf("level off\n"); + break; + + + default: + break; + } + return 0; +}; + + +slider_t *create_slider(char *caption, int id, int x, int y, + int w, int h, ctrl_t *parent) +{ + + slider_t *sld; + + if( !parent ) + return NULL; + + sld = (slider_t*)create_control(sizeof(slider_t), id, x, y, w, h, parent); + sld->ctrl.handler = sld_proc; + + sld->min = -5000; + sld->max = 0; + sld->current = 0; + sld->pos = 60; + sld->mode = 0; + sld->img_vol_slider = res_vol_slider; + + return sld; +}; + diff --git a/contrib/media/fplay/winlib/caption.c b/contrib/media/fplay/winlib/caption.c new file mode 100644 index 0000000000..52c9017919 --- /dev/null +++ b/contrib/media/fplay/winlib/caption.c @@ -0,0 +1,272 @@ + +#include +#include +#include +#include "winlib.h" + +#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[]; + +extern int res_full_btn[]; +extern int res_full_btn_hl[]; +extern int res_full_btn_pressed[]; + +extern uint32_t main_cursor; + +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; + + cpt->text = win->caption_txt; + + cpt->bitmap.width = 1920; + cpt->bitmap.height = CAPTION_HEIGHT; + cpt->bitmap.flags = 0; + + if( create_bitmap(&cpt->bitmap) ) + { + printf("not enough memory for caption bitmap\n"); + return 0; + } + + +// printf("win_w %d win_h %d\n", win->w, win->h); + ctx->pixmap = &cpt->bitmap; + ctx->offset_x = 0; + ctx->offset_y = 0; + + cpt->ctrl.ctx = ctx; + + btn = create_button(NULL, ID_CLOSE,0,5,18,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,18,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; + + btn = create_button(NULL, ID_FULLSCREEN,0,5,18,18,(ctrl_t*)cpt); + cpt->full_btn = btn; + + btn->img_default = res_full_btn; + btn->img_hilite = res_full_btn_hl; + btn->img_pressed = res_full_btn_pressed; + + update_caption_size(win); + + return 1; +}; + + +void update_caption_size(window_t *win) +{ + caption_t *cpt = &win->caption; + bitmap_t *bitmap = &cpt->bitmap; + + bitmap->width = win->w; + resize_bitmap(bitmap); + + 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->ctrl.rc.l = win->w - 27; + cpt->close_btn->ctrl.rc.r = cpt->close_btn->ctrl.rc.l + + cpt->close_btn->ctrl.w; + + cpt->minimize_btn->ctrl.rc.l = win->w - 27 - 18 - 5; + cpt->minimize_btn->ctrl.rc.r = cpt->minimize_btn->ctrl.rc.l + + cpt->minimize_btn->ctrl.w; + + cpt->full_btn->ctrl.rc.l = win->w - 27 - 18 -18 - 5 - 5; + cpt->full_btn->ctrl.rc.r = cpt->full_btn->ctrl.rc.l + + cpt->full_btn->ctrl.w; + +}; + + +extern int win_font; + +void draw_caption(caption_t *cpt) +{ + int *pixmap, *src; + rect_t rc; + int i, j, w; + + lock_bitmap(&cpt->bitmap); + + blit_raw(&cpt->ctx, res_caption_left, 0, 0, + CAPTION_CORNER_W, CAPTION_HEIGHT, CAPTION_CORNER_W*4); + + w = cpt->ctrl.w - (2*CAPTION_CORNER_W); + if( w > 0) + { + pixmap = (int*)cpt->ctx.pixmap->data; + 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.pixmap->pitch/4; + } + +// blit_raw(&cpt->ctx,res_caption_body, CAPTION_CORNER_W, 0, +// w, CAPTION_HEIGHT, 0); + + }; + + + blit_raw(&cpt->ctx,res_caption_right, cpt->ctrl.w - CAPTION_CORNER_W, 0, + CAPTION_CORNER_W, CAPTION_HEIGHT,CAPTION_CORNER_W*4); + + rc.l = 8; + rc.t = 0; + rc.r = cpt->ctrl.w - 27 - 18 - 18 - 5 - 5 - 8; + rc.b = 18; + + draw_text_ext(cpt->ctx.pixmap, win_font, cpt->text, &rc, 0xFFFFFFFF); + + 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); + }; + + win->child_over = child; + if( child ) + { + send_message(child, MSG_MOUSEENTER, 0, arg2); + 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->win_command = WIN_CLOSED; + break; + + case ID_MINIMIZE: + __asm__ __volatile__( + "int $0x40" + ::"a"(18),"b"(10)); + win->win_state = MINIMIZED; + send_message((ctrl_t*)win, MSG_SIZE, 0, 0); + break; + case ID_FULLSCREEN: + { + int screensize; + + win->saved = win->rc; + win->saved_state = win->win_state; + screensize = GetScreenSize(); + __asm__ __volatile__( + "int $0x40" + ::"a"(67), "b"(0), "c"(0), + "d"((screensize >> 16)-1),"S"((screensize & 0xFFFF)-1) ); + win->win_state = FULLSCREEN; + window_update_layout(win); + }; + 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); + + lock_bitmap(&cpt->bitmap); + + Blit(cpt->ctx.pixmap->data, 0, 0, 0, 0, cpt->ctrl.w, cpt->ctrl.h, + cpt->ctrl.w, cpt->ctrl.h, cpt->ctx.pixmap->pitch); +}; + diff --git a/contrib/media/fplay/winlib/control.h b/contrib/media/fplay/winlib/control.h new file mode 100644 index 0000000000..162f58257a --- /dev/null +++ b/contrib/media/fplay/winlib/control.h @@ -0,0 +1,212 @@ +#ifndef __CONTROL_H__ +#define __CONTROL_H_ + +#include +#include "link.h" + +typedef struct +{ + int l; + int t; + int r; + int b; +}rect_t; + +typedef struct ctx +{ + bitmap_t *pixmap; + 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 +{ + ctrl_t ctrl; + + 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 +{ + ctrl_t ctrl; + int min; + int max; + int current; + int pos; + int vol; + int visible; + void *img_level; +}level_t; + +typedef struct +{ + ctrl_t ctrl; + int min; + int max; + int current; + int pos; + int mode; + void *img_slider; + void *img_vol_slider; +}slider_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_KEY 0x002 +#define MSG_BUTTON 0x003 +#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 PRG_PROGRESS 0x102 + +#define ID_CLOSE 1 +#define ID_MINIMIZE 2 +#define ID_FULLSCREEN 3 + +#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); + +void blit_raw(ctx_t *ctx, void *raw, int x, int y, int w, int h, int pitch); + +#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) +#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) + + +#endif diff --git a/contrib/media/fplay/winlib/fontlib.c b/contrib/media/fplay/winlib/fontlib.c new file mode 100644 index 0000000000..8f65dfca75 --- /dev/null +++ b/contrib/media/fplay/winlib/fontlib.c @@ -0,0 +1,184 @@ + +#include +#include +#include +#include +#include +//#include "font_droid.h" +#include +#include FT_FREETYPE_H +#include + +extern char res_def_font[]; + +typedef struct +{ + int l; + int t; + int r; + int b; +}rect_t; + +typedef unsigned int color_t; + +unsigned int ansi2utf32(unsigned char ch); + +void my_draw_bitmap(bitmap_t *win, FT_Bitmap *bitmap, int dstx, int dsty, int col) +{ + uint8_t *dst; + uint8_t *src, *tmpsrc; + + uint32_t *tmpdst; + int i, j; + + dst = win->data + dsty * win->pitch + dstx*4; + src = bitmap->buffer; + + for( i = 0; i < bitmap->rows; i++ ) + { + tmpdst = (uint32_t*)dst; + tmpsrc = src; + + dst+= win->pitch; + src+= bitmap->pitch; + + for( j = 0; j < bitmap->width; j++) + { + int a = *tmpsrc++; + int sr, sg, sb; + int dr, dg, db; + + if( a != 0) a++; + + db = *tmpdst & 0xFF; + dg = (*tmpdst >> 8) & 0xFF; + dr = (*tmpdst >> 16) &0xFF; + + sb = col & 0xFF; + sg = (col >> 8) & 0xFF; + sr = (col >> 16) &0xFF; + + db = (a*sb + db*(256-a))/256; + dg = (a*sg + dg*(256-a))/256; + dr = (a*sr + dr*(256-a))/256; + + *tmpdst++ = 0xFF000000|(dr<<16)|(dg<<8)|db; + }; + } +}; + + +int draw_text_ext(bitmap_t *winbitmap, FT_Face face, char *text, rect_t *rc, int color) +{ + FT_UInt glyph_index; + FT_Bool use_kerning = 0; + FT_UInt previous; + int x, y, w; + char ch; + int err = 0; + + use_kerning = FT_HAS_KERNING( face ); + previous = 0; + + x = rc->l << 6; + y = rc->b; + + w = (rc->r - rc->l) << 6; + + while( ch = *text++ ) + { + glyph_index = FT_Get_Char_Index( face, ansi2utf32(ch) ); + + if ( use_kerning && previous && glyph_index ) + { + FT_Vector delta; + FT_Get_Kerning( face, previous, glyph_index, FT_KERNING_DEFAULT, &delta ); + x += delta.x ; + } + + if( x + face->glyph->advance.x > w) + break; + + err = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); + if ( err ) + continue; + + err = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL ); + if ( err ) + continue; + + my_draw_bitmap(winbitmap, &face->glyph->bitmap, (x >> 6) + face->glyph->bitmap_left, + y - face->glyph->bitmap_top, color); + + x += face->glyph->advance.x; + previous = glyph_index; + }; + + return err; +}; + + +int init_fontlib() +{ + int err; + + static FT_Library library; + FT_Face face = NULL; + + err = FT_Init_FreeType( &library ); + if ( err ) + { + printf("an error occurred during FreeType initialization\n"); + goto done; + } + +// err = FT_New_Face( library, "/hd0/1/IstokWeb.ttf", 0, &face ); + + err = FT_New_Memory_Face( library, res_def_font, 277996, 0, &face ); + printf("err %d\n", err); + if ( err == FT_Err_Unknown_File_Format ) + { + printf("font format is unsupported\n"); + goto done; + + } + else if ( err ) + { + printf("font file could not be read or broken\n"); + goto done; + + } + + err = FT_Set_Char_Size( face, 0, 11*64, 96, 96 ); +// err = FT_Set_Pixel_Sizes( face, 0, 100 ); + +done: + + return (int)face; +}; + +// draw_text(face,"/hd0/1/demo", 10, 80, 0x00000000); + + +unsigned int ansi2utf32(unsigned char ch) +{ + if(ch < 0x80) + return ch; + + if(ch < 0xB0) + return 0x410-0x80 + ch; + + if(ch < 0xE0) + return 0; + + if(ch < 0xF0) + return 0x440-0xE0 + ch; + + if(ch == 0xF0) + return 0x401; + else if(ch==0xF1) + return 0x451; + else return 0; +} + + diff --git a/contrib/media/fplay/winlib/frame.c b/contrib/media/fplay/winlib/frame.c new file mode 100644 index 0000000000..eec8b4b7de --- /dev/null +++ b/contrib/media/fplay/winlib/frame.c @@ -0,0 +1,289 @@ + +#include +#include +#include +#include "winlib.h" + +#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 = (int*)win->ctx->pixmap->data; + 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->pixmap->pitch/4; + }; + + + pixmap = (int*)win->ctx->pixmap->data; + 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->pixmap->pitch/4; + }; + + pixmap = (int*)win->ctx->pixmap->data; + + 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->pixmap->pitch/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; + + if(win->win_state == FULLSCREEN) + return 0; + + 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 <310) + w = 310; + 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; +} + diff --git a/contrib/media/fplay/winlib/panel.c b/contrib/media/fplay/winlib/panel.c new file mode 100644 index 0000000000..fc0e51ebce --- /dev/null +++ b/contrib/media/fplay/winlib/panel.c @@ -0,0 +1,314 @@ +#include +#include +#include +#include "winlib.h" + +#define PANEL_CORNER_W 8 +#define FRAME_WIDTH 7 + +#define ID_PLAY 100 +#define ID_STOP 101 +#define ID_PROGRESS 102 +#define ID_VOL_LEVEL 103 +#define ID_VOL_CTRL 104 + +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_stop_btn[]; +extern int res_stop_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; + level_t *lvl; + slider_t *sld; + + 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; + + panel->layout = 0; + + panel->bitmap.width = 1920; + panel->bitmap.height = PANEL_HEIGHT; + panel->bitmap.flags = 0; + + if( create_bitmap(&panel->bitmap) ) + { + printf("not enough memory for panel bitmap\n"); + return 0; + } + + ctx->pixmap = &panel->bitmap; + ctx->offset_x = 0; + ctx->offset_y = 0; + + 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; + + btn = create_button(NULL, ID_STOP,0,19,24,24,&panel->ctrl); + panel->stop_btn = btn; + + btn->img_default = res_stop_btn; + btn->img_hilite = res_stop_btn; + btn->img_pressed = res_stop_btn_pressed; + + prg = create_progress(NULL,ID_PROGRESS,0,4,0,10,&panel->ctrl); + panel->prg = prg; + + lvl = create_level(NULL, ID_VOL_LEVEL, 0, 20, 96, 10, &panel->ctrl); + lvl->vol = -1875; + panel->lvl = lvl; + + sld = create_slider(NULL, ID_VOL_CTRL, 0, 20, 96+12, 12, &panel->ctrl); + panel->sld = sld; + +// 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; +}; + + +static void panel_update_layout(panel_t *panel) +{ + progress_t *prg = panel->prg; + level_t *lvl = panel->lvl; + + if(panel->layout == 0) + { + prg->ctrl.rc.l = panel->ctrl.rc.l; + prg->ctrl.rc.t = panel->ctrl.rc.t+7; + prg->ctrl.rc.r = panel->ctrl.rc.r; + prg->ctrl.rc.b = prg->ctrl.rc.t + prg->ctrl.h; + prg->ctrl.w = prg->ctrl.rc.r - prg->ctrl.rc.l; + + lvl->ctrl.rc.l = panel->ctrl.rc.l; + lvl->ctrl.rc.t = panel->ctrl.rc.t+7; + lvl->ctrl.rc.r = panel->lvl->ctrl.rc.l + panel->lvl->ctrl.w; + lvl->ctrl.rc.b = panel->lvl->ctrl.rc.t + panel->lvl->ctrl.h; + } + else + { + lvl->ctrl.rc.l = panel->ctrl.rc.l; + lvl->ctrl.rc.t = panel->ctrl.rc.t+7; + lvl->ctrl.rc.r = lvl->ctrl.rc.l + lvl->ctrl.w; + lvl->ctrl.rc.b = lvl->ctrl.rc.t + lvl->ctrl.h; + + prg->ctrl.rc.l = lvl->ctrl.rc.r; + prg->ctrl.rc.t = panel->ctrl.rc.t+7; + prg->ctrl.rc.r = panel->ctrl.rc.r; + prg->ctrl.rc.b = prg->ctrl.rc.t + prg->ctrl.h; + prg->ctrl.w = prg->ctrl.rc.r - prg->ctrl.rc.l; + }; +}; + +void panel_set_layout(panel_t *panel, int layout) +{ + panel->layout = layout; + panel->lvl->visible = layout; + + panel_update_layout(panel); + + send_message(&panel->prg->ctrl, MSG_PAINT, 0, 0); + + if(layout) + send_message(&panel->lvl->ctrl, MSG_PAINT, 0, 0); +}; + +void update_panel_size(window_t *win) +{ + panel_t *panel = &win->panel; + bitmap_t *bitmap = &panel->bitmap; + + bitmap->width = win->w; + resize_bitmap(bitmap); + + 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->ctrl.rc.l = win->w/2 - 16; + panel->play_btn->ctrl.rc.t = panel->ctrl.rc.t+19; + panel->play_btn->ctrl.rc.r = panel->play_btn->ctrl.rc.l + panel->play_btn->ctrl.w; + panel->play_btn->ctrl.rc.b = panel->play_btn->ctrl.rc.t + panel->play_btn->ctrl.h; + + panel->stop_btn->ctrl.rc.l = win->w/2 - 44; + panel->stop_btn->ctrl.rc.t = panel->ctrl.rc.t+23; + panel->stop_btn->ctrl.rc.r = panel->stop_btn->ctrl.rc.l + panel->stop_btn->ctrl.w; + panel->stop_btn->ctrl.rc.b = panel->stop_btn->ctrl.rc.t + panel->stop_btn->ctrl.h; + + panel->sld->ctrl.rc.l = panel->ctrl.rc.l; + panel->sld->ctrl.rc.t = panel->ctrl.rc.t+28; + panel->sld->ctrl.rc.r = panel->sld->ctrl.rc.l + panel->sld->ctrl.w; + panel->sld->ctrl.rc.b = panel->sld->ctrl.rc.t + panel->sld->ctrl.h; + + panel_update_layout(panel); +}; + + +void draw_panel(panel_t *panel) +{ + int *pixmap, *src; + int i, j, w; + + lock_bitmap(&panel->bitmap); + + blit_raw(&panel->ctx, res_panel_left, 0, 0, + PANEL_CORNER_W, PANEL_HEIGHT, PANEL_CORNER_W*4); + + + w = panel->ctrl.w - (2*PANEL_CORNER_W); + if( w > 0) + { + pixmap = (int*)panel->ctx.pixmap->data; + 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.pixmap->pitch/4; + } + }; + + blit_raw(&panel->ctx, res_panel_right, panel->ctrl.w - PANEL_CORNER_W, 0, + PANEL_CORNER_W, PANEL_HEIGHT, PANEL_CORNER_W*4); + + + ctrl_t *child; + child = (ctrl_t*)panel->ctrl.child.next; + + while( &child->link != &panel->ctrl.child) + { + send_message(child, MSG_PAINT, 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 ID_STOP: + case ID_PROGRESS: + case ID_VOL_CTRL: + 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); + + lock_bitmap(&panel->bitmap); + + Blit(panel->ctx.pixmap->data, panel->draw.l, panel->draw.t, + 0, 0, panel->ctrl.w, panel->ctrl.h, + panel->ctrl.w, panel->ctrl.h, panel->ctx.pixmap->pitch); +}; + diff --git a/contrib/media/fplay/winlib/window.c b/contrib/media/fplay/winlib/window.c new file mode 100644 index 0000000000..06cd4d55e2 --- /dev/null +++ b/contrib/media/fplay/winlib/window.c @@ -0,0 +1,691 @@ + +#include +#include +#include +#include +#include "winlib.h" + +#define DBG(format,...) + +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; + +int win_font; + + +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) +{ + char proc_info[1024]; + int stride; + +// __asm__ __volatile__("int3"); + + +// ctx_t *ctx = &Window.client_ctx; + + if(handler==0) return 0; + + BeginDraw(); + DrawWindow(x, y, w-1, h-1, + NULL,0,0x41); + EndDraw(); + + get_proc_info(proc_info); + + x = *(uint32_t*)(proc_info+34); + y = *(uint32_t*)(proc_info+38); + w = *(uint32_t*)(proc_info+42)+1; + h = *(uint32_t*)(proc_info+46)+1; + + Window.handler = handler; + // Window.ctx = ctx; + + list_initialize(&Window.link); + list_initialize(&Window.child); + + +// Window.bitmap.width = 1920; +// Window.bitmap.height = 1080; +// Window.bitmap.flags = 0; + + // if( create_bitmap(&Window.bitmap) ) + // { + // printf("not enough memory for window bitmap\n"); + // return 0; + // } + + // ctx->pixmap = &Window.bitmap; + // ctx->offset_x = 0; + // ctx->offset_y = 0; + + 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); + send_message(win, MSG_DRAW_CLIENT,0,0); + +// 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->data, win->client.l, win->client.t, + 0, 0, w, h, w, h,win->ctx->pixmap->pitch); +}; + + +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) + state = MAXIMIZED; + else + 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 && +// state == win->win_state) +// return; + + if(win->win_state != FULLSCREEN) + win->win_state = state; + +#if 0 + int old_size; + int new_size; + int pitch; + + + old_size = win->bitmap.pitch * win->bitmap.height; + old_size = (old_size+4095) & ~4095; + + pitch = ALIGN(win->w*4, 16); + + new_size = pitch * win->h; + new_size = (new_size+4095) & ~4095; + + if( new_size < old_size) + user_unmap(win->bitmap.data, new_size, old_size-new_size); + + win->bitmap.width = win->w; + win->bitmap.pitch = pitch; +#endif + + 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->client, old_pos.x, old_pos.y)) + return send_message((ctrl_t*)win, msg, 0, old_pos.val); + + if(win->win_state == FULLSCREEN) + return 0; + + 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); + } + + + 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); +// DefineButton(15, 15, 0x00000001, 0); + EndDraw(); + + send_message((ctrl_t*)win, MSG_DRAW_CLIENT, 0, 0); + + if(win->win_state == FULLSCREEN) + { + need_update=0; + return; + }; + + blit_caption(&win->caption); + blit_panel(&win->panel); + +// blit_client(win); + 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: + printf("key pressed\n"); + key = get_key(); + if( key.state == 0) + send_message((ctrl_t*)win, ev, 0, key.code); + continue; + + case 3: + printf("Button pressed\n"); + continue; + + case 6: + do_sys_mouse(win); + continue; + + default: + printf("event %d\n", ev); + continue; + }; + }; +} + +void render_time(void *render); + +void run_render(window_t *win, void *render) +{ + int ev; + oskey_t key; + int button; + + 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 3: + button = get_os_button(); + if(button == 1) + win->win_command = WIN_CLOSED; + 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); + + win_font = init_fontlib(); + + return 1; +} + +int fini_winlib() +{ + int ret; + + ret = destroy_cursor(cursor_nesw); + ret |= destroy_cursor(cursor_nwse); + ret |= destroy_cursor(cursor_we); + ret |= destroy_cursor(cursor_ns); + + return ret; +}; + + + +void init_winlib(void) +{ + __asm__ __volatile__( + "int $0x40" + ::"a"(40), "b"(0xC0000027)); + __asm__ __volatile__( + "int $0x40" + ::"a"(66), "b"(1),"c"(1)); + + 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->data, ctrl->rc.l, ctrl->rc.t, src_x, src_y, + ctrl->w, ctrl->h, ctx_w, ctx_h, ctrl->ctx->pixmap->pitch); + +// 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"(0x20),"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)); +} diff --git a/contrib/media/fplay/winlib/winlib.h b/contrib/media/fplay/winlib/winlib.h new file mode 100644 index 0000000000..0865e50e50 --- /dev/null +++ b/contrib/media/fplay/winlib/winlib.h @@ -0,0 +1,150 @@ +#ifndef __WINLIB_H__ +#define __WINLIB_H__ + +#include + +#include "control.h" + +#define CAPTION_HEIGHT 24 +#define PANEL_HEIGHT 55 + +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; + bitmap_t bitmap; + char *text; + ctrl_t *child_over; + + button_t *full_btn; + button_t *minimize_btn; + button_t *close_btn; + +}caption_t; + +typedef struct +{ + ctrl_t ctrl; + ctx_t ctx; + bitmap_t bitmap; + rect_t draw; + ctrl_t *child_over; + int layout; + progress_t *prg; + level_t *lvl; + slider_t *sld; + button_t *play_btn; + button_t *stop_btn; +}panel_t; + +enum win_state{ + NORMAL, MINIMIZED, ROLLED, MAXIMIZED, FULLSCREEN +}; + +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 saved; + rect_t client; + +// ctx_t client_ctx; +// bitmap_t bitmap; + bitmap_t bitmap; + + char *caption_txt; + ctrl_t *child_over; + ctrl_t *child_focus; + + caption_t caption; + panel_t panel; + frame_t frame; + + enum win_state win_state; + enum win_state saved_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); +level_t *create_level(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); +slider_t *create_slider(char *caption, 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