Updated French 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     // Save in QSettings
96     events.clear();
97     settings.setValue("events", events);
98   }
99
100   static void deleteEvents(QByteArray event_id) {
101     deleteEvents(ProfileEvent::findByID(event_id));
102   }
103
104   static void deleteEvents(ProfileEvent *pe) {
105     // unregistering events
106     foreach(const long &cookie, pe->alarmd_cookies) {
107       qDebug("Unregistering event with cookie %ld", cookie);
108       alarmd_event_del(cookie);
109     }
110     pe->alarmd_cookies.clear();
111     ProfileEvent::clearCookies(pe->getID());
112   }
113
114   static void setProfileEvents(QByteArray event_id) {
115     setProfileEvents(ProfileEvent::findByID(event_id));
116   }
117
118   static bool checkIfStillActive(ProfileEvent *pe) {
119     Q_ASSERT(pe->activated);
120     foreach(const long &cookie, pe->alarmd_cookies) {
121       alarm_event_t *eve = 0;
122       if((eve = alarmd_event_get(cookie)) != 0) {
123         // Free all dynamic memory associated with the alarm event
124         alarm_event_delete(eve);
125         return true;
126       }
127     }
128     return false;
129   }
130
131   static void setProfileEvents(ProfileEvent *pe) {
132     Q_ASSERT(pe->activated);
133     // First clear old alarmd events
134     foreach(const long &cookie, pe->alarmd_cookies) {
135       qDebug("Unregistering event with cookie %ld", cookie);
136       alarmd_event_del(cookie);
137     }
138     pe->alarmd_cookies.clear();
139     // Then setting new events
140     long c1 = newProfileEvent(SILENT, pe->from_time, pe->days);
141     Q_ASSERT(c1 > 0);
142     if(c1 > 0)
143       pe->alarmd_cookies << c1;
144     long c2 = newProfileEvent(GENERAL, pe->to_time, pe->days);
145     Q_ASSERT(c2 > 0);
146     if(c2 > 0)
147       pe->alarmd_cookies << c2;
148     // Save in QSettings
149     ProfileEvent::setCookies(pe->getID(), pe->alarmd_cookies);
150     // Set Profile to SILENT if we are currently in the silent time slot
151     if(pe->affectsCurrentTime())
152       DBusBackend::setProfile(SILENT);
153   }
154
155 protected:
156   static long newProfileEvent(Profile p, const QTime &event_time, QList<int> days) {
157     Q_ASSERT(!days.empty());
158     qDebug("Registering an event");
159     if(days.empty()) days << NEVER;
160     // Create the default alarm struct.
161     alarm_event_t *newEvent = alarm_event_create();
162     // Set the APP ID
163     alarm_event_set_alarm_appid(newEvent, "TimedSilencer");
164     // Set the title
165     if(p == SILENT)
166       alarm_event_set_title(newEvent, "silent_profile");
167     else
168       alarm_event_set_title(newEvent, "general_profile");
169     // Timing
170     if(days.first() == EVERY_DAY) {
171       newEvent->recur_secs = 86400; // 24 hours
172       newEvent->recur_count = -1; // Reoccur infinitely
173       newEvent->alarm_time = toTime_t(event_time); // Set event time
174     } else {
175       if(days.first() == NEVER) {
176         newEvent->alarm_time = toTime_t(event_time); // Set event time
177       } else {
178         qDebug("Using the new recurrence API");
179         newEvent->recur_count = -1;
180         newEvent->recur_secs = 0; // We re not using this way for recurrence
181         alarm_recur_t* recur = alarm_event_add_recurrences(newEvent, 1);
182         // Set event time
183         recur->special = ALARM_RECUR_SPECIAL_NONE;
184         recur->mask_mon = ALARM_RECUR_MON_ALL;
185         recur->mask_mday = ALARM_RECUR_MDAY_ALL;
186         recur->mask_hour = (1ul << event_time.hour());
187         recur->mask_min = (1ull << event_time.minute());
188         recur->mask_wday = daysToMask(days);
189         Q_ASSERT(newEvent->recurrence_cnt == 1);
190       }
191     }
192     //Add 1 action to our alarm event, and assign it to the "act" variable
193     alarm_action_t *act = alarm_event_add_actions(newEvent, 1);
194     // Actions are documented here:
195     // http://maemo.org/api_refs/5.0/5.0-final/libalarm/libalarm_8h.html#cc8e6f439d134448001132132476683c910f7626ec85a4170659b53fa2f0abc7
196     //Setup this action to be an "DBus command" one; also set it up to use DBUS auto-activation.
197     act->flags = ALARM_ACTION_WHEN_TRIGGERED | ALARM_ACTION_DBUS_USE_ACTIVATION | ALARM_ACTION_TYPE_DBUS;
198
199     //Setup the DBus params for this action
200     alarm_action_set_dbus_interface(act, "com.nokia.profiled");
201     alarm_action_set_dbus_service(act, "com.nokia.profiled");
202     alarm_action_set_dbus_path(act, "/com/nokia/profiled");
203     alarm_action_set_dbus_name(act, "set_profile");
204
205     if(p == SILENT) {
206       const char* param = "silent";
207       alarm_action_set_dbus_args(act, DBUS_TYPE_STRING, &param, DBUS_TYPE_INVALID);
208     } else {
209       const char* param = "general";
210       alarm_action_set_dbus_args(act, DBUS_TYPE_STRING, &param, DBUS_TYPE_INVALID);
211     }
212
213     // Finally with everything setup, try to add your event to the alarm queue
214     long cookie = alarmd_event_add(newEvent);
215     // Free all dynamic memory associated with the alarm event
216     alarm_event_delete(newEvent);
217     return cookie;
218   }
219 };
220
221 #endif // ALARMD_TALKER_H