Project

General

Profile

main.cc

skins-qt/main.cc - Jim Turner, December 06, 2019 15:08

 
1
/*  Fauxdacious - Cross-platform multimedia player
2
 *  Copyright (C) 2005-2011  Audacious development team.
3
 *
4
 *  BMP - Cross-platform multimedia player
5
 *  Copyright (C) 2003-2004  BMP development team.
6
 *
7
 *  Based on XMMS:
8
 *  Copyright (C) 1998-2003  XMMS development team.
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; under version 3 of the License.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses>.
21
 *
22
 *  The Audacious team does not consider modular code linking to
23
 *  Audacious or using our public API to be a derived work.
24
 */
25

    
26
#include <math.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <sys/time.h>
30
#include <QMouseEvent>
31

    
32
#include <libfauxdcore/audstrings.h>
33
#include <libfauxdcore/drct.h>
34
#include <libfauxdcore/hook.h>
35
#include <libfauxdcore/i18n.h>
36
#include <libfauxdcore/mainloop.h>
37
#include <libfauxdcore/plugins.h>
38
#include <libfauxdcore/runtime.h>
39
#include <libfauxdcore/playlist.h>
40
#include <libfauxdqt/libfauxdqt.h>
41

    
42
#include "../ui-common/dialogs-qt.h"
43

    
44
#include "actions-mainwin.h"
45
#include "actions-playlist.h"
46
#include "dnd.h"
47
#include "menus.h"
48
#include "plugin.h"
49
#include "skins_cfg.h"
50
#include "equalizer.h"
51
#include "main.h"
52
#include "vis-callbacks.h"
53
#include "playlistwin.h"
54
#include "button.h"
55
#include "hslider.h"
56
#include "menurow.h"
57
#include "monostereo.h"
58
#include "number.h"
59
#include "playlist-widget.h"
60
#include "playstatus.h"
61
#include "textbox.h"
62
#include "window.h"
63
#include "vis.h"
64
#include "skins_util.h"
65
#include "view.h"
66
#include "skinselector.h"
67

    
68
#define SEEK_THRESHOLD 200 /* milliseconds */
69
#define SEEK_SPEED 50 /* milliseconds per pixel */
70

    
71
class MainWindow : public Window
72
{
73
public:
74
    MainWindow (bool shaded) :
75
        Window (WINDOW_MAIN, & config.player_x, & config.player_y,
76
         shaded ? MAINWIN_SHADED_WIDTH : skin.hints.mainwin_width,
77
         shaded ? MAINWIN_SHADED_HEIGHT : skin.hints.mainwin_height, shaded),
78
        m_dialogs (this) {}
79

    
80
private:
81
    DialogWindows m_dialogs;
82
    int m_scroll_delta_x = 0;
83
    int m_scroll_delta_y = 0;
84

    
85
    void draw (QPainter & cr);
86
    bool button_press (QMouseEvent * event);
87
    void enterEvent (QEvent * event);
88
    int m_playlist = -1;
89
    int m_popup_pos = -1;
90
    bool scroll (QWheelEvent * event);
91
};
92

    
93
Window * mainwin;
94

    
95
Button * mainwin_eq, * mainwin_pl;
96
TextBox * mainwin_info;
97
MenuRow * mainwin_menurow;
98

    
99
SkinnedVis * mainwin_vis;
100
SmallVis * mainwin_svis;
101

    
102
static int last_skin = -1;
103
static bool skip_toggle = true;   // JWT:NEEDED SINCE mainwin_playback_begin SEEMS TO GET CALLED *TWICE* EACH TIME?!
104
static bool seeking = false;
105
static int seek_start, seek_time;
106

    
107
static TextBox * locked_textbox = nullptr;
108
static String locked_old_text;
109

    
110
static QueuedFunc status_message_timeout;
111
static QueuedFunc mainwin_volume_release_timeout;
112

    
113
static Button * mainwin_menubtn, * mainwin_minimize, * mainwin_shade, * mainwin_close;
114
static Button * mainwin_shaded_menubtn, * mainwin_shaded_minimize, * mainwin_shaded_shade, * mainwin_shaded_close;
115

    
116
static Button * mainwin_rew, * mainwin_fwd;
117
static Button * mainwin_eject;
118
static Button * mainwin_play, * mainwin_pause, * mainwin_stop;
119
static Button * mainwin_shuffle, * mainwin_repeat;
120

    
121
static TextBox * mainwin_stime_min, * mainwin_stime_sec;
122
static TextBox * mainwin_rate_text, * mainwin_freq_text, * mainwin_othertext;
123

    
124
static PlayStatus * mainwin_playstatus;
125
static SkinnedNumber * mainwin_minus_num, * mainwin_10min_num, * mainwin_min_num;
126
static SkinnedNumber * mainwin_10sec_num, * mainwin_sec_num;
127
static HSlider * mainwin_position, * mainwin_sposition;
128

    
129
static HSlider * mainwin_volume, * mainwin_balance;
130
static MonoStereo * mainwin_monostereo;
131

    
132
static Button * mainwin_srew, * mainwin_splay, * mainwin_spause;
133
static Button * mainwin_sstop, * mainwin_sfwd, * mainwin_seject, * mainwin_about;
134

    
135
static void mainwin_position_motion_cb ();
136
static void mainwin_position_release_cb ();
137
static void seek_timeout (void * rewind);
138

    
139
static bool showing_about_window = false;  /* JWT: TRUE WHEN "ABOUT" WINDOW IS DISPLAYED, SO WE CAN TOGGLE IF OFF */
140

    
141
/* always returns a 6-character string */
142
static StringBuf format_time (int time, int length)
143
{
144
    bool zero = aud_get_bool (nullptr, "leading_zero");
145
    bool remaining = aud_get_bool ("skins", "show_remaining_time");
146

    
147
    if (remaining && length > 0)
148
    {
149
        time = (length - time) / 1000;
150
        time = aud::clamp(0, time, 359999); // 99:59:59
151

    
152
        if (time < 60)
153
            return str_printf (zero ? "-00:%02d" : " -0:%02d", time);
154
        else if (time < 6000)
155
            return str_printf (zero ? "%03d:%02d" : "%3d:%02d", -time / 60, time % 60);
156
        else
157
            return str_printf ("%3d:%02d", -time / 3600, time / 60 % 60);
158
    }
159
    else
160
    {
161
        time /= 1000;
162
        time = aud::clamp(0, time, 3599999); // 999:59:59
163

    
164
        if (time < 6000)
165
            return str_printf (zero ? " %02d:%02d" : " %2d:%02d", time / 60, time % 60);
166
        else if (time < 60000)
167
            return str_printf ("%3d:%02d", time / 60, time % 60);
168
        else
169
            return str_printf ("%3d:%02d", time / 3600, time / 60 % 60);
170
    }
171
}
172

    
173
static void mainwin_menubtn_cb ()
174
{
175
    int x, y;
176
    mainwin->getPosition (& x, & y);
177
    menu_popup (UI_MENU_MAIN, x + 6 * config.scale,
178
     y + MAINWIN_SHADED_HEIGHT * config.scale, false, false);
179
}
180

    
181
static void mainwin_minimize_cb ()
182
{
183
    mainwin->showMinimized ();
184
}
185

    
186
static void mainwin_shade_toggle ()
187
{
188
    view_set_player_shaded (! aud_get_bool ("skins", "player_shaded"));
189
}
190

    
191
static void mainwin_lock_info_text (const char * text)
192
{
193
    if (! locked_textbox)
194
    {
195
        locked_textbox = skin.hints.mainwin_othertext_is_status ? mainwin_othertext : mainwin_info;
196
        locked_old_text = locked_textbox->get_text ();
197
    }
198

    
199
    locked_textbox->set_text (text);
200
}
201

    
202
static void mainwin_release_info_text (void * = nullptr)
203
{
204
    if (locked_textbox)
205
    {
206
        locked_textbox->set_text (locked_old_text);
207
        locked_textbox = nullptr;
208
        locked_old_text = String ();
209
    }
210
}
211

    
212
static void set_info_text (TextBox * textbox, const char * text)
213
{
214
    if (textbox == locked_textbox)
215
        locked_old_text = String (text);
216
    else
217
        textbox->set_text (text);
218
}
219

    
220
#define mainwin_set_info_text(t) set_info_text (mainwin_info, (t))
221
#define mainwin_set_othertext(t) set_info_text (mainwin_othertext, (t))
222

    
223
void mainwin_show_status_message (const char * message)
224
{
225
    mainwin_lock_info_text (message);
226
    status_message_timeout.queue (1000, mainwin_release_info_text, nullptr);
227
}
228

    
229
static void mainwin_set_song_title (const char * title)
230
{
231
    StringBuf buf;
232

    
233
    if (title)
234
        buf = str_printf (_("%s - Fauxdacious"), (const char *) str_get_first_line (title));
235
    else
236
        buf = str_copy (_("Fauxdacious"));
237

    
238
/* JWT:DON'T DO THIS:    int instance = aud_get_instance ();
239
    if (instance != 1)
240
        str_append_printf (buf, " (%d)", instance);
241
*/
242
    String instancename = aud_get_instancename ();
243
    if (instancename != String ("fauxdacious"))
244
        str_append_printf (buf, " (%s)", (const char *) instancename);
245
    mainwin->setWindowTitle ((const char *) buf);
246
    mainwin_set_info_text ((const char *) buf);
247
}
248

    
249
static void title_change ()
250
{
251
    if (aud_drct_get_ready ())
252
        mainwin_set_song_title (aud_drct_get_title ());
253
    else
254
        mainwin_set_song_title ("Buffering ...");
255
}
256

    
257
static void setup_widget (Widget * widget, int x, int y, bool show)
258
{
259
    widget->setVisible (show);
260
    mainwin->move_widget (false, widget, x, y);
261
}
262

    
263
void mainwin_refresh_hints ()
264
{
265
    const SkinHints * p = & skin.hints;
266

    
267
    mainwin_menurow->setVisible (p->mainwin_menurow_visible);
268
    mainwin_rate_text->setVisible (p->mainwin_streaminfo_visible);
269
    mainwin_freq_text->setVisible (p->mainwin_streaminfo_visible);
270
    mainwin_monostereo->setVisible (p->mainwin_streaminfo_visible);
271

    
272
    mainwin_info->set_width (p->mainwin_text_width);
273

    
274
    setup_widget (mainwin_vis, p->mainwin_vis_x, p->mainwin_vis_y, p->mainwin_vis_visible);
275
    setup_widget (mainwin_info, p->mainwin_text_x, p->mainwin_text_y, p->mainwin_text_visible);
276
    setup_widget (mainwin_othertext, p->mainwin_infobar_x, p->mainwin_infobar_y, p->mainwin_othertext_visible);
277

    
278
    bool playing = aud_drct_get_playing ();
279
    bool can_seek = aud_drct_get_length () > 0;
280

    
281
    setup_widget (mainwin_minus_num, p->mainwin_number_0_x, p->mainwin_number_0_y, playing);
282
    setup_widget (mainwin_10min_num, p->mainwin_number_1_x, p->mainwin_number_1_y, playing);
283
    setup_widget (mainwin_min_num, p->mainwin_number_2_x, p->mainwin_number_2_y, playing);
284
    setup_widget (mainwin_10sec_num, p->mainwin_number_3_x, p->mainwin_number_3_y, playing);
285
    setup_widget (mainwin_sec_num, p->mainwin_number_4_x, p->mainwin_number_4_y, playing);
286
    setup_widget (mainwin_position, p->mainwin_position_x, p->mainwin_position_y, can_seek);
287

    
288
    setup_widget (mainwin_playstatus, p->mainwin_playstatus_x, p->mainwin_playstatus_y, true);
289
    setup_widget (mainwin_volume, p->mainwin_volume_x, p->mainwin_volume_y, true);
290
    setup_widget (mainwin_balance, p->mainwin_balance_x, p->mainwin_balance_y, true);
291
    setup_widget (mainwin_rew, p->mainwin_previous_x, p->mainwin_previous_y, true);
292
    setup_widget (mainwin_play, p->mainwin_play_x, p->mainwin_play_y, true);
293
    setup_widget (mainwin_pause, p->mainwin_pause_x, p->mainwin_pause_y, true);
294
    setup_widget (mainwin_stop, p->mainwin_stop_x, p->mainwin_stop_y, true);
295
    setup_widget (mainwin_fwd, p->mainwin_next_x, p->mainwin_next_y, true);
296
    setup_widget (mainwin_eject, p->mainwin_eject_x, p->mainwin_eject_y, true);
297
    setup_widget (mainwin_eq, p->mainwin_eqbutton_x, p->mainwin_eqbutton_y, true);
298
    setup_widget (mainwin_pl, p->mainwin_plbutton_x, p->mainwin_plbutton_y, true);
299
    setup_widget (mainwin_shuffle, p->mainwin_shuffle_x, p->mainwin_shuffle_y, true);
300
    setup_widget (mainwin_repeat, p->mainwin_repeat_x, p->mainwin_repeat_y, true);
301
    setup_widget (mainwin_about, p->mainwin_about_x, p->mainwin_about_y, true);
302
    setup_widget (mainwin_minimize, p->mainwin_minimize_x, p->mainwin_minimize_y, true);
303
    setup_widget (mainwin_shade, p->mainwin_shade_x, p->mainwin_shade_y, true);
304
    setup_widget (mainwin_close, p->mainwin_close_x, p->mainwin_close_y, true);
305

    
306
    if (aud_get_bool ("skins", "player_shaded"))
307
        mainwin->resize (MAINWIN_SHADED_WIDTH, MAINWIN_SHADED_HEIGHT);
308
    else
309
        mainwin->resize (p->mainwin_width, p->mainwin_height);
310

    
311
    mainwin_vis->set_colors ();
312
}
313

    
314
/* note that the song info is not translated since it is displayed using
315
 * the skinned bitmap font, which supports only the English alphabet */
316
static void mainwin_set_song_info (int bitrate, int samplerate, int channels)
317
{
318
    char scratch[32];
319
    int length;
320

    
321
    if (bitrate > 0)
322
    {
323
        if (bitrate < 1000000)
324
            snprintf (scratch, sizeof scratch, "%3d", bitrate / 1000);
325
        else
326
            snprintf (scratch, sizeof scratch, "%2dH", bitrate / 100000);
327

    
328
        mainwin_rate_text->set_text (scratch);
329
    }
330
    else
331
        mainwin_rate_text->set_text (nullptr);
332

    
333
    if (samplerate > 0)
334
    {
335
        snprintf (scratch, sizeof scratch, "%2d", samplerate / 1000);
336
        mainwin_freq_text->set_text (scratch);
337
    }
338
    else
339
        mainwin_freq_text->set_text (nullptr);
340

    
341
    mainwin_monostereo->set_num_channels (channels);
342

    
343
    if (bitrate > 0)
344
        snprintf (scratch, sizeof scratch, "%d kbps", bitrate / 1000);
345
    else
346
        scratch[0] = 0;
347

    
348
    if (samplerate > 0)
349
    {
350
        length = strlen (scratch);
351
        snprintf (scratch + length, sizeof scratch - length, "%s%d kHz", length ?
352
         ", " : "", samplerate / 1000);
353
    }
354

    
355
    if (channels > 0)
356
    {
357
        length = strlen (scratch);
358
        snprintf (scratch + length, sizeof scratch - length, "%s%s", length ?
359
         ", " : "", channels > 2 ? "surround" : channels > 1 ? "stereo" : "mono");
360
    }
361

    
362
    mainwin_set_othertext (scratch);
363
}
364

    
365
static void info_change ()
366
{
367
    int bitrate, samplerate, channels;
368
    aud_drct_get_info (bitrate, samplerate, channels);
369
    mainwin_set_song_info (bitrate, samplerate, channels);
370
}
371

    
372
static void playback_pause ()
373
{
374
    mainwin_playstatus->set_status (STATUS_PAUSE);
375
}
376

    
377
static void playback_unpause ()
378
{
379
    mainwin_playstatus->set_status (STATUS_PLAY);
380
}
381

    
382
void mainwin_playback_begin ()
383
{
384
    mainwin_update_song_info ();
385

    
386
    if (aud_get_bool ("skins", "use_random_skins"))
387
    {
388
        if (skinlist.len () <= 0)
389
            skinlist_update ();
390
        if (! skip_toggle && skinlist.len () > 1)
391
        {
392
            int randskin = rand () % skinlist.len ();
393
            while (randskin == last_skin)
394
                randskin = rand () % skinlist.len ();
395

    
396
            if (skin_load (skinlist[randskin].path))
397
                view_apply_skin ();
398
            last_skin = randskin;
399
        }
400
        skip_toggle = ! skip_toggle;
401
    }
402

    
403
    mainwin_stime_min->show ();
404
    mainwin_stime_sec->show ();
405
    mainwin_minus_num->show ();
406
    mainwin_10min_num->show ();
407
    mainwin_min_num->show ();
408
    mainwin_10sec_num->show ();
409
    mainwin_sec_num->show ();
410

    
411
    if (aud_drct_get_length () > 0)
412
    {
413
        mainwin_position->show ();
414
        mainwin_sposition->show ();
415
    }
416

    
417
    if (aud_drct_get_paused ())
418
        playback_pause ();
419
    else
420
        playback_unpause ();
421

    
422
    title_change ();
423
    info_change ();
424
}
425

    
426
static void mainwin_playback_stop ()
427
{
428
    seeking = false;
429
    timer_remove (TimerRate::Hz10, seek_timeout);
430

    
431
    mainwin_set_song_title (nullptr);
432

    
433
    mainwin_vis->clear ();
434
    mainwin_svis->clear ();
435

    
436
    mainwin_minus_num->hide ();
437
    mainwin_10min_num->hide ();
438
    mainwin_min_num->hide ();
439
    mainwin_10sec_num->hide ();
440
    mainwin_sec_num->hide ();
441
    mainwin_stime_min->hide ();
442
    mainwin_stime_sec->hide ();
443
    mainwin_position->hide ();
444
    mainwin_sposition->hide ();
445

    
446
    mainwin_position->set_pressed (false);
447
    mainwin_sposition->set_pressed (false);
448

    
449
    /* clear sampling parameter displays */
450
    mainwin_rate_text->set_text (nullptr);
451
    mainwin_freq_text->set_text (nullptr);
452
    mainwin_monostereo->set_num_channels (0);
453
    mainwin_set_othertext ("");
454

    
455
    mainwin_playstatus->set_status (STATUS_STOP);
456

    
457
    playlistwin_hide_timer();
458
}
459

    
460
static void record_toggled ()
461
{
462
    if (aud_drct_get_record_enabled ())
463
        mainwin_show_status_message (_("Recording on"));
464
    else
465
        mainwin_show_status_message (_("Recording off"));
466
}
467

    
468
static void repeat_toggled ()
469
{
470
    mainwin_repeat->set_active (aud_get_bool (nullptr, "repeat"));
471
}
472

    
473
static void shuffle_toggled ()
474
{
475
    mainwin_shuffle->set_active (aud_get_bool (nullptr, "shuffle"));
476
}
477

    
478
static void no_advance_toggled ()
479
{
480
    if (aud_get_bool (nullptr, "no_playlist_advance"))
481
        mainwin_show_status_message (_("Single mode."));
482
    else
483
        mainwin_show_status_message (_("Playlist mode."));
484
}
485

    
486
static void stop_after_song_toggled ()
487
{
488
    if (aud_get_bool (nullptr, "stop_after_current_song"))
489
        mainwin_show_status_message (_("Stopping after song."));
490
}
491

    
492
bool MainWindow::scroll (QWheelEvent * event)
493
{
494
    m_scroll_delta_x += event->angleDelta ().x ();
495
    m_scroll_delta_y += event->angleDelta ().y ();
496

    
497
    /* we want discrete steps here */
498
    int steps_x = m_scroll_delta_x / 120;
499
    int steps_y = m_scroll_delta_y / 120;
500

    
501
    if (steps_x != 0)
502
    {
503
        m_scroll_delta_x -= 120 * steps_x;
504
        int step_size = aud_get_int (0, "step_size");
505
        aud_drct_seek (aud_drct_get_time () - steps_x * step_size * 1000);
506
    }
507

    
508
    if (steps_y != 0)
509
    {
510
        m_scroll_delta_y -= 120 * steps_y;
511
        int volume_delta = aud_get_int (0, "volume_delta");
512
        aud_drct_set_volume_main (aud_drct_get_volume_main () + steps_y * volume_delta);
513
    }
514

    
515
    return true;
516
}
517

    
518
bool MainWindow::button_press (QMouseEvent * event)
519
{
520
    if (event->button () == Qt::LeftButton &&
521
            event->type () == QEvent::MouseButtonDblClick &&
522
            event->y () < 14 * config.scale)
523
    {
524
        mainwin_shade_toggle ();
525
        return true;
526
    }
527

    
528
    if (event->button () == Qt::RightButton && event->type () == QEvent::MouseButtonPress)
529
    {
530
        menu_popup (UI_MENU_MAIN, event->globalX (), event->globalY (), false, false);
531
        return true;
532
    }
533

    
534
    return Window::button_press (event);
535
}
536

    
537
void MainWindow::enterEvent (QEvent * event)  // JWT:FUNCTION ADDED FOR POPUP SONG INFO-
538
{                                             // WHEN HOVERING OVER SHADED MAIN WINDOW:
539
    if (is_shaded ())
540
    {
541
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
542
        int mousex = mouseEvent->y ();  // JWT:THIS SEEMS 2B BASSACKWARDS (x<->y)?!
543
        if (mousex > 78 && mousex < 165)
544
        {
545
            if (aud_get_bool (nullptr, "show_filepopup_for_tuple"))
546
                   {
547
                              m_playlist = aud_playlist_get_active ();
548
                m_popup_pos = aud_playlist_get_position (m_playlist);
549
                //audqt::infopopup_hide ();
550

    
551
                if (m_popup_pos >= 0)
552
                    audqt::infopopup_show (m_playlist, m_popup_pos);
553
            }
554
        }
555
    }
556
}
557

    
558
static void mainwin_playback_rpress (Button * button, QMouseEvent * event)
559
{
560
    menu_popup (UI_MENU_PLAYBACK, event->globalX (), event->globalY (), false, false);
561
}
562

    
563
bool Window::keypress (QKeyEvent * event)
564
{
565
    if (playlistwin_list->handle_keypress (event))
566
        return true;
567

    
568
    switch (event->key ())
569
    {
570
        case Qt::Key_Left:
571
            aud_drct_seek (aud_drct_get_time () - 5000);
572
            break;
573
        case Qt::Key_Right:
574
            aud_drct_seek (aud_drct_get_time () + 5000);
575
            break;
576
        case Qt::Key_Space:
577
            aud_drct_pause ();
578
            break;
579
        default:
580
            return false;
581
    }
582

    
583
    return true;
584
}
585

    
586
#if 0
587
void mainwin_drag_data_received (GtkWidget * widget, GdkDragContext * context,
588
 int x, int y, GtkSelectionData * selection_data, unsigned info, unsigned time, void *)
589
{
590
    g_return_if_fail (selection_data != nullptr);
591

592
    const char * data = (const char *) gtk_selection_data_get_data (selection_data);
593
    g_return_if_fail (data);
594

595
    if (str_has_prefix_nocase (data, "file:///"))
596
    {
597
        if (str_has_suffix_nocase (data, ".wsz\r\n") || str_has_suffix_nocase
598
         (data, ".zip\r\n"))
599
        {
600
            on_skin_view_drag_data_received (0, context, x, y, selection_data, info, time, 0);
601
            return;
602
        }
603
    }
604

605
    audgui_urilist_open (data);
606
}
607
#endif
608

    
609
static int time_now ()
610
{
611
    struct timeval tv;
612
    gettimeofday (& tv, nullptr);
613
    return (tv.tv_sec % (24 * 3600) * 1000 + tv.tv_usec / 1000);
614
}
615

    
616
static int time_diff (int a, int b)
617
{
618
    if (a > 18 * 3600 * 1000 && b < 6 * 3600 * 1000) /* detect midnight */
619
        b += 24 * 3600 * 1000;
620
    return (b > a) ? b - a : 0;
621
}
622

    
623
static void seek_timeout (void * rewind)
624
{
625
    int held = time_diff (seek_time, time_now ());
626
    if (held < SEEK_THRESHOLD)
627
        return;
628

    
629
    int position;
630
    if (aud::from_ptr<bool> (rewind))
631
        position = seek_start - held / SEEK_SPEED;
632
    else
633
        position = seek_start + held / SEEK_SPEED;
634

    
635
    position = aud::clamp (position, 0, 219);
636
    mainwin_position->set_pos (position);
637
    mainwin_position_motion_cb ();
638
}
639

    
640
static void seek_press (QMouseEvent * event, bool rewind)
641
{
642
    if (event->button () != Qt::LeftButton || seeking)
643
        return;
644

    
645
    seeking = true;
646
    seek_start = mainwin_position->get_pos ();
647
    seek_time = time_now ();
648
    timer_add (TimerRate::Hz10, seek_timeout, aud::to_ptr (rewind));
649
}
650

    
651
static void seek_release (QMouseEvent * event, bool rewind)
652
{
653
    if (event->button () != Qt::LeftButton || ! seeking)
654
        return;
655

    
656
    if (! aud_drct_get_playing () || time_diff (seek_time, time_now ()) <
657
     SEEK_THRESHOLD)
658
    {
659
        if (rewind)
660
            aud_drct_pl_prev ();
661
        else
662
            aud_drct_pl_next ();
663
    }
664
    else
665
        mainwin_position_release_cb ();
666

    
667
    seeking = false;
668
    timer_remove (TimerRate::Hz10, seek_timeout);
669
}
670

    
671
static void mainwin_rew_press (Button * button, QMouseEvent * event)
672
    { seek_press (event, true); }
673
static void mainwin_rew_release (Button * button, QMouseEvent * event)
674
    { seek_release (event, true); }
675
static void mainwin_fwd_press (Button * button, QMouseEvent * event)
676
    { seek_press (event, false); }
677
static void mainwin_fwd_release (Button * button, QMouseEvent * event)
678
    { seek_release (event, false); }
679

    
680
static void mainwin_shuffle_cb (Button * button, QMouseEvent * event)
681
    { aud_set_bool (nullptr, "shuffle", button->get_active ()); }
682
static void mainwin_repeat_cb (Button * button, QMouseEvent * event)
683
    { aud_set_bool (nullptr, "repeat", button->get_active ()); }
684
static void mainwin_eq_cb (Button * button, QMouseEvent * event)
685
    { view_set_show_equalizer (button->get_active ()); }
686
static void mainwin_pl_cb (Button * button, QMouseEvent * event)
687
    { view_set_show_playlist (button->get_active ()); }
688

    
689
static void mainwin_spos_set_knob ()
690
{
691
    int pos = mainwin_sposition->get_pos ();
692
    int x = (pos < 6) ? 17 : (pos < 9) ? 20 : 23;
693
    mainwin_sposition->set_knob (x, 36, x, 36);
694
}
695

    
696
static void mainwin_spos_motion_cb ()
697
{
698
    mainwin_spos_set_knob ();
699

    
700
    int pos = mainwin_sposition->get_pos ();
701
    int length = aud_drct_get_length ();
702
    int time = (pos - 1) * length / 12;
703

    
704
    StringBuf buf = format_time (time, length);
705

    
706
    mainwin_stime_min->set_text (buf);
707
    mainwin_stime_sec->set_text (buf + 4);
708
}
709

    
710
static void mainwin_spos_release_cb ()
711
{
712
    mainwin_spos_set_knob ();
713

    
714
    int pos = mainwin_sposition->get_pos ();
715
    aud_drct_seek (aud_drct_get_length () * (pos - 1) / 12);
716
}
717

    
718
static void mainwin_position_motion_cb ()
719
{
720
    int length = aud_drct_get_length () / 1000;
721
    int pos = mainwin_position->get_pos ();
722
    int time = pos * length / 219;
723

    
724
    mainwin_lock_info_text (str_printf (_("Seek to %d:%-2.2d / %d:%-2.2d"),
725
     time / 60, time % 60, length / 60, length % 60));
726
}
727

    
728
static void mainwin_position_release_cb ()
729
{
730
    int length = aud_drct_get_length ();
731
    int pos = mainwin_position->get_pos ();
732
    int time = (int64_t) pos * length / 219;
733

    
734
    aud_drct_seek(time);
735
    mainwin_release_info_text();
736
}
737

    
738
void mainwin_adjust_volume_motion (int v)
739
{
740
    aud_drct_set_volume_main (v);
741
    mainwin_lock_info_text (str_printf (_("Volume: %d%%"), v));
742
}
743

    
744
void mainwin_adjust_volume_release ()
745
{
746
    mainwin_release_info_text ();
747
}
748

    
749
void mainwin_adjust_balance_motion (int b)
750
{
751
    aud_drct_set_volume_balance (b);
752

    
753
    if (b < 0)
754
        mainwin_lock_info_text (str_printf (_("Balance: %d%% left"), -b));
755
    else if (b == 0)
756
        mainwin_lock_info_text (_("Balance: center"));
757
    else
758
        mainwin_lock_info_text (str_printf (_("Balance: %d%% right"), b));
759
}
760

    
761
void mainwin_adjust_balance_release ()
762
{
763
    mainwin_release_info_text ();
764
}
765

    
766
static void mainwin_volume_set_frame ()
767
{
768
    int pos = mainwin_volume->get_pos ();
769
    int frame = (pos * 27 + 25) / 51;
770
    mainwin_volume->set_frame (0, 15 * frame);
771
}
772

    
773
void mainwin_set_volume_slider (int percent)
774
{
775
    mainwin_volume->set_pos ((percent * 51 + 50) / 100);
776
    mainwin_volume_set_frame ();
777
}
778

    
779
static void mainwin_volume_motion_cb ()
780
{
781
    mainwin_volume_set_frame ();
782
    int pos = mainwin_volume->get_pos ();
783
    int vol = (pos * 100 + 25) / 51;
784

    
785
    mainwin_adjust_volume_motion (vol);
786
    equalizerwin_set_volume_slider (vol);
787
}
788

    
789
static void mainwin_volume_release_cb ()
790
{
791
    mainwin_volume_set_frame ();
792
    mainwin_adjust_volume_release ();
793
}
794

    
795
static void mainwin_balance_set_frame ()
796
{
797
    int pos = mainwin_balance->get_pos ();
798
    int frame = (abs (pos - 12) * 27 + 6) / 12;
799
    mainwin_balance->set_frame (9, 15 * frame);
800
}
801

    
802
void mainwin_set_balance_slider (int percent)
803
{
804
    if (percent > 0)
805
        mainwin_balance->set_pos (12 + (percent * 12 + 50) / 100);
806
    else
807
        mainwin_balance->set_pos (12 + (percent * 12 - 50) / 100);
808

    
809
    mainwin_balance_set_frame ();
810
}
811

    
812
static void mainwin_balance_motion_cb ()
813
{
814
    mainwin_balance_set_frame ();
815
    int pos = mainwin_balance->get_pos ();
816

    
817
    int bal;
818
    if (pos > 12)
819
        bal = ((pos - 12) * 100 + 6) / 12;
820
    else
821
        bal = ((pos - 12) * 100 - 6) / 12;
822

    
823
    mainwin_adjust_balance_motion (bal);
824
    equalizerwin_set_balance_slider (bal);
825
}
826

    
827
static void mainwin_balance_release_cb ()
828
{
829
    mainwin_balance_set_frame ();
830
    mainwin_adjust_volume_release ();
831
}
832

    
833
void mainwin_set_volume_diff (int diff)
834
{
835
    int vol = aud_drct_get_volume_main ();
836

    
837
    vol = aud::clamp (vol + diff, 0, 100);
838
    mainwin_adjust_volume_motion (vol);
839
    mainwin_set_volume_slider (vol);
840
    equalizerwin_set_volume_slider (vol);
841

    
842
    mainwin_volume_release_timeout.queue (700,
843
     [] (void *) { mainwin_volume_release_cb (); }, nullptr);
844
}
845

    
846
void mainwin_mr_change (MenuRowItem i)
847
{
848
    switch (i)
849
    {
850
        case MENUROW_OPTIONS:
851
            mainwin_lock_info_text (_("Options Menu"));
852
            break;
853
        case MENUROW_ALWAYS:
854
            if (aud_get_bool ("skins", "always_on_top"))
855
                mainwin_lock_info_text (_("Disable 'Always On Top'"));
856
            else
857
                mainwin_lock_info_text (_("Enable 'Always On Top'"));
858
            break;
859
        case MENUROW_FILEINFOBOX:
860
            mainwin_lock_info_text (_("File Info Box"));
861
            break;
862
        case MENUROW_SCALE:
863
            mainwin_lock_info_text (_("Double Size"));
864
            break;
865
        case MENUROW_VISUALIZATION:
866
            mainwin_lock_info_text (_("Visualizations"));
867
            break;
868
        default:
869
            break;
870
    }
871
}
872

    
873
void mainwin_mr_release (MenuRowItem i, QMouseEvent * event)
874
{
875
    switch (i)
876
    {
877
        case MENUROW_OPTIONS:
878
            menu_popup (UI_MENU_VIEW, event->globalX (), event->globalY (), false, false);
879
            break;
880
        case MENUROW_ALWAYS:
881
            view_set_on_top (! aud_get_bool ("skins", "always_on_top"));
882
            break;
883
        case MENUROW_FILEINFOBOX:
884
            audqt::infowin_show_current ();
885
            break;
886
        case MENUROW_SCALE:
887
            view_set_double_size (! aud_get_bool ("skins", "double_size"));
888
            break;
889
        case MENUROW_VISUALIZATION:
890
            audqt::prefswin_show_plugin_page (PluginType::Vis);
891
            break;
892
        default:
893
            break;
894
    }
895

    
896
    mainwin_release_info_text();
897
}
898

    
899
bool change_timer_mode_cb (QMouseEvent * event)
900
{
901
    if (event->type () != QEvent::MouseButtonPress || event->button () != Qt::LeftButton)
902
        return false;
903

    
904
    view_set_show_remaining (! aud_get_bool ("skins", "show_remaining_time"));
905
    return true;
906
}
907

    
908
static bool mainwin_info_button_press (QMouseEvent * event)
909
{
910
    if (event->type () == QEvent::MouseButtonPress && event->button () == Qt::RightButton)
911
    {
912
        menu_popup (UI_MENU_PLAYBACK, event->globalX (), event->globalY (), false, false);
913
        return true;
914
    }
915

    
916
    if (event->type () == QEvent::MouseButtonDblClick && event->button () == Qt::LeftButton)
917
    {
918
        audqt::infowin_show_current ();
919
        return true;
920
    }
921

    
922
    return false;
923
}
924

    
925
static void showhide_about_window_cb (QMouseEvent * event)
926
{
927
        if (showing_about_window)
928
        {
929
                audqt::aboutwindow_hide ();
930
                showing_about_window = false;
931
        }
932
        else
933
        {
934
                audqt::aboutwindow_show ();
935
                showing_about_window = true;
936
        }
937
}
938

    
939
static void mainwin_create_widgets ()
940
{
941
    mainwin_menubtn = new Button (9, 9, 0, 0, 0, 9, SKIN_TITLEBAR, SKIN_TITLEBAR);
942
    mainwin->put_widget (false, mainwin_menubtn, 6, 3);
943
    mainwin_menubtn->on_release ((ButtonCB) mainwin_menubtn_cb);
944

    
945
    mainwin_minimize = new Button (9, 9, 9, 0, 9, 9, SKIN_TITLEBAR, SKIN_TITLEBAR);
946
    mainwin->put_widget (false, mainwin_minimize, 244, 3);
947
    mainwin_minimize->on_release ((ButtonCB) mainwin_minimize_cb);
948

    
949
    mainwin_shade = new Button (9, 9, 0, 18, 9, 18, SKIN_TITLEBAR, SKIN_TITLEBAR);
950
    mainwin->put_widget (false, mainwin_shade, 254, 3);
951
    mainwin_shade->on_release ((ButtonCB) mainwin_shade_toggle);
952

    
953
    mainwin_close = new Button (9, 9, 18, 0, 18, 9, SKIN_TITLEBAR, SKIN_TITLEBAR);
954
    mainwin->put_widget (false, mainwin_close, 264, 3);
955
    mainwin_close->on_release ((ButtonCB) skins_close);
956

    
957
    mainwin_rew = new Button (23, 18, 0, 0, 0, 18, SKIN_CBUTTONS, SKIN_CBUTTONS);
958
    mainwin->put_widget (false, mainwin_rew, 16, 88);
959
    mainwin_rew->on_press (mainwin_rew_press);
960
    mainwin_rew->on_release (mainwin_rew_release);
961
    mainwin_rew->on_rpress (mainwin_playback_rpress);
962

    
963
    mainwin_fwd = new Button (22, 18, 92, 0, 92, 18, SKIN_CBUTTONS, SKIN_CBUTTONS);
964
    mainwin->put_widget (false, mainwin_fwd, 108, 88);
965
    mainwin_fwd->on_press (mainwin_fwd_press);
966
    mainwin_fwd->on_release (mainwin_fwd_release);
967
    mainwin_fwd->on_rpress (mainwin_playback_rpress);
968

    
969
    mainwin_play = new Button (23, 18, 23, 0, 23, 18, SKIN_CBUTTONS, SKIN_CBUTTONS);
970
    mainwin->put_widget (false, mainwin_play, 39, 88);
971
    mainwin_play->on_release ((ButtonCB) aud_drct_play);
972
    mainwin_play->on_rpress (mainwin_playback_rpress);
973

    
974
    mainwin_pause = new Button (23, 18, 46, 0, 46, 18, SKIN_CBUTTONS, SKIN_CBUTTONS);
975
    mainwin->put_widget (false, mainwin_pause, 62, 88);
976
    mainwin_pause->on_release ((ButtonCB) aud_drct_pause);
977
    mainwin_pause->on_rpress (mainwin_playback_rpress);
978

    
979
    mainwin_stop = new Button (23, 18, 69, 0, 69, 18, SKIN_CBUTTONS, SKIN_CBUTTONS);
980
    mainwin->put_widget (false, mainwin_stop, 85, 88);
981
    mainwin_stop->on_release ((ButtonCB) aud_drct_stop);
982
    mainwin_stop->on_rpress (mainwin_playback_rpress);
983

    
984
    mainwin_eject = new Button (22, 16, 114, 0, 114, 16, SKIN_CBUTTONS, SKIN_CBUTTONS);
985
    mainwin->put_widget (false, mainwin_eject, 136, 89);
986
    mainwin_eject->on_release ((ButtonCB) action_play_file);
987

    
988
    mainwin_shuffle = new Button (46, 15, 28, 0, 28, 15, 28, 30, 28, 45, SKIN_SHUFREP, SKIN_SHUFREP);
989
    mainwin->put_widget (false, mainwin_shuffle, 164, 89);
990
    mainwin_shuffle->set_active (aud_get_bool (nullptr, "shuffle"));
991
    mainwin_shuffle->on_release (mainwin_shuffle_cb);
992

    
993
    mainwin_repeat = new Button (28, 15, 0, 0, 0, 15, 0, 30, 0, 45, SKIN_SHUFREP, SKIN_SHUFREP);
994
    mainwin->put_widget (false, mainwin_repeat, 210, 89);
995
    mainwin_repeat->set_active (aud_get_bool (nullptr, "repeat"));
996
    mainwin_repeat->on_release (mainwin_repeat_cb);
997

    
998
    mainwin_eq = new Button (23, 12, 0, 61, 46, 61, 0, 73, 46, 73, SKIN_SHUFREP, SKIN_SHUFREP);
999
    mainwin->put_widget (false, mainwin_eq, 219, 58);
1000
    mainwin_eq->on_release (mainwin_eq_cb);
1001

    
1002
    mainwin_pl = new Button (23, 12, 23, 61, 69, 61, 23, 73, 69, 73, SKIN_SHUFREP, SKIN_SHUFREP);
1003
    mainwin->put_widget (false, mainwin_pl, 242, 58);
1004
    mainwin_pl->on_release (mainwin_pl_cb);
1005

    
1006
    String font;
1007
    if (! config.mainwin_use_bitmapfont)
1008
        font = aud_get_str ("skins", "mainwin_font");
1009

    
1010
    bool shaded = aud_get_bool ("skins", "mainwin_shaded");
1011
    mainwin_info = new TextBox (153, font, ! shaded && config.autoscroll);
1012
    mainwin->put_widget (false, mainwin_info, 112, 27);
1013
    mainwin_info->on_press (mainwin_info_button_press);
1014

    
1015
    mainwin_othertext = new TextBox (153, nullptr, false);
1016
    mainwin->put_widget (false, mainwin_othertext, 112, 43);
1017

    
1018
    mainwin_rate_text = new TextBox (15, nullptr, false);
1019
    mainwin->put_widget (false, mainwin_rate_text, 111, 43);
1020

    
1021
    mainwin_freq_text = new TextBox (10, nullptr, false);
1022
    mainwin->put_widget (false, mainwin_freq_text, 156, 43);
1023

    
1024
    mainwin_menurow = new MenuRow;
1025
    mainwin->put_widget (false, mainwin_menurow, 10, 22);
1026

    
1027
    mainwin_volume = new HSlider (0, 51, SKIN_VOLUME, 68, 13, 0, 0, 14, 11, 15, 422, 0, 422);
1028
    mainwin->put_widget (false, mainwin_volume, 107, 57);
1029
    mainwin_volume->on_move (mainwin_volume_motion_cb);
1030
    mainwin_volume->on_release (mainwin_volume_release_cb);
1031

    
1032
    mainwin_balance = new HSlider (0, 24, SKIN_BALANCE, 38, 13, 9, 0, 14, 11, 15, 422, 0, 422);
1033
    mainwin->put_widget (false, mainwin_balance, 177, 57);
1034
    mainwin_balance->on_move (mainwin_balance_motion_cb);
1035
    mainwin_balance->on_release (mainwin_balance_release_cb);
1036

    
1037
    mainwin_monostereo = new MonoStereo;
1038
    mainwin->put_widget (false, mainwin_monostereo, 212, 41);
1039

    
1040
    mainwin_playstatus = new PlayStatus;
1041
    mainwin->put_widget (false, mainwin_playstatus, 24, 28);
1042

    
1043
    mainwin_minus_num = new SkinnedNumber;
1044
    mainwin->put_widget (false, mainwin_minus_num, 36, 26);
1045

    
1046
    mainwin_10min_num = new SkinnedNumber;
1047
    mainwin->put_widget (false, mainwin_10min_num, 48, 26);
1048

    
1049
    mainwin_min_num = new SkinnedNumber;
1050
    mainwin->put_widget (false, mainwin_min_num, 60, 26);
1051

    
1052
    mainwin_10sec_num = new SkinnedNumber;
1053
    mainwin->put_widget (false, mainwin_10sec_num, 78, 26);
1054

    
1055
    mainwin_sec_num = new SkinnedNumber;
1056
    mainwin->put_widget (false, mainwin_sec_num, 90, 26);
1057

    
1058
    mainwin_about = new Button (20, 25);
1059
    mainwin->put_widget (false, mainwin_about, 247, 83);
1060
    /* JWT: mainwin_about->on_release ((ButtonCB) audqt::aboutwindow_show); */
1061
    mainwin_about->on_release ((ButtonCB) showhide_about_window_cb);
1062

    
1063
    mainwin_vis = new SkinnedVis;
1064
    mainwin->put_widget (false, mainwin_vis, 24, 43);
1065

    
1066
    mainwin_position = new HSlider (0, 219, SKIN_POSBAR, 248, 10, 0, 0, 29, 10, 248, 0, 278, 0);
1067
    mainwin->put_widget (false, mainwin_position, 16, 72);
1068
    mainwin_position->on_move (mainwin_position_motion_cb);
1069
    mainwin_position->on_release (mainwin_position_release_cb);
1070

    
1071
    /* shaded */
1072

    
1073
    mainwin_shaded_menubtn = new Button (9, 9, 0, 0, 0, 9, SKIN_TITLEBAR, SKIN_TITLEBAR);
1074
    mainwin->put_widget (true, mainwin_shaded_menubtn, 6, 3);
1075
    mainwin_shaded_menubtn->on_release ((ButtonCB) mainwin_menubtn_cb);
1076

    
1077
    mainwin_shaded_minimize = new Button (9, 9, 9, 0, 9, 9, SKIN_TITLEBAR, SKIN_TITLEBAR);
1078
    mainwin->put_widget (true, mainwin_shaded_minimize, 244, 3);
1079
    mainwin_shaded_minimize->on_release ((ButtonCB) mainwin_minimize_cb);
1080

    
1081
    mainwin_shaded_shade = new Button (9, 9, 0, 27, 9, 27, SKIN_TITLEBAR, SKIN_TITLEBAR);
1082
    mainwin->put_widget (true, mainwin_shaded_shade, 254, 3);
1083
    mainwin_shaded_shade->on_release ((ButtonCB) mainwin_shade_toggle);
1084

    
1085
    mainwin_shaded_close = new Button (9, 9, 18, 0, 18, 9, SKIN_TITLEBAR, SKIN_TITLEBAR);
1086
    mainwin->put_widget (true, mainwin_shaded_close, 264, 3);
1087
    mainwin_shaded_close->on_release ((ButtonCB) skins_close);
1088

    
1089
    mainwin_srew = new Button (8, 7);
1090
    mainwin->put_widget (true, mainwin_srew, 169, 4);
1091
    mainwin_srew->on_release ((ButtonCB) aud_drct_pl_prev);
1092

    
1093
    mainwin_splay = new Button (10, 7);
1094
    mainwin->put_widget (true, mainwin_splay, 177, 4);
1095
    mainwin_splay->on_release ((ButtonCB) aud_drct_play);
1096

    
1097
    mainwin_spause = new Button (10, 7);
1098
    mainwin->put_widget (true, mainwin_spause, 187, 4);
1099
    mainwin_spause->on_release ((ButtonCB) aud_drct_pause);
1100

    
1101
    mainwin_sstop = new Button (9, 7);
1102
    mainwin->put_widget (true, mainwin_sstop, 197, 4);
1103
    mainwin_sstop->on_release ((ButtonCB) aud_drct_stop);
1104

    
1105
    mainwin_sfwd = new Button (8, 7);
1106
    mainwin->put_widget (true, mainwin_sfwd, 206, 4);
1107
    mainwin_sfwd->on_release ((ButtonCB) aud_drct_pl_next);
1108

    
1109
    mainwin_seject = new Button (9, 7);
1110
    mainwin->put_widget (true, mainwin_seject, 216, 4);
1111
    mainwin_seject->on_release ((ButtonCB) action_play_file);
1112

    
1113
    mainwin_svis = new SmallVis ();
1114
    mainwin->put_widget (true, mainwin_svis, 79, 5);
1115

    
1116
    mainwin_sposition = new HSlider (1, 13, SKIN_TITLEBAR, 17, 7, 0, 36, 3, 7, 17, 36, 17, 36);
1117
    mainwin->put_widget (true, mainwin_sposition, 226, 4);
1118
    mainwin_sposition->on_move (mainwin_spos_motion_cb);
1119
    mainwin_sposition->on_release (mainwin_spos_release_cb);
1120

    
1121
    mainwin_stime_min = new TextBox (15, nullptr, false);
1122
    mainwin->put_widget (true, mainwin_stime_min, 130, 4);
1123
    mainwin_stime_min->on_press (change_timer_mode_cb);
1124

    
1125
    mainwin_stime_sec = new TextBox (10, nullptr, false);
1126
    mainwin->put_widget (true, mainwin_stime_sec, 147, 4);
1127
    mainwin_stime_sec->on_press (change_timer_mode_cb);
1128
}
1129

    
1130
#if 0
1131
static gboolean state_cb (GtkWidget * widget, GdkEventWindowState * event, void *)
1132
{
1133
    if (event->changed_mask & GDK_WINDOW_STATE_STICKY)
1134
        view_set_sticky (!! (event->new_window_state & GDK_WINDOW_STATE_STICKY));
1135

1136
    if (event->changed_mask & GDK_WINDOW_STATE_ABOVE)
1137
        view_set_on_top (!! (event->new_window_state & GDK_WINDOW_STATE_ABOVE));
1138

1139
    return true;
1140
}
1141
#endif
1142

    
1143
void MainWindow::draw (QPainter & cr)
1144
{
1145
    int width = is_shaded () ? MAINWIN_SHADED_WIDTH : skin.hints.mainwin_width;
1146
    int height = is_shaded () ? MAINWIN_SHADED_HEIGHT : skin.hints.mainwin_height;
1147

    
1148
    skin_draw_pixbuf (cr, SKIN_MAIN, 0, 0, 0, 0, width, height);
1149
    skin_draw_mainwin_titlebar (cr, is_shaded (), true);
1150
}
1151

    
1152
static void mainwin_create_window ()
1153
{
1154
    bool shaded = aud_get_bool ("skins", "player_shaded");
1155

    
1156
    mainwin = new MainWindow (shaded);
1157

    
1158
#if 0
1159
    GtkWidget * w = mainwin->gtk ();
1160
    drag_dest_set (w);
1161

1162
    g_signal_connect (w, "drag-data-received", (GCallback) mainwin_drag_data_received, nullptr);
1163
    g_signal_connect (w, "window-state-event", (GCallback) state_cb, nullptr);
1164
#endif
1165

    
1166
    hook_associate ("playback begin", (HookFunction) mainwin_playback_begin, nullptr);
1167
    hook_associate ("playback ready", (HookFunction) mainwin_playback_begin, nullptr);
1168
    hook_associate ("playback seek", (HookFunction) mainwin_update_song_info, nullptr);
1169
    hook_associate ("playback stop", (HookFunction) mainwin_playback_stop, nullptr);
1170
    hook_associate ("playback pause", (HookFunction) playback_pause, nullptr);
1171
    hook_associate ("playback unpause", (HookFunction) playback_unpause, nullptr);
1172
    hook_associate ("title change", (HookFunction) title_change, nullptr);
1173
    hook_associate ("info change", (HookFunction) info_change, nullptr);
1174
    hook_associate ("enable record", (HookFunction) record_toggled, nullptr);
1175
    hook_associate ("set repeat", (HookFunction) repeat_toggled, nullptr);
1176
    hook_associate ("set shuffle", (HookFunction) shuffle_toggled, nullptr);
1177
    hook_associate ("set no_playlist_advance", (HookFunction) no_advance_toggled, nullptr);
1178
    hook_associate ("set stop_after_current_song", (HookFunction) stop_after_song_toggled, nullptr);
1179
}
1180

    
1181
void mainwin_unhook ()
1182
{
1183
    seeking = false;
1184
    timer_remove (TimerRate::Hz10, seek_timeout);
1185

    
1186
    status_message_timeout.stop ();
1187
    mainwin_volume_release_timeout.stop ();
1188

    
1189
    hook_dissociate ("playback begin", (HookFunction) mainwin_playback_begin);
1190
    hook_dissociate ("playback ready", (HookFunction) mainwin_playback_begin);
1191
    hook_dissociate ("playback seek", (HookFunction) mainwin_update_song_info);
1192
    hook_dissociate ("playback stop", (HookFunction) mainwin_playback_stop);
1193
    hook_dissociate ("playback pause", (HookFunction) playback_pause);
1194
    hook_dissociate ("playback unpause", (HookFunction) playback_unpause);
1195
    hook_dissociate ("title change", (HookFunction) title_change);
1196
    hook_dissociate ("info change", (HookFunction) info_change);
1197
    hook_dissociate ("enable record", (HookFunction) record_toggled);
1198
    hook_dissociate ("set repeat", (HookFunction) repeat_toggled);
1199
    hook_dissociate ("set shuffle", (HookFunction) shuffle_toggled);
1200
    hook_dissociate ("set no_playlist_advance", (HookFunction) no_advance_toggled);
1201
    hook_dissociate ("set stop_after_current_song", (HookFunction) stop_after_song_toggled);
1202

    
1203
    start_stop_visual (true);
1204

    
1205
    locked_textbox = nullptr;
1206
    locked_old_text = String ();
1207
}
1208

    
1209
void mainwin_create ()
1210
{
1211
    mainwin_create_window ();
1212
    mainwin_create_widgets ();
1213
    mainwin_set_song_title (nullptr);
1214
}
1215

    
1216
static void mainwin_update_volume ()
1217
{
1218
    int volume = aud_drct_get_volume_main ();
1219
    int balance = aud_drct_get_volume_balance ();
1220

    
1221
    mainwin_set_volume_slider (volume);
1222
    mainwin_set_balance_slider (balance);
1223
    equalizerwin_set_volume_slider (volume);
1224
    equalizerwin_set_balance_slider (balance);
1225
}
1226

    
1227
static void mainwin_update_time_display (int time, int length)
1228
{
1229
    StringBuf scratch = format_time (time, length);
1230

    
1231
    mainwin_minus_num->set (scratch[0]);
1232
    mainwin_10min_num->set (scratch[1]);
1233
    mainwin_min_num->set (scratch[2]);
1234
    mainwin_10sec_num->set (scratch[4]);
1235
    mainwin_sec_num->set (scratch[5]);
1236

    
1237
    if (! mainwin_sposition->get_pressed ())
1238
    {
1239
        mainwin_stime_min->set_text (scratch);
1240
        mainwin_stime_sec->set_text (scratch + 4);
1241
    }
1242

    
1243
    playlistwin_set_time (scratch, scratch + 4);
1244
}
1245

    
1246
static void mainwin_update_time_slider (int time, int length)
1247
{
1248
    mainwin_position->setVisible (length > 0);
1249
    mainwin_sposition->setVisible (length > 0);
1250

    
1251
    if (length > 0 && ! seeking)
1252
    {
1253
        if (time < length)
1254
        {
1255
            mainwin_position->set_pos (time * (int64_t) 219 / length);
1256
            mainwin_sposition->set_pos (1 + time * (int64_t) 12 / length);
1257
        }
1258
        else
1259
        {
1260
            mainwin_position->set_pos (219);
1261
            mainwin_sposition->set_pos (13);
1262
        }
1263

    
1264
        mainwin_spos_set_knob ();
1265
    }
1266
}
1267

    
1268
void mainwin_update_song_info ()
1269
{
1270
    mainwin_update_volume ();
1271

    
1272
    if (! aud_drct_get_playing ())
1273
        return;
1274

    
1275
    int time = 0, length = 0;
1276
    if (aud_drct_get_ready ())
1277
    {
1278
        time = aud_drct_get_time ();
1279
        length = aud_drct_get_length ();
1280
    }
1281

    
1282
    mainwin_update_time_display (time, length);
1283
    mainwin_update_time_slider (time, length);
1284
}