1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2015 Joël Krähemann
3 *
4 * This file is part of GSequencer.
5 *
6 * GSequencer is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GSequencer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GSequencer. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <ags/lib/ags_time.h>
21
22 #include <math.h>
23
24 #ifdef __APPLE__
25 #include <mach/clock.h>
26 #include <mach/mach.h>
27 #endif
28
29 /**
30 * SECTION:ags_time
31 * @short_description: utility functions of time
32 * @title: AgsTime
33 * @section_id:
34 * @include: ags/lib/ags_time.h
35 *
36 * Functions to help you dealing with time.
37 */
38
39 /**
40 * ags_time_get_uptime_from_offset:
41 * @offset: the offset in tics
42 * @bpm: the beats per minute
43 * @delay: the buffer time as delay
44 * @delay_factor: tact segmentation
45 *
46 * Calculates uptime from @offset by applying factors @bpm, @delay and @delay_factor
47 * giving you the result as string.
48 *
49 * Returns: (transfer full): the string containing the time, a minus sign is prepend if factors
50 * are invalid
51 *
52 * Since: 3.0.0
53 */
54 gchar*
ags_time_get_uptime_from_offset(guint offset,gdouble bpm,gdouble delay,gdouble delay_factor)55 ags_time_get_uptime_from_offset(guint offset,
56 gdouble bpm,
57 gdouble delay,
58 gdouble delay_factor)
59 {
60 gchar *uptime;
61
62 gdouble delay_min, delay_sec, delay_msec;
63 gdouble tact_redux;
64 guint min, sec, msec;
65
66 if(bpm <= 0.0 ||
67 delay <= 0.0 ||
68 delay_factor <= 0.0){
69 return(g_strdup_printf("-%s",
70 AGS_TIME_ZERO));
71 }
72
73 /* translate to time string */
74 tact_redux = offset;
75
76 delay_sec = 16.0 * delay_factor * bpm / 60.0;
77 delay_min = delay_sec * 60.0;
78 delay_msec = delay_sec / 1000.0;
79
80 min = (guint) floor(tact_redux / delay_min);
81
82 if(min > 0){
83 tact_redux = tact_redux - (min * delay_min);
84 }
85
86 sec = (guint) floor(tact_redux / delay_sec);
87
88 if(sec > 0){
89 tact_redux = tact_redux - (sec * delay_sec);
90 }
91
92 msec = (guint) floor(tact_redux / delay_msec);
93
94 uptime = g_strdup_printf("%.4d:%.2d.%.3d", min, sec, msec);
95
96 return(uptime);
97 }
98
99 /**
100 * ags_time_timeout_expired:
101 * @start_time: the start time #timespec-struct
102 * @timeout_delay: the delay #timespec-struct
103 *
104 * Check @start_time plus @timeout_delay against current time.
105 *
106 * Returns: %TRUE if timeout expired, otherwise %FALSE
107 *
108 * Since: 3.0.0
109 */
110 gboolean
ags_time_timeout_expired(struct timespec * start_time,struct timespec * timeout_delay)111 ags_time_timeout_expired(struct timespec *start_time,
112 struct timespec *timeout_delay)
113 {
114 struct timespec current_time;
115 struct timespec deadline;
116
117 #ifdef __APPLE__
118 clock_serv_t cclock;
119 mach_timespec_t mts;
120 #endif
121
122 if(start_time == NULL ||
123 timeout_delay == NULL){
124 return(TRUE);
125 }
126
127 #ifdef __APPLE__
128 host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
129
130 clock_get_time(cclock, &mts);
131 mach_port_deallocate(mach_task_self(), cclock);
132
133 current_time.tv_sec = mts.tv_sec;
134 current_time.tv_nsec = mts.tv_nsec;
135 #else
136 clock_gettime(CLOCK_MONOTONIC, ¤t_time);
137 #endif
138
139 if(start_time->tv_nsec + timeout_delay->tv_nsec >= AGS_NSEC_PER_SEC){
140 deadline.tv_sec = start_time->tv_sec + timeout_delay->tv_sec + 1;
141 deadline.tv_nsec = (start_time->tv_nsec + timeout_delay->tv_nsec) - AGS_NSEC_PER_SEC;
142 }else{
143 deadline.tv_sec = start_time->tv_sec + timeout_delay->tv_sec;
144 deadline.tv_nsec = start_time->tv_nsec + timeout_delay->tv_nsec;
145 }
146
147 if(current_time.tv_sec > deadline.tv_sec){
148 return(TRUE);
149 }else{
150 if(current_time.tv_sec == deadline.tv_sec &&
151 current_time.tv_nsec > deadline.tv_nsec){
152 return(TRUE);
153 }
154 }
155
156 return(FALSE);
157 }
158