Added spanish translation
[timedsilencer] / alarmd_backend.h
1 /*
2  * This file is part of TimedSilencer.
3  *
4  *  TimedSilencer 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 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  TimedSilencer 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 TimedSilencer.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #ifndef ALARMD_TALKER_H
19 #define ALARMD_TALKER_H
20
21 #include <QTime>
22 #include <QString>
23 #include <QSettings>
24 #include <QPair>
25 #include <alarmd/libalarm.h>
26 #include <dbus-1.0/dbus/dbus-protocol.h>
27 #include <time.h>
28
29 #include "phone_profile.h"
30 #include "dbus_backend.h"
31 #include "profileevent.h"
32
33 // Alarmd documentation found at:
34 // http://wiki.maemo.org/Documentation/Maemo_5_Developer_Guide/Using_Generic_Platform_Components/Alarm_Framework
35 class AlarmdBackend : public QObject {
36   Q_OBJECT
37 private:
38   static time_t toTime_t(const QTime &t) {
39     int time_diff = QTime::currentTime().secsTo(t);
40     if(time_diff < 0) {
41       // Add 24 hours
42       time_diff += 86400;
43     }
44     qDebug("time diff: %d", time_diff);
45     return (time_t) time(0) + time_diff;
46   }
47
48   static uint32_t daysToMask(QList<int> days) {
49     uint32_t mask = 0;
50     foreach(const int& d, days) {
51       switch(d) {
52       case MON:
53         mask |= ALARM_RECUR_WDAY_MON;
54         break;
55       case TUE:
56         mask |= ALARM_RECUR_WDAY_TUE;
57         break;
58       case WED:
59         mask |= ALARM_RECUR_WDAY_WED;
60         break;
61       case THU:
62         mask |= ALARM_RECUR_WDAY_THU;
63         break;
64       case FRI:
65         mask |= ALARM_RECUR_WDAY_FRI;
66         break;
67       case SAT:
68         mask |= ALARM_RECUR_WDAY_SAT;
69         break;
70       case SUN:
71         mask |= ALARM_RECUR_WDAY_SUN;
72         break;
73       default:
74         Q_ASSERT(0); // Should never go here
75         mask |= ALARM_RECUR_WDAY_ALL;
76         break;
77       }
78     }
79     return mask;
80   }
81
82 public:
83   // Is only called on program uninstall
84   static void deleteAllEvents() {
85     QSettings settings("TimedSilencer", "TimedSilencer");
86     QHash<QString, QVariant> events = settings.value("events").toHash();
87     foreach(QVariant var_ev, events) {
88       ProfileEvent *pe = ProfileEvent::load(var_ev);
89       foreach(const long &cookie, pe->alarmd_cookies) {
90         qDebug("Unregistering event with cookie %ld", cookie);
91         alarmd_event_del(cookie);
92       }
93       delete pe;
94     }
95     // Delete possible orphan events
96     cookie_t *orphan_cookies = alarmd_event_query(0,0,0,0, "TimedSilencer");
97     int i = 0;
98     while(orphan_cookies && orphan_cookies[i] != 0) {
99       alarmd_event_del(orphan_cookies[i]);
100       ++i;
101     }
102     // Save in QSettings
103     events.clear();
104     settings.setValue("events", events);
105   }
106
107   static void deleteOrphanEvents(QList<long> known_cookies) {
108     cookie_t *orphan_cookies = alarmd_event_query(0,0,0,0, "TimedSilencer");
109     int i = 0;
110     while(orphan_cookies && orphan_cookies[i] != 0) {
111       if(!known_cookies.contains(orphan_cookies[i]))
112         alarmd_event_del(orphan_cookies[i]);
113       ++i;
114     }
115   }
116
117   static void deleteEvents(QByteArray event_id) {
118     deleteEvents(ProfileEvent::findByID(event_id));
119   }
120
121   static void deleteEvents(ProfileEvent *pe) {
122     // unregistering events
123     foreach(const long &cookie, pe->alarmd_cookies) {
124       qDebug("Unregistering event with cookie %ld", cookie);
125       alarmd_event_del(cookie);
126     }
127     pe->alarmd_cookies.clear();
128     ProfileEvent::clearCookies(pe->getID());
129   }
130
131   static void setProfileEvents(QByteArray event_id) {
132     setProfileEvents(ProfileEvent::findByID(event_id));
133   }
134
135   static bool checkIfStillActive(ProfileEvent *pe) {
136     Q_ASSERT(pe->activated);
137     foreach(const long &cookie, pe->alarmd_cookies) {
138       alarm_event_t *eve = 0;
139       if((eve = alarmd_event_get(cookie)) != 0) {
140         // Free all dynamic memory associated with the alarm event
141         alarm_event_delete(eve);
142         return true;
143       }
144     }
145     return false;
146   }
147
148   static void setProfileEvents(ProfileEvent *pe) {
149     Q_ASSERT(pe->activated);
150     // First clear old alarmd events
151     foreach(const long &cookie, pe->alarmd_cookies) {
152       qDebug("Unregistering event with cookie %ld", cookie);
153       alarmd_event_del(cookie);
154     }
155     pe->alarmd_cookies.clear();
156     // Then setting new events
157     long c1 = newProfileEvent(SILENT, pe->from_time, pe->days);
158     Q_ASSERT(c1 > 0);
159     if(c1 > 0)
160       pe->alarmd_cookies << c1;
161     long c2 = newProfileEvent(GENERAL, pe->to_time, pe->days);
162     Q_ASSERT(c2 > 0);
163     if(c2 > 0)
164       pe->alarmd_cookies << c2;
165     // Save in QSettings
166     ProfileEvent::setCookies(pe->getID(), pe->alarmd_cookies);
167     // Set Profile to SILENT if we are currently in the silent time slot
168     if(pe->affectsCurrentTime())
169       DBusBackend::setProfile(SILENT);
170   }
171
172 protected:
173   static long newProfileEvent(Profile p, const QTime &event_time, QList<int> days) {
174     Q_ASSERT(!days.empty());
175     qDebug("Registering an event");
176     if(days.empty()) days << NEVER;
177     // Create the default alarm struct.
178     alarm_event_t *newEvent = alarm_event_create();
179     // Set the APP ID
180     alarm_event_set_alarm_appid(newEvent, "TimedSilencer");
181     // Set the title
182     if(p == SILENT)
183       alarm_event_set_title(newEvent, "silent_profile");
184     else
185       alarm_event_set_title(newEvent, "general_profile");
186     // Timing
187     if(days.first() == EVERY_DAY) {
188       newEvent->recur_secs = 86400; // 24 hours
189       newEvent->recur_count = -1; // Reoccur infinitely
190       newEvent->alarm_time = toTime_t(event_time); // Set event time
191     } else {
192       if(days.first() == NEVER) {
193         newEvent->alarm_time = toTime_t(event_time); // Set event time
194       } else {
195         qDebug("Using the new recurrence API");
196         newEvent->recur_count = -1;
197         newEvent->recur_secs = 0; // We re not using this way for recurrence
198         alarm_recur_t* recur = alarm_event_add_recurrences(newEvent, 1);
199         // Set event time
200         recur->special = ALARM_RECUR_SPECIAL_NONE;
201         recur->mask_mon = ALARM_RECUR_MON_ALL;
202         recur->mask_mday = ALARM_RECUR_MDAY_ALL;
203         recur->mask_hour = (1ul << event_time.hour());
204         recur->mask_min = (1ull << event_time.minute());
205         recur->mask_wday = daysToMask(days);
206         Q_ASSERT(newEvent->recurrence_cnt == 1);
207       }
208     }
209     //Add 1 action to our alarm event, and assign it to the "act" variable
210     alarm_action_t *act = alarm_event_add_actions(newEvent, 1);
211     // Actions are documented here:
212     // http://maemo.org/api_refs/5.0/5.0-final/libalarm/libalarm_8h.html#cc8e6f439d134448001132132476683c910f7626ec85a4170659b53fa2f0abc7
213     //Setup this action to be an "DBus command" one; also set it up to use DBUS auto-activation.
214     act->flags = ALARM_ACTION_WHEN_TRIGGERED | ALARM_ACTION_DBUS_USE_ACTIVATION | ALARM_ACTION_TYPE_DBUS;
215
216     //Setup the DBus params for this action
217     alarm_action_set_dbus_interface(act, "com.nokia.profiled");
218     alarm_action_set_dbus_service(act, "com.nokia.profiled");
219     alarm_action_set_dbus_path(act, "/com/nokia/profiled");
220     alarm_action_set_dbus_name(act, "set_profile");
221
222     if(p == SILENT) {
223       const char* param = "silent";
224       alarm_action_set_dbus_args(act, DBUS_TYPE_STRING, &param, DBUS_TYPE_INVALID);
225     } else {
226       const char* param = "general";
227       alarm_action_set_dbus_args(act, DBUS_TYPE_STRING, &param, DBUS_TYPE_INVALID);
228     }
229
230     // Finally with everything setup, try to add your event to the alarm queue
231     long cookie = alarmd_event_add(newEvent);
232     // Free all dynamic memory associated with the alarm event
233     alarm_event_delete(newEvent);
234     return cookie;
235   }
236 };
237
238 #endif // ALARMD_TALKER_H