Пример #1
0
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));
}
Пример #2
0
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;
}
Пример #3
0
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);
}
Пример #4
0
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);
}
Пример #5
0
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()");
}