ardour
msvc_poll.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 John Emmas
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #ifdef COMPILER_MSVC
21 
22 //#include <glib/gtimer.h>
23 #include "pbd/msvc_pbd.h"
24 
25 #ifndef _DWORD_DEFINED
26 #define _DWORD_DEFINED
27 typedef unsigned long DWORD;
28 #endif // !_DWORD_DEFINED
29 
30 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
31  * *
32  * Note that this entire strategy failed to work, at least for pipes. It turned *
33  * out that Windows 'tell()' always returns 0 when used on a pipe. This strategy *
34  * is now deprecated, having been replaced by a new pipe-like object, which I've *
35  * called 'PBD::pipex'. This polling functionality is included here mostly so *
36  * that Ardour will build and launch under Windows. However, any module that *
37  * relies on polling a pipe will eventually need to use the new pipex object. *
38  * This code will allow it to compile and link successfully, although it won't *
39  * poll successfully at run time. Having said that, these functions might well *
40  * work for ports and/or other machanisms that get represented by a file handle. *
41  * *
42  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
43 
44 int poll_input (struct pollfd *fds, nfds_t nfds, int& elapsed_time, int timeout)
45 {
46 DWORD dwOldTickCount,
47  dwNewTickCount = GetTickCount();
48 bool input = false,
49  error = false;
50 int ret = 0;
51 
52  if (NULL != fds)
53  {
54  nfds_t loop;
55  short ev_mask = (POLLOUT|POLLWRNORM|POLLWRBAND);
56 
57  errno = NO_ERROR;
58 
59  do
60  {
61  dwOldTickCount = dwNewTickCount;
62 
63  for (loop=0; loop<nfds; loop++)
64  fds[loop].revents = 0;
65 
66  for (loop=0; (loop<nfds && !error); loop++)
67  {
68  if (!(fds[loop].events & ev_mask))
69  {
70  long pos = _tell(fds[loop].fd);
71 
72  if (0 > pos)
73  {
74  // An error occured ('errno' should have been set by '_tell()')
75  ret = (-1);
76  fds[loop].revents = POLLERR;
77  if (fds[loop].events & POLLRDNORM)
78  fds[loop].revents |= POLLRDNORM;
79  if (fds[loop].events & POLLRDBAND)
80  fds[loop].revents |= POLLRDBAND;
81  if (fds[loop].events & POLLPRI)
82  fds[loop].revents |= POLLPRI;
83 
84  // Do we want to abort on error?
85  if (fds[loop].events & POLLERR)
86  error = true;
87  }
88  else if (pos > 0)
89  {
90  // Input characters were found for this fd
91  ret += 1;
92  if (fds[loop].events & POLLRDNORM)
93  fds[loop].revents |= POLLRDNORM;
94  if (fds[loop].events & POLLRDBAND)
95  fds[loop].revents |= POLLRDBAND;
96  if (fds[loop].events & POLLPRI)
97  fds[loop].revents |= POLLPRI;
98 
99  // Do we want to abort on input?
100  if ((fds[loop].events & POLLIN) ||
101  (fds[loop].events & POLLPRI) ||
102  (fds[loop].events & POLLRDNORM) ||
103  (fds[loop].events & POLLRDBAND))
104  input = true;
105  }
106  }
107  }
108 
109  if (input)
110  break;
111 
112  dwNewTickCount = GetTickCount();
113  elapsed_time += (dwNewTickCount-dwOldTickCount);
114  // Note that the above will wrap round if the user leaves
115  // his computer powered up for more than about 50 days!
116 
117  // Sleep briefly because GetTickCount() only has an accuracy of 10mS
118  Sleep(10); // For some reason 'g_usleep()' craps over everything here. Different 'C' runtimes???
119 
120  } while ((!error) && ((timeout == (-1)) || (elapsed_time < timeout)));
121  }
122  else
123  {
124  errno = ERROR_BAD_ARGUMENTS;
125  ret = (-1);
126  }
127 
128  return (ret);
129 }
130 
131 int poll_output (struct pollfd *fds, nfds_t nfds, int& elapsed_time, int timeout)
132 {
133 int ret = 0; // This functionality is not yet implemented
134 
135  if (NULL != fds)
136  {
137  // Just flag whichever pollfd was specified for writing
138  short ev_mask = (POLLOUT|POLLWRNORM|POLLWRBAND);
139 
140  errno = NO_ERROR;
141  elapsed_time = 0;
142 
143  for (nfds_t loop=0; loop<nfds; loop++)
144  {
145  if (fds[loop].events & ev_mask)
146  {
147  fds[loop].revents = POLLNVAL;
148  errno = ERROR_INVALID_ACCESS;
149  ret = (-1);
150  }
151  }
152  }
153  else
154  {
155  errno = ERROR_BAD_ARGUMENTS;
156  ret = (-1);
157  }
158 
159  return (ret);
160 }
161 
162 //***************************************************************
163 //
164 // poll()
165 //
166 // Emulates POSIX poll() using Win32 _tell().
167 //
168 // Returns:
169 //
170 // On Success: A positive integer indicating the total number
171 // of file descriptors that were available for
172 // writing or had data available for reading.
173 // On Failure: -1 (the actual error is saved in 'errno').
174 //
176 poll (struct pollfd *fds, nfds_t nfds, int timeout)
177 {
178 int elapsed_time = 0;
179 int ret = (-1);
180 
181  // Note that this functionality is not fully implemented.
182  // At the time of writing, Ardour seems only to poll on
183  // read pipes. Therefore return an error if any write
184  // pipe seems to have been specified or if too many file
185  // descriptors were passed.
186  short ev_mask = (POLLOUT|POLLWRNORM|POLLWRBAND);
187 
188  if ((nfds > OPEN_MAX) || (nfds > NPOLLFILE))
189  {
190  errno = ERROR_TOO_MANY_OPEN_FILES;
191  }
192  else
193  {
194  ret = 0;
195 
196  for (nfds_t loop=0; loop<nfds; loop++)
197  {
198  if (fds[loop].events & ev_mask)
199  {
200  ret = poll_output(fds, nfds, elapsed_time, timeout);
201  break;
202  }
203  }
204 
205  if (0 == ret)
206  {
207  // Poll for input
208  ret = poll_input(fds, nfds, elapsed_time, timeout);
209  }
210  }
211 
212  return (ret);
213 }
214 
215 #endif //COMPILER_MSVC
#define LIBPBD_API
#define POLLOUT
Definition: msvc_pbd.h:96
LIBPBD_API Transmitter error
#define POLLERR
Definition: msvc_pbd.h:97
#define NPOLLFILE
Definition: msvc_pbd.h:100
#define POLLPRI
Definition: msvc_pbd.h:95
#define POLLNVAL
Definition: msvc_pbd.h:99
#define POLLWRNORM
Definition: msvc_pbd.h:104
#define POLLIN
Definition: msvc_pbd.h:94
#define PBD_APICALLTYPE
Definition: msvc_pbd.h:55
#define POLLRDBAND
Definition: msvc_pbd.h:103
#define POLLWRBAND
Definition: msvc_pbd.h:105
#define POLLRDNORM
Definition: msvc_pbd.h:102