Exemple #1
0
void TapeImage_HandleBlock0x010(SAMPLE_BUFFER *pBuffer, char *pBlockDataPtr)
{
	TZX_DATA_SIGNAL_DESCRIPTION DataDescription;

	/* setup pilot tone */
	OutputWaves(pBuffer, 2168, 3220);
	
	/* sync pulse 1 */
	OutputPulse(pBuffer, 667);

	/* sync pulse 2 */
	OutputPulse(pBuffer, 735);

	/* data */
	DataDescription.LengthOfOneBitPulseInTStates = 1710;
	DataDescription.LengthOfZeroBitPulseInTStates = 855;
	DataDescription.pData = pBlockDataPtr + 0x04;
	DataDescription.Length = TapeImage_GetWord(pBlockDataPtr+0x02);
	DataDescription.NumberOfBitsUsedInLastByte = 8;
	
	OutputData(pBuffer, &DataDescription);

	/* pause after block */
	OutputPause(pBuffer, TapeImage_GetWord(pBlockDataPtr + 0x00));
}
Exemple #2
0
void TapeImage_HandleBlock0x011(SAMPLE_BUFFER *pBuffer, char *pBlockDataPtr)
{
	TZX_DATA_SIGNAL_DESCRIPTION DataDescription;

	/* setup pilot tone */
	OutputWaves(pBuffer, TapeImage_GetWord(pBlockDataPtr+0), TapeImage_GetWord(pBlockDataPtr+0x0a));

	/* sync pulse 1 */
	OutputPulse(pBuffer, TapeImage_GetWord(pBlockDataPtr+2));

	/* sync pulse 2 */
	OutputPulse(pBuffer, TapeImage_GetWord(pBlockDataPtr+4));

	/* data */
	DataDescription.LengthOfOneBitPulseInTStates = TapeImage_GetWord(pBlockDataPtr + 0x08);
	DataDescription.LengthOfZeroBitPulseInTStates = TapeImage_GetWord(pBlockDataPtr + 0x06);
	DataDescription.pData = pBlockDataPtr + 0x012;
	DataDescription.Length = TapeImage_GetValue(pBlockDataPtr + 0x0f, 3);
	DataDescription.NumberOfBitsUsedInLastByte = TapeImage_GetByte(pBlockDataPtr + 0x0c);

	OutputData(pBuffer, &DataDescription);

	/* pause after block */
	OutputPause(pBuffer, TapeImage_GetWord(pBlockDataPtr + 0x0d));
}
Exemple #3
0
/* Handle Block 0x014 - Pure Data*/
void TapeImage_HandleBlock0x014(SAMPLE_BUFFER *pBuffer, char *pBlockDataPtr)
{
	TZX_DATA_SIGNAL_DESCRIPTION DataDescription;
	/* data */
	DataDescription.LengthOfOneBitPulseInTStates = TapeImage_GetWord(pBlockDataPtr + 0x02);
	DataDescription.LengthOfZeroBitPulseInTStates = TapeImage_GetWord(pBlockDataPtr + 0x00);
	DataDescription.pData = pBlockDataPtr + 0x0a;
	DataDescription.Length = TapeImage_GetValue(pBlockDataPtr + 0x07, 3);
	DataDescription.NumberOfBitsUsedInLastByte = TapeImage_GetByte(pBlockDataPtr + 0x04);

	OutputData(pBuffer, &DataDescription);

	/* pause after block */
	OutputPause(pBuffer, TapeImage_GetWord(pBlockDataPtr + 0x05));
}
Exemple #4
0
/* pause */
void TapeImage_HandleBlock0x020(SAMPLE_BUFFER *pBuffer, char *pBlockDataPtr)
{
	/* pause */
	OutputPause(pBuffer, TapeImage_GetWord(pBlockDataPtr + 0x00));
}
Exemple #5
0
static void * avLoop( void * arg )
{
	int loc_frames = 0;
	int loc_bytes;
	int loc_quit = 1;
	
	NMS_SRV_STATUS_t loc_preState = NMS_STATUS_PLAYER_STOPPED;
	int loc_cur_t = 0;
	int loc_next_t = 0;
	int loc_prev_t = 0;
	int loc_first_time = 0;
	int loc_preload;
	int loc_ffrw_scan_step = 0;
	media_buf_t loc_buf;
	long loc_info_duration;

	LOCK_PLAYMUTEX();
	if(editmode)
	{
		playState = NMS_STATUS_PLAYER_VF;
		loc_preload = 1;
		frameByFrame = 1;
	}
	else
	{
		playState =NMS_STATUS_PLAYER_PLAY; 
		loc_preload = PRELOAD_FRAMES;
		frameByFrame = 0;
	}
	UNLOCK_PLAYMUTEX();
	
	do
	{
		DBGMSG("In avloop now.");	
		/* preload */
		while (loc_frames < loc_preload)
		{
			if (1 == OutputGetBuffer(&loc_buf, 0, 1))
			{
				WPRINT("GetBuffer failed.");
				break;
			}
			
			loc_bytes = InputGetData(&loc_buf);
			if (loc_bytes == 0) continue;
			if (loc_bytes <0 )
			{
				// hit EOF, set flag to flush.
				loc_quit = 0;
				
				LOCK_PLAYMUTEX();
				playing = 0;
				UNLOCK_PLAYMUTEX();
				break; 
			}
			//DBGMSG("input data returned. ");
			LOCK_PLAYMUTEX();
			playtime = OutputGetPlaytime();
			UNLOCK_PLAYMUTEX();

#ifdef LOG_TIME_STAMP__
			if (loc_buf.curbuf == &loc_buf.abuf)
				DBGLOG("   aT = %d\n", loc_buf.curbuf->tsms);
			else
				DBGLOG("---vT = %d\n", loc_buf.curbuf->tsms);
#endif
			
			OutputWrite(&loc_buf);
			if (loc_buf.curbuf == &loc_buf.abuf) loc_frames++;
		}
		DBGMSG("preload finished.");
		OutputStart();
		/* start output */
		DBGMSG("output started.");
	} while(0);
	
	LOCK_PLAYMUTEX();
	preloaded = 1;
	everPlayed = 1;
	UNLOCK_PLAYMUTEX();
	
 main_play_loop:
	// preloaded...
	while (1)
	{	
		int loc_playState;
		int loc_iSeekFlag;
		int loc_iBookMark;
		int loc_sfrwLevelFinal;

		LOCK_PLAYMUTEX();
		if (!playing)
		{
			UNLOCK_PLAYMUTEX();
			break;
		}
		loc_playState = playState;
		UNLOCK_PLAYMUTEX();
		
		switch (loc_playState)
		{
		case NMS_STATUS_PLAYER_PAUSE:
			if (loc_preState != NMS_STATUS_PLAYER_PAUSE)
			{
				OutputPause(1);
				LOCK_PLAYMUTEX();
				playedOrPaused = NMS_STATUS_PLAYER_PAUSE;
				UNLOCK_PLAYMUTEX();
				loc_preState = NMS_STATUS_PLAYER_PAUSE;
			}
			continue;

		case NMS_STATUS_PLAYER_PLAY:
			{
				LOCK_PLAYMUTEX();
				loc_iSeekFlag = iSeekFlag;
				loc_iBookMark = iBookMark;
				UNLOCK_PLAYMUTEX();

				if (loc_preState != NMS_STATUS_PLAYER_PLAY || loc_iSeekFlag)
				{
					LOCK_PLAYMUTEX();
					playedOrPaused = NMS_STATUS_PLAYER_PLAY;		
					loc_info_duration = info.duration;			
					UNLOCK_PLAYMUTEX();

					if (loc_preState == NMS_STATUS_PLAYER_PAUSE)
					{
						OutputPause(0);	

						LOCK_PLAYMUTEX();
						muted = 0;
						UNLOCK_PLAYMUTEX();
					}
					else if (loc_iSeekFlag)
					{
						if (loc_info_duration - loc_iBookMark > 100)
						{
							loc_next_t = InputSeek(loc_iBookMark);						
							OutputFlush(loc_next_t);
						}
						LOCK_PLAYMUTEX();
						iSeekFlag = 0;
						UNLOCK_PLAYMUTEX();
					}
					else
					{
						LOCK_PLAYMUTEX();
						if (muted)
						{
							muted = 0;
							OutputMute(muted);
						}
						loc_sfrwLevelFinal = sfrwLevelFinal;
						UNLOCK_PLAYMUTEX();

						if (loc_preState == NMS_STATUS_PLAYER_SF)
						{
							int loc_cur_tmp;

							LOCK_PLAYMUTEX();
							loc_cur_tmp = playtime;
							UNLOCK_PLAYMUTEX();

							loc_next_t = loc_first_time + (loc_cur_tmp - loc_first_time) / loc_sfrwLevelFinal;
							loc_next_t = InputSeek(loc_next_t);
							OutputFlush(loc_next_t);	
						}
					}
					loc_preState = NMS_STATUS_PLAYER_PLAY;					
					loc_prev_t = 0;
				}				
			}
			break;
		case NMS_STATUS_PLAYER_FF:
		case NMS_STATUS_PLAYER_RW:
			if (loc_preState != loc_playState)
			{
				LOCK_PLAYMUTEX();
				loc_cur_t = playtime;
				UNLOCK_PLAYMUTEX();

				OutputFlush(loc_cur_t);
				if (loc_preState == NMS_STATUS_PLAYER_PAUSE)
					OutputPause(0);
				
				LOCK_PLAYMUTEX();
				if (!muted)
				{
					muted = 1;
					OutputMute(muted);
				}
				loc_cur_t = playtime;
				loc_first_time = loc_cur_t;
				loc_next_t = loc_cur_t;
				loc_prev_t = loc_cur_t;
				loc_preState = playState;
				UNLOCK_PLAYMUTEX();
			}

			LOCK_PLAYMUTEX();
			if (ffrwLevel == 0)
			{
				UNLOCK_PLAYMUTEX();
				continue;
			}
			else if (ffrwLevel > 2)
				loc_ffrw_scan_step = SCAN_STEP2_MS;
			else 
				loc_ffrw_scan_step = SCAN_STEP1_MS;

 
		get_new_timestamp:
			if (loc_preState == NMS_STATUS_PLAYER_FF)
			{
				loc_info_duration = info.duration;
				if (loc_info_duration != 0 && (playtime + ffrwLevel * loc_ffrw_scan_step) >= loc_info_duration)
				{
					loc_next_t = loc_info_duration;
					loc_next_t = InputSeek(loc_next_t);
					OutputFlush(loc_next_t);
					
					if(editmode)
					{
						playState = NMS_STATUS_PLAYER_PLAY;
						UNLOCK_PLAYMUTEX();
						break;	
					}
					else
					{
						loc_quit = 0;
						UNLOCK_PLAYMUTEX();
						goto bail;
					}					
				}
				else
				{
					playtime += ffrwLevel * loc_ffrw_scan_step;
					loc_next_t = playtime;
					if (rptState == NMS_PLAYBACK_REPEAT_ON)
					{
						if (loc_next_t >= rptB)
						{
							loc_next_t = rptB;
							loc_next_t = InputSeek(loc_next_t);
							OutputFlush(loc_next_t);
							UNLOCK_PLAYMUTEX();
							continue;
						}
					}
				}
			}
			else
			{
				if (playtime +ffrwLevel * loc_ffrw_scan_step <= 0)
				{
					loc_next_t = 0;
					loc_next_t = InputSeek(loc_next_t);
					OutputFlush(loc_next_t);
					if(editmode)
					{
						playState = NMS_STATUS_PLAYER_VF;
						frameByFrame = 1;
						loc_preState = NMS_STATUS_PLAYER_PLAY;
						UNLOCK_PLAYMUTEX();
						break;
					}
					else
						playState = NMS_STATUS_PLAYER_PLAY;

					ffrwLevel = 0;
					UNLOCK_PLAYMUTEX();
					continue;
				}
				else
				{
					playtime += ffrwLevel * loc_ffrw_scan_step;
					loc_next_t = playtime;
					if (rptState == NMS_PLAYBACK_REPEAT_ON)
					{
						if (loc_next_t <= rptA)
						{
							loc_next_t = rptA;
							loc_next_t = InputSeek(loc_next_t);
							OutputFlush(loc_next_t);
							UNLOCK_PLAYMUTEX();
							continue;
						}
					}
				}
			}

			loc_next_t = InputSeek(loc_next_t);
			OutputFlush(loc_next_t);
			if ((loc_preState == NMS_STATUS_PLAYER_FF && loc_prev_t >= loc_next_t) ||
				(loc_preState == NMS_STATUS_PLAYER_RW && loc_prev_t <= loc_next_t))
			{
				goto get_new_timestamp;
			}
			loc_prev_t = loc_cur_t;
			loc_cur_t = loc_next_t;			
			UNLOCK_PLAYMUTEX();
			break;

		case NMS_STATUS_PLAYER_VF:
			LOCK_PLAYMUTEX();
			DBGLOG("!!!!!!!!!!!!!!!play VF,mute=%d\n",muted);
			if (frameByFrame == 1)
			{
				OutputPause(0);
				loc_cur_t = playtime;
				OutputFlush(loc_cur_t);
				if (!muted)
				{
					muted = 1;
		            OutputMute(muted);
				}
			}
			playState = NMS_STATUS_PLAYER_PAUSE;
			loc_cur_t = playtime;
			UNLOCK_PLAYMUTEX();

			loc_next_t = loc_cur_t;
			loc_prev_t = loc_cur_t;
			loc_first_time = loc_cur_t;
			
			break;

		case NMS_STATUS_PLAYER_SF:
			if (loc_preState != NMS_STATUS_PLAYER_SF)
			{
				LOCK_PLAYMUTEX();
				loc_cur_t = playtime;
				OutputFlush(loc_cur_t);
				if (loc_preState == NMS_STATUS_PLAYER_PAUSE)
					OutputPause(0);
				if (!muted)
				{
					muted = 1;
					OutputMute(muted);
				}
				loc_cur_t = playtime;
				UNLOCK_PLAYMUTEX();

				loc_next_t = loc_cur_t;
				loc_prev_t = loc_cur_t;
				loc_preState = NMS_STATUS_PLAYER_SF;				
			}
			break;

		case NMS_STATUS_PLAYER_STOPPED:
			if (loc_preState == NMS_STATUS_PLAYER_PAUSE)
				OutputPause(0);
			loc_preState = NMS_STATUS_PLAYER_STOPPED;
			loc_quit = 1;
			goto bail;

		default:
			LOCK_PLAYMUTEX();
			playState = loc_preState;
			UNLOCK_PLAYMUTEX();
			break;
		}

		LOCK_PLAYMUTEX();
		if (rptState == NMS_PLAYBACK_REPEAT_ON)
		{
			loc_cur_t = playtime;
			if (loc_cur_t > rptB)
			{				
				loc_cur_t = InputSeek(rptA);
				OutputFlush(loc_cur_t);
			}
		}
		UNLOCK_PLAYMUTEX();
		
		if ( 1 == OutputGetBuffer(&loc_buf, 1000, 0))
		{
			//DBGMSG("buffer full or playback paused!");
			continue;
		}

		loc_bytes = InputGetData(&loc_buf);
		if (loc_bytes == 0)
		{
			WPRINT("zero bytes returned!");
			continue;
		}

		LOCK_PLAYMUTEX();
		if (loc_bytes < 0) 
		{
			if(editmode)
			{
				UNLOCK_PLAYMUTEX();
				continue;	
			}
			else
			{
				WPRINT("EOF reached!");
				// hit EOF, set flag to flush.
				loc_quit = 0;
				UNLOCK_PLAYMUTEX();
				break;
			}
		}
		UNLOCK_PLAYMUTEX();

#ifdef LOG_TIME_STAMP__
		if (loc_buf.curbuf == &loc_buf.abuf)
			DBGLOG("   aT = %d\n", loc_buf.curbuf->tsms);
		else
			DBGLOG("---vT = %d\n", loc_buf.curbuf->tsms);
#endif

		LOCK_PLAYMUTEX();
		playtime = OutputGetPlaytime();
		if (loc_buf.curbuf == &loc_buf.abuf)
		{
			if (loc_preState != NMS_STATUS_PLAYER_PLAY && rptState != NMS_PLAYBACK_REPEAT_ON)
			{
				UNLOCK_PLAYMUTEX();
				continue;
			}
		}
		UNLOCK_PLAYMUTEX();

		if (loc_preState != NMS_STATUS_PLAYER_PLAY && loc_preState != NMS_STATUS_PLAYER_PAUSE)
		{
			if (loc_first_time == 0)
			{
				loc_first_time = loc_cur_t;
			}
			if (loc_preState == NMS_STATUS_PLAYER_SF)
			{
				loc_buf.vbuf.tsms = loc_buf.vbuf.tsms - loc_first_time;
				LOCK_PLAYMUTEX();
				loc_buf.vbuf.tsms *= sfrwLevel;
				UNLOCK_PLAYMUTEX();
				loc_buf.vbuf.tsms += loc_first_time;
			}		
			loc_prev_t = loc_cur_t;
		}
		
		OutputWrite(&loc_buf);
	}
	
	DBGMSG("Exit main playback loop.\n");
	// if quit, re-fetch the lock here
	
 bail:
	LOCK_PLAYMUTEX();
	ffrwLevel = 0;
	sfrwLevel = 0;
	UNLOCK_PLAYMUTEX();
	
	if (loc_preState == NMS_STATUS_PLAYER_PAUSE)
	{
		OutputPause(0);
	}

	LOCK_PLAYMUTEX();
	if (muted)
	{
		muted = 0;
		OutputMute(muted);
	}
	UNLOCK_PLAYMUTEX();
	
	// We used to call InputFinish here, but let's wait a while, because we may be asked to seek again later,
	// while draining the output buffer. And we'll need input to be active if we want to have something to seek into.
	
	if (loc_quit)
	{
		LOCK_PLAYMUTEX();
		InputFinish();
		// If we're quitting the server, we really don't want to wait that video output is drained.
		// We flush it down the toilet without sending it to the TV.
		OutputFinish(0);
		UNLOCK_PLAYMUTEX();
	}
	else
	{
		unsigned long remain;
		
		// We're at the EOF of a playback. We may have some data left in the dm320
		// gargantuan output buffers, and we need to properly make sure it goes all to TV before we're done.
		//
		// We can't really call a blocking flush here (like OutputFinish(1)).
		// This is because the server will freeze otherwise and be unable to process 
		// commands (like STOP or PAUSE) that come in during the final draining of the output buffer.
		//
		// This is an improvement over the old way of just waiting some time before calling the 
		// blocking flush: it instead keeps checking the amount of data in the dm320 video output buffer 
		// and doesn't call the blocking flush until it's all drained. It sleeps a small amount of time 
		// between checks, then before the next check it processes commands.
		//
		// HACK:
		// It works better than before, however it's still a bit of an hack, since this
		// polling is really not elegant at all. It is much better to setup a callback and 
		// have imedia call us when there's no more data in the output buffer. 
		// Or something like that. --nero

		LOCK_PLAYMUTEX();
		playing = 1; //Restore the playback flag, since we're still actually playing.
		UNLOCK_PLAYMUTEX();

		remain = OutputGetBufferedSize();
		WPRINT("Entering buffer drain loop (remain %lu bytes).\n", remain);
		
		while (remain > 0)
		{
			
			LOCK_PLAYMUTEX();
			if (!playing) 
			{
				UNLOCK_PLAYMUTEX();
				break;
			}
			
			DBGMSG("Draining output buffer. Bytes remaining: %lu\n", remain);
			if (playState == NMS_STATUS_PLAYER_PAUSE) OutputPause(1);
			else 
			{
				OutputPause(0);
				
				// If we're asked to seek (ffw, rew or point-seek), let's just return in the main loop.
				// The logic in the loop will take care of everything else, we don't need to do anything more here.
				if (playState == NMS_STATUS_PLAYER_FF || playState == NMS_STATUS_PLAYER_RW ||
					(playState == NMS_STATUS_PLAYER_PLAY && iSeekFlag != 0)) 
				{
					DBGMSG("Going back to main playback loop.\n");
					UNLOCK_PLAYMUTEX();
					goto main_play_loop;
				}
			}
			UNLOCK_PLAYMUTEX();

			usleep(DRAIN_POLL_TICK);
			remain = OutputGetBufferedSize();
		}
		DBGMSG("Exited drain loop. Playing: %d - Remain: %lu\n", playing, remain);
		
		LOCK_PLAYMUTEX();
		InputFinish();
		OutputPause(0); //before finish output must make sure pause flag is cleared
		
		//Let's always call a final non-blocking flush. Thus if there are bugs in the above logic, 
		//we notice a clip at end of video (due to flushing to kingdom come the last part of data), 
		//and hopefully we come here to look ;) --nero
		OutputFinish(0);
		UNLOCK_PLAYMUTEX();
	}

	// clear playing and ffrw flag, and release lock before
	// joining ffrw thread.
	LOCK_PLAYMUTEX();
	playing = 0;
	
	rptState = NMS_PLAYBACK_REPEAT_OFF;	
	if (playtype == NPT_FILE)
		playState = NMS_STATUS_PLAYER_STOPPED;
	else
		playState = NMS_STATUS_PLAYER_NEXT;	
	
	DBGMSG("input output finished.");
	
	// check to play next file.
	if ((0 == loc_quit) && (playtype != NPT_FILE))
	{
		DBGMSG("searching for next file.");
		//if repeat is single and the file is not played, stop nextfile loop
		if (!((repeat == RM_REPEAT) && (errorStatus == NMS_STATUS_NOT_PLAYABLE)))
			trackChange = TC_NORMAL;
		
		UNLOCK_PLAYMUTEX();
		pthread_cond_broadcast(&nextFileCond);
	}
	else UNLOCK_PLAYMUTEX();

	pthread_exit(NULL);
}