⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 seq_instr.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *   Generic Instrument routines for ALSA sequencer *   Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz> * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * */ #include <sound/driver.h>#include <linux/init.h>#include <linux/slab.h>#include <sound/core.h>#include "seq_clientmgr.h"#include <sound/seq_instr.h>#include <sound/initval.h>MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer instrument library.");MODULE_LICENSE("GPL");static void snd_instr_lock_ops(snd_seq_kinstr_list_t *list){	if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) {		spin_lock_irqsave(&list->ops_lock, list->ops_flags);	} else {		down(&list->ops_mutex);	}}static void snd_instr_unlock_ops(snd_seq_kinstr_list_t *list){	if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) {		spin_unlock_irqrestore(&list->ops_lock, list->ops_flags);	} else {		up(&list->ops_mutex);	}}static snd_seq_kinstr_t *snd_seq_instr_new(int add_len, int atomic){	snd_seq_kinstr_t *instr;		instr = kzalloc(sizeof(snd_seq_kinstr_t) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);	if (instr == NULL)		return NULL;	instr->add_len = add_len;	return instr;}static int snd_seq_instr_free(snd_seq_kinstr_t *instr, int atomic){	int result = 0;	if (instr == NULL)		return -EINVAL;	if (instr->ops && instr->ops->remove)		result = instr->ops->remove(instr->ops->private_data, instr, 1);	if (!result)		kfree(instr);	return result;}snd_seq_kinstr_list_t *snd_seq_instr_list_new(void){	snd_seq_kinstr_list_t *list;	list = kzalloc(sizeof(snd_seq_kinstr_list_t), GFP_KERNEL);	if (list == NULL)		return NULL;	spin_lock_init(&list->lock);	spin_lock_init(&list->ops_lock);	init_MUTEX(&list->ops_mutex);	list->owner = -1;	return list;}void snd_seq_instr_list_free(snd_seq_kinstr_list_t **list_ptr){	snd_seq_kinstr_list_t *list;	snd_seq_kinstr_t *instr;	snd_seq_kcluster_t *cluster;	int idx;	unsigned long flags;	if (list_ptr == NULL)		return;	list = *list_ptr;	*list_ptr = NULL;	if (list == NULL)		return;		for (idx = 0; idx < SNDRV_SEQ_INSTR_HASH_SIZE; idx++) {				while ((instr = list->hash[idx]) != NULL) {			list->hash[idx] = instr->next;			list->count--;			spin_lock_irqsave(&list->lock, flags);			while (instr->use) {				spin_unlock_irqrestore(&list->lock, flags);				schedule_timeout_interruptible(1);				spin_lock_irqsave(&list->lock, flags);			}							spin_unlock_irqrestore(&list->lock, flags);			if (snd_seq_instr_free(instr, 0)<0)				snd_printk(KERN_WARNING "instrument free problem\n");		}		while ((cluster = list->chash[idx]) != NULL) {			list->chash[idx] = cluster->next;			list->ccount--;			kfree(cluster);		}	}	kfree(list);}static int instr_free_compare(snd_seq_kinstr_t *instr,			      snd_seq_instr_header_t *ifree,			      unsigned int client){	switch (ifree->cmd) {	case SNDRV_SEQ_INSTR_FREE_CMD_ALL:		/* all, except private for other clients */		if ((instr->instr.std & 0xff000000) == 0)			return 0;		if (((instr->instr.std >> 24) & 0xff) == client)			return 0;		return 1;	case SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE:		/* all my private instruments */		if ((instr->instr.std & 0xff000000) == 0)			return 1;		if (((instr->instr.std >> 24) & 0xff) == client)			return 0;		return 1;	case SNDRV_SEQ_INSTR_FREE_CMD_CLUSTER:		/* all my private instruments */		if ((instr->instr.std & 0xff000000) == 0) {			if (instr->instr.cluster == ifree->id.cluster)				return 0;			return 1;		}		if (((instr->instr.std >> 24) & 0xff) == client) {			if (instr->instr.cluster == ifree->id.cluster)				return 0;		}		return 1;	}	return 1;}int snd_seq_instr_list_free_cond(snd_seq_kinstr_list_t *list,			         snd_seq_instr_header_t *ifree,			         int client,			         int atomic){	snd_seq_kinstr_t *instr, *prev, *next, *flist;	int idx;	unsigned long flags;	snd_instr_lock_ops(list);	for (idx = 0; idx < SNDRV_SEQ_INSTR_HASH_SIZE; idx++) {		spin_lock_irqsave(&list->lock, flags);		instr = list->hash[idx];		prev = flist = NULL;		while (instr) {			while (instr && instr_free_compare(instr, ifree, (unsigned int)client)) {				prev = instr;				instr = instr->next;			}			if (instr == NULL)				continue;			if (instr->ops && instr->ops->notify)				instr->ops->notify(instr->ops->private_data, instr, SNDRV_SEQ_INSTR_NOTIFY_REMOVE);			next = instr->next;			if (prev == NULL) {				list->hash[idx] = next;			} else {				prev->next = next;			}			list->count--;			instr->next = flist;			flist = instr;			instr = next;		}		spin_unlock_irqrestore(&list->lock, flags);		while (flist) {			instr = flist;			flist = instr->next;			while (instr->use)				schedule_timeout_interruptible(1);			if (snd_seq_instr_free(instr, atomic)<0)				snd_printk(KERN_WARNING "instrument free problem\n");			instr = next;		}	}	snd_instr_unlock_ops(list);	return 0;	}static int compute_hash_instr_key(snd_seq_instr_t *instr){	int result;		result = instr->bank | (instr->prg << 16);	result += result >> 24;	result += result >> 16;	result += result >> 8;	return result & (SNDRV_SEQ_INSTR_HASH_SIZE-1);}#if 0static int compute_hash_cluster_key(snd_seq_instr_cluster_t cluster){	int result;		result = cluster;	result += result >> 24;	result += result >> 16;	result += result >> 8;	return result & (SNDRV_SEQ_INSTR_HASH_SIZE-1);}#endifstatic int compare_instr(snd_seq_instr_t *i1, snd_seq_instr_t *i2, int exact){	if (exact) {		if (i1->cluster != i2->cluster ||		    i1->bank != i2->bank ||		    i1->prg != i2->prg)			return 1;		if ((i1->std & 0xff000000) != (i2->std & 0xff000000))			return 1;		if (!(i1->std & i2->std))			return 1;		return 0;	} else {		unsigned int client_check;				if (i2->cluster && i1->cluster != i2->cluster)			return 1;		client_check = i2->std & 0xff000000;		if (client_check) {			if ((i1->std & 0xff000000) != client_check)				return 1;		} else {			if ((i1->std & i2->std) != i2->std)				return 1;		}		return i1->bank != i2->bank || i1->prg != i2->prg;	}}snd_seq_kinstr_t *snd_seq_instr_find(snd_seq_kinstr_list_t *list,				     snd_seq_instr_t *instr,				     int exact,				     int follow_alias){	unsigned long flags;	int depth = 0;	snd_seq_kinstr_t *result;	if (list == NULL || instr == NULL)		return NULL;	spin_lock_irqsave(&list->lock, flags);      __again:	result = list->hash[compute_hash_instr_key(instr)];	while (result) {		if (!compare_instr(&result->instr, instr, exact)) {			if (follow_alias && (result->type == SNDRV_SEQ_INSTR_ATYPE_ALIAS)) {				instr = (snd_seq_instr_t *)KINSTR_DATA(result);				if (++depth > 10)					goto __not_found;				goto __again;			}			result->use++;			spin_unlock_irqrestore(&list->lock, flags);			return result;		}		result = result->next;	}      __not_found:	spin_unlock_irqrestore(&list->lock, flags);	return NULL;}void snd_seq_instr_free_use(snd_seq_kinstr_list_t *list,			    snd_seq_kinstr_t *instr){	unsigned long flags;	if (list == NULL || instr == NULL)		return;	spin_lock_irqsave(&list->lock, flags);	if (instr->use <= 0) {		snd_printk(KERN_ERR "free_use: fatal!!! use = %i, name = '%s'\n", instr->use, instr->name);	} else {		instr->use--;	}	spin_unlock_irqrestore(&list->lock, flags);}static snd_seq_kinstr_ops_t *instr_ops(snd_seq_kinstr_ops_t *ops, char *instr_type){	while (ops) {		if (!strcmp(ops->instr_type, instr_type))			return ops;		ops = ops->next;	}	return NULL;}static int instr_result(snd_seq_event_t *ev,			int type, int result,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -