PcmAudioFile.c 7.1 KB
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <dirent.h>  
#include <sys/stat.h>  

#include "JZsdkLib.h"
#include "Megaphone/AudioMange/AudioMange.h"

#define PCM_DIR "/root/sdcard/pcm"

//创建一个pcm节点
static struct AudioMange_Node *g_PcmList = NULL;
static struct AudioMange_Node *g_PcmListtail = NULL; // 用于跟踪链表的尾部  

static int g_PcmListNum = 0; //用于记录链表中的节点数量
static int g_PcmList_CurrentNum = 0; //用于记录链表中当前节点位置

/*****************
 * 
 *  获取pcm文件列表的歌曲数
 * 
 * ************/
int PcmFile_GetListNum()
{
	return g_PcmListNum;
}

/*********
 * 
 *  pcm文件链表注销
 * 
**********/
static T_JZsdkReturnCode PcmFile_FreeAudioList()
{
	//清空尾部指针
	g_PcmListtail = NULL; 

	//清空歌曲数量
	g_PcmListNum = 0; //记录链表中一共有几首歌
	g_PcmList_CurrentNum = 0; //记录播放当前第几首歌

	//释放掉整个链表
	Jzsdk_Free_AndioMange_Node(&g_PcmList);

	g_PcmList = NULL;

	return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}

/*********
 * 
 *  pcm文件链表刷新
 * 
**********/
T_JZsdkReturnCode PcmFile_FlushList()
{
	//读取audio文件夹,并将歌曲名放入音频列表
	DIR *dir;  
    struct dirent *entry;  
	struct stat fileStat;
    
    //创建一个临时pcm节点
    struct AudioMange_audio_struct PcmInfo;  
	T_JZsdkReturnCode ret;
  
	//检查是否存在pcm文件夹,没有则创建一个
    if(JZsdk_check_directory_exists_posix(PCM_DIR) != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
    {
        JZSDK_LOG_ERROR("不存在pcm文件夹,创建一个");
        JZsdk_Osal_Mkdir(PCM_DIR);
    }

	//确定音频文件夹存在
    if ((dir = opendir(PCM_DIR)) == NULL) 
    {  
		JZSDK_LOG_ERROR("音频文件夹获取失败");
		return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
	}

	//查看歌曲存放链表是否有注册过
	if (g_PcmList != NULL)
	{
		PcmFile_FreeAudioList();
	}
	
	while ((entry = readdir(dir)) != NULL) 
	{  
		const unsigned char *filename = entry->d_name;  
		unsigned int fileSize;
		int len = strlen(filename);  

		// // 获取文件状态信息,包括大小  
		// if (stat(filename, &fileStat) == 0) 
		// {  
		// 	fileSize = (unsigned long long)fileStat.st_size;  
		// }
		// else
		// {
		// 	JZSDK_LOG_ERROR("%s文件信息获取错误",filename);
		// 	fileSize = 0;
		// 	continue;
		// }
			
		// 跳过目录和隐藏文件,并检查文件扩展名  
		if (entry->d_type != DT_DIR && strcmp(filename, ".") != 0 && strcmp(filename, "..") != 0) 
		{ 	
			//printf("获取到%s\n",filename);

			// 检查后缀  
			if (JZsdk_strings_suffix_comparison_withLen((const unsigned char *)filename, len, (const unsigned char *)".pcm") == JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS
				|| JZsdk_strings_suffix_comparison_withLen((const unsigned char *)filename, len, (const unsigned char *)".PCM") == JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS
			) 
			{
				// 处理文件  
				memset(&PcmInfo, 0, sizeof(PcmInfo)); // 清除audioInfo结构  

				//写入文件名
				strncpy(PcmInfo.FileName, entry->d_name, JZSDK_FILE_NAME_SIZE_MAX); 

				unsigned char fileDir [256];
				snprintf(fileDir, sizeof(fileDir), "%s/%s",PCM_DIR, filename);

				//写入文件大小
				JZsdk_Fs_ReadFileSize(fileDir, &(PcmInfo.FileSize));

				//根据文件大小写入时长信息
                int temp_time = (PcmInfo.FileSize * 8) / (16000 * 16 * 1); //这条是pcm算时长,超准确
                //int temp_time = (PcmInfo.FileSize * 8) / (16000); //这条是opus算时长,超准确
                PcmInfo.Time = temp_time;

				//写入文件名长度    
				PcmInfo.FileNameLen = len;

				// 创建新节点 
				struct AudioMange_Node *newNode = NULL;
				ret = Jzsdk_Create_AndioMange_Node(&newNode, PcmInfo) ;  
				if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS) 
				{  
					JZSDK_LOG_ERROR("存放pcm节点 %s 失败", entry->d_name); 
					continue;  
				}  

				// 将新节点添加到链表末尾  
				Jzsdk_AddAudioNodeToCircularList(&g_PcmList, &g_PcmListtail, &newNode);

				// 歌曲计数+1
				g_PcmListNum++;
			}
		}
	}  
  
    closedir(dir);  

	//设置默认播放歌曲
	g_PcmList_CurrentNum = 0;

	//打印一遍已加载的音乐
	JZsdk_PrintfAuidoNode_AudioList(g_PcmList);

	JZSDK_LOG_INFO("刷新pcm列表已完成");

    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;  
}


/*********************************
 * 
 * 
 *  获取某序号下的歌曲名字
 * 
 * 
 * *********************************/
T_JZsdkReturnCode Megaphone_PcmFile_GetAudioNameByIndex(int index, unsigned char *name, int *name_len)
{
	T_JZsdkReturnCode ret ;

	//判断歌曲列表是否有歌
	if (g_PcmListNum == 0)
	{
		JZSDK_LOG_INFO("pcm列表中没有歌");
		return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
	}

	//判断序号是否在数量内
	if (index > g_PcmListNum)
	{
		JZSDK_LOG_INFO("pcm列表中没有第%d首歌",index);
		return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
	}

	//根据当前的索引值,获取当前的歌曲节点
	struct AudioMange_Node *Current = NULL;	
	ret = getAudioMange_NodeAtIndex(g_PcmList, &Current, index);
	if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
	{
		return ret;
	}
	if (Current == NULL)
	{
		return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
	}

	//获取名字,后期这里要改动以下,太危险了, 要限制长度
	memcpy(name, Current->audioInfo.FileName, Current->audioInfo.FileNameLen);
	*name_len = Current->audioInfo.FileNameLen;

	return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}

/***********
 * 
 *   查询pcm是否存在于列表
 * 
 * **********/
T_JZsdkReturnCode Megaphone_PcmFile_IsExistInList(unsigned char *str, unsigned int str_len)
{
	T_JZsdkReturnCode	ret;

    //1、查询该名字是否存在于音乐列表中
	struct AudioMange_audio_struct songToFind;
	memset(&songToFind, 0, sizeof(struct AudioMange_audio_struct));

	memset(songToFind.FileName, 0 ,sizeof(songToFind.FileName));
	memcpy(songToFind.FileName, str, str_len);

	ret = JZsdk_isSongInAudioList(g_PcmList, songToFind);
	if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
	{
		JZSDK_LOG_ERROR("播放文件不存在于pcm列表 %s", songToFind.FileName);
		return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
	}

	return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}

/*****************
 * 
 *  查询pcm信息
 * 
 * 
 * 	**************/
T_JZsdkReturnCode PcmFile_GetAudioInfo(unsigned char *str, unsigned int str_len, struct AudioMange_audio_struct *songToFind)
{
	T_JZsdkReturnCode	ret;

    //1、查询该名字是否存在于音乐列表中
	memset(songToFind->FileName, 0 ,sizeof(songToFind->FileName));
	memcpy(songToFind->FileName, str, str_len);

	ret = JZsdk_isSongInAudioList(g_PcmList, (*songToFind));
	if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
	{
		JZSDK_LOG_ERROR("播放文件不存在于pcm列表 %s", songToFind->FileName);
		return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
	}

	//2、获取歌曲信息
	JZsdk_GetSongInDudioList_AudioInfo(g_PcmList, songToFind);

	return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}

/*********
 * 
 *  pcm文件初始化
 * 
**********/
T_JZsdkReturnCode Megaphone_PcmFile_Init()
{
	//刷新pcm列表(用于加载新的pcm文件)
	PcmFile_FlushList();

	JZSDK_LOG_DEBUG("pcmFile Init Complete");
}