Errcode pj_i_read_uncomp1(char *fname, /* name of file for error report * NULL == no reporting */ Flifile *flif, struct rcel *fscreen, /* optional screen to update */ Fli_frame *ff, /* frame buffer */ Boolean colors) /* wait for vblank and update * hardware palette? */ /* seeks to and reads first frame into *ff using fii_read_uncomp() * assuming frame1_oset in the Flifile header is valid will update *fscreen * if *fscreen is non-NULL */ { Errcode err; if((err = pj_fli_seek_first(flif)) < 0) return(err); return(pj_fli_read_uncomp(fname,flif,fscreen,ff,colors)); }
Errcode pj_flic_play_until(char *path, FlicPlayOptions *requested_options, UserEventFunc *event_detect, void *udata) /***************************************************************************** * play a flic until the user-specified event routine returns FALSE to stop. * * Returns: * Success if ended due to user's event detect routine. * 1 if ended due to a keyhit and options.keyhit_stops_playback==TRUE. * (neg) if ended due to error. ****************************************************************************/ { Errcode err; Boolean we_opened_video = FALSE; Boolean we_initialized_clock = FALSE; ULONG clock; ULONG num_frames; FlicRaster virt_raster; FlicRaster *root_raster = NULL; FlicRaster *playback_raster = NULL; Fli_frame *ff = NULL; Flic theflic = {0}; Flifile *flif; Fli_head *flihdr; FliLibCtl *libctl; UserEventData event_data; FlicPlayOptions options; /*------------------------------------------------------------------------ * validate parms, init options, etc. *----------------------------------------------------------------------*/ if (NULL == path || NULL == event_detect) return pj_error_internal(Err_internal_pointer, modulename, __LINE__); if (NULL == requested_options) { pj_playoptions_init(&options); } else { options = *requested_options; } /*------------------------------------------------------------------------ * open the flic. *----------------------------------------------------------------------*/ err = pj_flic_open(path, &theflic); if (Success > err) goto ERROR_EXIT; flif = theflic.flifile; flihdr = &flif->hdr; libctl = theflic.libctl; /*------------------------------------------------------------------------ * open the video raster, or use the caller-provided raster. *----------------------------------------------------------------------*/ if (NULL != options.playback_raster) { root_raster = (FlicRaster *)options.playback_raster; we_opened_video = FALSE; } else { err = pj_video_get_current(NULL, NULL, &root_raster); if (Success > err) { err = pj_video_find_open(flihdr->width, flihdr->height, &root_raster); if (Success > err) goto ERROR_EXIT; we_opened_video = TRUE; } } /*------------------------------------------------------------------------ * setup placement of the playback raster based on the caller-provided * options, or the default option of centering the flic on the raster. *----------------------------------------------------------------------*/ if (0 == options.x && 0 == options.y) { playback_raster = pj_raster_center_virtual(root_raster, &virt_raster, flihdr->width, flihdr->height); } else { playback_raster = pj_raster_clip_virtual(root_raster, &virt_raster, options.x, options.y, flihdr->width, flihdr->height); if (NULL == playback_raster) { err = Err_clipped; goto ERROR_EXIT; /* totally clipped, just punt */ } } pj_raster_clear(playback_raster); /*------------------------------------------------------------------------ * do some misc setup before starting the actual playback... *----------------------------------------------------------------------*/ if(Success > (err = pj_fli_alloc_cbuf(&ff,flihdr->width,flihdr->height,COLORS))) { goto ERROR_EXIT; } num_frames = flihdr->frame_count; theflic.userdata = udata; event_data.userdata = udata; event_data.flic = &theflic; event_data.cur_loop = 0; event_data.cur_frame = 0; event_data.num_frames = num_frames; if (options.speed < 0) options.speed = flihdr->speed; we_initialized_clock = !pj_clock_init(); /*------------------------------------------------------------------------ * do the playback... *----------------------------------------------------------------------*/ for (;;) { /*-------------------------------------------------------------------- * the first time through, and if the event detector has called * pj_flic_rewind(), libctl->cur_frame is zero, and we have to seek * back to frame 1 (the brun frame). *------------------------------------------------------------------*/ if (0 == libctl->cur_frame) pj_seek(flif->fd, flihdr->frame1_oset, JSEEK_START); /*-------------------------------------------------------------------- * if the frame we're about to display is the ring frame, we increment * the cur_loop counter, and set the cur_frame to zero. that's * because displaying the ring frame is really a fast way to display * frame zero without un-brun'ing it again. *------------------------------------------------------------------*/ if (num_frames == libctl->cur_frame) { event_data.cur_frame = 0; ++event_data.cur_loop; } else { event_data.cur_frame = libctl->cur_frame; } /*-------------------------------------------------------------------- * get the current clock now, so that the delta time between frames * included the time it takes to render the frame. * render the frame. *------------------------------------------------------------------*/ clock = options.speed + pj_clock_1000(); if(Success > (err = pj_fli_read_uncomp(path,flif,(Rcel *)playback_raster,ff,TRUE))) goto ERROR_EXIT; /*-------------------------------------------------------------------- * call the event detector repeatedly, until it requests a stop, or * it's time to display the next frame. also check the keyboard * after each event_detect() call, if the caller has asked for that. *------------------------------------------------------------------*/ do { if (FALSE == event_detect(&event_data)) { err = Success; goto ERROR_EXIT; } if (options.keyhit_stops_playback) { if (pj_key_is()) { pj_key_in(); err = 1; goto ERROR_EXIT; } } } while (clock >= pj_clock_1000()); /*-------------------------------------------------------------------- * increment the frame counter; if it becomes greater than the frame * count, that means we just displayed the ring frame and have to * seek back to the second frame (not the first (brun'd) frame!). *------------------------------------------------------------------*/ if (++libctl->cur_frame > num_frames) { pj_seek(flif->fd, flihdr->frame2_oset, JSEEK_START); libctl->cur_frame = 1; } } ERROR_EXIT: pj_flic_close(&theflic); if (NULL != ff) pj_free(ff); if (we_opened_video) pj_video_close(&root_raster); if (we_initialized_clock) pj_clock_cleanup(); return err; }
Errcode pla_seek_frame(int frame) { int i; Errcode err; LONG frame_oset; Fli_frame *cbuf = pcb.cbuf; Boolean seek_one; LONG cmap_cksum; Rcel *seekcel; if(pcb.flif.fd == JNONE && pcb.rfli == NULL) return(Success); /* wrap frame */ frame = fli_wrap_frame(&pcb.flif,frame); if(frame > pcb.frame_ix) { frame_oset = pcb.next_frame_oset; i = pcb.frame_ix; seek_one = (i == frame - 1); } else if(frame < pcb.frame_ix) { if(pcb.frame_ix == pcb.flif.hdr.frame_count - 1) /* do ring frame */ { frame_oset = pcb.next_frame_oset; i = pcb.frame_ix; } else /* re seek from start */ { frame_oset = pcb.flif.hdr.frame1_oset; i = -1; } seek_one = (frame == 0); } else /* same frame as current */ goto done; if(seek_one) { seekcel = pcb.dcel; } else /* more than one frame */ { /* let's try to seek in background if there is memory */ if((seekcel = clone_rcel(pcb.dcel)) == NULL) seekcel = pcb.dcel; cmap_cksum = cmap_crcsum(seekcel->cmap); } /* if the fli is in ram get frame from ram if there */ if(pcb.rfli) { if(frame_oset == pcb.flif.hdr.frame1_oset) pcb.rframe = pcb.rfli->frames; while(i++ != frame) { if(pcb.rframe->doff < 0) { uncomp_ramframe(seekcel,pcb.rframe, pcb.flif.hdr.width, pcb.flif.hdr.height, seek_one); } else { if((frame_oset = pj_seek(pcb.flif.fd,pcb.rframe->doff, JSEEK_START)) < Success) { return(frame_oset); } if((err = pj_fli_read_uncomp(pcb.script_mode?NULL:pcb.fliname, &pcb.flif,seekcel,cbuf,seek_one)) < Success) { goto error; } } /* last one is ring frame if present. Some plays may not have a * ring frame */ if((pcb.rframe = pcb.rframe->next) == NULL) { pcb.rframe = pcb.rfli->frames->next; i = 0; } } if((frame_oset = pcb.rframe->doff) < 0) frame_oset = -frame_oset; goto seek_done; } if((frame_oset = pj_seek(pcb.flif.fd,frame_oset,JSEEK_START)) < Success) { err = frame_oset; goto error; } while(i++ != frame) { if((err = pj_fli_read_uncomp(pcb.script_mode?NULL:pcb.fliname, &pcb.flif,seekcel,cbuf,seek_one)) < Success) { goto error; } if(i >= pcb.flif.hdr.frame_count) { if((frame_oset = pj_seek(pcb.flif.fd, pcb.flif.hdr.frame2_oset,JSEEK_START)) < Success) { err = frame_oset; goto error; } i = 0; } else { frame_oset += cbuf->size; /* add size of frame read in */ } } seek_done: if(!seek_one) { if(seekcel != pcb.dcel) { pj_blitrect(seekcel,0,0,pcb.dcel,0,0, pcb.dcel->width,pcb.dcel->height); pj_cmap_copy(seekcel->cmap,pcb.dcel->cmap); pj_rcel_free(seekcel); } if(cmap_cksum != cmap_crcsum(pcb.dcel->cmap)) pj_cmap_load(pcb.dcel, pcb.dcel->cmap); } if(frame == 0) pcb.next_frame_oset = pcb.flif.hdr.frame2_oset; else pcb.next_frame_oset = frame_oset; done: pcb.frame_ix = frame; err = Success; error: return(err); }
Errcode open_curfli(Boolean load_colors,Boolean force_ram) { Errcode err; Boolean open_fli = TRUE; Ramframe *frame1; close_curfli(); if((pcb.rfli = find_ramfli(pcb.fliname)) != NULL && pcb.rfli->frames != NULL ) { if(pcb.rfli->fhead) /* get header from ramfli file not needed! */ { pcb.flif.hdr = *(pcb.rfli->fhead); open_fli = FALSE; } force_ram = FALSE; } else { pcb.rfli = NULL; } /* if we need a disk file we need the file open and a de-compression * buffer for the file records */ if(open_fli) { if((err = pj_fli_open(pcb.fliname,&pcb.flif,JREADONLY)) < Success) return(err); if((err = pj_fli_alloc_cbuf(&pcb.cbuf, pcb.flif.hdr.width, pcb.flif.hdr.height, vb.pencel->cmap->num_colors)) < Success) { goto error; } } pcb.speed = pcb.flif.hdr.speed; make_playcel(pcb.flif.hdr.width, pcb.flif.hdr.height); if(force_ram) /* if requested and not there already load fli into ram */ { if((err = add_ramfli(pcb.fliname,&pcb.rfli)) < Success) goto error; pcb.rfli->flags |= (RF_LOAD_RING|RF_LOAD_FIRST); if((err = load_ramfli(pcb.rfli, &pcb.flif)) < Success) goto error; if(pcb.rfli->frames == NULL) /* no frames loaded */ pcb.rfli = NULL; } if(pcb.rfli) { frame1 = pcb.rfli->frames; pcb.rframe = frame1->next; if(frame1->doff < 0) { uncomp_ramframe(pcb.dcel,frame1,pcb.flif.hdr.width, pcb.flif.hdr.height, load_colors); goto done; } } if((err = pj_fli_seek_first(&pcb.flif)) < Success) goto error; if((err = pj_fli_read_uncomp(NULL, &pcb.flif, pcb.dcel, pcb.cbuf, load_colors)) < Success) { goto error; } done: pcb.next_frame_oset = pcb.flif.hdr.frame2_oset; return(Success); error: pj_clear_rast(vb.pencel); close_curfli(); return(err); }
static Errcode play_until(Flic *pflic, EventFunc *event_detect) /***************************************************************************** * play a flic until the caller-specified event routine returns FALSE to stop. ****************************************************************************/ { Errcode err; ULONG clock; Flifile *flif; Fli_head *flihdr; Boolean stop_the_playback; Boolean mouse_was_on; /*------------------------------------------------------------------------ * do some misc setup before starting the actual playback... *----------------------------------------------------------------------*/ if (pflic->see_mouse) { mouse_was_on = show_mouse(); } else { mouse_was_on = hide_mouse(); } if (pflic->root_raster == vb.pencel) { dirties(); } flif = pflic->flifile; flihdr = &flif->hdr; if (pflic->speed < 0) { pflic->speed = flihdr->speed; } /*------------------------------------------------------------------------ * do the playback... *----------------------------------------------------------------------*/ stop_the_playback = FALSE; do { /*-------------------------------------------------------------------- * the first time through, or when the poco event detector has called * FlicRewind(), cur_frame is BEFORE_FIRST_FRAME, and we have to * seek back to frame 1 (the brun frame). *------------------------------------------------------------------*/ if (pflic->event_data.cur_frame == BEFORE_FIRST_FRAME) { pj_seek(flif->fd, flihdr->frame1_oset, JSEEK_START); pflic->event_data.cur_frame = 0; } else { ++pflic->event_data.cur_frame; } /*-------------------------------------------------------------------- * render the frame. * get the current clock first, so that the delta time between frames * includes the time it takes to render the frame. *------------------------------------------------------------------*/ clock = pflic->speed + pj_clock_1000(); if(Success > (err = pj_fli_read_uncomp(NULL, flif, pflic->playback_raster, pflic->framebuf,TRUE))) { goto ERROR_EXIT; } /*-------------------------------------------------------------------- * if the frame we just displayed is the ring frame, we increment * the cur_loop counter, and set the cur_frame to zero. that's * because displaying the ring frame is really a fast way to display * frame zero without un-brun'ing it again. we also seek back to * the second frame at this point, so that if the event detector kicks * us out and we're called again later, we'll be properly positioned. *------------------------------------------------------------------*/ ++pflic->frames_played; if (pflic->event_data.cur_frame == pflic->event_data.num_frames) { pj_seek(flif->fd, flihdr->frame2_oset, JSEEK_START); ++pflic->event_data.cur_loop; pflic->event_data.cur_frame = 0; } /*-------------------------------------------------------------------- * call the event detector repeatedly, until it requests a stop, or * it's time to display the next frame. also check the keyboard * after each event_detect() call, if the caller has asked for that. *------------------------------------------------------------------*/ do { if (FALSE == event_detect(pflic) || (pflic->input_stops_playback && any_user_input())) { stop_the_playback = TRUE; } } while (clock >= pj_clock_1000() && !stop_the_playback); } while (!stop_the_playback); err = Success; ERROR_EXIT: if (pflic->see_mouse) { if (!mouse_was_on) { hide_mouse(); } } else { if (mouse_was_on) { show_mouse(); } } return internal_error(err, "Error reported by play_until()"); }