1 /**
2  * Copyright (c) 2016, Timothy Stack
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * * Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  * * Neither the name of Timothy Stack nor the names of its contributors
15  * may be used to endorse or promote products derived from this software
16  * without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * @file spectroview_curses.hh
30  */
31 
32 #ifndef spectro_source_hh
33 #define spectro_source_hh
34 
35 #include <math.h>
36 #include <time.h>
37 
38 #include <map>
39 #include <vector>
40 
41 #include "ansi_scrubber.hh"
42 #include "textview_curses.hh"
43 
44 struct spectrogram_bounds {
45     time_t sb_begin_time{0};
46     time_t sb_end_time{0};
47     double sb_min_value_out{0.0};
48     double sb_max_value_out{0.0};
49     int64_t sb_count{0};
50 };
51 
52 struct spectrogram_thresholds {
53     int st_green_threshold{0};
54     int st_yellow_threshold{0};
55 };
56 
57 struct spectrogram_request {
spectrogram_requestspectrogram_request58     explicit spectrogram_request(spectrogram_bounds &sb)
59         : sr_bounds(sb) {
60     };
61 
62     spectrogram_bounds &sr_bounds;
63     unsigned long sr_width{0};
64     time_t sr_begin_time{0};
65     time_t sr_end_time{0};
66     double sr_column_size{0};
67 };
68 
69 struct spectrogram_row {
~spectrogram_rowspectrogram_row70     ~spectrogram_row() {
71         delete[] this->sr_values;
72     }
73 
74     struct row_bucket {
row_bucketspectrogram_row::row_bucket75         row_bucket() : rb_counter(0), rb_marks(0) { };
76 
77         int rb_counter;
78         int rb_marks;
79     };
80 
81     row_bucket *sr_values{nullptr};
82     unsigned long sr_width{0};
83     double sr_column_size{0.0};
84 
add_valuespectrogram_row85     void add_value(spectrogram_request &sr, double value, bool marked) {
86         long index = lrint((value - sr.sr_bounds.sb_min_value_out) / sr.sr_column_size);
87 
88         this->sr_values[index].rb_counter += 1;
89         if (marked) {
90             this->sr_values[index].rb_marks += 1;
91         }
92     };
93 };
94 
95 class spectrogram_value_source {
96 public:
97     virtual ~spectrogram_value_source() = default;
98 
99     virtual void spectro_bounds(spectrogram_bounds &sb_out) = 0;
100 
101     virtual void spectro_row(spectrogram_request &sr,
102                              spectrogram_row &row_out) = 0;
103 
104     virtual void spectro_mark(textview_curses &tc,
105                               time_t begin_time, time_t end_time,
106                               double range_min, double range_max) = 0;
107 };
108 
109 class spectrogram_source
110     : public text_sub_source,
111       public text_time_translator,
112       public list_overlay_source,
113       public list_input_delegate {
114 public:
invalidate()115     void invalidate() {
116         this->ss_cached_bounds.sb_count = 0;
117         this->ss_row_cache.clear();
118         this->ss_cursor_column = -1;
119     };
120 
121     bool list_input_handle_key(listview_curses &lv, int ch) override;
122 
123     bool list_value_for_overlay(const listview_curses &lv,
124                                 int y, int bottom,
125                                 vis_line_t row,
126                                 attr_line_t &value_out) override;
127 
128     size_t text_line_count() override;
129 
130     size_t text_line_width(textview_curses &tc) override;
131 
text_size_for_line(textview_curses & tc,int row,line_flags_t flags)132     size_t text_size_for_line(textview_curses &tc, int row, line_flags_t flags) override {
133         return 0;
134     };
135 
136     nonstd::optional<struct timeval> time_for_row(vis_line_t row) override;
137 
138     nonstd::optional<vis_line_t> row_for_time(struct timeval time_bucket) override;
139 
140     void text_value_for_line(textview_curses &tc,
141                              int row,
142                              std::string &value_out,
143                              line_flags_t flags) override;
144 
145     void text_attrs_for_line(textview_curses &tc,
146                              int row,
147                              string_attrs_t &value_out) override;
148 
149     void cache_bounds();
150 
151     spectrogram_row &load_row(textview_curses &tc, int row);
152 
153     int ss_granularity{60};
154     spectrogram_value_source *ss_value_source{nullptr};
155     spectrogram_bounds ss_cached_bounds;
156     spectrogram_thresholds ss_cached_thresholds;
157     size_t ss_cached_line_count{0};
158     std::map<time_t, spectrogram_row> ss_row_cache;
159     vis_line_t ss_cursor_top;
160     int ss_cursor_column{-1};
161 };
162 
163 #endif
164