1/* $Id$ */
2
3/***
4  This file is part of avahi.
5
6  avahi is free software; you can redistribute it and/or modify it
7  under the terms of the GNU Lesser General Public License as
8  published by the Free Software Foundation; either version 2.1 of the
9  License, or (at your option) any later version.
10
11  avahi is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14  Public License for more details.
15
16  You should have received a copy of the GNU Lesser General Public
17  License along with avahi; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  USA.
20***/
21
22#include <sys/time.h>
23#ifdef QT4
24#include <Qt/qsocketnotifier.h>
25#include <Qt/qobject.h>
26#include <Qt/qtimer.h>
27#else
28#include <qsocketnotifier.h>
29#include <qobject.h>
30#include <qtimer.h>
31#endif
32#include <avahi-common/timeval.h>
33#include "qt-watch.h"
34
35class AvahiWatch : public QObject
36{
37    Q_OBJECT
38public:
39    AvahiWatch(int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void* userdata);
40    ~AvahiWatch() {}
41    AvahiWatchEvent getEvents() const { return m_incallback ? m_lastEvent : (AvahiWatchEvent)0; }
42    void setWatchedEvents(AvahiWatchEvent event);
43
44private slots:
45    void gotIn();
46    void gotOut();
47
48private:
49    QSocketNotifier* m_in;
50    QSocketNotifier* m_out;
51    //FIXME: ERR and HUP?
52    AvahiWatchCallback m_callback;
53    AvahiWatchEvent m_lastEvent;
54    int m_fd;
55    void* m_userdata;
56    bool m_incallback;
57};
58
59class AvahiTimeout : public QObject
60{
61    Q_OBJECT
62
63public:
64    AvahiTimeout(const struct timeval* tv, AvahiTimeoutCallback callback, void* userdata);
65    ~AvahiTimeout() {}
66    void update(const struct timeval* tv);
67
68private slots:
69    void timeout();
70
71private:
72    QTimer m_timer;
73    AvahiTimeoutCallback m_callback;
74    void* m_userdata;
75};
76
77
78
79AvahiWatch::AvahiWatch(int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void* userdata) :
80    m_in(0), m_out(0),  m_callback(callback), m_fd(fd), m_userdata(userdata), m_incallback(false)
81{
82    setWatchedEvents(event);
83}
84
85void AvahiWatch::gotIn()
86{
87    m_lastEvent = AVAHI_WATCH_IN;
88    m_incallback=true;
89    m_callback(this,m_fd,m_lastEvent,m_userdata);
90    m_incallback=false;
91}
92
93void AvahiWatch::gotOut()
94{
95    m_lastEvent = AVAHI_WATCH_IN;
96    m_incallback=true;
97    m_callback(this,m_fd,m_lastEvent,m_userdata);
98    m_incallback=false;
99}
100
101void AvahiWatch::setWatchedEvents(AvahiWatchEvent event)
102{
103    if (!(event & AVAHI_WATCH_IN)) { delete m_in; m_in=0; }
104    if (!(event & AVAHI_WATCH_OUT)) { delete m_out; m_out=0; }
105    if (event & AVAHI_WATCH_IN) {
106	m_in = new QSocketNotifier(m_fd,QSocketNotifier::Read, this);
107	connect(m_in,SIGNAL(activated(int)),SLOT(gotIn()));
108    }
109    if (event & AVAHI_WATCH_OUT) {
110	m_out = new QSocketNotifier(m_fd,QSocketNotifier::Write, this);
111	connect(m_out,SIGNAL(activated(int)),SLOT(gotOut()));
112    }
113}
114
115AvahiTimeout::AvahiTimeout(const struct timeval* tv, AvahiTimeoutCallback callback, void *userdata) :
116    m_callback(callback), m_userdata(userdata)
117{
118    connect(&m_timer, SIGNAL(timeout()), this, SLOT(timeout()));
119#ifdef QT4
120    m_timer.setSingleShot(true);
121#endif
122    update(tv);
123}
124
125void AvahiTimeout::update(const struct timeval *tv)
126{
127    m_timer.stop();
128    if (tv) {
129    AvahiUsec u = avahi_age(tv)/1000;
130#ifdef QT4
131    m_timer.start( (u>0) ? 0 : -u);
132#else
133    m_timer.start( (u>0) ? 0 : -u,true);
134#endif
135    }
136}
137
138void AvahiTimeout::timeout()
139{
140    m_callback(this,m_userdata);
141}
142
143static AvahiWatch* q_watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback,
144    void *userdata)
145{
146    return new AvahiWatch(fd, event, callback, userdata);
147}
148
149static void q_watch_update(AvahiWatch *w, AvahiWatchEvent events)
150{
151    w->setWatchedEvents(events);
152}
153
154static AvahiWatchEvent q_watch_get_events(AvahiWatch *w)
155{
156    return w->getEvents();
157}
158
159static void q_watch_free(AvahiWatch *w)
160{
161    delete w;
162}
163
164static AvahiTimeout* q_timeout_new(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback,
165    void *userdata)
166{
167    return new AvahiTimeout(tv, callback, userdata);
168}
169
170static void q_timeout_update(AvahiTimeout *t, const struct timeval *tv)
171{
172    t->update(tv);
173}
174
175static void q_timeout_free(AvahiTimeout *t)
176{
177    delete t;
178}
179
180const AvahiPoll* avahi_qt_poll_get(void)
181{
182    static const AvahiPoll qt_poll = {
183        NULL,
184        q_watch_new,
185        q_watch_update,
186        q_watch_get_events,
187        q_watch_free,
188        q_timeout_new,
189        q_timeout_update,
190        q_timeout_free
191    };
192
193    return &qt_poll;
194}
195
196#ifdef QT4
197#include "qt-watch.moc4"
198#else
199#include "qt-watch.moc3"
200#endif
201