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