1 /*
2    gnauralnet_clocksync.c
3    Core methods and variables for common timing on the GnauralNet network
4    Depends on:
5    gnauralnet.h
6    gnauralnet_clocksync.c
7    gnauralnet_lists.c
8    gnauralnet_main.c
9    gnauralnet_socket.c
10 
11    Copyright (C) 2008  Bret Logan
12 
13    This program is free software; you can redistribute it and/or modify
14    it under the terms of the GNU General Public License as published by
15    the Free Software Foundation; either version 2 of the License, or
16    (at your option) any later version.
17 
18    This program is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21    GNU General Public License for more details.
22 
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27 
28 #include "gnauralnet.h"
29 
30 ////////////////////////////////////////
31 //This returns the number of microsecs (usecs) since last call;
32 //IMPORTANT: first call will return garbage, so it is
33 //STRONGLY recommended to make that first call before anything
34 //critical.
GN_Time_ElapsedSinceLastCall()35 unsigned int GN_Time_ElapsedSinceLastCall ()
36 {
37  static GTimeVal lasttime = { 0, 0 };
38  unsigned int result;
39  GTimeVal curtime;
40 
41  g_get_current_time (&curtime);
42  result =
43   (((curtime.tv_sec - lasttime.tv_sec) * 1e6) +
44    (curtime.tv_usec - lasttime.tv_usec));
45  memcpy (&lasttime, &curtime, sizeof (GTimeVal));
46 
47  return result;
48 }
49 
50 ////////////////////////////////////////
51 //Update data for the friend's entry with this incoming Time data.
52 //returns GNAURALNET_SUCCESS if time info was legit (PacketID, etc.),
53 //GNAURALNET_FAILURE if not.
GN_Time_ProcessIncomingData(GN_Friend * curFriend)54 int GN_Time_ProcessIncomingData (GN_Friend * curFriend)
55 {
56  if (NULL == curFriend)
57  {
58   return GNAURALNET_FAILURE;
59  }
60 
61  //do stuff that gets recorded even if packet gets discarded:
62  g_get_current_time (&(curFriend->Time_Recv));
63 
64  //make sure this wasn't first packet between us, or that
65  //friend is remembering me from before I restarted:
66  if (2 > curFriend->RecvCount)
67  {
68   GN_DBGOUT ("Haven't known Friend long enough to share Time");
69   return GNAURALNET_FAILURE;
70  }
71 
72  curFriend->Time_PacketRoundTrip =
73   (((curFriend->Time_Recv.tv_sec - curFriend->Time_Send.tv_sec) * 1e6) +
74    (curFriend->Time_Recv.tv_usec - curFriend->Time_Send.tv_usec));
75 
76  GN_DBGOUT_INT ("PacketRoundTrip time:", curFriend->Time_PacketRoundTrip);
77 
78  if (0 == curFriend->Time_AverageOffset)
79  {
80   curFriend->Time_AverageOffset = 0.5 * curFriend->Time_PacketRoundTrip;
81   GN_DBGOUT_DBL ("New friend, starting Offset at:",
82 		 curFriend->Time_AverageOffset);
83  }
84  else
85  {
86   curFriend->Time_AverageOffset =
87    (curFriend->Time_AverageOffset - (0.1 * curFriend->Time_AverageOffset)) +
88    (0.05 * curFriend->Time_PacketRoundTrip);
89   GN_DBGOUT_DBL ("Offset from Friend:", curFriend->Time_AverageOffset);
90  }
91 
92  //do the BinauralBeat stuff if GN_STANDALONE is not defined:
93  GN_Running_ProcessIncomingData (curFriend);
94  return GNAURALNET_SUCCESS;
95 }
96 
97 ////////////////////////////////////////
98 //Give this the friend in question for this incoming Time data.
99 //returns GNAURALNET_SUCCESS if time info was legit (PacketID, etc.),
100 //GNAURALNET_FAILURE if not.
GN_Time_ProcessOutgoingData(GN_Friend * curFriend)101 void GN_Time_ProcessOutgoingData (GN_Friend * curFriend)
102 {
103  if (NULL == curFriend)
104  {
105   return;
106  }
107 
108  //++curFriend->PacketID;       //uchar, so no need to net-order
109  //curFriend->PacketID_expected = curFriend->PacketID + 1;      //uchar, so no need to net-order
110 
111  g_get_current_time (&(curFriend->Time_Send));
112 
113  //20080221: this segment is meaningless now:
114  if (0 != curFriend->RecvCount)
115  {
116   curFriend->Time_DelayOnMe =
117    ((curFriend->Time_Send.tv_sec - curFriend->Time_Recv.tv_sec) * 1e6) +
118    (curFriend->Time_Send.tv_usec - curFriend->Time_Recv.tv_usec);
119   GN_DBGOUT_UINT ("Delay on Me:", curFriend->Time_DelayOnMe);
120  }
121 
122  //do the BinauralBeat stuff if GN_STANDALONE is not defined:
123  GN_Running_ProcessOutgoingData (curFriend);
124 }
125 
126 ////////////////////////////////////////////////////////////////
127 //Called by anything that breaks continuity of a runing schedule.
128 //Like FF, RW, STOP, PAUSE, engine-reloading, etc.
GN_Time_ResetSeniority()129 void GN_Time_ResetSeniority ()
130 {
131  g_get_current_time (&(GN_My.RunningStartTime));
132 }
133 
134 ////////////////////////////////////////////////////////////////
135 //The following was provided so that apps not requiring BB could
136 //be run; it was done by putting all calls that need BB vars in
137 //gnauralnet_running.c
138 #ifdef GN_STANDALONE
139 ////////////////////////////////////////
140 //THIS IS A DUMMY FUNCTIONl see gnauralnet_running.c for real one
GN_Running_ProcessIncomingData(GN_Friend * curFriend)141 void GN_Running_ProcessIncomingData (GN_Friend * curFriend)
142 {
143  if (NULL == curFriend)
144  {
145   return;
146  }
147 
148  if (0 == GN_My.RunningID || curFriend->RunningID != GN_My.RunningID)
149  {
150   return;
151  }
152  //  unsigned int CurrentSampleCount;
153  //  int LoopCount;
154 }
155 
156 ////////////////////////////////////////
157 //THIS IS A DUMMY FUNCTION see gnauralnet_running.c for real one
GN_Running_ProcessOutgoingData(GN_Friend * curFriend)158 void GN_Running_ProcessOutgoingData (GN_Friend * curFriend)
159 {
160  if (NULL == curFriend)
161  {
162   return;
163  }
164 
165  if (0 == GN_My.RunningID || curFriend->RunningID != GN_My.RunningID)
166  {
167   return;
168  }
169  //  unsigned int CurrentSampleCount;
170  //  int LoopCount;
171 }
172 #endif
173