2 wmget - A background download manager as a Window Maker dock app
3 Copyright (c) 2001-2003 Aaron Trickey <aaron@amtrickey.net>
5 Permission is hereby granted, free of charge, to any person
6 obtaining a copy of this software and associated documentation files
7 (the "Software"), to deal in the Software without restriction,
8 including without limitation the rights to use, copy, modify, merge,
9 publish, distribute, sublicense, and/or sell copies of the Software,
10 and to permit persons to whom the Software is furnished to do so,
11 subject to the following conditions:
13 The above copyright notice and this permission notice shall be
14 included in all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 ********************************************************************
25 dockapp/da_run.c - Main dockapp loop; fd polling; periodic callback
27 This file implements dockapp_run(), which provides the main loop of
28 the dockapp application. In addition, it implements
29 dockapp_add_pollfd(), which adds polling of arbitrary file
30 descriptors to the main loop, and dockapp_set_periodic_callback(),
31 which sets up a periodic app callback.
45 /* we keep two parallel structures... one, the list of pollfd's for
46 * poll(2)'s benefit, and the other, the collection of callback
50 dockapp_rv_t (*cb
) (void *cbdata
, short revents
);
60 static struct pollfd da_pollfds
[da_max_pollfds
];
61 static da_pollcb da_pollcbs
[da_max_pollfds
];
62 static int da_num_pollfds
= 0;
65 dockapp_rv_t
dockapp_add_pollfd (
68 dockapp_rv_t (*cb
) (void *, short pollstatus
),
74 assert (da_num_pollfds
< da_max_pollfds
);
77 fprintf (stderr, "adding pollfd #%d, fd = %d, events = %hu\n",
78 da_num_pollfds, fd, pollevents);
81 pfd
= da_pollfds
+ da_num_pollfds
;
82 pcb
= da_pollcbs
+ da_num_pollfds
;
85 pfd
->events
= pollevents
;
95 dockapp_rv_t
dockapp_remove_pollfd (
98 int i
= da_num_pollfds
;
99 struct pollfd
*pfd
= da_pollfds
;
100 da_pollcb
*pcb
= da_pollcbs
;
102 for ( ; i
; --i
, ++pfd
, ++pcb
) {
104 memmove (pfd
, pfd
+ 1, (i
- 1) * sizeof (struct pollfd
));
105 memmove (pcb
, pcb
+ 1, (i
- 1) * sizeof (da_pollcb
));
111 return dockapp_invalid_arg
;
115 /* periodic callback info... if da_timer_cb is null, then no callback is
118 static dockapp_rv_t (*da_timer_cb
) (void *) = 0;
119 static void *da_timer_cbdata
;
120 static struct timeval da_timer_next_timeout
;
121 static long da_timer_interval_msec
;
124 static void da_reset_timer (void)
128 rv
= gettimeofday (&da_timer_next_timeout
, 0);
133 "da_reset_timer: RIGHT NOW is %ld.%ld, msec = %ld\n",
134 da_timer_next_timeout.tv_sec,
135 da_timer_next_timeout.tv_usec,
136 da_timer_interval_msec);
139 da_timer_next_timeout
.tv_usec
140 += (da_timer_interval_msec
% 1000L) * 1000L;
142 da_timer_next_timeout
.tv_sec
143 += da_timer_interval_msec
/ 1000L
144 + da_timer_next_timeout
.tv_usec
/ 1000000L;
146 da_timer_next_timeout
.tv_usec
%= 1000000L;
150 "da_reset_timer: NEXT TIMEOUT is %ld.%ld\n",
151 da_timer_next_timeout.tv_sec,
152 da_timer_next_timeout.tv_usec);
157 static long da_timer_msec_remaining (void)
159 struct timeval right_now
;
162 rv
= gettimeofday (&right_now
, 0);
165 (da_timer_next_timeout
.tv_sec
- right_now
.tv_sec
) * 1000L
166 + (da_timer_next_timeout
.tv_usec
- right_now
.tv_usec
) / 1000L;
170 void dockapp_set_periodic_callback (
172 dockapp_rv_t (*cb
) (void *),
176 da_timer_cbdata
= cbdata
;
178 da_timer_interval_msec
= msec
;
184 void dockapp_remove_periodic_callback (void)
188 da_timer_interval_msec
= 0;
192 /* this is the main loop for the dockapp...
194 dockapp_rv_t
dockapp_run (void)
198 int poll_timeout
= -1; /* infinite unless periodic callback */
201 if (da_timer_msec_remaining () <= 0) {
202 rv
= da_timer_cb (da_timer_cbdata
);
206 poll_timeout
= da_timer_msec_remaining ();
210 fprintf (stderr, "about to poll(%d fd, %d timeout)\n",
211 da_num_pollfds, poll_timeout);
214 rv
= poll (da_pollfds
, da_num_pollfds
, poll_timeout
);
217 fprintf (stderr, "poll returned %d\n", rv);
221 /* poll timed out; let's loop back up and let the logic
222 * prior to the poll() invoke the user-defined periodic
227 /* Disregard EINTR; just means that a signal was caught.
234 /* poll returned with some nonzero number of events...
235 * collect the callback structures first, then invoke the
236 * callbacks, since the callback functions are allowed to
237 * create and destroy callbacks as well
240 da_pollcb callbacks
[da_max_pollfds
];
244 for (i
= 0; i
< da_num_pollfds
&& ncallbacks
< rv
; ++i
) {
245 if (da_pollfds
[i
].revents
) {
246 callbacks
[ncallbacks
] = da_pollcbs
[i
];
247 callbacks
[ncallbacks
].revents
248 = da_pollfds
[i
].revents
;
253 for (c
= callbacks
; ncallbacks
; --ncallbacks
, ++c
) {
254 if (c
->cb (c
->cbdata
, c
->revents
) == dockapp_exit
) {
255 fprintf (stderr
, "exiting dockapp_run()\n");