From 58604406f839d70cd821e466c9592dbe5c96d4e5 Mon Sep 17 00:00:00 2001
From: 23rd <23rd@vivaldi.net>
Date: Mon, 29 Apr 2019 16:41:51 +0300
Subject: [PATCH] Added initial implementation touchbar.

---
 .../media/player/media_player_widget.cpp      |   3 +
 .../platform/linux/specific_linux.cpp         |   4 +
 .../platform/mac/main_window_mac.mm           |  18 ++
 .../platform/mac/specific_mac_p.mm            |  19 +-
 Telegram/SourceFiles/platform/mac/touchbar.h  |  37 +++
 Telegram/SourceFiles/platform/mac/touchbar.mm | 275 ++++++++++++++++++
 .../SourceFiles/platform/platform_specific.h  |   7 +
 .../SourceFiles/platform/win/specific_win.cpp |   4 +
 Telegram/gyp/telegram_sources.txt             |   2 +
 9 files changed, 362 insertions(+), 7 deletions(-)
 create mode 100644 Telegram/SourceFiles/platform/mac/touchbar.h
 create mode 100644 Telegram/SourceFiles/platform/mac/touchbar.mm

diff --git a/Telegram/SourceFiles/media/player/media_player_widget.cpp b/Telegram/SourceFiles/media/player/media_player_widget.cpp
index 8ad4c1fd1..a9cb65403 100644
--- a/Telegram/SourceFiles/media/player/media_player_widget.cpp
+++ b/Telegram/SourceFiles/media/player/media_player_widget.cpp
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 */
 #include "media/player/media_player_widget.h"
 
+#include "platform/platform_specific.h"
 #include "data/data_document.h"
 #include "data/data_session.h"
 #include "ui/widgets/labels.h"
@@ -166,6 +167,7 @@ Widget::Widget(QWidget *parent) : RpWidget(parent)
 	});
 	setType(AudioMsgId::Type::Song);
 	_playPause->finishTransform();
+	Platform::SetTouchBar(Platform::TouchBarType::AudioPlayer);
 }
 
 void Widget::updateVolumeToggleIcon() {
@@ -190,6 +192,7 @@ void Widget::setCloseCallback(Fn<void()> callback) {
 }
 
 void Widget::stopAndClose() {
+	Platform::SetTouchBar(Platform::TouchBarType::None);
 	_voiceIsActive = false;
 	if (_type == AudioMsgId::Type::Voice) {
 		const auto songData = instance()->current(AudioMsgId::Type::Song);
diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp
index 31f32cc66..ccfafddcc 100644
--- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp
+++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp
@@ -406,6 +406,10 @@ void RequestPermission(PermissionType type, Fn<void(PermissionStatus)> resultCal
 void OpenSystemSettingsForPermission(PermissionType type) {
 }
 
+void SetTouchBar(TouchBarType type) {
+	// TouchBar is Mac only feature.
+}
+
 bool OpenSystemSettings(SystemSettingsType type) {
 	if (type == SystemSettingsType::Audio) {
 		auto options = std::vector<QString>();
diff --git a/Telegram/SourceFiles/platform/mac/main_window_mac.mm b/Telegram/SourceFiles/platform/mac/main_window_mac.mm
index 47a5f1d29..3c4d13786 100644
--- a/Telegram/SourceFiles/platform/mac/main_window_mac.mm
+++ b/Telegram/SourceFiles/platform/mac/main_window_mac.mm
@@ -30,6 +30,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include <IOKit/hidsystem/ev_keymap.h>
 #include <SPMediaKeyTap.h>
 
+#include "media/player/media_player_instance.h"
+#include "media/audio/media_audio.h"
+#include "platform/mac/touchbar.h"
+
 @interface MainWindowObserver : NSObject {
 }
 
@@ -107,6 +111,8 @@ public:
 	void willExitFullScreen();
 
 	bool clipboardHasText();
+    
+    TouchBar *_touchBar;
 
 	~Private();
 
@@ -183,6 +189,9 @@ MainWindow::Private::Private(MainWindow *window)
 , _observer([[MainWindowObserver alloc] init:this]) {
 	_generalPasteboard = [NSPasteboard generalPasteboard];
 
+	_touchBar = [[TouchBar alloc] init];
+	[_touchBar setTouchBarType:Platform::TouchBarType::AudioPlayer];
+
 	@autoreleasepool {
 
 	[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:_observer selector:@selector(activeSpaceDidChange:) name:NSWorkspaceActiveSpaceDidChangeNotification object:nil];
@@ -208,6 +217,10 @@ void MainWindow::Private::setWindowBadge(const QString &str) {
 
 void MainWindow::Private::setWindowTitle(const QString &str) {
 	_public->setWindowTitle(str);
+    if ([[NSApplication sharedApplication] respondsToSelector:@selector(isAutomaticCustomizeTouchBarMenuItemEnabled)]) {
+        [NSApplication sharedApplication].automaticCustomizeTouchBarMenuItemEnabled = YES;
+    }
+	[NSApplication sharedApplication].mainWindow.touchBar = [_touchBar makeTouchBar];
 	updateNativeTitle();
 }
 
@@ -388,6 +401,11 @@ MainWindow::MainWindow()
 			_private->updateNativeTitle();
 		}
 	});
+    
+    subscribe(Media::Player::instance()->updatedNotifier(),
+      [=](const Media::Player::TrackState &state) {
+          [_private->_touchBar handlePropertyChange:state];
+    });
 }
 
 void MainWindow::closeWithoutDestroy() {
diff --git a/Telegram/SourceFiles/platform/mac/specific_mac_p.mm b/Telegram/SourceFiles/platform/mac/specific_mac_p.mm
index aa9897723..75f5805ea 100644
--- a/Telegram/SourceFiles/platform/mac/specific_mac_p.mm
+++ b/Telegram/SourceFiles/platform/mac/specific_mac_p.mm
@@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "media/audio/media_audio.h"
 #include "media/player/media_player_instance.h"
 #include "platform/mac/mac_utilities.h"
+#include "platform/mac/touchbar.h"
 #include "lang/lang_keys.h"
 #include "base/timer.h"
 #include "styles/style_window.h"
@@ -214,14 +215,18 @@ bool IsApplicationActive() {
 }
 
 void SetApplicationIcon(const QIcon &icon) {
-    NSImage *image = nil;
-    if (!icon.isNull()) {
-        auto pixmap = icon.pixmap(1024, 1024);
+	NSImage *image = nil;
+	if (!icon.isNull()) {
+		auto pixmap = icon.pixmap(1024, 1024);
 		pixmap.setDevicePixelRatio(cRetinaFactor());
-        image = static_cast<NSImage*>(qt_mac_create_nsimage(pixmap));
-    }
-    [[NSApplication sharedApplication] setApplicationIconImage:image];
-    [image release];
+		image = static_cast<NSImage*>(qt_mac_create_nsimage(pixmap));
+	}
+	[[NSApplication sharedApplication] setApplicationIconImage:image];
+	[image release];
+}
+
+void SetTouchBar(TouchBarType type) {
+	
 }
 
 void InitOnTopPanel(QWidget *panel) {
diff --git a/Telegram/SourceFiles/platform/mac/touchbar.h b/Telegram/SourceFiles/platform/mac/touchbar.h
new file mode 100644
index 000000000..db683566e
--- /dev/null
+++ b/Telegram/SourceFiles/platform/mac/touchbar.h
@@ -0,0 +1,37 @@
+/*
+ This file is part of Telegram Desktop,
+ the official desktop application for the Telegram messaging service.
+ 
+ For license and copyright information please follow this link:
+ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
+ */
+
+#include "platform/platform_specific.h"
+#include "media/audio/media_audio.h"
+#include "media/player/media_player_instance.h"
+#import <Cocoa/Cocoa.h>
+
+static NSString * _Nullable BASE_ID = @"telegram.touchbar";
+static NSTouchBarCustomizationIdentifier _Nullable customID = @"telegram.touchbar";
+static NSTouchBarItemIdentifier _Nullable seekBar = [NSString stringWithFormat:@"%@.seekbar", BASE_ID];
+static NSTouchBarItemIdentifier _Nullable play = [NSString stringWithFormat:@"%@.play", BASE_ID];
+static NSTouchBarItemIdentifier _Nullable nextItem = [NSString stringWithFormat:@"%@.nextItem", BASE_ID];
+static NSTouchBarItemIdentifier _Nullable previousItem = [NSString stringWithFormat:@"%@.previousItem", BASE_ID];
+static NSTouchBarItemIdentifier _Nullable nextChapter = [NSString stringWithFormat:@"%@.nextChapter", BASE_ID];
+static NSTouchBarItemIdentifier _Nullable previousChapter = [NSString stringWithFormat:@"%@.previousChapter", BASE_ID];
+static NSTouchBarItemIdentifier _Nullable cycleAudio = [NSString stringWithFormat:@"%@.cycleAudio", BASE_ID];
+static NSTouchBarItemIdentifier _Nullable cycleSubtitle = [NSString stringWithFormat:@"%@.cycleSubtitle", BASE_ID];
+static NSTouchBarItemIdentifier _Nullable currentPosition = [NSString stringWithFormat:@"%@.currentPosition", BASE_ID];
+static NSTouchBarItemIdentifier _Nullable timeLeft = [NSString stringWithFormat:@"%@.timeLeft", BASE_ID];
+
+@interface TouchBar : NSTouchBar
+@property Platform::TouchBarType touchBarType;
+
+@property(retain) NSDictionary * _Nullable touchbarItems;
+@property(nonatomic, assign) double duration;
+@property(nonatomic, assign) double position;
+
+- (nullable NSTouchBar *) makeTouchBar;
+- (void)handlePropertyChange:(Media::Player::TrackState)property;
+
+@end
diff --git a/Telegram/SourceFiles/platform/mac/touchbar.mm b/Telegram/SourceFiles/platform/mac/touchbar.mm
new file mode 100644
index 000000000..ca13b493a
--- /dev/null
+++ b/Telegram/SourceFiles/platform/mac/touchbar.mm
@@ -0,0 +1,275 @@
+/*
+ This file is part of Telegram Desktop,
+ the official desktop application for the Telegram messaging service.
+ 
+ For license and copyright information please follow this link:
+ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
+ */
+
+#import "touchbar.h"
+#import <QuartzCore/QuartzCore.h>
+
+#include "mainwindow.h"
+#include "mainwidget.h"
+#include "core/sandbox.h"
+#include "core/application.h"
+#include "core/crash_reports.h"
+#include "storage/localstorage.h"
+#include "media/audio/media_audio.h"
+#include "media/player/media_player_instance.h"
+#include "media/view/media_view_playback_progress.h"
+#include "media/audio/media_audio.h"
+#include "platform/mac/mac_utilities.h"
+#include "platform/platform_specific.h"
+#include "lang/lang_keys.h"
+#include "base/timer.h"
+#include "styles/style_window.h"
+
+namespace {
+constexpr auto kPlayPause = 0x000;
+constexpr auto kPlaylistPrevious = 0x001;
+constexpr auto kPlaylistNext = 0x002;
+constexpr auto kSavedMessages = 0x002;
+    
+constexpr auto kMs = 1000;
+    
+constexpr auto kSongType = AudioMsgId::Type::Song;
+}
+
+@interface TouchBar()<NSTouchBarDelegate>
+@end
+
+@implementation TouchBar
+
+- (instancetype)init {
+    self = [super init];
+    if (self) {
+        self.touchBarType = Platform::TouchBarType::None;
+
+        self.touchbarItems = @{
+            seekBar: [NSMutableDictionary dictionaryWithDictionary:@{
+                @"type": @"slider",
+                @"name": @"Seek Bar",
+                @"cmd":  [NSNumber numberWithInt:kPlayPause]
+            }],
+            play: [NSMutableDictionary dictionaryWithDictionary:@{
+                @"type":     @"button",
+                @"name":     @"Play Button",
+                @"cmd":      [NSNumber numberWithInt:kPlayPause],
+                @"image":    [NSImage imageNamed:NSImageNameTouchBarPauseTemplate],
+                @"imageAlt": [NSImage imageNamed:NSImageNameTouchBarPlayTemplate]
+            }],
+            previousItem: [NSMutableDictionary dictionaryWithDictionary:@{
+                @"type":  @"button",
+                @"name":  @"Previous Playlist Item",
+                @"cmd":   [NSNumber numberWithInt:kPlaylistPrevious],
+                @"image": [NSImage imageNamed:NSImageNameTouchBarGoBackTemplate]
+            }],
+            nextItem: [NSMutableDictionary dictionaryWithDictionary:@{
+                @"type":  @"button",
+                @"name":  @"Next Playlist Item",
+                @"cmd":   [NSNumber numberWithInt:kPlaylistNext],
+                @"image": [NSImage imageNamed:NSImageNameTouchBarGoForwardTemplate]
+            }],
+            previousChapter: [NSMutableDictionary dictionaryWithDictionary:@{
+                @"type":  @"button",
+                @"name":  @"Previous Chapter",
+                @"cmd":   [NSNumber numberWithInt:kPlayPause],
+                @"image": [NSImage imageNamed:NSImageNameTouchBarSkipBackTemplate]
+            }],
+            nextChapter: [NSMutableDictionary dictionaryWithDictionary:@{
+                @"type":  @"button",
+                @"name":  @"Next Chapter",
+                @"cmd":   [NSNumber numberWithInt:kPlayPause],
+                @"image": [NSImage imageNamed:NSImageNameTouchBarSkipAheadTemplate]
+            }],
+            cycleAudio: [NSMutableDictionary dictionaryWithDictionary:@{
+                @"type":  @"button",
+                @"name":  @"Cycle Audio",
+                @"cmd":   [NSNumber numberWithInt:kPlayPause],
+                @"image": [NSImage imageNamed:NSImageNameTouchBarAudioInputTemplate]
+            }],
+            cycleSubtitle: [NSMutableDictionary dictionaryWithDictionary:@{
+                @"type":  @"button",
+                @"name":  @"Cycle Subtitle",
+                @"cmd":   [NSNumber numberWithInt:kPlayPause],
+                @"image": [NSImage imageNamed:NSImageNameTouchBarComposeTemplate]
+            }],
+            currentPosition: [NSMutableDictionary dictionaryWithDictionary:@{
+                @"type": @"text",
+                @"name": @"Current Position"
+            }]
+        };
+    }
+    return self;
+}
+
+- (nullable NSTouchBar *) makeTouchBar{
+    NSTouchBar *touchBar = [[NSTouchBar alloc] init];
+    touchBar.delegate = self;
+    touchBar.customizationIdentifier = @"TOUCH_BAR";
+
+    touchBar.customizationIdentifier = customID;
+    touchBar.defaultItemIdentifiers = @[play, previousItem, nextItem, seekBar];
+    touchBar.customizationAllowedItemIdentifiers = @[play, seekBar, previousItem,
+        nextItem, previousChapter, nextChapter, cycleAudio, cycleSubtitle,
+        currentPosition];
+    
+    return touchBar;
+}
+
+- (nullable NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar
+                makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
+    if ([self.touchbarItems[identifier][@"type"] isEqualToString:@"slider"]) {
+        NSSliderTouchBarItem *item = [[NSSliderTouchBarItem alloc] initWithIdentifier:identifier];
+        item.slider.minValue = 0.0f;
+        item.slider.maxValue = 1.0f;
+        item.target = self;
+        item.action = @selector(seekbarChanged:);
+        item.customizationLabel = self.touchbarItems[identifier][@"name"];
+        [self.touchbarItems[identifier] setObject:item.slider forKey:@"view"];
+        return item;
+    } else if ([self.touchbarItems[identifier][@"type"] isEqualToString:@"button"]) {
+        NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
+        NSImage *image = self.touchbarItems[identifier][@"image"];
+        NSButton *button = [NSButton buttonWithImage:image target:self action:@selector(buttonAction:)];
+        item.view = button;
+        item.customizationLabel = self.touchbarItems[identifier][@"name"];
+        [self.touchbarItems[identifier] setObject:button forKey:@"view"];
+        return item;
+    } else if ([self.touchbarItems[identifier][@"type"] isEqualToString:@"text"]) {
+        NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
+        NSTextField *text = [NSTextField labelWithString:@"0:00"];
+        text.alignment = NSTextAlignmentCenter;
+        item.view = text;
+        item.customizationLabel = self.touchbarItems[identifier][@"name"];
+        [self.touchbarItems[identifier] setObject:text forKey:@"view"];
+        return item;
+    }
+
+    return nil;
+}
+
+- (void)handlePropertyChange:(Media::Player::TrackState)property {
+    self.position = property.position < 0 ? 0 : property.position;
+    self.duration = property.length;
+    [self updateTouchBarTimeItems];
+    NSButton *playButton = self.touchbarItems[play][@"view"];
+    if (property.state == Media::Player::State::Playing) {
+        playButton.image = self.touchbarItems[play][@"image"];
+    } else {
+        playButton.image = self.touchbarItems[play][@"imageAlt"];
+    }
+    
+    [self.touchbarItems[nextItem][@"view"]
+     setEnabled:Media::Player::instance()->nextAvailable(kSongType)];
+    [self.touchbarItems[previousItem][@"view"]
+     setEnabled:Media::Player::instance()->previousAvailable(kSongType)];
+}
+
+- (NSString *)formatTime:(int)time {
+    const int seconds = time % 60;
+    const int minutes = (time / 60) % 60;
+    const int hours = time / (60 * 60);
+
+    NSString *stime = hours > 0 ? [NSString stringWithFormat:@"%d:", hours] : @"";
+    stime = (stime.length > 0 || minutes > 9) ?
+        [NSString stringWithFormat:@"%@%02d:", stime, minutes] :
+        [NSString stringWithFormat:@"%d:", minutes];
+    stime = [NSString stringWithFormat:@"%@%02d", stime, seconds];
+
+    return stime;
+}
+
+- (void)removeConstraintForIdentifier:(NSTouchBarItemIdentifier)identifier {
+    NSTextField *field = self.touchbarItems[identifier][@"view"];
+    [field removeConstraint:self.touchbarItems[identifier][@"constrain"]];
+}
+
+- (void)applyConstraintFromString:(NSString *)string
+                    forIdentifier:(NSTouchBarItemIdentifier)identifier {
+    NSTextField *field = self.touchbarItems[identifier][@"view"];
+    if (field) {
+        NSString *fString = [[string componentsSeparatedByCharactersInSet:
+            [NSCharacterSet decimalDigitCharacterSet]] componentsJoinedByString:@"0"];
+        NSTextField *textField = [NSTextField labelWithString:fString];
+        NSSize size = [textField frame].size;
+
+        NSLayoutConstraint *con =
+            [NSLayoutConstraint constraintWithItem:field
+                                         attribute:NSLayoutAttributeWidth
+                                         relatedBy:NSLayoutRelationEqual
+                                            toItem:nil
+                                         attribute:NSLayoutAttributeNotAnAttribute
+                                        multiplier:1.0
+                                          constant:(int)ceil(size.width * 1.5)];
+        [field addConstraint:con];
+        [self.touchbarItems[identifier] setObject:con forKey:@"constrain"];
+    }
+}
+
+- (void)updateTouchBarTimeItemConstrains {
+    [self removeConstraintForIdentifier:currentPosition];
+
+    if (self.duration <= 0) {
+        [self applyConstraintFromString:[self formatTime:self.position]
+                          forIdentifier:currentPosition];
+    } else {
+        NSString *durFormat = [self formatTime:self.duration];
+        [self applyConstraintFromString:durFormat forIdentifier:currentPosition];
+    }
+}
+
+- (void)updateTouchBarTimeItems {
+    NSSlider *seekSlider = self.touchbarItems[seekBar][@"view"];
+    NSTextField *curPosItem = self.touchbarItems[currentPosition][@"view"];
+
+    if (self.duration <= 0) {
+        seekSlider.enabled = NO;
+        seekSlider.doubleValue = 0;
+    } else {
+        seekSlider.enabled = YES;
+        if (!seekSlider.highlighted) {
+            seekSlider.doubleValue = (self.position / self.duration) * seekSlider.maxValue;
+        }
+    }
+    const auto timeToString = [&](int t) {
+        return [self formatTime:(int)floor(t / kMs)];
+    };
+    curPosItem.stringValue = [NSString stringWithFormat:@"%@ / %@",
+                              timeToString(self.position),
+                              timeToString(self.duration)];
+
+    [self updateTouchBarTimeItemConstrains];
+}
+
+- (NSString *)getIdentifierFromView:(id)view {
+    NSString *identifier;
+    for (identifier in self.touchbarItems)
+        if([self.touchbarItems[identifier][@"view"] isEqual:view])
+            break;
+    return identifier;
+}
+
+- (void)buttonAction:(NSButton *)sender {
+    NSString *identifier = [self getIdentifierFromView:sender];
+    const auto command = [self.touchbarItems[identifier][@"cmd"] intValue];
+    LOG(("BUTTON %1").arg(command));
+    Core::Sandbox::Instance().customEnterFromEventLoop([=] {
+        if (command == kPlayPause) {
+            Media::Player::instance()->playPause();
+        } else if (command == kPlaylistPrevious) {
+            Media::Player::instance()->previous();
+        } else if (command == kPlaylistNext) {
+            Media::Player::instance()->next();
+        }
+    });
+}
+
+- (void)seekbarChanged:(NSSliderTouchBarItem *)sender {
+    Core::Sandbox::Instance().customEnterFromEventLoop([&] {
+        Media::Player::instance()->finishSeeking(kSongType, sender.slider.doubleValue);
+    });
+}
+
+@end
diff --git a/Telegram/SourceFiles/platform/platform_specific.h b/Telegram/SourceFiles/platform/platform_specific.h
index 919065a02..3c8a782db 100644
--- a/Telegram/SourceFiles/platform/platform_specific.h
+++ b/Telegram/SourceFiles/platform/platform_specific.h
@@ -26,6 +26,11 @@ enum class SystemSettingsType {
 	Audio,
 };
 
+enum class TouchBarType {
+	AudioPlayer,
+	None,
+};
+
 void SetWatchingMediaKeys(bool watching);
 bool IsApplicationActive();
 void SetApplicationIcon(const QIcon &icon);
@@ -40,6 +45,8 @@ void RequestPermission(PermissionType type, Fn<void(PermissionStatus)> resultCal
 void OpenSystemSettingsForPermission(PermissionType type);
 bool OpenSystemSettings(SystemSettingsType type);
 
+void SetTouchBar(TouchBarType type);
+
 [[nodiscard]] QString SystemLanguage();
 [[nodiscard]] QString SystemCountry();
 
diff --git a/Telegram/SourceFiles/platform/win/specific_win.cpp b/Telegram/SourceFiles/platform/win/specific_win.cpp
index ea8071405..ff1045e58 100644
--- a/Telegram/SourceFiles/platform/win/specific_win.cpp
+++ b/Telegram/SourceFiles/platform/win/specific_win.cpp
@@ -646,6 +646,10 @@ void OpenSystemSettingsForPermission(PermissionType type) {
 	}
 }
 
+void SetTouchBar(TouchBarType type) {
+	// TouchBar is Mac only feature.
+}
+
 bool OpenSystemSettings(SystemSettingsType type) {
 	if (type == SystemSettingsType::Audio) {
 		crl::on_main([] {
diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt
index df4d7e910..43e043a55 100644
--- a/Telegram/gyp/telegram_sources.txt
+++ b/Telegram/gyp/telegram_sources.txt
@@ -589,6 +589,8 @@
 <(src_loc)/platform/mac/specific_mac_p.h
 <(src_loc)/platform/mac/window_title_mac.mm
 <(src_loc)/platform/mac/window_title_mac.h
+<(src_loc)/platform/mac/touchbar.h
+<(src_loc)/platform/mac/touchbar.mm
 <(src_loc)/platform/win/audio_win.cpp
 <(src_loc)/platform/win/audio_win.h
 <(src_loc)/platform/win/file_utilities_win.cpp