static NotificationAttributes * LookupNotificationAttributes(struct ListHead * attributesList, int shortServerID, ObjectIDType objectID, ObjectInstanceIDType objectInstanceID, ResourceIDType resourceID) { NotificationAttributes * result = NULL; if (attributesList != NULL) { struct ListHead * i; ListForEach(i, attributesList) { NotificationAttributes * attributes = ListEntry(i, NotificationAttributes, list); if ((attributes != NULL) && (attributes->ShortServerID == shortServerID) && (attributes->ObjectID == objectID) && (attributes->ObjectInstanceID == objectInstanceID) && (attributes->ResourceID == resourceID)) { result = attributes; break; } } if (result == NULL) { // doesn't exist yet, so create result = malloc(sizeof(NotificationAttributes)); memset(result, 0, sizeof(NotificationAttributes)); memset(result->Valid, 0, sizeof(result->Valid)); result->ObjectID = objectID; result->ObjectInstanceID = objectInstanceID; result->ResourceID = resourceID; result->ShortServerID = shortServerID; ListAdd(&result->list, attributesList); } }
//////////////////////////////////////////////////// // 功能: // 输入: // 输出: // 返回: // 说明: //////////////////////////////////////////////////// int MediaSrvRegistCallback(int type, DWORD device, PMEDIA_CALLBACK callback) { PLIST n; PLIST head; PCALLBACK_LINK check; PCALLBACK_LINK link; // 申请节点,并初始化 link = kmalloc(sizeof(CALLBACK_LINK)); if(link == NULL) return -1; kmemcpy(&link->Callback, callback, sizeof(MEDIA_CALLBACK)); link->Type = type; link->Device = device; ListInit(&link->Link); // 检查设备是否已经注册 head = &MediaCallbackList; for(n=ListFirst(head); n!=head; n=ListNext(n)) { check = ListEntry(n, CALLBACK_LINK, Link); if(&check->Callback == callback) { kfree(link); return -1; } } ListInsert(&MediaCallbackList, &link->Link); return 0; }
//////////////////////////////////////////////////// // 功能: 结束某一任务的媒体播放,并锁定媒体播放任务 // 输入: // 输出: // 返回: // 说明: //////////////////////////////////////////////////// void MediaTerminateLock(HANDLE htask) { PMEDIA_OBJECT obj; PLIST list; kMutexWait(hMediaMutex); list = &MediaObjList; if(!ListEmpty(list)) { // 获取正在音频任务节点 obj = ListEntry(ListFirst(list), MEDIA_OBJECT, Link); if(obj->hTask == htask) { // 结束当前正在录放的音频任务 obj->Cb.MediaClose(obj->Media, 1); obj->Cb.MediaDestroy(obj->Media); ListRemove(&obj->Link); HandleDestroy(obj->Header.Handle, MEDIA_MAGIC); if(obj->MediaInfo) kfree(obj->MediaInfo); kfree(obj); } } }
//////////////////////////////////////////////////// // 功能: // 输入: // 输出: // 返回: // 说明: //////////////////////////////////////////////////// int MediaSrvDestroyNotify(void *media) { PLIST head; PLIST n; PMEDIA_OBJECT obj; // kMutexWait(hMediaMutex); head = &MediaObjList; // 搜索指定音频任务 for(n = ListFirst(head); n != head; n = ListNext(n)) { obj = ListEntry(n, MEDIA_OBJECT, Link); if(obj->Media == media) { // 释放当前节点 kdebug(mod_media, PRINT_INFO, "CLOSE Notify: 0x%x\n", obj->Header.Handle); ListRemove(&obj->Link); HandleDestroy(obj->Header.Handle, MEDIA_MAGIC); if(obj->MediaInfo) kfree(obj->MediaInfo); kfree(obj); // 启动下一个等待任务 n = ListFirst(head); if(n != head) { obj = ListEntry(n, MEDIA_OBJECT, Link); if(obj->Mode == MEDIA_MODE_WAIT) { if(obj->Cb.MediaOpen(obj->Media) < 0) { ListRemove(&obj->Link); HandleDestroy(obj->Header.Handle, MEDIA_MAGIC); if(obj->MediaInfo) kfree(obj->MediaInfo); kfree(obj); } } } // kMutexRelease(hMediaMutex); return 0; } } // kMutexRelease(hMediaMutex); return -1; }
void for_each(T const &fn) { struct udev_list_entry *entry; udev_list_entry_foreach(entry, p) { if (!fn(ListEntry(entry))) break; } }
void Array_Free(struct ListHead * ValueList, AwaResourceType resourceType) { struct ListHead * current, * next; ListForEachSafe(current, next, ValueList) { ArrayItem * valueItem = ListEntry(current, ArrayItem, List); ListRemove(current); Array_FreeItem(valueItem, resourceType); }
int MediaSrvDestroy(HANDLE hmedia) #endif { PMEDIA_OBJECT obj; int playback; kMutexWait(hMediaMutex); // 获取音频对象 obj = (PMEDIA_OBJECT)HandleGet(hmedia, MEDIA_MAGIC); if(obj == NULL) { kdebug(mod_media, PRINT_ERROR, "CLOSE NULL: 0x%x\n", hmedia); kMutexRelease(hMediaMutex); return -1; } kdebug(mod_media, PRINT_INFO, "CLOSE: 0x%x\n", hmedia); // 结束当前正在录放的音频任务 playback = obj->Cb.MediaClose(obj->Media, 1); obj = (PMEDIA_OBJECT)HandleGet(hmedia, MEDIA_MAGIC); if(obj == NULL) { kdebug(mod_media, PRINT_ERROR, "CLOSE NULL NULL: 0x%x\n", hmedia); kMutexRelease(hMediaMutex); return -1; } obj->Cb.MediaDestroy(obj->Media); // 释放当前节点 ListRemove(&obj->Link); HandleDestroy(hmedia, MEDIA_MAGIC); if(obj->MediaInfo) kfree(obj->MediaInfo); kfree(obj); // 启动下一个等待任务 if(!ListEmpty(&MediaObjList)) { obj = ListEntry(ListFirst(&MediaObjList), MEDIA_OBJECT, Link); if(playback && (obj->Mode == MEDIA_MODE_WAIT)) { if(obj->Cb.MediaOpen(obj->Media) < 0) { HandleDestroy(obj->Header.Handle, MEDIA_MAGIC); if(obj->MediaInfo) kfree(obj->MediaInfo); kfree(obj); } } } kMutexRelease(hMediaMutex); return 0; }
static Lwm2mServerType * GetServerObjectByObjectInstanceID(Lwm2mContextType * context, int objectInstanceID) { Lwm2mServerType * serverObject = NULL; struct ListHead * i; ListForEach(i, Lwm2mCore_GetServerList(context)) { Lwm2mServerType * server = ListEntry(i, Lwm2mServerType, list); if (server->ServerObjectInstanceID == objectInstanceID) { serverObject = server; } }
static Lwm2mObserverType * LookupObserver(void * ctxt, AddressType * addr, ObjectIDType objectID, ObjectInstanceIDType objectInstanceID, ResourceIDType resourceID) { Lwm2mContextType * context = (Lwm2mContextType *) ctxt; struct ListHead * i, *n; ListForEachSafe(i, n, Lwm2mCore_GetObserverList(context)) { Lwm2mObserverType * observer = ListEntry(i, Lwm2mObserverType, list); if ((observer->ObjectID == objectID) && (observer->ObjectInstanceID == objectInstanceID) && (observer->ResourceID == resourceID) && (memcmp(&observer->Address, addr, sizeof(AddressType)) == 0)) { return observer; } }
//Performs the user mode memory checks on the current memory context static bool MemChecks(unsigned int addr, unsigned int length, unsigned int flagsReqd) { //Kernel checks handled separately if(addr >= 0xC0000000) { //Return true if not wrapping around return (addr + length) >= addr; } //Find first region MemContext * context = ProcCurrProcess->memContext; MemRegion * region = MemRegionFind(context, (void *) addr); while(region != NULL && (region->flags & flagsReqd) == flagsReqd) { //Calculate data left unsigned int end = region->start + region->length; unsigned int lengthLeft = end - addr; if(lengthLeft >= length) { //Passed (since we known this region is readable) return true; } //Move to next region if it is continuous if(region->listItem.next == &context->regions) { //This is the last region, fail return false; } region = ListEntry(region->listItem.next, MemRegion, listItem); if (region->start == end) { //Not continuous, fail return false; } //Update parameters addr = region->start; length -= lengthLeft; } return false; }
//////////////////////////////////////////////////// // 功能: 根据媒体类型,获取媒体回调函数 // 输入: // 输出: // 返回: // 说明: //////////////////////////////////////////////////// static int MediaSrvGetCallback(int type, PMEDIA_CALLBACK callback) { PLIST n; PLIST head; PCALLBACK_LINK link; // 检查设备是否已经注册 head = &MediaCallbackList; for(n=ListFirst(head); n!=head; n=ListNext(n)) { link = ListEntry(n, CALLBACK_LINK, Link); if((link->Type & type) == type) { kmemcpy(callback, &link->Callback, sizeof(MEDIA_CALLBACK)); return 0; } } return -1; }
//Sets the PROCESS alarm TimerTime TimerSetAlarm(TimerTime time) { TimerTime timeLeft; TimerQueue * queueHead; //First, remove previous alarm if(ProcCurrProcess->alarmPtr != NULL) { //Get time left queueHead = ListEntry(ProcCurrProcess->alarmPtr, TimerQueue, list); timeLeft = queueHead->endTime - currentTime; //Remove from list + free ListDelete(&queueHead->list); MemKFree(queueHead); //Wipe from process ProcCurrProcess->alarmPtr = NULL; } else { timeLeft = 0; } //If time is not 0, create new alarm if(time != 0) { //Create alarm queueHead = MemKAlloc(sizeof(TimerQueue)); queueHead->process = ProcCurrProcess; queueHead->endTime = time; //Add to list AddTimerToQueue(queueHead, &alarmQueueHead); //Add to process ProcCurrProcess->alarmPtr = &queueHead->list; } return timeLeft; }
//////////////////////////////////////////////////// // 功能: 得到BUF里剩余数据的时间 // 输入: // 输出: // 返回: // 说明: //////////////////////////////////////////////////// int GetDacSpaceCount() { int i; int len; PLIST head, n; PDAC_DEVICE dac; PRESAMPLE presample; kMutexWait(hDacMutex); len = 0; head = &DacList; if( head ) { n=ListFirst(head); dac = ListEntry(n, DAC_DEVICE, Link); if( dac ) { presample = &dac->Resample; for( i = 0 ; i < MAX_PCMBUFS ; i++ ) { if( presample->BufFlag[i] == DAC_BUF_WRITE ) len +=DAC_PCMBUF_SIZE; } } } presample = &DacDevice; for( i = 0 ; i < MAX_PCMBUFS ; i++ ) { if( presample->BufFlag[i] == DAC_BUF_WRITE ) len +=DAC_PCMBUF_SIZE; } kMutexRelease(hDacMutex); len = ((long long)len * nMplayerSamplerate * nMplayerChannels * 2) / (DAC_SAMPLE_RATIO * 2 * 2); len = len & (~0x03); return len; }
//////////////////////////////////////////////////// // 功能: // 输入: // 输出: // 返回: // 说明: //////////////////////////////////////////////////// static void DacWriteThread(DWORD p) { int bopen; char play_flag; short *pcm; short gvol; pcm = NULL; bopen = 0; gvol = 0; for(;;) { PLIST head, n; short *src[4]; short vol[4]; PDAC_DEVICE dac[4]; int chs; int i, j; int tmp; // 等待DAC设备创建 if(!bopen) { kSemaWait(hDacSema, 0); bopen = 1; pcm = (short*)kmalloc(DAC_PCMBUF_SIZE); } // 检查DAC是否已经关闭 kMutexWait(hDacMutex); if(ListEmpty(&DacList)) { if(pcm) { kfree(pcm); pcm = NULL; } bopen = 0; kMutexRelease(hDacMutex); continue; } // 检查缓冲区是否获取 if(pcm == NULL) { kMutexRelease(hDacMutex); sTimerSleep(1000, NULL); continue; } // 获取采样数据到临时缓冲区 head = &DacList; chs = play_flag = 0; for(n=ListFirst(head); n!=head; n=ListNext(n)) { dac[chs] = ListEntry(n, DAC_DEVICE, Link); src[chs] = DacGetPcmBuf(dac[chs]); vol[chs] = dac[chs]->Volume * DacGetGloalVolume() / 10; if( dac[chs]->fThreadStart ) play_flag = 1; if(++chs == 4) break; // 最多合成4通道 } // 检查是否存在有效数据 for(i=0; i<chs; i++) { if(src[i]) break; } if( play_flag == 0 ) { kMutexRelease(hDacMutex); sTimerSleep(10, NULL); continue; } if(i == chs ) { kMutexRelease(hDacMutex); sTimerSleep(10, NULL); continue; } if(chs > 1) { // 强制同步合成声音. 注意: // 1. 两路声音, 单独播放时不会卡, 但是合成播放卡, 可能是因为这两路声音s // 产生数据的 速率 不同造成的. 当其中一路很快, 另外一路很慢, // 就会以 速率 快的一路来合成声音, 导致 速率 慢的一路声音卡. // 2. 解决方法是强制快的一路等待慢的一路. // 3. 但是声音暂停和声音在停止过程中这两种情况, 不需要同步. for(i = 0; i < chs; i++) { //kprintf("src[%d]:0x%08x, Pause:%d, fThreadStart:%d, vol[%d]:%d\n", i, src[i], dac[i]->Pause, dac[i]->fThreadStart, i, vol[i]); // 无数据, 非暂停, 已经开始合成, 声音不是在停止的过程中 if( !src[i] && !dac[i]->Pause && dac[i]->fThreadStart == 1 ) { break; } } // 表示有某路声音没有数据, 但是不表示这路声音会卡. if(i != chs) { int buf_cnt = 0; PRESAMPLE presample; // 求DAC输出缓冲中还有多少个 有数据 的缓冲. presample = &DacDevice; for( j = 0 ; j < MAX_PCMBUFS ; j++ ) { if( presample->BufFlag[j] == DAC_BUF_READ ) buf_cnt++; } // 如果DAC缓冲少, 认为 有可能 会造成所有声音都卡, 所以合成有 // 数据的声音. 其结果是没有数据的那路声音一定会卡, // 即使这路声音本身 已经存有(缓冲中) 的数据播放是不会卡的. // DAC缓冲多, 那么睡眠, 等待没有数据的那路声音. if(buf_cnt <= 11) { //kprintf("bufcount:%d\n", buf_cnt); } else { //kprintf("bufcount:%d\n", buf_cnt); kMutexRelease(hDacMutex); sTimerSleep(10, NULL); continue; } } } // 合成多通道音频数据 if(chs > 1) { for(i=0; i<DAC_PCMBUF_SIZE/sizeof(short); i++) { tmp = 0; for(j=0; j<chs; j++) { if(src[j] && vol[j]) tmp += src[j][i] * vol[j]; } tmp /= 1024; if(tmp >= 32767) { pcm[i] = 32767; nErrorData++; } else if(tmp < -32767) { pcm[i] = -32767; nErrorData++; } else pcm[i] = (short)tmp; } } else // 处理单通道音频数据 { short volume; volume = vol[0]; for(i=0; i<DAC_PCMBUF_SIZE/sizeof(short); i++) pcm[i] = (short)((src[0][i] * volume) / 1024); } DacOutDeviceSet(); // 写入音频数据到DMA处理缓冲 if(SavePcmData(pcm)) { // 设置缓冲区读取完毕 for(i=0; i<chs; i++) { if(src[i] != NULL) DacGetPcmOk(dac[i]); } if( fBeginDma == INIT_DMA_TRANS ) { fBeginDma = RUNING_DMA_TRANS; } kMutexRelease(hDacMutex); } else { kMutexRelease(hDacMutex); sTimerSleep(10, NULL); } } }
//Timer interrupt static void TimerInterrupt(IntrContext * iContext) { IGNORE_PARAM iContext; //Update system time currentTime += PIT_TICKS_PER_INTERRUPT; //Decrement quantum if(TimerQuantum > 0) { --TimerQuantum; } //Stop beep if run out of time if(beepEndTime != 0 && currentTime >= beepEndTime) { TimerBeepStop(); } //Process sleep queue if(!ListEmpty(&sleepQueueHead)) { TimerQueue * head = ListEntry(sleepQueueHead.next, TimerQueue, list); TimerQueue * newHead; while(currentTime >= head->endTime) { //Wake up head ProcWakeUp(head->thread); //Get next head newHead = ListEntry(head->list.next, TimerQueue, list); //Remove current from queue ListDelete(&head->list); MemKFree(head); //Next head head = newHead; //Check wrapped if(ListEmpty(&sleepQueueHead)) { break; } } } //Process alarm queue if(!ListEmpty(&alarmQueueHead)) { TimerQueue * head = ListEntry(alarmQueueHead.next, TimerQueue, list); TimerQueue * newHead; while(currentTime >= head->endTime) { //Send signal and remove process pointer ProcSignalSendProcess(head->process, SIGALRM); head->process->alarmPtr = NULL; //Get next head newHead = ListEntry(head->list.next, TimerQueue, list); //Remove current from queue ListDelete(&head->list); MemKFree(head); //Next head head = newHead; //Check wrapped if(ListEmpty(&alarmQueueHead)) { break; } } } }
HANDLE MediaSrvCreate(void *media, char *name, int type, int preempt) #endif { PLIST head; PLIST n; PMEDIA_OBJECT obj; // 参数检查 if(media == NULL) return NULL; // 检查当前是否存在录放任务 kMutexWait(hMediaMutex); head = &MediaObjList; if(!ListEmpty(head) && (preempt != MEDIA_MODE_NORMAL)) { // 检查是否强行结束正在录放的音频 if(preempt == MEDIA_MODE_PREEMPTIVE) { // 获取正在音频任务节点 n = ListFirst(head); obj = ListEntry(n, MEDIA_OBJECT, Link); // 结束当前正在录放的音频任务 obj->Cb.MediaClose(obj->Media, 1); obj->Cb.MediaDestroy(obj->Media); // 释放当前节点 ListRemove(&obj->Link); HandleDestroy(obj->Header.Handle, MEDIA_MAGIC); if(obj->MediaInfo) kfree(obj->MediaInfo); kfree(obj); // 申请并初始化节点 obj = MediaSrvObjCreate(media, name, type); if(obj == NULL) { kMutexRelease(hMediaMutex); return NULL; } // 启动新的播放任务 if(obj->Cb.MediaOpen(obj->Media) < 0) { if(obj->MediaInfo) kfree(obj->MediaInfo); kfree(obj); kMutexRelease(hMediaMutex); return NULL; } // 把节点插入任务队列 ListInsert(head, &obj->Link); } else { // 申请并初始化节点 obj = MediaSrvObjCreate(media, name, type); if(obj == NULL) { kMutexRelease(hMediaMutex); return NULL; } // 把当前音频插入等待队列尾部 ListInsert(ListPrev(head), &obj->Link); } } else { // 申请并初始化节点 obj = MediaSrvObjCreate(media, name, type); if(obj == NULL) { kMutexRelease(hMediaMutex); return NULL; } // 启动新的录放任务 if(obj->Cb.MediaOpen(obj->Media) < 0) { if(obj->MediaInfo) kfree(obj->MediaInfo); kfree(obj); kMutexRelease(hMediaMutex); return NULL; } // 把当前音频插入等待队列尾部 ListInsert(head, &obj->Link); } kMutexRelease(hMediaMutex); { HANDLE hret = HandleSet(obj, MEDIA_MAGIC, sMediaSrvDestroy); kdebug(mod_media, PRINT_INFO, "OPEN: 0x%x\n", hret); return hret; } }
int MediaSrvMaster(char *process, int max, int type) #endif { PMEDIA_OBJECT obj; PLIST head; PLIST n; int tasks; int owners; int len; // 获取媒体使用的设备 kMutexWait(hMediaMutex); // if(ListEmpty(&MediaObjList)) // { // kMutexRelease(hMediaMutex); // return 0; // } // 循环获取所有正在播放的音频任务名称,并用分隔符返回 if(process) kstrcpy(process, ""); tasks = 0; len = 0; head = &MediaObjList; for(n=ListFirst(head); n!=head; n=ListNext(n)) { // 获取打开设备对象 obj = ListEntry(n, MEDIA_OBJECT, Link); if(process) { if(tasks) { len++; if(len < max) kstrcat(process, ";"); } if(obj->MediaInfo) { len += kstrlen(obj->MediaInfo); if(len < max) kstrcat(process, obj->MediaInfo); } else { len += 6; if(len < max) kstrcat(process, "<NULL>"); } } tasks++; } // 获取打开DAC设备情况 owners = DacGetOwners(); if(owners > tasks) { if(process) { if(tasks) { len++; if(len < max) kstrcat(process, ";"); } len += 8; if(len < max) kstrcat(process, "<DIRECT>"); } tasks = owners; } kMutexRelease(hMediaMutex); return tasks; }