diff options
-rw-r--r-- | apps/plugins/CATEGORIES | 1 | ||||
-rw-r--r-- | apps/plugins/SOURCES | 1 | ||||
-rw-r--r-- | apps/plugins/alarmclock.c | 164 | ||||
-rw-r--r-- | manual/plugins/alarmclock.tex | 48 | ||||
-rw-r--r-- | manual/plugins/main.tex | 2 |
5 files changed, 216 insertions, 0 deletions
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES index 4951f0db9c..f1e18832bc 100644 --- a/apps/plugins/CATEGORIES +++ b/apps/plugins/CATEGORIES | |||
@@ -1,4 +1,5 @@ | |||
1 | alpine_cdc,apps | 1 | alpine_cdc,apps |
2 | alarmclock,apps | ||
2 | autostart,apps | 3 | autostart,apps |
3 | battery_bench,apps | 4 | battery_bench,apps |
4 | bench_scaler,apps | 5 | bench_scaler,apps |
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES index da906e6967..88ddff5e29 100644 --- a/apps/plugins/SOURCES +++ b/apps/plugins/SOURCES | |||
@@ -107,6 +107,7 @@ vu_meter.c | |||
107 | wormlet.c | 107 | wormlet.c |
108 | 108 | ||
109 | #if CONFIG_RTC | 109 | #if CONFIG_RTC |
110 | alarmclock.c | ||
110 | #endif /* CONFIG_RTC */ | 111 | #endif /* CONFIG_RTC */ |
111 | 112 | ||
112 | #if (MEMORYSIZE <= 8) && !defined(SIMULATOR) /* loaders, only needed for Archos */ | 113 | #if (MEMORYSIZE <= 8) && !defined(SIMULATOR) /* loaders, only needed for Archos */ |
diff --git a/apps/plugins/alarmclock.c b/apps/plugins/alarmclock.c new file mode 100644 index 0000000000..c8653dcd64 --- /dev/null +++ b/apps/plugins/alarmclock.c | |||
@@ -0,0 +1,164 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Clément Pit-Claudel | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "plugin.h" | ||
23 | #include "lib/pluginlib_actions.h" | ||
24 | |||
25 | PLUGIN_HEADER | ||
26 | |||
27 | const struct button_mapping *plugin_contexts[] = {generic_directions, | ||
28 | generic_actions}; | ||
29 | |||
30 | static int current = 0; | ||
31 | static int alarm[2] = {0, 0}, maxval[2] = {24, 60}; | ||
32 | static bool quit = false, usb = false, waiting = false, done = false; | ||
33 | |||
34 | static inline int get_button(void) { | ||
35 | return pluginlib_getaction(HZ/2, plugin_contexts, 2); | ||
36 | } | ||
37 | |||
38 | int rem_seconds(void) { | ||
39 | return (((alarm[0] - rb->get_time()->tm_hour) * 3600) | ||
40 | +((alarm[1] - rb->get_time()->tm_min) * 60) | ||
41 | -(rb->get_time()->tm_sec)); | ||
42 | } | ||
43 | |||
44 | void draw(void) { | ||
45 | char info[128]; | ||
46 | rb->lcd_clear_display(); | ||
47 | |||
48 | int secs = rem_seconds(); | ||
49 | |||
50 | if (waiting) | ||
51 | rb->snprintf(info, sizeof(info), "Next alarm in %02dh," | ||
52 | " %02dmn, and %02ds.", | ||
53 | secs / 3600, (secs / 60) % 60, secs % 60); | ||
54 | else { | ||
55 | if (current == 0) | ||
56 | rb->snprintf(info, sizeof(info), "Set alarm at [%02d]:%02d.", | ||
57 | alarm[0], | ||
58 | alarm[1]); | ||
59 | else | ||
60 | rb->snprintf(info, sizeof(info), "Set alarm at %02d:[%02d].", | ||
61 | alarm[0], | ||
62 | alarm[1]); | ||
63 | } | ||
64 | |||
65 | int w, h; | ||
66 | rb->lcd_getstringsize(info, &w, &h); | ||
67 | |||
68 | if (w > LCD_WIDTH || h > LCD_HEIGHT) | ||
69 | rb->splash(0, info); | ||
70 | else { | ||
71 | rb->lcd_putsxy((LCD_WIDTH - w) / 2, (LCD_HEIGHT - h) / 2, info); | ||
72 | rb->lcd_update(); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | bool can_play(void) { | ||
77 | int audio_status = rb->audio_status(); | ||
78 | if ((!audio_status && rb->global_status->resume_index != -1) | ||
79 | && (rb->playlist_resume() != -1)) { | ||
80 | return true; | ||
81 | } | ||
82 | else if (audio_status & AUDIO_STATUS_PAUSE) | ||
83 | return true; | ||
84 | |||
85 | return false; | ||
86 | } | ||
87 | |||
88 | void play(void) { | ||
89 | int audio_status = rb->audio_status(); | ||
90 | if (!audio_status && rb->global_status->resume_index != -1) { | ||
91 | if (rb->playlist_resume() != -1) { | ||
92 | rb->playlist_start(rb->global_status->resume_index, | ||
93 | rb->global_status->resume_offset); | ||
94 | } | ||
95 | } | ||
96 | else if (audio_status & AUDIO_STATUS_PAUSE) | ||
97 | rb->audio_resume(); | ||
98 | } | ||
99 | |||
100 | enum plugin_status plugin_start(const void* parameter) | ||
101 | { | ||
102 | int button; | ||
103 | (void)parameter; | ||
104 | |||
105 | if (!can_play()) { | ||
106 | rb->splash(4*HZ, "No track to resume! This plugin will resume a track " | ||
107 | "at a specific time. Therefore, you need to first play" | ||
108 | " one, and then pause it and start the plugin again."); | ||
109 | quit = true; | ||
110 | } | ||
111 | |||
112 | while(!quit) { | ||
113 | button = get_button(); | ||
114 | |||
115 | if (button == PLA_QUIT) | ||
116 | quit = true; | ||
117 | |||
118 | draw(); | ||
119 | if (waiting) { | ||
120 | if (rem_seconds() <= 0) { | ||
121 | quit = done = true; | ||
122 | play(); | ||
123 | } | ||
124 | } | ||
125 | else { | ||
126 | switch (button) { | ||
127 | case PLA_UP: | ||
128 | case PLA_UP_REPEAT: | ||
129 | alarm[current] = (alarm[current] + 1) % maxval[current]; | ||
130 | break; | ||
131 | |||
132 | case PLA_DOWN: | ||
133 | case PLA_DOWN_REPEAT: | ||
134 | alarm[current] = (alarm[current] + maxval[current] - 1) | ||
135 | % maxval[current]; | ||
136 | break; | ||
137 | |||
138 | case PLA_LEFT: | ||
139 | case PLA_LEFT_REPEAT: | ||
140 | case PLA_RIGHT: | ||
141 | case PLA_RIGHT_REPEAT: | ||
142 | current = (current + 1) % 2; | ||
143 | break; | ||
144 | |||
145 | case PLA_FIRE: { | ||
146 | if (rem_seconds() < 0) | ||
147 | alarm[0] += 24; | ||
148 | |||
149 | waiting = true; | ||
150 | break; | ||
151 | } | ||
152 | |||
153 | default: | ||
154 | if (rb->default_event_handler(button) == SYS_USB_CONNECTED) | ||
155 | quit = usb = true; | ||
156 | break; | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | |||
161 | return (usb) ? PLUGIN_USB_CONNECTED | ||
162 | : (done ? PLUGIN_GOTO_WPS : PLUGIN_OK); | ||
163 | } | ||
164 | |||
diff --git a/manual/plugins/alarmclock.tex b/manual/plugins/alarmclock.tex new file mode 100644 index 0000000000..58d9b3a3db --- /dev/null +++ b/manual/plugins/alarmclock.tex | |||
@@ -0,0 +1,48 @@ | |||
1 | \subsection{Alarm Clock} | ||
2 | |||
3 | This plugin is an alarm clock, which resumes a paused song at a given time. | ||
4 | |||
5 | \subsubsection{Key configuration} | ||
6 | \begin{table} | ||
7 | \begin{btnmap}{}{} | ||
8 | \opt{RECORDER_PAD,IAUDIO_X5_PAD,IRIVER_H300_PAD,IPOD_4G_PAD,IPOD_3G_PAD% | ||
9 | ,GIGABEAT_PAD,GIGABEAT_S_PAD,MROBE100_PAD,SANSA_C200_PAD% | ||
10 | ,SANSA_E200_PAD,IRIVER_H10_PAD,SANSA_FUZE_PAD} | ||
11 | {\ButtonLeft{} / \ButtonRight} | ||
12 | \opt{COWON_D2_PAD}{\TouchMidRight{} / \TouchMidLeft} | ||
13 | \opt{HAVEREMOTEKEYMAP}{& } | ||
14 | & Switch between hours/minutes selection \\ | ||
15 | \opt{RECORDER_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,GIGABEAT_PAD,GIGABEAT_S_PAD% | ||
16 | ,MROBE100_PAD}{\ButtonUp{} / \ButtonDown} | ||
17 | \opt{IPOD_3G_PAD,IPOD_4G_PAD,SANSA_E200_PAD,SANSA_FUZE_PAD} | ||
18 | {\ButtonScrollFwd{} / \ButtonScrollBack} | ||
19 | \opt{SANSA_C200_PAD}{\ButtonVolUp{} / \ButtonVolDown} | ||
20 | \opt{IRIVER_H10_PAD}{\ButtonScrollUp{} / \ButtonScrollDown} | ||
21 | \opt{COWON_D2_PAD}{\ButtonMinus{} / \ButtonPlus} | ||
22 | \opt{HAVEREMOTEKEYMAP}{& } | ||
23 | & Increase/Decrease hours/minutes \\ | ||
24 | \opt{RECORDER_PAD}{\ButtonPlay} | ||
25 | \opt{IRIVER_H10_PAD}{\ButtonRew} | ||
26 | \opt{IRIVER_H300_PAD,IAUDIO_X5_PAD,IPOD_4G_PAD,IPOD_3G_PAD,SANSA_C200_PAD% | ||
27 | ,SANSA_E200_PAD,GIGABEAT_PAD,GIGABEAT_S_PAD,MROBE100_PAD% | ||
28 | ,SANSA_FUZE_PAD} | ||
29 | {\ButtonSelect} | ||
30 | \opt{COWON_D2_PAD}{\ButtonPlus{} or \TouchBottomMiddle} | ||
31 | \opt{HAVEREMOTEKEYMAP}{& } | ||
32 | & Set the alarm \\ | ||
33 | \opt{RECORDER_PAD,IRIVER_H300_PAD}{\ButtonOff} | ||
34 | \opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonMenu + \ButtonSelect} | ||
35 | \opt{IAUDIO_X5_PAD,IRIVER_H10_PAD,SANSA_E200_PAD,SANSA_C200_PAD,GIGABEAT_PAD% | ||
36 | ,MROBE100_PAD}{\ButtonPower} | ||
37 | \opt{SANSA_FUZE_PAD}{Long \ButtonHome} | ||
38 | \opt{GIGABEAT_S_PAD}{\ButtonBack} | ||
39 | \opt{COWON_D2_PAD}{\ButtonPower{} or \TouchBottomRight} | ||
40 | \opt{HAVEREMOTEKEYMAP}{& } | ||
41 | & Exit \\ | ||
42 | \end{btnmap} | ||
43 | \end{table} | ||
44 | |||
45 | \subsubsection{Setting up an alarm} | ||
46 | First select a track, and play it. Then, pause it, and launch the ``alarmclock'' | ||
47 | plugin. Enter a 24h-time (eg. 13:58), and set the alarm. Music playback will | ||
48 | resume when reaching the selected time. | ||
diff --git a/manual/plugins/main.tex b/manual/plugins/main.tex index 6bce439c56..8d1057cfa9 100644 --- a/manual/plugins/main.tex +++ b/manual/plugins/main.tex | |||
@@ -200,6 +200,8 @@ option from the \setting{Context Menu} (see \reference{ref:Contextmenu}).} | |||
200 | 200 | ||
201 | \section{Applications} | 201 | \section{Applications} |
202 | 202 | ||
203 | \opt{rtc}{\input{plugins/alarmclock.tex}} | ||
204 | |||
203 | \opt{archosplayer,archosrecorder,archosfmrecorder}{\input{plugins/alpinecdc.tex}} | 205 | \opt{archosplayer,archosrecorder,archosfmrecorder}{\input{plugins/alpinecdc.tex}} |
204 | 206 | ||
205 | {\input{plugins/batterybenchmark.tex}} | 207 | {\input{plugins/batterybenchmark.tex}} |