]> git.vomp.tv Git - vompclient.git/blob - eventdispatcher.cc
Extended recordings menu, including artwork from tvscraper
[vompclient.git] / eventdispatcher.cc
1 /*
2     Copyright 2007 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include "eventdispatcher.h"
22 #include <stdlib.h>
23
24
25 EventDispatcher::EventDispatcher()
26 {
27 #ifndef WIN32
28   pthread_mutex_init(&mutex, NULL);
29 #else
30   mutex = CreateMutex(NULL, FALSE, NULL);
31 #endif
32 }
33
34 void EventDispatcher::edRegister(EDReceiver* edr)
35 {
36   edLock();
37   receivers.push_back(edr);
38   edUnlock();
39 }  
40
41 bool EventDispatcher::edFindAndCall(void* userTag)
42 {
43   edLock();
44   
45   EDReceiver* edr = NULL;
46   EDRL::iterator i;
47   for(i = receivers.begin(); i != receivers.end(); i++)
48   {
49     if (ed_cb_find(*i, userTag))
50     {
51       edr = *i;
52       break; // found (by asking the EventDispatcher implementor to check if userTag is for *i
53     }
54   }
55   
56   if ((i == receivers.end()) || edr->callinprogress || edr->nomorecalls)
57   {
58     edUnlock();
59     return false;
60   }
61   
62   edr->callinprogress = true;
63   edUnlock();
64   bool edr_delete=false;
65   bool edrType = edr->call(userTag,edr_delete);
66   edLock();
67   edr->callinprogress = false;
68
69   if (edrType == false) // it's a multicall
70   {
71     if (edr->nomorecalls) // External has called unRegister - probably the receiver
72     {
73       // wake up the thread waiting in unregister
74       #ifndef WIN32
75       pthread_cond_signal(&edr->cond);
76       #else
77       SetEvent(edr->cond);
78       #endif
79     }
80   }
81   else // It's a single call. The receiver should be removed from the list. There will be a thread to wake up
82   {
83     for(i = receivers.begin(); i != receivers.end(); i++)
84     {
85       if (*i == edr)
86       {
87         receivers.erase(i);
88         break;
89       }
90     }
91     #ifndef WIN32
92     if (i == receivers.end()) abort(); // should never happen
93     // but it can happen under windows ... how??
94     #endif
95     
96     #ifndef WIN32
97     pthread_cond_signal(&edr->cond);
98     #else
99     SetEvent(edr->cond);
100     #endif
101     if (edr_delete) delete edr;
102   }
103   
104   edUnlock();
105   return true;
106 }
107
108 void EventDispatcher::edUnregister(EDReceiver* edr)
109 {
110   edLock();
111
112   EDRL::iterator i;
113   for(i = receivers.begin(); i != receivers.end(); i++)
114   {
115     if (*i == edr) break; // found
116   }
117
118   // Not in the list. Already unregistered? Perhaps vdr::connectionDied already removed this streamclient
119   // FIXME, this should probably be done another way. A call to edUnregister with an object that may or may not be in the list? Not good.
120   if (i == receivers.end())
121   {
122     edUnlock();
123     return;
124   }
125
126   if (!edr->callinprogress)
127   {
128     receivers.erase(i);
129     edUnlock();
130     return;
131   }
132
133   edr->nomorecalls = true;
134   
135   // edUnlock, wait for callinprogres=false (cond to be signalled), lock  
136 #ifndef WIN32
137   pthread_cond_wait(&edr->cond, &mutex);
138 #else
139   ReleaseMutex(mutex);
140   WaitForSingleObject(edr->cond,INFINITE);
141   WaitForSingleObject(mutex, INFINITE);
142   ResetEvent(edr->cond);
143
144 #endif
145
146   for(i = receivers.begin(); i != receivers.end(); i++)
147   {
148     if (*i == edr) break; // found
149   }
150
151   if (i == receivers.end()) abort(); // should never happen
152
153   receivers.erase(i);
154   edUnlock();
155 }
156
157 // ---------------------------------------
158
159 void EventDispatcher::edLock()
160 {
161 #ifndef WIN32
162   pthread_mutex_lock(&mutex);
163 #else
164   WaitForSingleObject(mutex, INFINITE);
165 #endif
166 }
167
168 void EventDispatcher::edUnlock()
169 {
170 #ifndef WIN32
171   pthread_mutex_unlock(&mutex);
172 #else
173   ReleaseMutex(mutex);
174 #endif
175 }
176
177 // ---------------------------------------
178
179 void EventDispatcher::edSleepThisReceiver(EDReceiver* edr)
180 {
181   // For blocking version, not callback version. Call with edLock locked
182   
183 #ifndef WIN32
184   pthread_cond_wait(&edr->cond, &mutex);
185 #else
186    ResetEvent(edr->cond);
187    ReleaseMutex(mutex);
188    WaitForSingleObject(edr->cond,INFINITE);
189    ResetEvent(edr->cond);
190    WaitForSingleObject(mutex, INFINITE);
191 #endif
192 }
193
194 // -------------- EDReceiver implementation
195
196 EDReceiver::EDReceiver()
197 {
198   nomorecalls = false;
199   callinprogress = false;
200 #ifndef WIN32
201   pthread_cond_init(&cond, NULL);
202 #else
203    cond = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL);
204 #endif
205 }
206
207 EDReceiver::~EDReceiver()
208 {
209 #ifdef WIN32
210   if (cond!=NULL) CloseHandle(cond);
211 #else
212   pthread_cond_destroy(&cond);
213 #endif
214 }