1 /*
2  * Copyright 1993 Network Computing Devices, Inc.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name Network Computing Devices, Inc. not be
9  * used in advertising or publicity pertaining to distribution of this
10  * software without specific, written prior permission.
11  *
12  * THIS SOFTWARE IS PROVIDED 'AS-IS'.  NETWORK COMPUTING DEVICES, INC.,
13  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
14  * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
15  * PARTICULAR PURPOSE, OR NONINFRINGEMENT.  IN NO EVENT SHALL NETWORK
16  * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
17  * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
18  * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
19  * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  * $NCDId: @(#)HandleEv.c,v 1.9 1993/08/11 17:01:58 greg Exp $
23  */
24 
25 /*
26  * This file contains utilities contains an event handler takes care of
27  * dispatching the various events that might come into an application. The
28  * idea is to hide most of the mainline activity so that simple applications
29  * don't have to fuss with things.
30  *
31  * For example, an application that wants to play a sound from a file or memory
32  * buffer asynchronously needs to wait for events telling it when it can
33  * write to the ImportElement in the flow.
34  */
35 
36 #include "Alibint.h"
37 
38 void
AuHandleEvents(AuServer * aud)39 AuHandleEvents(AuServer *aud)
40 {
41     int             nevents;
42     AuEvent         event;
43 
44     while (1)
45     {
46 	/* do our best to find an event */
47 	nevents = _AuEventsQueued(aud, AuEventsQueuedAlready);
48 
49 	if (!nevents)
50 	{
51 	    nevents = _AuEventsQueued(aud, AuEventsQueuedAfterFlush);
52 
53 	    if (!nevents)
54 	    {
55 		nevents = _AuEventsQueued(aud, AuEventsQueuedAfterReading);
56 
57 		if (!nevents)
58 		    return;
59 	    }
60 	}
61 
62 	/* got one, now do something with it */
63 	for (; nevents > 0; nevents--)
64 	{
65 	    AuNextEvent(aud, AuTrue, &event);	/* dequeue the event */
66 	    (void) AuDispatchEvent(aud, &event);	/* go deal with it */
67 	}
68     }
69 }
70 
71 AuBool
AuDispatchEvent(AuServer * aud,AuEvent * event)72 AuDispatchEvent(
73                 AuServer       *aud,
74                 AuEvent        *event
75                 )
76 {
77     AuBool          result = AuFalse;
78     AuEventHandlerRec *handler = NULL, *next;
79 
80     do
81     {
82 	if ((handler = AuLookupEventHandler(aud, event, handler))
83         					!= (AuEventHandlerRec *) NULL)
84 	{
85             next = handler->next;	/* could be removed by handler */
86 	    result |= (*(handler->callback)) (aud, event, handler);
87 	    handler = next;
88 	}
89     } while (handler);
90 
91     return result;
92 }
93 
94 AuEventHandlerRec *
AuLookupEventHandler(AuServer * aud,AuEvent * event,AuEventHandlerRec * handler)95 AuLookupEventHandler(
96                      AuServer *aud,
97                      AuEvent *event,
98                      AuEventHandlerRec *handler
99                      )
100 {
101     /*
102      * From the given start location (NULL indicates beginning), walk down
103      * the handlers list looking for a match.
104      */
105     if (!handler)
106 	handler = aud->eventhandlerq;
107 
108     /*
109      * This could be done more efficiently than a linear lookup, but there
110      * are relatively few events in the audio protocol, so the overhead
111      * should be acceptable.
112      */
113     for (; handler; handler = handler->next)
114     {
115 	if ((handler->mask & AuEventHandlerTypeMask) &&
116 	    (handler->type != event->type))
117 	    continue;
118 
119 	if ((handler->mask & AuEventHandlerIDMask) &&
120 	    (handler->id != event->auany.id))
121 	    continue;
122 
123 	break;			/* got one! */
124     }
125 
126     return handler;
127 }
128 
129 AuEventHandlerRec *
AuRegisterEventHandler(AuServer * aud,AuMask mask,int type,AuID id,AuEventHandlerCallback callback,AuPointer data)130 AuRegisterEventHandler(
131                        AuServer       *aud,
132                        AuMask          mask,
133                        int             type,
134                        AuID            id,
135                        AuEventHandlerCallback callback,
136                        AuPointer       data
137                        )
138 {
139     AuEventHandlerRec *handler;
140 
141     if (!(handler = (AuEventHandlerRec *) Aumalloc(sizeof(AuEventHandlerRec))))
142 	return NULL;
143 
144     handler->aud = aud;
145     handler->mask = mask;
146     handler->type = type;
147     handler->id = id;
148     handler->callback = callback;
149     handler->data = data;
150 
151     _AuAddToLinkedList(aud->eventhandlerq, handler);
152 
153     return handler;
154 }
155 
156 void
AuUnregisterEventHandler(AuServer * aud,AuEventHandlerRec * handler)157 AuUnregisterEventHandler(
158                          AuServer       *aud,
159                          AuEventHandlerRec *handler
160                          )
161 {
162     _AuRemoveFromLinkedList(aud->eventhandlerq, handler);
163     Aufree(handler);
164 }
165