Пример #1
0
static int newThread(pthread_t * thread,
					 const pthread_attr_t * attr,
					 void *(*start_routine)(void*), void * arg)
{
	int status;
	
	status = pthread_create(thread, attr, start_routine, arg);
	if (status)
	{
		WPRINT("Thread was not created!");
		switch (status)
		{
		case EAGAIN:
			EPRINT("The system lacked the necessary resources to create "
				   "another thread, or the system-imposed limit on the total "
				   "number of threads in a process {PTHREAD_THREADS_MAX} " 
				   "would be exceeded.");
			break;
		case EINVAL:
			EPRINT("The value specified by attr is invalid.");
			break;
		case EPERM:
			EPRINT("The caller does not have appropriate permission to "
				   "set  the  required "
				   "scheduling  parameters  or scheduling policy.");
			break;
		default:
			EPRINT("Unknown error!");
			break;
		}
	}
	return status;
}
Пример #2
0
static int sanity_check_server_events(SServerConfigs *_this,SServerEvents *newevent)
{
	/* Check that compulsory things exist */
	if(newevent->eventType==0 )
	{
		EPRINTC(PrintComp_IrcCfg,"Eventtype missing!");
		goto ErrgetOutServer;
	}
	WPRINTC(PrintComp_IrcCfg,"No proper sanity checks for server event configs written!");
	/* Fill non specified defaults */
	if(NULL==newevent->event_string)
	{
		WPRINT
		(
			"Text event with no event string specified! (eventId %d, server %s)",
			newevent->eventId,
			_this->domain
		);
	}

	return 0;
ErrgetOutServer:
	/* TODO: Find a way if callback for this ID is registered. If so, ignore all checks. */
	EPRINTC(PrintComp_IrcCfg,"Invalid config for event %d on server %s",newevent->eventId,_this->domain);
	return -1;

}
Пример #3
0
/**
 * Stop current playback.
 */
void
SrvStop( void )
{
	int loc_going;
	int loc_fileIdx;
	int loc_everPlayed;
	int loc_playtype;

	LOCK_PLAYMUTEX();
	loc_going = going;
	loc_fileIdx = fileIdx;
	loc_playtype = playtype;
	UNLOCK_PLAYMUTEX();

	if (loc_going)
	  // if playing, set history before shutdown.
	{

		char * path = NULL;
		char buf[PATH_MAX];
		DBGMSG("Stop server playback.");
		switch (loc_playtype)
		{
		case NPT_FILE:
			LOCK_PLAYMUTEX();
			path = strcpy(buf, trackName); 
			UNLOCK_PLAYMUTEX();
			break;
		case NPT_DIR:
			path = nextFileFromDir(loc_fileIdx,buf,PATH_MAX); break;
		default: //history not supported.
			WPRINT("play history not supported.");
			break;
		}

		LOCK_PLAYMUTEX();
		loc_fileIdx = fileIdx;
		loc_everPlayed = everPlayed;
		UNLOCK_PLAYMUTEX();

		if (path)
		{
			int mark;

			LOCK_PLAYMUTEX();			
			mark = playtime;
			UNLOCK_PLAYMUTEX();

			if (loc_everPlayed) SetPlayHistory(loc_playtype, loc_fileIdx, mark, path);
		}
	}	

	stopServer();

	LOCK_PLAYMUTEX();
	// player has been stop upon user request.
	errorStatus = NMS_STATUS_PLAYER_STOPPED;
	UNLOCK_PLAYMUTEX();
}
int aplogd_rambuf_space(int index)
{
	int temp_filled = aplogd_rambuf_bytes_filled(index);
	if (temp_filled < 0 || temp_filled > aplogd_ram_buff_size)
	{
		WPRINT("Could not get bytes filled\n");
		return -1;
	}
	return (aplogd_ram_buff_size - temp_filled);
}
/* aplogd_io_remove_poll_fd()
 *
 * Description: This function removes an fd from the poll list
 *
 * @num: (int) Poll struct array offset to remove
 *
 * Return: None
 *
 * Notes: None
 */
void aplogd_io_remove_poll_fd(int num)
{
	DPRINT("Removing fd %d (fd = %d) from list\n", num,
			aplogd_io_fd[num].fd);
	if (num < 0 || num >= APLOGD_MAX_IO_FDS )
	{
		WPRINT("Poll index out of bounds\n");
		return;
	}
	aplogd_io_fd[num].fd = -1;
	aplogd_io_fd[num].events = 0;
	aplogd_io_fd[num].revents = 0;
}
int aplogd_rambuf_output(int index)
{
	int ret_val = 0;
	int need_written = 0;
	int size_written = 0;

	/* From here on out we can only manipulate the output list */

	VPRINT("output index:%d\n", index );
	need_written=aplogd_rambuf_bytes_filled(index);
	VPRINT("need_written=%d.\n",need_written);
	if(!aplogd_io_array[index].input_buf_base || !(need_written >0))
	{
		return -1;
	}
	if (aplogd_io_array[index].output_fd < 0)
	{
		WPRINT("output fd hasn't been initialized.\n");
		aplogd_io_array[index].input_buf = aplogd_io_array[index].input_buf_base;
		ret_val = -1;
		return ret_val;
	}

	while(need_written >0) {
		size_written = write(aplogd_io_array[index].output_fd, (void*)aplogd_io_array[index].input_buf_base, need_written);
		if (size_written < 0 )
		{
			EPRINT("output write: size_written=%d, errno=%d\n", size_written, errno);
			if (ENOSPC == errno)
				aplogd_close_output();
			if (EBADF == errno)
				aplogd_io_array[index].output_fd=-1;
			ret_val=-1;
			return ret_val;
		}
		need_written -= size_written;
		total_write_size+=size_written;
	}
	aplogd_io_array[index].input_buf = aplogd_io_array[index].input_buf_base;
        if (total_write_size >=aplogd_logfile_max)
        {
		ALOGI("aplogd_logfile_max=%d, total_write_size=%d\n",aplogd_logfile_max, total_write_size);
		aplogd_close_output();
		aplogd_io_backupall(g_current_storage);
		aplogd_output_setup(g_current_storage);
		total_write_size=0;
        }
	return ret_val;
}
/* aplogd_io_fd_setup()
 *
 * Description: This function sets up a unix datagram socket at the path
 * provided.
 *
 * @pathname: (const char *) Desired unix socket path
 *
 * Return: (int) Sockets fd on success; -1 on failure
 *
 * Notes: None
 */
int aplogd_io_fd_setup(const char * pathname)
{
	int fd = -1;

	DPRINT("Entered fd setup.pathname=%s\n",pathname);
	/* Setup sockaddr */
	fd = open(pathname,  O_RDONLY |O_NONBLOCK);
	if (fd < 0)
	{
		WPRINT("Couldn't open the file: %s\n",pathname);
		return -1;
	}
	DPRINT("Successfully returning fd: %d\n", fd);
	return fd;
}
Пример #8
0
/**
 * Get file path.
 *
 */
int    
SrvGetFilePath(int idx, void * pathbuf,const int bufsize)
{
	int ret = -1;
	char * pc = (char*)pathbuf;
	int loc_going;
	int loc_playtype;

	LOCK_PLAYMUTEX();
	loc_going = going;
	loc_playtype = playtype;
	UNLOCK_PLAYMUTEX();
	
	DBGMSG("get file path.");
	
	*pc = 0;
	if (loc_going)
	{
		if (loc_playtype == NPT_FILE)
		{
			LOCK_PLAYMUTEX();			
			strcpy(pc, trackName);
			UNLOCK_PLAYMUTEX();
			ret = 0;
		}
		else if (loc_playtype == NPT_DIR)
		{
			if (idx >= 0)
			{
				nextFileFromDir(idx,pc,bufsize);
				//DBGMSG("filepath = [%s]", path);
				ret = 0;
			}
		}
		else 
		{
			//FIXME:
			WPRINT("unknown play type.");
		}
	}
	return ret;
}
int LogfilterAndBuffering(
		AndroidLogFormat *p_format,
		const AndroidLogEntry *entry, int index)
{
	char *outBuffer = NULL;
	size_t totalLen=0;
	int ret_val=0;
	size_t len=0;
	if (0 == android_log_shouldPrintLine(p_format, entry->tag,
				entry->priority)) {
		VPRINT("No need to output.\n");
		ret_val=0;
		return ret_val;
	}

	outBuffer = android_log_formatLogLine(p_format, defaultBuffer,
			sizeof(defaultBuffer), entry, &totalLen);

	if (!outBuffer){
		EPRINT("Failed in android_log_formatLogLine.\n");
		ret_val=-1;
		return ret_val;
	}
        len= aplogd_rambuf_space(index);
	if(len >  totalLen ){
		memcpy(aplogd_io_array[index].input_buf, outBuffer, totalLen);
		aplogd_io_array[index].input_buf += totalLen;
		ret_val=totalLen;
		if(outBuffer !=defaultBuffer)
			free(outBuffer);
	}else{
		WPRINT("no enough buffer to contain log messages.len=%d totallen=%d.entry->messageLen=%d\n",len, totalLen,entry->messageLen);
		if(outBuffer !=defaultBuffer)
			free(outBuffer);
		ret_val=-1;
		aplogd_bytes_lost += totalLen;
	}
	return ret_val;
}
Пример #10
0
/**
 * Server command receiver routine.
 *
 * @param pkt
 *        packet node.
 * @return
 *        15 to exit command thread, all other value
 *        are considered normal.
 */
int
SrvRxCmd( void * pkt )
{
	int ret = 0;
	int acked = 0;

	pkt_node_t * p = (pkt_node_t *)pkt;

	DBGLOG("command: %d", p->hdr.cmd);
	switch (p->hdr.cmd) 
	{
	case CMD_GET_VERSION:
		DBGLOG("CMD_GET_VERSION.");
		CoolCmdSendPacket(p->fd, CMD_GET_VERSION|NMS_CMD_ACK, 
					  (void*)version, strlen(version)+1);
		acked = 1;
		break;

		// careful: this will be the last command server responds to.
	case CMD_STOP_SERVER: 
		DBGLOG("CMD_STOP_SERVER.");
		ret = 15;
		break;
		
	case CMD_SET_INPUT_MODE:
		DBGLOG("CMD_SET_INPUT_MODE.");
		EncInputSetMode(*(int*)p->data);
		break;
		
	case CMD_SET_OUTPUT_MODE:
		DBGLOG("CMD_SET_OUTPUT_MODE.");
	  	{
			OutputSetMode(*(int*)p->data);
			if (SrvIsMonitorActive())
			{
				SrvStartMonitorInternal();
			}
			else if (SrvIsRecording())
			{
			}
			else if (SrvIsPlaying())
			{
				OutputActivateMode(0);
			}
	  	}
	  	break;

	case CMD_SET_OUTPUT_PROPORTIONS:
		DBGLOG("CMD_SET_OUTPUT_PROPORTIONS.");
		SrvSetProportions((*(int*)p->data));
		break;

	case CMD_GET_OUTPUT_PROPORTIONS:
		DBGLOG("CMD_GET_OUTPUT_PROPORTIONS.");
		int proportions = SrvGetProportions();
		CoolCmdSendPacket(p->fd, CMD_GET_OUTPUT_PROPORTIONS|NMS_CMD_ACK, 
		                  (void*)&proportions, sizeof(int));
		acked = 1;
		break;

	case CMD_START_SLIDE_SHOW:
		DBGLOG("CMD_START_SLIDE_SHOW.");
		{
			int startslideshow;
			startslideshow = SrvStartSlideShow();
			CoolCmdSendPacket(p->fd, CMD_START_SLIDE_SHOW|NMS_CMD_ACK, 
						  (void*)&startslideshow, sizeof(int));
			acked = 1;
			DBGLOG("CMD_START_SLIDE_SHOW completed.");
		}
		break;
		
	case CMD_SET_SLIDE_SHOW_IMAGE:
		DBGLOG("CMD_SLIDE_SHOW_SET_IMAGE.");
		{
			SrvSlideShowSetImage((char *)p->data);
		}
		break;
		
	case CMD_STOP_SLIDE_SHOW:
		DBGLOG("CMD_SLIDE_SHOW_STOP.");
		SrvStopSlideShow();
		break;
		
	case CMD_PLAY:
		DBGLOG("CMD_PLAY.");
		int ret = StartPlay(p->data, p->hdr.dataLen);
		CoolCmdSendPacket(p->fd, CMD_PLAY|NMS_CMD_ACK, 
					  (void*)&ret, sizeof(int));
		acked = 1;
		break;
		
	case CMD_PAUSE_UNPAUSE:
		DBGLOG("CMD_PAUSE_UNPAUSE.");
		SrvPauseUnpause();
		break;
		
	case CMD_STOP_PLAY:
		DBGLOG("CMD_STOP_PLAY.");
		SrvStop();
		break;
		
	case CMD_GET_SRV_STATUS:
		DBGLOG("CMD_GET_SRV_STATUS.");
	  	{
			int status;
			status = SrvGetSrvStatus();
			CoolCmdSendPacket(p->fd, CMD_GET_SRV_STATUS|NMS_CMD_ACK,                                                 
						  (void*)&status, sizeof(int));
			acked = 1;
	  	}
	  	break;
		
	case CMD_GET_VOLUME:
		DBGLOG("CMD_GET_VOLUME.");
		{
			int vol[2];
			SrvGetVolume(&vol[0], &vol[1]);
			CoolCmdSendPacket(p->fd, CMD_GET_VOLUME|NMS_CMD_ACK, 
						  (void*)vol, sizeof(vol));
			acked = 1;
		}
		break;
		
	case CMD_SET_VOLUME:
		DBGLOG("CMD_SET_VOLUME.");
		{
			int vol[2];
			int * pv;
			pv = (int*)p->data;
			vol[0] = *pv++;
			vol[1] = *pv;
			SrvSetVolume(vol[0], vol[1]);
		}
		break;
		
	case CMD_GET_PLAY_TIME:
		DBGLOG("CMD_GET_PLAYTIME.");
		{
			int t;
			t = SrvGetPlaytime();
			CoolCmdSendPacket(p->fd, CMD_GET_PLAY_TIME|NMS_CMD_ACK,                                                 
						  (void*)&t, sizeof(int));
			acked = 1;
		}
		break;
		
	case CMD_SEEK:
		DBGLOG("CMD_SEEK.");
		{
			int t;
			int *pv;
			pv = (int*)p->data;
			t = *pv;
			t = SrvSeek(t);
			CoolCmdSendPacket(p->fd, CMD_SEEK|NMS_CMD_ACK, 
						  (void*)&t, sizeof(int));
			acked = 1;
		}
		break;
		
	case CMD_TRACK_CHANGE:
		DBGLOG("CMD_TRACK_CHANGE.");
		{
			int track;
			int *pv;
			int retv;
			pv = (int*)p->data;
			track = *pv;
			retv = SrvTrackChange(track);
			CoolCmdSendPacket(p->fd, CMD_TRACK_CHANGE|NMS_CMD_ACK, 
						  (void*)&retv, sizeof(int));
			acked = 1;
		}
		break;
		
	case CMD_FF_RW:
		DBGLOG("CMD_FF_RW.");
		SrvFfRw(*(int*)p->data);
		break;
		
	case CMD_GET_FFRW_LEVEL:
		DBGLOG("CMD_GET_FFRW_LEVEL.");
	 	{
			int level = SrvGetFFRWLevel();
			CoolCmdSendPacket(p->fd, CMD_GET_FFRW_LEVEL|NMS_CMD_ACK, 
						  (void*)&level, sizeof(int));
			acked = 1;
	 	}
		break;

	case CMD_SF_RW:
		DBGLOG("CMD_SF_RW.");
		SrvSfRw(*(int*)p->data);
		break;
		
	case CMD_GET_SFRW_LEVEL:
		DBGLOG("CMD_GET_SFRW_LEVEL.");
	 	{
			int level = SrvGetSFRWLevel();
			CoolCmdSendPacket(p->fd, CMD_GET_SFRW_LEVEL|NMS_CMD_ACK, 
						  (void*)&level, sizeof(int));
			acked = 1;
	 	}
		break;
		
	case CMD_FRAME_BY_FRAME:	
		DBGLOG("CMD_FRAME_BY_FRAME.");	
		SrvFrameByFrame(*(int*)p->data);	
		break;

	case CMD_REPEAT_A_B:
		DBGLOG("CMD_REPEAT_A_B.");	
		SrvRepeatAB(*(int*)p->data);	
		break;
		
	case CMD_GET_REPEAT_AB_STATUS:
		DBGLOG("CMD_GET_REPEAT_AB_STATUS.");
		{
			int status = SrvGetRepeatABStatus();
			CoolCmdSendPacket(p->fd, CMD_GET_REPEAT_AB_STATUS|NMS_CMD_ACK, 
						  (void*)&status, sizeof(int));
			acked = 1;
		}
		break;
		
	case CMD_IS_PLAYING:
		DBGLOG("CMD_IS_PLAYING.");
		{
			int playing = SrvIsPlaying();
			CoolCmdSendPacket(p->fd, CMD_IS_PLAYING|NMS_CMD_ACK, 
						  (void*)&playing, sizeof(int));
			acked = 1;
		}
		break;
		
	case CMD_GET_PLAYMODE:
		DBGLOG("CMD_GET_PLAYMODE.");
		{
			int mode = SrvGetPlaymode();
			CoolCmdSendPacket(p->fd, CMD_GET_PLAYMODE|NMS_CMD_ACK, 
						  (void*)&mode, sizeof(int));
			acked = 1;
		}
		break;
		
	case CMD_SET_PLAYMODE:
		DBGLOG("CMD_SET_PLAYMODE.");
		{
			SrvSetPlaymode(*((int*)p->data));
		}
		break;
		
	case CMD_SET_EDITMODE:
		DBGLOG("CMD_SET_EDITMODE.");
		{
			SrvSetEditmode(*((int*)p->data));
		}
		break;	
		
	case CMD_GET_REPEATMODE:
		DBGLOG("CMD_GET_REPEATMODE.");
		{
			int mode = SrvGetRepeatmode();
			CoolCmdSendPacket(p->fd, CMD_GET_REPEATMODE|NMS_CMD_ACK, 
						  (void*)&mode, sizeof(int));
			acked = 1;
		}
		break;
		
	case CMD_SET_REPEATMODE:
		DBGLOG("CMD_SET_REPEATMODE.");
		{
			SrvSetRepeatmode(*((int*)p->data));
		}
		break;
		
	case CMD_GET_TOTAL_FILES:
		DBGLOG("CMD_GET_TOTAL_FILES.");
		{
			int num = SrvGetTotalFiles();
			CoolCmdSendPacket(p->fd, CMD_GET_TOTAL_FILES|NMS_CMD_ACK, 
						  (void*)&num, sizeof(int));
			acked = 1;
		}
		break;
		
	case CMD_GET_FILE_INDEX:
		DBGLOG("CMD_GET_FILE_INDEX.");
		{
			int idx = SrvGetFileIndex();
			CoolCmdSendPacket(p->fd, CMD_GET_FILE_INDEX|NMS_CMD_ACK, 
						  (void*)&idx, sizeof(int));
			acked = 1;
		}
		break;
		
	case CMD_GET_FILE_PATH:
		DBGLOG("CMD_GET_FILE_PATH.");
		{
			char path[PATH_MAX];
			int idx;
			int *pv;
			
			pv = (int*)p->data;
			idx = *pv;
			SrvGetFilePath(idx, path,PATH_MAX);
			
			CoolCmdSendPacket(p->fd, CMD_GET_FILE_PATH|NMS_CMD_ACK, 
						  (void*)path, strlen(path)+1);
			acked = 1;
		}
		break;
		
	case CMD_MEDIA_INFO:
		DBGLOG("CMD_MEDIA_INFO.");
		{
			media_info_t media_info;
			
			memset(&media_info, 0 , sizeof(media_info_t));
			SrvGetMediaInfo((char *)p->data, &media_info);
			
			CoolCmdSendPacket(p->fd,CMD_MEDIA_INFO|NMS_CMD_ACK,
						  (void *)(&media_info),sizeof(media_info_t));
			acked = 1;
		}
		break;		

		/* start of encoder interface. */
	case CMD_RECORD:
		DBGLOG("CMD_RECORD.");

		NMS_SRV_ERROR_DETAIL result;
		StartRecord(p->data, p->hdr.dataLen, &result);

		CoolCmdSendPacket(p->fd, CMD_RECORD | NMS_CMD_ACK,
		                  (void *)(&result), sizeof(NMS_SRV_ERROR_DETAIL));
		acked = 1;

		break;

	case CMD_PAUSE_UNPAUSE_RECORD:
		DBGLOG("CMD_PAUSE_UNPAUSE_RECORD.");
		SrvPauseRecord(*(int*)p->data);
		break;
		
	case CMD_STOP_RECORD:
		DBGLOG("CMD_STOP_RECORD.");
		SrvStopRecord();
		break;
		
	case CMD_GET_GAIN:
		DBGLOG("CMD_GET_GAIN.");
		{
			int gain[2];
			SrvGetGain(&gain[0], &gain[1]);
			CoolCmdSendPacket(p->fd, CMD_GET_GAIN|NMS_CMD_ACK, 
						  (void*)gain, sizeof(gain));
			acked = 1;
		}
		break;
		
	case CMD_SET_GAIN:
		DBGLOG("CMD_SET_GAIN.");
		{
			int gain[2];
			int * pg;
			pg = (int*)p->data;
			gain[0] = *pg++;
			gain[1] = *pg;
			SrvSetGain(gain[0], gain[1]);
		}
		break;
		
	case CMD_GET_RECORD_TIME:
		DBGLOG("CMD_GET_RECORD_TIME.");
		{
			int t;
			t = SrvGetRecordtime();
			CoolCmdSendPacket(p->fd, CMD_GET_RECORD_TIME|NMS_CMD_ACK, 
						  (void*)&t, sizeof(int));
			acked = 1;
		}
		break;

	case CMD_GET_RECORD_SIZE:
		DBGLOG("CMD_GET_RECORD_SIZE.");
		{
			unsigned int t;
			t = SrvGetRecordsize();
			CoolCmdSendPacket(p->fd, CMD_GET_RECORD_SIZE|NMS_CMD_ACK, 
						  (void*)&t, sizeof(unsigned int));
			acked = 1;
		}
		break;

	case CMD_GET_RECORD_ERROR:
		DBGLOG("CMD_GET_RECORD_ERROR.");
		{
			NMS_SRV_ERROR_DETAIL det;
			SrvGetRecordError(&det);
			
			CoolCmdSendPacket(p->fd, CMD_GET_RECORD_ERROR|NMS_CMD_ACK,
			                  (void*)&det, sizeof(NMS_SRV_ERROR_DETAIL));
			acked = 1;
		}
		break;
		
	case CMD_IS_RECORDING:
		DBGLOG("CMD_IS_RECORDING.");
		{
			int recording = SrvIsRecording();
			CoolCmdSendPacket(p->fd, CMD_IS_RECORDING|NMS_CMD_ACK, 
						  (void*)&recording, sizeof(int));
			acked = 1;
		}
		break;
		
	case CMD_START_MONITOR:
		DBGLOG("CMD_START_MONITOR.");
		{
			int startmonitor;
			int pid = (*(int*)p->data);
			startmonitor = SrvStartMonitor(pid);
			CoolCmdSendPacket(p->fd, CMD_START_MONITOR|NMS_CMD_ACK, 
						  (void*)&startmonitor, sizeof(int));
			acked = 1;
			DBGLOG("CMD_START_MONITOR completed.");
		}
		break;
		
	case CMD_STOP_MONITOR:
		DBGLOG("CMD_STOP_MONITOR.");

		int pid = (*(int*)p->data);
		SrvStopMonitor(pid);
		break;

	case CMD_IS_MONITOR_ENABLED:
		DBGLOG("CMD_IS_MONITOR_ENABLED.");
		{
			int monitoractive = SrvIsMonitorActive();
			CoolCmdSendPacket(p->fd, CMD_IS_MONITOR_ENABLED|NMS_CMD_ACK, 
						  (void*)&monitoractive, sizeof(int));
			acked = 1;
		}
		break;
		
	case CMD_CAP_INIT:
		DBGLOG("CMD_CAP_INIT.");
		{
			capture_desc_t desc;
			capture_ret_t capret;
			desc.capture_type = (*(int*)p->data);
			int suc = CaptureInit(&desc);
			if(suc)
			{
				capret.width = -1;
				capret.height = -1;
			}
			else
			{
				capret.width = desc.width;
				capret.height = desc.height;
			}
			capret.ret = suc;
			CoolCmdSendPacket(p->fd,CMD_CAP_INIT|NMS_CMD_ACK,
						  (void *)(&capret),sizeof(capture_ret_t));
			acked = 1;
		}
		break;	

	case CMD_CAP_GET_FRAME:
		DBGLOG("CMD_CAP_GET_FRAME.");
		{
			frame_desc_t desc;
			int suc = CaptureGetFrame(&desc);
			if(suc)
			{
				CoolCmdSendPacket(p->fd, CMD_CAP_GET_FRAME|NMS_CMD_ACK, 
						  (void *)(&suc), sizeof(int));
			}
			else
			{
				CoolCmdSendPacket(p->fd, CMD_CAP_GET_FRAME|NMS_CMD_ACK, 
						  (void *)(desc.data), desc.size);
				CaptureReleaseFrame();
			}
			acked = 1;
		}
		break;
			
	case CMD_CAP_FINISH:
		DBGLOG("CMD_CAP_FINISH.");
		{
			int suc = CaptureFinish();
			CoolCmdSendPacket(p->fd, CMD_CAP_FINISH|NMS_CMD_ACK, 
						  (void*)&suc, sizeof(int));
			acked = 1;
		}
		break;

	case CMD_PING:
		DBGLOG("CMD_PING.");
		break;

	default:
		/* retain the data for now. */
		WPRINT("unknown command, data retained.");
	    ret = 1; 
		break;
	}
	
	/* send back original command as ack. */
	if (!acked)	
	{
		CoolCmdSendPacket(p->fd, p->hdr.cmd|NMS_CMD_ACK, NULL, 0);
		DBGLOG("server acked.");
	}
	close(p->fd);
	
	/* release data. */
	if ( 0 == ret ) 
	{
		if (p->hdr.dataLen)  free(p->data);
	} 
	
	return ret;
}
Пример #11
0
// initialize directory.
// arg: original directory/file name
// function shall set up the following,
// 1. filter the directory properly
// 2. total number of playable contents:  totalFiles
// 3. current file index:                 fileIdx
static void * dirInit( void * arg )
{
	LOCK_PLAYMUTEX();	
	if (CoolBlockOpenDir(dirName, &node) < 0)
	{
		WPRINT("unable to open directory.");
	}
	else
	{
		//DBGMSG("dirPlayAV = [%d]", dirPlayAV);
		if (dirPlayAV == DPAV_AUDIO_)
		{
			CoolFilterDirectory(&node, CoolIsAudioFile, DF_ALL);
		}
		else if (dirPlayAV == DPAV_VIDEO_)
		{
			CoolFilterDirectory(&node, CoolIsVideoFile, DF_ALL);
		}
		else if (dirPlayAV == DPAV_NOT_DETERMINED_)
		{
#ifdef PLAY_VIDEO_FILE_ONLY
			CoolFilterDirectory(&node, CoolIsVideoFile, DF_ALL);
			dirPlayAV = DPAV_VIDEO_;
#else
			if (0 == CoolFilterDirectory(&node, CoolIsVideoFile, DF_ALL))
			{
				CoolFilterDirectory(&node, CoolIsAudioFile, DF_ALL);
				dirPlayAV = DPAV_AUDIO_;
			}
			else dirPlayAV = DPAV_VIDEO_;
#endif
		}
	}

	// if is playing, get index of currently playback file
	totalFiles = node.fdnum+node.ffnum;

	if (playing)
	{
		int fi;
		char path[PATH_MAX];
		
		fileIdx = 0;
		fi = totalFiles;

		while(fi--)
		{
			if (!strcmp(trackName,CoolCatFilename2Path(path, PATH_MAX, D_PATH, D_NAME(F_INDEX(fi)))))
			{
				//DBGMSG("fi = %d", fi);
				fileIdx = fi;
				break;
			}
			//DBGMSG("fname = [%s]", trackName);
			//DBGMSG("path = [%s]", path);
		}
	}
	
	// done with directory init, broadcast.
	DBGMSG("done with directory initialization.");
	dirInited = 1;
	UNLOCK_PLAYMUTEX();

	pthread_cond_broadcast(&playdirCond);
	pthread_exit(NULL);
}
Пример #12
0
static int playFile(const char * file)
{
	int status = -1;
	media_desc_t mdesc;
	
	
	//DBGLOG("playing file: [%s]", file);
	memset(&mdesc, 0, sizeof(media_desc_t));
	mdesc.ftype = NMS_WP_INVALID;
	
	if (!InputIsOurFile(file)) return -1;
	
	status = InputInit(file, &mdesc); 
	
	switch (status) 
	{
	case 0: //everything is fine
		break; 
	case 1:
		WPRINT("InputInit: DM320 is locked by something else. Please try again later.");
		LOCK_PLAYMUTEX();
		errorStatus = NMS_STATUS_OUTPUT_LOCKED;
		UNLOCK_PLAYMUTEX();
		goto bail_clean_input;
	default:
		WPRINT("InputInit: Unable to init device!");
		LOCK_PLAYMUTEX();
		errorStatus = NMS_STATUS_NOT_PLAYABLE;
		UNLOCK_PLAYMUTEX();
		goto bail_clean_input;
	}

	LOCK_PLAYMUTEX();
	InputGetInfo(file, &info);
	UNLOCK_PLAYMUTEX();


	if (InputStart(file)) 
	{
		status = -1;
		goto bail_clean_input;
	}

	status = OutputInit(&mdesc,OutputGetMode(),curProportions); 
	switch (status)
	{
	case 0: //everything is fine
		break;
	case 1:
		WPRINT("OutputInit: DM320 is locked by something else. Please try again later.");
		LOCK_PLAYMUTEX();
		errorStatus = NMS_STATUS_OUTPUT_LOCKED;
		UNLOCK_PLAYMUTEX();
		goto bail_clean_input;
	default:
		WPRINT("OutputInit: Unable to init output !");
		LOCK_PLAYMUTEX();
		if ((playtype == NPT_FILE) || (totalFiles <= 1) || (repeat == 1))
			errorStatus = NMS_STATUS_NOT_PLAYABLE;
		UNLOCK_PLAYMUTEX();
		goto bail_clean_input;
	} 

	OutputActivateMode(0);

	LOCK_PLAYMUTEX();
	playtime = 0;
	ffrwLevel = 0;
	sfrwLevel = 0;
	sfrwLevelFinal = 0;
	muted = 0;
	playing  = 1;
	trackChange = TC_DISABLE;
	UNLOCK_PLAYMUTEX();
	
	if (newThread(&avThread, NULL, avLoop, NULL)) 
	{
		status = -1;
		goto bail_clean_input;
	}
	
	return 0;
	
bail_clean_input:
	LOCK_PLAYMUTEX();
	InputFinish();
	UNLOCK_PLAYMUTEX();
	return status;
}
Пример #13
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);
}
Пример #14
0
/**
 * Play back specified directory.
 * If file is specified, start playback that file.
 * If file is not specified, choose first file based on playmode.
 * Following playback only plays either video or audio, that is, playback
 * video only if first playback is video and playback audio only if first
 * playback is audio.
 *
 * @param dir
 *        directory path.
 * @return
 *        0 if directory playback started, in other words, at lease one
 *        playable file is found, otherwise nonzero.
 *        1 if any of the files found that output was locked when trying to play.
 */
int
SrvPlayDir( const char * dir )
{
	int status = -1;
	struct stat st;
	char * fname;
	char path[PATH_MAX];
	char loc_dirName[PATH_MAX];
	int isDir = 0;
	int loc_repeat;
	
	DBGMSG("play directory: [%s]", dir);
	stopServer();

	strcpy(loc_dirName, dir);

	LOCK_PLAYMUTEX();
	strcpy(dirName, dir);
	strcpy(trackName, dir);
	everPlayed = 0;
	dirInited = 0;
	going = 1;
	fileCnt = 1;
	playtype = NPT_DIR;
	dirPlayAV = DPAV_NOT_DETERMINED_;
	UNLOCK_PLAYMUTEX();

	// if dir corresponds to a file, start to play file immediately.
	// thus to remove the long startup delay.
	if ( 0 == stat(loc_dirName, &st) ) 
	{
		if ( S_ISDIR(st.st_mode) ) 
		{  
			isDir = 1;
			// it is a directory, continue
			//DBGMSG("directory, continue", dir);
		}
		else
		{
			char loc_trackName[PATH_MAX];

			LOCK_PLAYMUTEX();
			strcpy(loc_trackName, trackName);
			UNLOCK_PLAYMUTEX();

			isDir = 0;

			// it is a file, try to play it first.
			status = playFile(loc_trackName);
			
			if (0 == status) 
			{
				LOCK_PLAYMUTEX();
				dirPlayAV = CoolIsAudioFile(loc_trackName)? 1 : 2;
				UNLOCK_PLAYMUTEX();
			}

			// get the directory name
			{
				int len;
				char * p;
				
				LOCK_PLAYMUTEX();
				len = strlen(dirName);
				p = dirName+len;
				while(*p != '/') p--;
				*p = 0;
				UNLOCK_PLAYMUTEX();
			}
		}
	} 
	else 
	{ 
		WPRINT("Directory status not available!");	
		return -1;
	}
	
	LOCK_PLAYMUTEX();
	strcpy(loc_dirName, dirName);
	UNLOCK_PLAYMUTEX();

	if (stat(loc_dirName, &st) == -1)
	{
		LOCK_PLAYMUTEX();		
		errorStatus = NMS_STATUS_NOT_PLAYABLE;
		UNLOCK_PLAYMUTEX();
		return -1;
	}

	if (newThread(&nextFileThread, NULL, nextFileLoop, NULL))
	{
		return -1;
	}

	//DBGMSG("create directory init thread", dir);
	// Create thread to init directory.
	if (newThread(&dirInitThread, NULL, dirInit, NULL))
	{
		stopServer();
		return -1;
	}

	// file played?
	// If not, wait to get first file played, because we have to return
	// a status here to indicate whether the playback can be successfully 
	// started or not.
	if (status)
	{
		LOCK_PLAYMUTEX();
		loc_repeat = repeat;
		UNLOCK_PLAYMUTEX();
		
		// not single repeat or trackName is directory, wait to get first file played 
		if (loc_repeat != RM_REPEAT || isDir) 
		{
			int cnt; // counter of retry
			int idx = 0;

			//DBGMSG("playback not started yet", dir);
			// NO, wait till directory is initialized.
			LOCK_PLAYMUTEX();
			while (!dirInited) 
				pthread_cond_wait(&playdirCond, &playMutex);
			
			// Now try to get next file and play it.
			fileIdx = 0;
			cnt = totalFiles;
			UNLOCK_PLAYMUTEX();

			// try each file at most once.
			while(cnt--)
			{
				fname = nextFileFromDir(idx,path,PATH_MAX);
				if (!fname) break;
				
				status = playFile(fname);
				
				//DBGMSG("status = [%d]", status);
				if (!status) break;
				else
				{
					LOCK_PLAYMUTEX();
					idx++;
					fileIdx++;
					UNLOCK_PLAYMUTEX();
				}
			} 
			if (cnt <= 0)
			{
				LOCK_PLAYMUTEX();
				errorStatus = NMS_STATUS_NOT_PLAYABLE;
				UNLOCK_PLAYMUTEX();
			}
		}
	}
	
	// Stop server to clean up if not able to play.
	if (status)	stopServer();
	else
	{
		LOCK_PLAYMUTEX();
		playState = NMS_STATUS_PLAYER_PLAY; 
		errorStatus = NMS_STATUS_OK;
		UNLOCK_PLAYMUTEX();
	}

	return status;
}