Skip to content

Commit 3e7460a

Browse files
committed
audio with time zone conversion; bugfix config with --no-yaml-scan
1 parent 8f486e8 commit 3e7460a

File tree

10 files changed

+158
-34
lines changed

10 files changed

+158
-34
lines changed

AudioApp/src/components/browser.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@
146146
<thead>
147147
<tr>
148148
<th class="text-left">Location</th>
149-
<th class="text-left">Time</th>
149+
<th class="text-left">Time <span style="font-size: 0.7em;">{{time_zone}}</span></th>
150150
<th class="text-left">Device</th>
151151
<th class="text-left">Id</th>
152152
</tr>
@@ -244,6 +244,7 @@ export default defineComponent({
244244
computed: {
245245
...mapState({
246246
samples_table_count: state => state.project.samples_table_count,
247+
time_zone: state => state.project.time_zone,
247248
}),
248249
refreshConfirmNeeded() {
249250
const count = this.samples_table_count;
@@ -416,6 +417,9 @@ export default defineComponent({
416417
params.end = t + (86400 - 1);
417418
}
418419
}
420+
if(this.time_zone) {
421+
params.tz = this.time_zone;
422+
}
419423
this.requestError = false;
420424
this.requestLoading = true;
421425
var response = await this.$api.get('samples2', { params });

AudioApp/src/pages/project/main.vue

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<q-btn :icon="$refs.browser.movePrevSelectedSampleRequested ? 'recycling' : 'navigate_before'" padding="xs" :class="{'element-hidden': $refs.browser.movePrevSelectedSampleRequested || !$refs.browser.hasSelectedSamplePrev}" @click="if(userSelectedLabelNamesChanged) {onSaveLabels();} $refs.browser.movePrevSelectedSampleRequested = true" title="Move to previous sample on the browsed list of samples"/>
99
<span class="text-weight-bold" v-if="sample.location"><q-icon name="home"/>{{sample.location}}</span>
1010
<span class="text-weight-regular text-grey-9" style="padding-left: 10px;" v-if="sample.date"><q-icon name="calendar_today"/>{{sample.date}}</span>
11-
<span class="text-weight-light text-grey-7" style="padding-left: 5px;" v-if="sample.time"><q-icon name="query_builder"/>{{sample.time}}</span>
11+
<span class="text-weight-light text-grey-9" style="padding-left: 5px;" v-if="sample.time"><q-icon name="query_builder"/>{{sample.time}} <span class="text-weight-light text-grey-7" style="font-size: 0.7em;">{{time_zone}}</span></span>
1212
<span class="text-weight-thin text-grey-6" style="padding-left: 10px; font-family: monospace;" v-if="sample.device"><q-icon name="memory"/>{{sample.device}}</span>
1313
<span class="text-weight-bold" v-if="(!sample.location || !sample.device) && sample.date === undefined"><q-icon name="fingerprint"/>{{sample.id}}</span>
1414
<span class="text-weight-thin text-grey-6" style="padding-left: 10px;" v-if="sampleRate"><q-icon name="leaderboard"/>{{Math.trunc(sampleRate/1000)}}<sup style="font-size: 0.8em">.{{sampleRatemhz}}</sup> kHz</span>
@@ -598,7 +598,9 @@ export default defineComponent({
598598
player_spectrum_shrink_Factor: state => state.project.player_spectrum_shrink_Factor,
599599
player_time_expansion_factor: state => state.project.player_time_expansion_factor,
600600
player_static_lines_frequency: state => state.project.player_static_lines_frequency,
601-
player_mouse_move_factor: state => state.project.player_mouse_move_factor,
601+
player_mouse_move_factor: state => state.project.player_mouse_move_factor,
602+
time_zone: state => state.project.time_zone,
603+
project_data: state => state.project.data,
602604
}),
603605
player_fft_cutoff_lower() {
604606
let c = Math.floor((this.player_fft_cutoff_lower_frequency * this.player_fft_window) / this.sampleRate);
@@ -1191,6 +1193,9 @@ export default defineComponent({
11911193
try {
11921194
var urlPath = 'samples2/' + this.selectedSampleId;
11931195
var params = {samples: true, sample_rate: true, labels: true,};
1196+
if(this.time_zone) {
1197+
params.tz = this.time_zone;
1198+
}
11941199
this.sampleLoading = true;
11951200
this.sampleError = false;
11961201
var response = await this.$api.get(urlPath, {params});
@@ -1397,6 +1402,13 @@ export default defineComponent({
13971402
selectedSampleId: {
13981403
immediate: true,
13991404
async handler() {
1405+
if(this.project_data !== undefined) {
1406+
this.refreshSample();
1407+
}
1408+
}
1409+
},
1410+
async project_data() {
1411+
if(this.project_data !== undefined) {
14001412
this.refreshSample();
14011413
}
14021414
},
@@ -1460,6 +1472,7 @@ export default defineComponent({
14601472
},
14611473
},
14621474
async mounted() {
1475+
//this.$store.dispatch('project/init');
14631476
this.audio = new Audio();
14641477
this.audio.addEventListener('playing', e => this.onAudioPlaying(e));
14651478
this.audio.addEventListener('pause', e => this.onAudioPause(e));

AudioApp/src/store/project.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ state: {
4343
detail_fft_window_overlap_percent: 0.75,
4444
default_detail_fft_window_overlap_percent: 0.75,
4545

46+
time_zone: 'UTC',
47+
default_time_zone: 'UTC',
48+
4649
profiles: {},
4750
profileIds: [''],
4851
profileDefaultId: '(Project defaults)',
@@ -120,6 +123,10 @@ mutations: {
120123
if(settings.detail_fft_window_overlap_percent !== undefined) {
121124
state.default_detail_fft_window_overlap_percent = settings.detail_fft_window_overlap_percent;
122125
}
126+
127+
if(settings.time_zone !== undefined) {
128+
state.default_time_zone = settings.time_zone;
129+
}
123130
},
124131
set(state, settings) {
125132
if(settings.player_fft_window !== undefined) {
@@ -158,6 +165,10 @@ mutations: {
158165
if(settings.detail_fft_window_overlap_percent !== undefined) {
159166
state.detail_fft_window_overlap_percent = settings.detail_fft_window_overlap_percent;
160167
}
168+
169+
if(settings.time_zone !== undefined) {
170+
state.time_zone = settings.time_zone;
171+
}
161172
},
162173
setProfile(state, profileID) {
163174
this.commit('project/setDefaultProfile');

src/audio/AudioProjectConfig.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public final class AudioProjectConfig {
3939
private final Map<String, AudioProfile> profileMap;
4040

4141
public final int audio_cache_max_files;
42+
public final String time_zone;
4243

4344
public static class Builder {
4445
public String project = "default_project"; // project name is needed
@@ -65,6 +66,7 @@ public static class Builder {
6566
public Map<String, AudioProfile> profileMap = null;
6667

6768
public int audio_cache_max_files = 20;
69+
public String time_zone = "UTC";
6870

6971
public Builder() {}
7072

@@ -100,6 +102,7 @@ public Builder(YamlMap yamlMap) {
100102
}
101103

102104
audio_cache_max_files = yamlMap.optInt("audio_cache_max_files", audio_cache_max_files);
105+
yamlMap.optFunString("time_zone", s -> time_zone = s);
103106
}
104107
}
105108

@@ -128,6 +131,7 @@ public AudioProjectConfig(Builder builder) {
128131
profileMap = builder.profileMap == null ? null : new LinkedHashMap<String, AudioProfile>(builder.profileMap);
129132

130133
audio_cache_max_files = builder.audio_cache_max_files;
134+
time_zone = builder.time_zone;
131135
Logger.info(this);
132136
}
133137

@@ -157,6 +161,7 @@ public String toString() {
157161
+ player_fft_cutoff_lower_frequency + ", player_fft_cutoff_upper_frequency="
158162
+ player_fft_cutoff_upper_frequency + ", player_mouse_move_factor=" + player_mouse_move_factor
159163
+ ", detail_fft_window_overlap_percent=" + detail_fft_window_overlap_percent + ", profileMap="
160-
+ profileMap + ", audio_cache_max_files=" + audio_cache_max_files + "]";
164+
+ profileMap + ", audio_cache_max_files=" + audio_cache_max_files + ", time_zone="
165+
+ time_zone + "]";
161166
}
162167
}

src/audio/CommandlineConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public Builder(String[] args) {
1919
String arg = args[i];
2020
switch(arg) {
2121
case "--no-yaml-scan":
22+
this.no_yaml_scan = true;
2223
break;
2324
default:
2425
throw new RuntimeException("unknown command line arg: |" + arg + "| available args: --no-yaml-scan");

src/audio/server/api/ProjectHandler.java

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ private void handleRoot(String project, Request request, HttpServletResponse res
7575
String dates_of_location = Web.getString(request, "dates_of_location", null);
7676
boolean fInventory = Web.getFlagBoolean(request, "inventory");
7777
boolean fSamplesTableCount = Web.getFlagBoolean(request, "samples_table_count");
78+
String reqTimeZone = Web.getString(request, "tz", "UTC");
79+
int timeZoneOffsetSeconds = AudioTimeUtil.getTimeZoneOffsetSeconds(reqTimeZone);
80+
7881
AudioProjectConfig config = broker.config().audioConfig;
7982
if(!config.project.equals(project)) {
8083
throw new RuntimeException("unknown project");
@@ -118,6 +121,8 @@ private void handleRoot(String project, Request request, HttpServletResponse res
118121
json.value(config.player_mouse_move_factor);
119122
json.key("detail_fft_window_overlap_percent");
120123
json.value(config.detail_fft_window_overlap_percent);
124+
json.key("time_zone");
125+
json.value(config.time_zone);
121126

122127
if(config.hasProfiles()) {
123128
json.key("profiles");
@@ -180,8 +185,8 @@ private void handleRoot(String project, Request request, HttpServletResponse res
180185
json.value(samples_table_count);
181186
}
182187

183-
LongConsumer timestampDateTimeWriter = AudioTimeUtil.timestampDateTimeWriter(json);
184-
LongConsumer timestampDateWriter = AudioTimeUtil.timestampDateWriter(json);
188+
LongConsumer timestampDateTimeWriter = AudioTimeUtil.timestampDateTimeWriter(json, timeZoneOffsetSeconds);
189+
LongConsumer timestampDateWriter = AudioTimeUtil.timestampDateWriter(json, timeZoneOffsetSeconds);
185190

186191
if(fTimestamps) {
187192
json.key("timestamps");
@@ -231,27 +236,11 @@ private void handleRoot(String project, Request request, HttpServletResponse res
231236
json.value(entry.location);
232237
if(entry.start != Long.MIN_VALUE) {
233238
json.key("start");
234-
json.object();
235-
json.key("timestamp");
236-
json.value(entry.start);
237-
LocalDateTime dateTime = AudioTimeUtil.ofAudiotime(entry.start);
238-
json.key("date");
239-
json.value(dateTime.toLocalDate());
240-
json.key("time");
241-
json.value(dateTime.toLocalTime());
242-
json.endObject();
239+
AudioTimeUtil.writeTimestampDateTime(json, entry.start, timeZoneOffsetSeconds);
243240
}
244241
if(entry.end != Long.MAX_VALUE) {
245242
json.key("end");
246-
json.object();
247-
json.key("timestamp");
248-
json.value(entry.end);
249-
LocalDateTime dateTime = AudioTimeUtil.ofAudiotime(entry.end);
250-
json.key("date");
251-
json.value(dateTime.toLocalDate());
252-
json.key("time");
253-
json.value(dateTime.toLocalTime());
254-
json.endObject();
243+
AudioTimeUtil.writeTimestampDateTime(json, entry.end, timeZoneOffsetSeconds);
255244
}
256245
json.endObject();
257246
});

src/audio/server/api/Sample2Handler.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ private void handleRoot_GET(Sample2 sample, Request request, HttpServletResponse
120120
boolean reqSamples = Web.getFlagBoolean(request, "samples");
121121
boolean reqSampleRate = Web.getFlagBoolean(request, "sample_rate");
122122
boolean reqLabels = Web.getFlagBoolean(request, "labels");
123+
String reqTimeZone = Web.getString(request, "tz", "UTC");
124+
int timeZoneOffsetSeconds = AudioTimeUtil.getTimeZoneOffsetSeconds(reqTimeZone);
123125

124126
json.object();
125127
json.key("sample");
@@ -137,7 +139,7 @@ private void handleRoot_GET(Sample2 sample, Request request, HttpServletResponse
137139
json.value(sample.device);
138140
}
139141
if(sample.hasTimestamp()) {
140-
AudioTimeUtil.writePropsTimestampDateTime(json, sample.timestamp);
142+
AudioTimeUtil.writePropsTimestampDateTime(json, sample.timestamp, timeZoneOffsetSeconds);
141143
}
142144
if(reqSamples && sample.hasSamples()) {
143145
json.key("samples");

src/audio/server/api/Samples2Handler.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ private void handleRoot(Request request, HttpServletResponse response) throws IO
8484
boolean flagCount = Web.getFlagBoolean(request, "count");
8585
boolean flagDevices = Web.getFlagBoolean(request, "devices");
8686
boolean flagSamples = Web.getFlagBoolean(request, "samples");
87+
String reqTimeZone = Web.getString(request, "tz", "UTC");
88+
int timeZoneOffsetSeconds = AudioTimeUtil.getTimeZoneOffsetSeconds(reqTimeZone);
8789

8890
Consumer<Sample2> sampleWriter = sample -> {
8991
json.object();
@@ -100,7 +102,7 @@ private void handleRoot(Request request, HttpServletResponse response) throws IO
100102
//json.key("timestamp");
101103
//json.value(sample.timestamp);
102104
//Logger.info(sample.timestamp);
103-
LocalDateTime dateTime = AudioTimeUtil.ofAudiotime(sample.timestamp);
105+
LocalDateTime dateTime = AudioTimeUtil.ofAudiotime(sample.timestamp, timeZoneOffsetSeconds);
104106
json.key("date");
105107
json.value(dateTime.toLocalDate());
106108
json.key("time");

src/audio/task/Task_audio_sample_statistics.java

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
import java.text.DecimalFormat;
77
import java.text.DecimalFormatSymbols;
88
import java.time.Duration;
9+
import java.time.LocalDateTime;
10+
import java.time.ZoneOffset;
11+
import java.time.ZonedDateTime;
912
import java.util.Locale;
1013

1114
import org.tinylog.Logger;
@@ -32,10 +35,12 @@
3235
@Param(name = "col_sample", type = Type.BOOLEAN, preset = "TRUE", description = "Include column 'sample' in CSV output. Folder path including filename.")
3336
@Param(name = "col_device", type = Type.BOOLEAN, preset = "TRUE", description = "Include column 'device' in CSV output.")
3437
@Param(name = "col_duration", type = Type.BOOLEAN, preset = "FALSE", description = "Include column 'duration' in CSV output.")
35-
@Param(name = "col_time_zone", type = Type.BOOLEAN, preset = "FALSE", description = "Include column 'time_zone' in CSV output.")
38+
@Param(name = "col_original_time_zone", type = Type.BOOLEAN, preset = "FALSE", description = "Include column 'original_time_zone' of recording in CSV output. This may not be identical to the time zone of the 'time' column.")
3639
@Param(name = "col_temperature", type = Type.BOOLEAN, preset = "FALSE", description = "Include column 'temperature' in CSV output.")
3740
@Param(name = "col_file_size", type = Type.BOOLEAN, preset = "FALSE", description = "Include column 'file_size' in CSV output and sum up total file size in log message.")
3841
@Param(name = "filename", type = Type.STRING, preset = "samples.csv", description = "Filename of output CSV-file.")
42+
@Param(name = "time_zone", type = Type.STRING, preset = "", description = "Set time zone of the 'time' column. e.g. UTC+1 If left empty, default time zone of project will be set.")
43+
@Param(name = "include_time_zone", type = Type.BOOLEAN, preset = "FALSE", description = "In 'time' column, include the time zone marker. If false, time zone marker is not included in output, but time zone conversions are still applied.")
3944
@Param(name = "filter_by_location", type = Type.STRING, preset = "", description = "(optional) Process the specified location only.")
4045
@Param(name = "filter_by_device", type = Type.STRING, preset = "", description = "(optional) Process the specified device id only.")
4146
@Param(name = "filter_by_time", type = Type.STRING, preset = "", description = "(optional) Process the specified range of time only. Format: yyyy-MM-ddTHH:mm:ss A shortened format leads to a range of time. e.g. 2022 means all samples from year 2022. e.g. 2022-02 means all samples from February at year 2022.")
@@ -64,10 +69,15 @@ public void run() {
6469
boolean col_sample = this.ctx.getParamBoolean("col_sample");
6570
boolean col_device = this.ctx.getParamBoolean("col_device");
6671
boolean col_duration = this.ctx.getParamBoolean("col_duration");
67-
boolean col_time_zone = this.ctx.getParamBoolean("col_time_zone");
72+
boolean col_original_time_zone = this.ctx.getParamBoolean("col_original_time_zone");
6873
boolean col_temperature = this.ctx.getParamBoolean("col_temperature");
6974
boolean col_file_size = this.ctx.getParamBoolean("col_file_size");
7075
String filename = this.ctx.getParamString("filename");
76+
String reqTimeZone = this.ctx.getParamString("time_zone");
77+
boolean include_time_zone = this.ctx.getParamBoolean("include_time_zone");
78+
String tz = reqTimeZone.isBlank() ? ctx.broker.config().audioConfig.time_zone : reqTimeZone;
79+
int timeZoneOffsetSeconds = AudioTimeUtil.getTimeZoneOffsetSeconds(tz);
80+
ZoneOffset timeZoneOffset = include_time_zone ? ZoneOffset.ofTotalSeconds(timeZoneOffsetSeconds) : null;
7181
String filter_by_location = this.ctx.getParamString("filter_by_location");
7282
String filter_by_device = this.ctx.getParamString("filter_by_device");
7383
String filter_by_time = this.ctx.getParamString("filter_by_time");
@@ -103,8 +113,8 @@ public void run() {
103113
if(col_duration) {
104114
cols.add("duration");
105115
}
106-
if(col_time_zone) {
107-
cols.add("time_zone");
116+
if(col_original_time_zone) {
117+
cols.add("original_time_zone");
108118
}
109119
if(col_temperature) {
110120
cols.add("temperature");
@@ -133,8 +143,15 @@ public void run() {
133143
row.add(location);
134144
}
135145
if(col_time) {
136-
String timeName = AudioTimeUtil.ofAudiotime(sample.timestamp).toString();
137-
row.add(timeName);
146+
LocalDateTime dt = AudioTimeUtil.ofAudiotime(sample.timestamp, timeZoneOffsetSeconds);
147+
if(include_time_zone) {
148+
ZonedDateTime zdt = ZonedDateTime.of(dt, timeZoneOffset);
149+
String timeName = zdt.toString();
150+
row.add(timeName);
151+
} else {
152+
String timeName = dt.toString();
153+
row.add(timeName);
154+
}
138155
}
139156
if(col_path || col_filename || col_sample) {
140157
Path path = root_data_path.relativize(sample.samplePath);
@@ -165,7 +182,7 @@ public void run() {
165182
row.add("NA");
166183
}
167184
}
168-
if(col_time_zone) {
185+
if(col_original_time_zone) {
169186
String utc_ = sample.getUTC();
170187
String utc = utc_ == null ? "" : utc_;
171188
row.add(utc);

0 commit comments

Comments
 (0)