1 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
2 
3 #include "smsamplewinview.hh"
4 #include "smnavigator.hh"
5 #include "smutils.hh"
6 
7 #include <QVBoxLayout>
8 
9 #define LOOP_NONE_TEXT              "No loop"
10 #define LOOP_FRAME_FORWARD_TEXT     "Frame loop forward"
11 #define LOOP_FRAME_PING_PONG_TEXT   "Frame loop ping-pong"
12 #define LOOP_TIME_FORWARD_TEXT      "Time loop forward"
13 #define LOOP_TIME_PING_PONG_TEXT    "Time loop ping-pong"
14 
15 using namespace SpectMorph;
16 
17 using std::string;
18 
19 SampleWinView::SampleWinView (Navigator *navigator)
20 {
21   this->navigator = navigator;
22 
23   zoom_controller = new ZoomController (this, 1, 5000, 10, 5000);
24   connect (zoom_controller, SIGNAL (zoom_changed()), this, SLOT (on_zoom_changed()));
25 
26   m_sample_view = new SampleView();
27   time_label = new QLabel();
28   connect (m_sample_view, SIGNAL (mouse_time_changed (int)), this, SLOT (on_mouse_time_changed (int)));
29   on_mouse_time_changed (0);
30 
31   edit_loop_start = new QPushButton ("Edit Loop Start");
32   edit_loop_end = new QPushButton ("Edit Loop End");
33 
34   connect (edit_loop_start, SIGNAL (clicked()), this, SLOT (on_edit_marker_changed()));
35   connect (edit_loop_end, SIGNAL (clicked()), this, SLOT (on_edit_marker_changed()));
36 
37   edit_loop_start->setCheckable (true);
38   edit_loop_end->setCheckable (true);
39 
40   loop_type_combo = new QComboBox();
41   loop_type_combo->addItem (LOOP_NONE_TEXT);
42   loop_type_combo->addItem (LOOP_FRAME_FORWARD_TEXT);
43   loop_type_combo->addItem (LOOP_FRAME_PING_PONG_TEXT);
44   loop_type_combo->addItem (LOOP_TIME_FORWARD_TEXT);
45   loop_type_combo->addItem (LOOP_TIME_PING_PONG_TEXT);
46 
47   connect (loop_type_combo, SIGNAL (currentIndexChanged (int)), this, SLOT (on_loop_type_changed()));
48 
49   show_tuning_button = new QPushButton ("Show Tuning");
50   connect (show_tuning_button, SIGNAL (clicked()), this, SLOT (on_show_tuning_changed()));
51   show_tuning_button->setCheckable (true);
52 
53   scroll_area = new QScrollArea();
54   scroll_area->setWidgetResizable (true);
55   scroll_area->setWidget (m_sample_view);
56 
57   zoom_controller->set_hscrollbar (scroll_area->horizontalScrollBar());
58   QGridLayout *grid = new QGridLayout();
59   grid->addWidget (scroll_area, 0, 0, 1, 3);
60   for (int i = 0; i < 3; i++)
61     {
62       grid->addWidget (zoom_controller->hwidget (i), 1, i);
63       grid->addWidget (zoom_controller->vwidget (i), 2, i);
64     }
65   QHBoxLayout *button_hbox = new QHBoxLayout();
66   button_hbox->addWidget (time_label);
67   button_hbox->addWidget (edit_loop_start);
68   button_hbox->addWidget (edit_loop_end);
69   button_hbox->addWidget (loop_type_combo);
70   button_hbox->addWidget (show_tuning_button);
71 
72   grid->addLayout (button_hbox, 3, 0, 1, 3);
73 
74   setLayout (grid);
75 }
76 
77 void
78 SampleWinView::load (const WavData *wav_data, Audio *audio)
79 {
80   m_sample_view->load (wav_data, audio);
81   if (audio)
82     {
83       if (audio->loop_type == Audio::LOOP_NONE)
84         loop_type_combo->setCurrentText (LOOP_NONE_TEXT);
85       else if (audio->loop_type == Audio::LOOP_FRAME_FORWARD)
86         loop_type_combo->setCurrentText (LOOP_FRAME_FORWARD_TEXT);
87       else if (audio->loop_type == Audio::LOOP_FRAME_PING_PONG)
88         loop_type_combo->setCurrentText (LOOP_FRAME_PING_PONG_TEXT);
89       else if (audio->loop_type == Audio::LOOP_TIME_FORWARD)
90         loop_type_combo->setCurrentText (LOOP_TIME_FORWARD_TEXT);
91       else if (audio->loop_type == Audio::LOOP_TIME_PING_PONG)
92         loop_type_combo->setCurrentText (LOOP_TIME_PING_PONG_TEXT);
93       else
94         {
95           g_assert_not_reached();
96         }
97     }
98 }
99 
100 void
101 SampleWinView::on_zoom_changed()
102 {
103   m_sample_view->set_zoom (zoom_controller->get_hzoom(), zoom_controller->get_vzoom());
104 }
105 
106 void
107 SampleWinView::on_mouse_time_changed (int time)
108 {
109   int ms = time % 1000;
110   time /= 1000;
111   int s = time % 60;
112   time /= 60;
113   int m = time;
114   time_label->setText (string_locale_printf ("Time: %02d:%02d:%03d ms", m, s, ms).c_str());
115 }
116 
117 void
118 SampleWinView::on_edit_marker_changed()
119 {
120   SampleView::EditMarkerType marker_type;
121 
122   QPushButton *btn = qobject_cast<QPushButton *> (sender());
123   if (btn == edit_loop_start)
124     marker_type = SampleView::MARKER_LOOP_START;
125   else if (btn == edit_loop_end)
126     marker_type = SampleView::MARKER_LOOP_END;
127   else
128     g_assert_not_reached();
129 
130   if (m_sample_view->edit_marker_type() == marker_type)  // we're selected already -> turn it off
131     marker_type = SampleView::MARKER_NONE;
132 
133   m_sample_view->set_edit_marker_type (marker_type);
134 
135   edit_loop_start->setChecked (marker_type == SampleView::MARKER_LOOP_START);
136   edit_loop_end->setChecked (marker_type == SampleView::MARKER_LOOP_END);
137 }
138 
139 void
140 SampleWinView::on_show_tuning_changed()
141 {
142   m_sample_view->set_show_tuning (show_tuning_button->isChecked());
143 }
144 
145 void
146 SampleWinView::on_loop_type_changed()
147 {
148   Audio *audio = navigator->get_audio();
149   if (audio)
150     {
151       string text = loop_type_combo->currentText().toLatin1().data();
152       Audio::LoopType new_loop_type;
153 
154       if (text == LOOP_NONE_TEXT)
155         new_loop_type = Audio::LOOP_NONE;
156       else if (text == LOOP_FRAME_FORWARD_TEXT)
157         new_loop_type = Audio::LOOP_FRAME_FORWARD;
158       else if (text == LOOP_FRAME_PING_PONG_TEXT)
159         new_loop_type = Audio::LOOP_FRAME_PING_PONG;
160       else if (text == LOOP_TIME_FORWARD_TEXT)
161         new_loop_type = Audio::LOOP_TIME_FORWARD;
162       else if (text == LOOP_TIME_PING_PONG_TEXT)
163         new_loop_type = Audio::LOOP_TIME_PING_PONG;
164       else
165         {
166           g_assert_not_reached();
167         }
168 
169       if (new_loop_type != audio->loop_type)
170         {
171           Q_EMIT audio_edit();
172           audio->loop_type = new_loop_type;
173         }
174     }
175 }
176 
177 SampleView *
178 SampleWinView::sample_view()
179 {
180   return m_sample_view;
181 }
182