Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * ALSA sequencer Ports * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl> */ #ifndef __SND_SEQ_PORTS_H #define __SND_SEQ_PORTS_H #include <sound/seq_kernel.h> #include "seq_lock.h" /* list of 'exported' ports */ /* Client ports that are not exported are still accessible, but are anonymous ports. If a port supports SUBSCRIPTION, that port can send events to all subscribersto a special address, with address (queue==SNDRV_SEQ_ADDRESS_SUBSCRIBERS). The message is then send to all recipients that are registered in the subscription list. A typical application for these SUBSCRIPTION events is handling of incoming MIDI data. The port doesn't 'know' what other clients are interested in this message. If for instance a MIDI recording application would like to receive the events from that port, it will first have to subscribe with that port. */ struct snd_seq_subscribers { struct snd_seq_port_subscribe info; /* additional info */ struct list_head src_list; /* link of sources */ struct list_head dest_list; /* link of destinations */ atomic_t ref_count; }; struct snd_seq_port_subs_info { struct list_head list_head; /* list of subscribed ports */ unsigned int count; /* count of subscribers */ unsigned int exclusive: 1; /* exclusive mode */ struct rw_semaphore list_mutex; rwlock_t list_lock; int (*open)(void *private_data, struct snd_seq_port_subscribe *info); int (*close)(void *private_data, struct snd_seq_port_subscribe *info); }; /* context for converting from legacy control event to UMP packet */ struct snd_seq_ump_midi2_bank { bool rpn_set; bool nrpn_set; bool bank_set; unsigned char cc_rpn_msb, cc_rpn_lsb; unsigned char cc_nrpn_msb, cc_nrpn_lsb; unsigned char cc_data_msb, cc_data_lsb; unsigned char cc_bank_msb, cc_bank_lsb; }; struct snd_seq_client_port { struct snd_seq_addr addr; /* client/port number */ struct module *owner; /* owner of this port */ char name[64]; /* port name */ struct list_head list; /* port list */ snd_use_lock_t use_lock; /* subscribers */ struct snd_seq_port_subs_info c_src; /* read (sender) list */ struct snd_seq_port_subs_info c_dest; /* write (dest) list */ int (*event_input)(struct snd_seq_event *ev, int direct, void *private_data, int atomic, int hop); void (*private_free)(void *private_data); void *private_data; unsigned int closing : 1; unsigned int timestamping: 1; unsigned int time_real: 1; int time_queue; /* capability, inport, output, sync */ unsigned int capability; /* port capability bits */ unsigned int type; /* port type bits */ /* supported channels */ int midi_channels; int midi_voices; int synth_voices; /* UMP direction and group */ unsigned char direction; unsigned char ump_group; #if IS_ENABLED(CONFIG_SND_SEQ_UMP) struct snd_seq_ump_midi2_bank midi2_bank[16]; /* per channel */ #endif }; struct snd_seq_client; /* return pointer to port structure and lock port */ struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client, int num); /* search for next port - port is locked if found */ struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *client, struct snd_seq_port_info *pinfo); /* unlock the port */ #define snd_seq_port_unlock(port) snd_use_lock_free(&(port)->use_lock) /* create a port, port number or a negative error code is returned */ int snd_seq_create_port(struct snd_seq_client *client, int port_index, struct snd_seq_client_port **port_ret); /* delete a port */ int snd_seq_delete_port(struct snd_seq_client *client, int port); /* delete all ports */ int snd_seq_delete_all_ports(struct snd_seq_client *client); /* set port info fields */ int snd_seq_set_port_info(struct snd_seq_client_port *port, struct snd_seq_port_info *info); /* get port info fields */ int snd_seq_get_port_info(struct snd_seq_client_port *port, struct snd_seq_port_info *info); /* add subscriber to subscription list */ int snd_seq_port_connect(struct snd_seq_client *caller, struct snd_seq_client *s, struct snd_seq_client_port *sp, struct snd_seq_client *d, struct snd_seq_client_port *dp, struct snd_seq_port_subscribe *info); /* remove subscriber from subscription list */ int snd_seq_port_disconnect(struct snd_seq_client *caller, struct snd_seq_client *s, struct snd_seq_client_port *sp, struct snd_seq_client *d, struct snd_seq_client_port *dp, struct snd_seq_port_subscribe *info); /* subscribe port */ int snd_seq_port_subscribe(struct snd_seq_client_port *port, struct snd_seq_port_subscribe *info); /* get matched subscriber */ int snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp, struct snd_seq_addr *dest_addr, struct snd_seq_port_subscribe *subs); #endif |