diff --git a/CMakeLists.txt b/CMakeLists.txt index f2207e04a..62d92b023 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,6 +176,7 @@ file(GLOB plugdata_resources ${CMAKE_CURRENT_SOURCE_DIR}/Resources/Fonts/InterVariable.ttf ${CMAKE_CURRENT_SOURCE_DIR}/Resources/Fonts/InterRegular.ttf ${CMAKE_CURRENT_SOURCE_DIR}/Resources/Fonts/RobotoMono-Regular.ttf + ${CMAKE_CURRENT_SOURCE_DIR}/Resources/Fonts/RobotoMono-Bold.ttf ${CMAKE_CURRENT_SOURCE_DIR}/Resources/Icons/plugdata_large_logo.png ${CMAKE_CURRENT_SOURCE_DIR}/Resources/Icons/plugdata_logo.png # Generated resources diff --git a/Libraries/JUCE b/Libraries/JUCE index 77ba47921..39cec94a9 160000 --- a/Libraries/JUCE +++ b/Libraries/JUCE @@ -1 +1 @@ -Subproject commit 77ba479218a73d826a970f4b704571398e29ed41 +Subproject commit 39cec94a9ac14ad07db6a89a7cd143208195fba5 diff --git a/Resources/Fonts/RobotoMono-Bold.ttf b/Resources/Fonts/RobotoMono-Bold.ttf new file mode 100644 index 000000000..bef439f3b Binary files /dev/null and b/Resources/Fonts/RobotoMono-Bold.ttf differ diff --git a/Resources/Scripts/package_resources.py b/Resources/Scripts/package_resources.py index 187ee5fa0..369556dbe 100644 --- a/Resources/Scripts/package_resources.py +++ b/Resources/Scripts/package_resources.py @@ -342,6 +342,7 @@ def generate_binary_data(output_dir, file_list): project_root + "/Resources/Fonts/InterVariable.ttf", project_root + "/Resources/Fonts/InterRegular.ttf", project_root + "/Resources/Fonts/RobotoMono-Regular.ttf", + project_root + "/Resources/Fonts/RobotoMono-Bold.ttf", project_root + "/Resources/Icons/plugdata_large_logo.png", project_root + "/Resources/Icons/plugdata_logo.png", "Documentation.bin", diff --git a/Source/Constants.h b/Source/Constants.h index 5d056b13c..b83a873b6 100644 --- a/Source/Constants.h +++ b/Source/Constants.h @@ -10,272 +10,272 @@ #include struct Icons { - inline static String const Open = "b"; - inline static String const Save = "c"; - inline static String const SaveAs = "d"; - inline static String const Undo = "e"; - inline static String const Redo = "f"; - inline static String const Add = "g"; - inline static String const AddObject = ";"; - inline static String const Settings = "h"; - inline static String const Sparkle = "i"; - inline static String const CPU = "j"; - inline static String const Clear = "k"; - inline static String const ClearText = "l"; - inline static String const Lock = "m"; - inline static String const Unlock = "n"; - inline static String const ConnectionStyle = "o"; - inline static String const Power = "p"; - inline static String const Audio = "q"; - inline static String const Search = "r"; - inline static String const Wand = "s"; - inline static String const Pencil = "t"; - inline static String const Grid = "u"; - inline static String const Pin = "v"; - inline static String const Keyboard = "w"; - inline static String const Folder = "x"; - inline static String const OpenedFolder = "y"; - inline static String const File = "z"; - inline static String const New = "z"; - inline static String const AutoScroll = "A"; - inline static String const Restore = "B"; - inline static String const Error = "C"; - inline static String const Message = "D"; - inline static String const Parameters = "E"; - inline static String const Presentation = "F"; - inline static String const Externals = "G"; - inline static String const Refresh = "H"; - inline static String const Up = "I"; - inline static String const Down = "J"; - inline static String const Edit = "K"; - inline static String const ThinDown = "L"; - inline static String const Sine = "M"; - inline static String const Documentation = "N"; - inline static String const AddCircled = "O"; - inline static String const Console = "P"; - inline static String const OpenLink = "Q"; - inline static String const Wrench = "R"; - inline static String const Back = "S"; - inline static String const Forward = "T"; - inline static String const Library = "U"; - inline static String const Menu = "V"; - inline static String const Info = "W"; - inline static String const Warning = "\""; - inline static String const History = "X"; - inline static String const Protection = "Y"; - inline static String const DevTools = "{"; - inline static String const Help = "\\"; - inline static String const Checkmark = "_"; - - inline static String const SavePatch = "Z"; - inline static String const ClosePatch = "["; - inline static String const CloseAllPatches = "]"; - inline static String const Centre = "}"; - inline static String const FitAll = ">"; - inline static String const Eye = "|"; - inline static String const Magnet = "%"; - inline static String const SnapEdges = "#"; - inline static String const SnapCenters = "$"; - inline static String const ExportState = "^"; - inline static String const Trash = "~"; - inline static String const CanvasSettings = "&"; - inline static String const Eyedropper = "@"; - inline static String const HeartFilled = "?"; - inline static String const HeartStroked = ">"; - - inline static String const Reset = "'"; - inline static String const More = "."; - inline static String const MIDI = "`"; - inline static String const PluginMode = "="; - inline static String const CommandInput = "+"; - - inline static String const Reorder = "("; - inline static String const Object = ":"; - inline static String const ObjectMulti = CharPointer_UTF8("\xc2\xb9"); - - inline static String const List = "!"; - inline static String const Graph = "<"; - - inline static String const Heart = ","; - inline static String const Download = "-"; - - inline static String const Copy = "0"; - inline static String const Paste = "1"; - inline static String const Duplicate = "2"; - inline static String const Cut = "3"; - - inline static String const Storage = CharPointer_UTF8("\xc3\x90"); - inline static String const Money = CharPointer_UTF8("\xc3\x91"); - inline static String const Time = CharPointer_UTF8("\xc3\x92"); - inline static String const Store = CharPointer_UTF8("\xc3\x8f"); - inline static String const PanelExpand = CharPointer_UTF8("\xc3\x8d"); - inline static String const PanelContract = CharPointer_UTF8("\xc3\x8c"); - inline static String const ItemGrid = " "; - - inline static String const AlignLeft = "4"; - inline static String const AlignRight = "5"; - inline static String const AlignHCentre = "6"; - inline static String const AlignHDistribute = "/"; - inline static String const AlignTop = "7"; - inline static String const AlignBottom = "8"; - inline static String const AlignVCentre = "9"; - inline static String const AlignVDistribute = "*"; - - inline static String const Home = CharPointer_UTF8("\xc3\x8e"); - - inline static String const ShowIndex = CharPointer_UTF8("\xc2\xbA"); - inline static String const ShowXY = CharPointer_UTF8("\xc2\xbb"); + static inline String const Open = "b"; + static inline String const Save = "c"; + static inline String const SaveAs = "d"; + static inline String const Undo = "e"; + static inline String const Redo = "f"; + static inline String const Add = "g"; + static inline String const AddObject = ";"; + static inline String const Settings = "h"; + static inline String const Sparkle = "i"; + static inline String const CPU = "j"; + static inline String const Clear = "k"; + static inline String const ClearText = "l"; + static inline String const Lock = "m"; + static inline String const Unlock = "n"; + static inline String const ConnectionStyle = "o"; + static inline String const Power = "p"; + static inline String const Audio = "q"; + static inline String const Search = "r"; + static inline String const Wand = "s"; + static inline String const Pencil = "t"; + static inline String const Grid = "u"; + static inline String const Pin = "v"; + static inline String const Keyboard = "w"; + static inline String const Folder = "x"; + static inline String const OpenedFolder = "y"; + static inline String const File = "z"; + static inline String const New = "z"; + static inline String const AutoScroll = "A"; + static inline String const Restore = "B"; + static inline String const Error = "C"; + static inline String const Message = "D"; + static inline String const Parameters = "E"; + static inline String const Presentation = "F"; + static inline String const Externals = "G"; + static inline String const Refresh = "H"; + static inline String const Up = "I"; + static inline String const Down = "J"; + static inline String const Edit = "K"; + static inline String const ThinDown = "L"; + static inline String const Sine = "M"; + static inline String const Documentation = "N"; + static inline String const AddCircled = "O"; + static inline String const Console = "P"; + static inline String const OpenLink = "Q"; + static inline String const Wrench = "R"; + static inline String const Back = "S"; + static inline String const Forward = "T"; + static inline String const Library = "U"; + static inline String const Menu = "V"; + static inline String const Info = "W"; + static inline String const Warning = "\""; + static inline String const History = "X"; + static inline String const Protection = "Y"; + static inline String const DevTools = "{"; + static inline String const Help = "\\"; + static inline String const Checkmark = "_"; + + static inline String const SavePatch = "Z"; + static inline String const ClosePatch = "["; + static inline String const CloseAllPatches = "]"; + static inline String const Centre = "}"; + static inline String const FitAll = ">"; + static inline String const Eye = "|"; + static inline String const Magnet = "%"; + static inline String const SnapEdges = "#"; + static inline String const SnapCenters = "$"; + static inline String const ExportState = "^"; + static inline String const Trash = "~"; + static inline String const CanvasSettings = "&"; + static inline String const Eyedropper = "@"; + static inline String const HeartFilled = "?"; + static inline String const HeartStroked = ">"; + + static inline String const Reset = "'"; + static inline String const More = "."; + static inline String const MIDI = "`"; + static inline String const PluginMode = "="; + static inline String const CommandInput = "+"; + + static inline String const Reorder = "("; + static inline String const Object = ":"; + static inline String const ObjectMulti = CharPointer_UTF8("\xc2\xb9"); + + static inline String const List = "!"; + static inline String const Graph = "<"; + + static inline String const Heart = ","; + static inline String const Download = "-"; + + static inline String const Copy = "0"; + static inline String const Paste = "1"; + static inline String const Duplicate = "2"; + static inline String const Cut = "3"; + + static inline String const Storage = CharPointer_UTF8("\xc3\x90"); + static inline String const Money = CharPointer_UTF8("\xc3\x91"); + static inline String const Time = CharPointer_UTF8("\xc3\x92"); + static inline String const Store = CharPointer_UTF8("\xc3\x8f"); + static inline String const PanelExpand = CharPointer_UTF8("\xc3\x8d"); + static inline String const PanelContract = CharPointer_UTF8("\xc3\x8c"); + static inline String const ItemGrid = " "; + + static inline String const AlignLeft = "4"; + static inline String const AlignRight = "5"; + static inline String const AlignHCentre = "6"; + static inline String const AlignHDistribute = "/"; + static inline String const AlignTop = "7"; + static inline String const AlignBottom = "8"; + static inline String const AlignVCentre = "9"; + static inline String const AlignVDistribute = "*"; + + static inline String const Home = CharPointer_UTF8("\xc3\x8e"); + + static inline String const ShowIndex = CharPointer_UTF8("\xc2\xbA"); + static inline String const ShowXY = CharPointer_UTF8("\xc2\xbb"); // ================== OBJECT ICONS ================== // generic - inline static String const GlyphGenericSignal = CharPointer_UTF8("\xc3\x80"); - inline static String const GlyphGeneric = CharPointer_UTF8("\xc3\x81"); + static inline String const GlyphGenericSignal = CharPointer_UTF8("\xc3\x80"); + static inline String const GlyphGeneric = CharPointer_UTF8("\xc3\x81"); // default - inline static String const GlyphEmptyObject = CharPointer_UTF8("\xc3\x82"); - inline static String const GlyphMessage = CharPointer_UTF8("\xc3\x84"); - inline static String const GlyphFloatBox = CharPointer_UTF8("\xc3\x83"); - inline static String const GlyphSymbolBox = CharPointer_UTF8("\xc3\x85"); - inline static String const GlyphListBox = CharPointer_UTF8("\xc3\x86"); - inline static String const GlyphComment = CharPointer_UTF8("\xc3\x87"); + static inline String const GlyphEmptyObject = CharPointer_UTF8("\xc3\x82"); + static inline String const GlyphMessage = CharPointer_UTF8("\xc3\x84"); + static inline String const GlyphFloatBox = CharPointer_UTF8("\xc3\x83"); + static inline String const GlyphSymbolBox = CharPointer_UTF8("\xc3\x85"); + static inline String const GlyphListBox = CharPointer_UTF8("\xc3\x86"); + static inline String const GlyphComment = CharPointer_UTF8("\xc3\x87"); // ui - inline static String const GlyphBang = CharPointer_UTF8("\xc2\xa1"); - inline static String const GlyphToggle = CharPointer_UTF8("\xc2\xa2"); - inline static String const GlyphButton = CharPointer_UTF8("\xc2\xa3"); - inline static String const GlyphKnob = CharPointer_UTF8("\xc2\xa4"); - inline static String const GlyphNumber = CharPointer_UTF8("\xc2\xa5"); - inline static String const GlyphHSlider = CharPointer_UTF8("\xc2\xa8"); - inline static String const GlyphVSlider = CharPointer_UTF8("\xc2\xa9"); - inline static String const GlyphHRadio = CharPointer_UTF8("\xc2\xa6"); - inline static String const GlyphVRadio = CharPointer_UTF8("\xc2\xa7"); - inline static String const GlyphCanvas = CharPointer_UTF8("\xc2\xaa"); - inline static String const GlyphKeyboard = CharPointer_UTF8("\xc2\xab"); - inline static String const GlyphVUMeter = CharPointer_UTF8("\xc2\xac"); - inline static String const GlyphArray = CharPointer_UTF8("\xc2\xae"); - inline static String const GlyphGOP = CharPointer_UTF8("\xc2\xaf"); - inline static String const GlyphOscilloscope = CharPointer_UTF8("\xc2\xb0"); - inline static String const GlyphFunction = CharPointer_UTF8("\xc2\xb1"); - inline static String const GlyphMessbox = CharPointer_UTF8("\xc2\xb5"); - inline static String const GlyphBicoeff = CharPointer_UTF8("\xc2\xb3"); + static inline String const GlyphBang = CharPointer_UTF8("\xc2\xa1"); + static inline String const GlyphToggle = CharPointer_UTF8("\xc2\xa2"); + static inline String const GlyphButton = CharPointer_UTF8("\xc2\xa3"); + static inline String const GlyphKnob = CharPointer_UTF8("\xc2\xa4"); + static inline String const GlyphNumber = CharPointer_UTF8("\xc2\xa5"); + static inline String const GlyphHSlider = CharPointer_UTF8("\xc2\xa8"); + static inline String const GlyphVSlider = CharPointer_UTF8("\xc2\xa9"); + static inline String const GlyphHRadio = CharPointer_UTF8("\xc2\xa6"); + static inline String const GlyphVRadio = CharPointer_UTF8("\xc2\xa7"); + static inline String const GlyphCanvas = CharPointer_UTF8("\xc2\xaa"); + static inline String const GlyphKeyboard = CharPointer_UTF8("\xc2\xab"); + static inline String const GlyphVUMeter = CharPointer_UTF8("\xc2\xac"); + static inline String const GlyphArray = CharPointer_UTF8("\xc2\xae"); + static inline String const GlyphGOP = CharPointer_UTF8("\xc2\xaf"); + static inline String const GlyphOscilloscope = CharPointer_UTF8("\xc2\xb0"); + static inline String const GlyphFunction = CharPointer_UTF8("\xc2\xb1"); + static inline String const GlyphMessbox = CharPointer_UTF8("\xc2\xb5"); + static inline String const GlyphBicoeff = CharPointer_UTF8("\xc2\xb3"); // general - inline static String const GlyphMetro = CharPointer_UTF8("\xc3\xa4"); - inline static String const GlyphCounter = CharPointer_UTF8("\xc3\xa6"); - inline static String const GlyphSelect = CharPointer_UTF8("\xc3\xa7"); - inline static String const GlyphRoute = CharPointer_UTF8("\xc3\xa8"); - inline static String const GlyphExpr = CharPointer_UTF8("\xc3\xb5"); - inline static String const GlyphLoadbang = CharPointer_UTF8("\xc3\xa9"); - inline static String const GlyphPack = CharPointer_UTF8("\xc3\xaa"); - inline static String const GlyphUnpack = CharPointer_UTF8("\xc3\xab"); - inline static String const GlyphPrint = CharPointer_UTF8("\xc3\xac"); - inline static String const GlyphNetsend = CharPointer_UTF8("\xc3\xae"); - inline static String const GlyphNetreceive = CharPointer_UTF8("\xc3\xad"); - inline static String const GlyphOSCsend = CharPointer_UTF8("\xc4\xb5"); - inline static String const GlyphOSCreceive = CharPointer_UTF8("\xc4\xb4"); - inline static String const GlyphTimer = CharPointer_UTF8("\xc3\xb6"); - inline static String const GlyphDelay = CharPointer_UTF8("\xc3\xb7"); - inline static String const GlyphTrigger = CharPointer_UTF8("\xc3\xb1"); - inline static String const GlyphMoses = CharPointer_UTF8("\xc3\xb2"); - inline static String const GlyphSpigot = CharPointer_UTF8("\xc3\xb3"); - inline static String const GlyphBondo = CharPointer_UTF8("\xc3\xb4"); - inline static String const GlyphSfz = CharPointer_UTF8("\xc3\xb8"); + static inline String const GlyphMetro = CharPointer_UTF8("\xc3\xa4"); + static inline String const GlyphCounter = CharPointer_UTF8("\xc3\xa6"); + static inline String const GlyphSelect = CharPointer_UTF8("\xc3\xa7"); + static inline String const GlyphRoute = CharPointer_UTF8("\xc3\xa8"); + static inline String const GlyphExpr = CharPointer_UTF8("\xc3\xb5"); + static inline String const GlyphLoadbang = CharPointer_UTF8("\xc3\xa9"); + static inline String const GlyphPack = CharPointer_UTF8("\xc3\xaa"); + static inline String const GlyphUnpack = CharPointer_UTF8("\xc3\xab"); + static inline String const GlyphPrint = CharPointer_UTF8("\xc3\xac"); + static inline String const GlyphNetsend = CharPointer_UTF8("\xc3\xae"); + static inline String const GlyphNetreceive = CharPointer_UTF8("\xc3\xad"); + static inline String const GlyphOSCsend = CharPointer_UTF8("\xc4\xb5"); + static inline String const GlyphOSCreceive = CharPointer_UTF8("\xc4\xb4"); + static inline String const GlyphTimer = CharPointer_UTF8("\xc3\xb6"); + static inline String const GlyphDelay = CharPointer_UTF8("\xc3\xb7"); + static inline String const GlyphTrigger = CharPointer_UTF8("\xc3\xb1"); + static inline String const GlyphMoses = CharPointer_UTF8("\xc3\xb2"); + static inline String const GlyphSpigot = CharPointer_UTF8("\xc3\xb3"); + static inline String const GlyphBondo = CharPointer_UTF8("\xc3\xb4"); + static inline String const GlyphSfz = CharPointer_UTF8("\xc3\xb8"); // MIDI - inline static String const GlyphMidiIn = CharPointer_UTF8("\xc4\x87"); - inline static String const GlyphMidiOut = CharPointer_UTF8("\xc4\x88"); - inline static String const GlyphNoteIn = CharPointer_UTF8("\xc4\x89"); - inline static String const GlyphNoteOut = CharPointer_UTF8("\xc4\x8a"); - inline static String const GlyphCtlIn = CharPointer_UTF8("\xc4\x8b"); - inline static String const GlyphCtlOut = CharPointer_UTF8("\xc4\x8c"); - inline static String const GlyphPgmIn = CharPointer_UTF8("\xc4\x8d"); - inline static String const GlyphPgmOut = CharPointer_UTF8("\xc4\x8e"); - inline static String const GlyphSysexIn = CharPointer_UTF8("\xc4\x8f"); - inline static String const GlyphSysexOut = CharPointer_UTF8("\xc4\x90"); - inline static String const GlyphMtof = CharPointer_UTF8("\xc4\x91"); - inline static String const GlyphFtom = CharPointer_UTF8("\xc4\x92"); - inline static String const GlyphAutotune = CharPointer_UTF8("\xc4\x93"); + static inline String const GlyphMidiIn = CharPointer_UTF8("\xc4\x87"); + static inline String const GlyphMidiOut = CharPointer_UTF8("\xc4\x88"); + static inline String const GlyphNoteIn = CharPointer_UTF8("\xc4\x89"); + static inline String const GlyphNoteOut = CharPointer_UTF8("\xc4\x8a"); + static inline String const GlyphCtlIn = CharPointer_UTF8("\xc4\x8b"); + static inline String const GlyphCtlOut = CharPointer_UTF8("\xc4\x8c"); + static inline String const GlyphPgmIn = CharPointer_UTF8("\xc4\x8d"); + static inline String const GlyphPgmOut = CharPointer_UTF8("\xc4\x8e"); + static inline String const GlyphSysexIn = CharPointer_UTF8("\xc4\x8f"); + static inline String const GlyphSysexOut = CharPointer_UTF8("\xc4\x90"); + static inline String const GlyphMtof = CharPointer_UTF8("\xc4\x91"); + static inline String const GlyphFtom = CharPointer_UTF8("\xc4\x92"); + static inline String const GlyphAutotune = CharPointer_UTF8("\xc4\x93"); // Multi~ - inline static String const GlyphMultiSnake = CharPointer_UTF8("\xc4\xbf"); - inline static String const GlyphMultiGet = CharPointer_UTF8("\xc5\x82"); - inline static String const GlyphMultiPick = CharPointer_UTF8("\xc5\x81"); - inline static String const GlyphMultiSig = CharPointer_UTF8("\xc5\x83"); - inline static String const GlyphMultiMerge = CharPointer_UTF8("\xc5\x84"); - inline static String const GlyphMultiUnmerge = CharPointer_UTF8("\xc5\x85"); + static inline String const GlyphMultiSnake = CharPointer_UTF8("\xc4\xbf"); + static inline String const GlyphMultiGet = CharPointer_UTF8("\xc5\x82"); + static inline String const GlyphMultiPick = CharPointer_UTF8("\xc5\x81"); + static inline String const GlyphMultiSig = CharPointer_UTF8("\xc5\x83"); + static inline String const GlyphMultiMerge = CharPointer_UTF8("\xc5\x84"); + static inline String const GlyphMultiUnmerge = CharPointer_UTF8("\xc5\x85"); // IO~ - inline static String const GlyphAdc = CharPointer_UTF8("\xc4\xaa"); - inline static String const GlyphDac = CharPointer_UTF8("\xc4\xab"); - inline static String const GlyphOut = CharPointer_UTF8("\xc4\xac"); - inline static String const GlyphBlocksize = CharPointer_UTF8("\xc4\xad"); - inline static String const GlyphSamplerate = CharPointer_UTF8("\xc4\xae"); - inline static String const GlyphSetDsp = CharPointer_UTF8("\xc4\xaf"); - inline static String const GlyphSend = CharPointer_UTF8("\xc4\xb0"); - inline static String const GlyphReceive = CharPointer_UTF8("\xc4\xb1"); - inline static String const GlyphSignalSend = CharPointer_UTF8("\xc4\xb2"); - inline static String const GlyphSignalReceive = CharPointer_UTF8("\xc4\xb3"); + static inline String const GlyphAdc = CharPointer_UTF8("\xc4\xaa"); + static inline String const GlyphDac = CharPointer_UTF8("\xc4\xab"); + static inline String const GlyphOut = CharPointer_UTF8("\xc4\xac"); + static inline String const GlyphBlocksize = CharPointer_UTF8("\xc4\xad"); + static inline String const GlyphSamplerate = CharPointer_UTF8("\xc4\xae"); + static inline String const GlyphSetDsp = CharPointer_UTF8("\xc4\xaf"); + static inline String const GlyphSend = CharPointer_UTF8("\xc4\xb0"); + static inline String const GlyphReceive = CharPointer_UTF8("\xc4\xb1"); + static inline String const GlyphSignalSend = CharPointer_UTF8("\xc4\xb2"); + static inline String const GlyphSignalReceive = CharPointer_UTF8("\xc4\xb3"); // OSC~ - inline static String const GlyphOsc = CharPointer_UTF8("\xc5\x8d"); - inline static String const GlyphPhasor = CharPointer_UTF8("\xc5\x8e"); - inline static String const GlyphSaw = CharPointer_UTF8("\xc5\x8f"); - inline static String const GlyphSaw2 = CharPointer_UTF8("\xc5\x90"); - inline static String const GlyphSquare = CharPointer_UTF8("\xc5\x91"); - inline static String const GlyphTriangle = CharPointer_UTF8("\xc5\x92"); - inline static String const GlyphImp = CharPointer_UTF8("\xc5\x93"); - inline static String const GlyphImp2 = CharPointer_UTF8("\xc5\x94"); - inline static String const GlyphWavetable = CharPointer_UTF8("\xc5\x95"); - inline static String const GlyphPlaits = CharPointer_UTF8("\xc5\x96"); - - inline static String const GlyphOscBL = CharPointer_UTF8("\xc5\x97"); - inline static String const GlyphSawBL = CharPointer_UTF8("\xc5\x98"); - inline static String const GlyphSawBL2 = CharPointer_UTF8("\xc5\x99"); - inline static String const GlyphSquareBL = CharPointer_UTF8("\xc5\x9a"); - inline static String const GlyphTriBL = CharPointer_UTF8("\xc5\x9b"); - inline static String const GlyphImpBL = CharPointer_UTF8("\xc5\x9c"); - inline static String const GlyphImpBL2 = CharPointer_UTF8("\xc5\x9d"); - inline static String const GlyphWavetableBL = CharPointer_UTF8("\xc5\x9e"); - inline static String const GlyphLFORamp = CharPointer_UTF8("\xc5\x8f"); - inline static String const GlyphLFOSaw = CharPointer_UTF8("\xc5\x9f"); - inline static String const GlyphLFOSquare = CharPointer_UTF8("\xc5\xa0"); - inline static String const GlyphPulse = CharPointer_UTF8("\xc5\xa1"); - inline static String const GlyphPinknoise = CharPointer_UTF8("\xc5\xa2"); + static inline String const GlyphOsc = CharPointer_UTF8("\xc5\x8d"); + static inline String const GlyphPhasor = CharPointer_UTF8("\xc5\x8e"); + static inline String const GlyphSaw = CharPointer_UTF8("\xc5\x8f"); + static inline String const GlyphSaw2 = CharPointer_UTF8("\xc5\x90"); + static inline String const GlyphSquare = CharPointer_UTF8("\xc5\x91"); + static inline String const GlyphTriangle = CharPointer_UTF8("\xc5\x92"); + static inline String const GlyphImp = CharPointer_UTF8("\xc5\x93"); + static inline String const GlyphImp2 = CharPointer_UTF8("\xc5\x94"); + static inline String const GlyphWavetable = CharPointer_UTF8("\xc5\x95"); + static inline String const GlyphPlaits = CharPointer_UTF8("\xc5\x96"); + + static inline String const GlyphOscBL = CharPointer_UTF8("\xc5\x97"); + static inline String const GlyphSawBL = CharPointer_UTF8("\xc5\x98"); + static inline String const GlyphSawBL2 = CharPointer_UTF8("\xc5\x99"); + static inline String const GlyphSquareBL = CharPointer_UTF8("\xc5\x9a"); + static inline String const GlyphTriBL = CharPointer_UTF8("\xc5\x9b"); + static inline String const GlyphImpBL = CharPointer_UTF8("\xc5\x9c"); + static inline String const GlyphImpBL2 = CharPointer_UTF8("\xc5\x9d"); + static inline String const GlyphWavetableBL = CharPointer_UTF8("\xc5\x9e"); + static inline String const GlyphLFORamp = CharPointer_UTF8("\xc5\x8f"); + static inline String const GlyphLFOSaw = CharPointer_UTF8("\xc5\x9f"); + static inline String const GlyphLFOSquare = CharPointer_UTF8("\xc5\xa0"); + static inline String const GlyphPulse = CharPointer_UTF8("\xc5\xa1"); + static inline String const GlyphPinknoise = CharPointer_UTF8("\xc5\xa2"); // effects~ - inline static String const GlyphCrusher = CharPointer_UTF8("\xc6\x99"); - inline static String const GlyphDelayEffect = CharPointer_UTF8("\xc6\x9a"); - inline static String const GlyphDrive = CharPointer_UTF8("\xc6\x9b"); - inline static String const GlyphFlanger = CharPointer_UTF8("\xc6\x9c"); - inline static String const GlyphReverb = CharPointer_UTF8("\xc6\x9d"); - inline static String const GlyphFreeze = CharPointer_UTF8("\xc6\x9e"); - inline static String const GlyphRingmod = CharPointer_UTF8("\xc6\xa2"); - inline static String const GlyphSVFilter = CharPointer_UTF8("\xc6\xa6"); - inline static String const GlyphClip = CharPointer_UTF8("\xc6\xa3"); - inline static String const GlyphFold = CharPointer_UTF8("\xc6\xa4"); - inline static String const GlyphWrap = CharPointer_UTF8("\xc6\xa5"); - inline static String const GlyphCombRev = CharPointer_UTF8("\xc6\x9f"); - inline static String const GlyphComp = CharPointer_UTF8("\xc6\xa0"); - inline static String const GlyphBallance = CharPointer_UTF8("\xc6\xa7"); - inline static String const GlyphPan = CharPointer_UTF8("\xc6\xa8"); + static inline String const GlyphCrusher = CharPointer_UTF8("\xc6\x99"); + static inline String const GlyphDelayEffect = CharPointer_UTF8("\xc6\x9a"); + static inline String const GlyphDrive = CharPointer_UTF8("\xc6\x9b"); + static inline String const GlyphFlanger = CharPointer_UTF8("\xc6\x9c"); + static inline String const GlyphReverb = CharPointer_UTF8("\xc6\x9d"); + static inline String const GlyphFreeze = CharPointer_UTF8("\xc6\x9e"); + static inline String const GlyphRingmod = CharPointer_UTF8("\xc6\xa2"); + static inline String const GlyphSVFilter = CharPointer_UTF8("\xc6\xa6"); + static inline String const GlyphClip = CharPointer_UTF8("\xc6\xa3"); + static inline String const GlyphFold = CharPointer_UTF8("\xc6\xa4"); + static inline String const GlyphWrap = CharPointer_UTF8("\xc6\xa5"); + static inline String const GlyphCombRev = CharPointer_UTF8("\xc6\x9f"); + static inline String const GlyphComp = CharPointer_UTF8("\xc6\xa0"); + static inline String const GlyphBallance = CharPointer_UTF8("\xc6\xa7"); + static inline String const GlyphPan = CharPointer_UTF8("\xc6\xa8"); // filters~ - inline static String const GlyphLowpass = CharPointer_UTF8("\xc7\x8b"); - inline static String const GlyphHighpass = CharPointer_UTF8("\xc7\x8c"); - inline static String const GlyphBandpass = CharPointer_UTF8("\xc7\x8d"); - inline static String const GlyphNotch = CharPointer_UTF8("\xc7\x8e"); - inline static String const GlyphRezLowpass = CharPointer_UTF8("\xc7\x8f"); - inline static String const GlyphRezHighpass = CharPointer_UTF8("\xc7\x90"); - inline static String const GlyphLowShelf = CharPointer_UTF8("\xc7\x91"); - inline static String const GlyphHighShelf = CharPointer_UTF8("\xc7\x92"); - inline static String const GlyphAllPass = CharPointer_UTF8("\xc7\x93"); - inline static String const GlyphFreqShift = CharPointer_UTF8("\xc6\x9a"); + static inline String const GlyphLowpass = CharPointer_UTF8("\xc7\x8b"); + static inline String const GlyphHighpass = CharPointer_UTF8("\xc7\x8c"); + static inline String const GlyphBandpass = CharPointer_UTF8("\xc7\x8d"); + static inline String const GlyphNotch = CharPointer_UTF8("\xc7\x8e"); + static inline String const GlyphRezLowpass = CharPointer_UTF8("\xc7\x8f"); + static inline String const GlyphRezHighpass = CharPointer_UTF8("\xc7\x90"); + static inline String const GlyphLowShelf = CharPointer_UTF8("\xc7\x91"); + static inline String const GlyphHighShelf = CharPointer_UTF8("\xc7\x92"); + static inline String const GlyphAllPass = CharPointer_UTF8("\xc7\x93"); + static inline String const GlyphFreqShift = CharPointer_UTF8("\xc6\x9a"); // plugdata icon with three styles - inline static String const PlugdataIconStandard = CharPointer_UTF8("\xc2\xbc"); - inline static String const PlugdataIconFilled = CharPointer_UTF8("\xc2\xbd"); - inline static String const PlugdataIconSilhouette = CharPointer_UTF8("\xc2\xbe"); + static inline String const PlugdataIconStandard = CharPointer_UTF8("\xc2\xbc"); + static inline String const PlugdataIconFilled = CharPointer_UTF8("\xc2\xbd"); + static inline String const PlugdataIconSilhouette = CharPointer_UTF8("\xc2\xbe"); }; enum PlugDataColour { @@ -430,7 +430,7 @@ struct Corners { static constexpr float largeCornerRadius = 8.0f; static constexpr float defaultCornerRadius = 5.0f; static constexpr float resizeHanleCornerRadius = 2.75f; - inline static float objectCornerRadius = 2.75f; + static inline float objectCornerRadius = 2.75f; }; enum Overlay { diff --git a/Source/Heavy/CppExporter.h b/Source/Heavy/CppExporter.h index 5e663ee0c..ca2ac0aa2 100644 --- a/Source/Heavy/CppExporter.h +++ b/Source/Heavy/CppExporter.h @@ -55,8 +55,7 @@ class CppExporter final : public ExporterBase { return true; auto const command = args.joinIntoString(" "); - exportingView->logToConsole("Command: " + command + "\n"); - Toolchain::startShellScript(command, this); + startShellScript(command); waitForProcessToFinish(-1); exportingView->flushConsole(); diff --git a/Source/Heavy/DPFExporter.h b/Source/Heavy/DPFExporter.h index e626dce7c..1516b3bfb 100644 --- a/Source/Heavy/DPFExporter.h +++ b/Source/Heavy/DPFExporter.h @@ -220,8 +220,7 @@ class DPFExporter final : public ExporterBase { return true; auto const command = args.joinIntoString(" "); - exportingView->logToConsole("Command: " + command + "\n"); - Toolchain::startShellScript(command, this); + startShellScript(command); waitForProcessToFinish(-1); exportingView->flushConsole(); @@ -234,11 +233,11 @@ class DPFExporter final : public ExporterBase { outputFile.getChildFile("hv").deleteRecursively(); outputFile.getChildFile("c").deleteRecursively(); - auto const DPF = Toolchain::dir.getChildFile("lib").getChildFile("dpf"); + auto const DPF = toolchainDir.getChildFile("lib").getChildFile("dpf"); DPF.copyDirectoryTo(outputFile.getChildFile("dpf")); if (exportType == 2 || exportType == 4) { - auto const DPFGui = Toolchain::dir.getChildFile("lib").getChildFile("dpf-widgets"); + auto const DPFGui = toolchainDir.getChildFile("lib").getChildFile("dpf-widgets"); DPFGui.copyDirectoryTo(outputFile.getChildFile("dpf-widgets")); } @@ -256,29 +255,29 @@ class DPFExporter final : public ExporterBase { outputFile.setAsCurrentWorkingDirectory(); - auto const bin = Toolchain::dir.getChildFile("bin"); + auto const bin = toolchainDir.getChildFile("bin"); auto make = bin.getChildFile("make" + exeSuffix); auto makefile = outputFile.getChildFile("Makefile"); - + #if JUCE_MAC - Toolchain::startShellScript("make -j4 -f " + makefile.getFullPathName(), this); + startShellScript("make -j4 -f " + makefile.getFullPathName()); #elif JUCE_WINDOWS - auto path = "export PATH=\"$PATH:" + pathToString(Toolchain::dir.getChildFile("bin")) + "\"\n"; - auto cc = "CC=" + pathToString(Toolchain::dir.getChildFile("bin").getChildFile("gcc.exe")) + " "; - auto cxx = "CXX=" + pathToString(Toolchain::dir.getChildFile("bin").getChildFile("g++.exe")) + " "; - auto shell = " SHELL=" + pathToString(Toolchain::dir.getChildFile("bin").getChildFile("bash.exe")).quoted(); - Toolchain::startShellScript(path + cc + cxx + pathToString(make) + " -j4 -f " + pathToString(makefile) + shell, this); + auto path = "export PATH=\"$PATH:" + pathToString(toolchainDir.getChildFile("bin")) + "\"\n"; + auto cc = "CC=" + pathToString(toolchainDir.getChildFile("bin").getChildFile("gcc.exe")) + " "; + auto cxx = "CXX=" + pathToString(toolchainDir.getChildFile("bin").getChildFile("g++.exe")) + " "; + auto shell = " SHELL=" + pathToString(toolchainDir.getChildFile("bin").getChildFile("bash.exe")).quoted(); + startShellScript(path + cc + cxx + pathToString(make) + " -j4 -f " + pathToString(makefile) + shell); #else // Linux or BSD - auto prepareEnvironmentScript = pathToString(Toolchain::dir.getChildFile("scripts").getChildFile("anywhere-setup.sh")) + "\n"; + auto prepareEnvironmentScript = pathToString(toolchainDir.getChildFile("scripts").getChildFile("anywhere-setup.sh")) + "\n"; auto buildScript = prepareEnvironmentScript + pathToString(make) + " -j4 -f " + pathToString(makefile); // For some reason we need to do this again outputFile.getChildFile("dpf").getChildFile("utils").getChildFile("generate-ttl.sh").setExecutePermission(true); - Toolchain::dir.getChildFile("scripts").getChildFile("anywhere-setup.sh").getChildFile("generate-ttl.sh").setExecutePermission(true); + toolchainDir.getChildFile("scripts").getChildFile("anywhere-setup.sh").getChildFile("generate-ttl.sh").setExecutePermission(true); - Toolchain::startShellScript(buildScript, this); + startShellScript(buildScript); #endif waitForProcessToFinish(-1); diff --git a/Source/Heavy/DaisyExporter.h b/Source/Heavy/DaisyExporter.h index 77377d3dc..d058c0286 100644 --- a/Source/Heavy/DaisyExporter.h +++ b/Source/Heavy/DaisyExporter.h @@ -73,7 +73,7 @@ class DaisyExporter final : public ExporterBase { flashButton.onClick = [this] { auto const tempFolder = File::getSpecialLocation(File::tempDirectory).getChildFile("Heavy-" + Uuid().toString().substring(10)); - Toolchain::deleteTempFileLater(tempFolder); + deleteTempFileLater(tempFolder); startExport(tempFolder); }; @@ -82,10 +82,10 @@ class DaisyExporter final : public ExporterBase { exportingView->monitorProcessOutput(this); exportingView->showState(ExportingProgressView::Flashing); - auto const bin = Toolchain::dir.getChildFile("bin"); + auto const bin = toolchainDir.getChildFile("bin"); auto const make = bin.getChildFile("make" + exeSuffix); auto const& gccPath = bin.getFullPathName(); - auto const sourceDir = Toolchain::dir.getChildFile("lib").getChildFile("libdaisy").getChildFile("core"); + auto const sourceDir = toolchainDir.getChildFile("lib").getChildFile("libdaisy").getChildFile("core"); int const result = flashBootloader(bin, sourceDir, make, gccPath); @@ -218,7 +218,7 @@ class DaisyExporter final : public ExporterBase { + pathToString(make) + " program-boot" + " GCC_PATH=" + gccPath; - Toolchain::startShellScript(bootloaderScript, this); + startShellScript(bootloaderScript); waitForProcessToFinish(-1); exportingView->flushConsole(); @@ -262,7 +262,7 @@ class DaisyExporter final : public ExporterBase { if (board == "custom") { metaDaisy.getDynamicObject()->setProperty("board_file", customBoardDefinition.getFullPathName()); } else if (extra_boards.contains(board)) { - metaDaisy.getDynamicObject()->setProperty("board_file", Toolchain::dir.getChildFile("etc").getChildFile(board + ".json").getFullPathName()); + metaDaisy.getDynamicObject()->setProperty("board_file", toolchainDir.getChildFile("etc").getChildFile(board + ".json").getFullPathName()); } else { metaDaisy.getDynamicObject()->setProperty("board", board); } @@ -301,7 +301,7 @@ class DaisyExporter final : public ExporterBase { } else if (size == 3) { metaDaisy.getDynamicObject()->setProperty( "linker_script", - Toolchain::dir.getChildFile("etc").getChildFile("linkers").getChildFile("sram_linker_sdram.lds").getFullPathName()); + toolchainDir.getChildFile("etc").getChildFile("linkers").getChildFile("sram_linker_sdram.lds").getFullPathName()); metaDaisy.getDynamicObject()->setProperty("bootloader", "BOOT_SRAM"); } else if (size == 4) { metaDaisy.getDynamicObject()->setProperty("linker_script", "../../libdaisy/core/STM32H750IB_qspi.lds"); @@ -309,7 +309,7 @@ class DaisyExporter final : public ExporterBase { } else if (size == 5) { metaDaisy.getDynamicObject()->setProperty( "linker_script", - Toolchain::dir.getChildFile("etc").getChildFile("linkers").getChildFile("qspi_linker_sdram.lds").getFullPathName()); + toolchainDir.getChildFile("etc").getChildFile("linkers").getChildFile("qspi_linker_sdram.lds").getFullPathName()); metaDaisy.getDynamicObject()->setProperty("bootloader", "BOOT_QSPI"); } else if (size == 6) { metaDaisy.getDynamicObject()->setProperty("linker_script", customLinker.getFullPathName()); @@ -333,8 +333,8 @@ class DaisyExporter final : public ExporterBase { } auto const command = args.joinIntoString(" "); - exportingView->logToConsole("Command: " + command + "\n"); - Toolchain::startShellScript(command, this); + startShellScript(command); + waitForProcessToFinish(-1); exportingView->flushConsole(); @@ -353,8 +353,8 @@ class DaisyExporter final : public ExporterBase { metaJsonFile.copyFileTo(outputFile.getChildFile("meta.json")); if (compile) { - auto bin = Toolchain::dir.getChildFile("bin"); - auto libDaisy = Toolchain::dir.getChildFile("lib").getChildFile("libdaisy"); + auto bin = toolchainDir.getChildFile("bin"); + auto libDaisy = toolchainDir.getChildFile("lib").getChildFile("libdaisy"); auto make = bin.getChildFile("make" + exeSuffix); auto compiler = bin.getChildFile("arm-none-eabi-gcc" + exeSuffix); @@ -371,17 +371,22 @@ class DaisyExporter final : public ExporterBase { sourceDir.getChildFile("build").createDirectory(); auto const& gccPath = pathToString(bin); + // Bit hacky, but the only way to get colour coding on daisy builds for Windows +#if JUCE_WINDOWS + sourceDir.getChildFile("Makefile").appendText("\nCFLAGS += -fdiagnostics-color=always"); +#endif + auto buildScript = pathToString(make) + " -j4 -f " + pathToString(sourceDir.getChildFile("Makefile")).quoted() #if JUCE_WINDOWS - + " SHELL=" + pathToString(Toolchain::dir.getChildFile("bin").getChildFile("bash.exe")).quoted() + + " SHELL=" + pathToString(toolchainDir.getChildFile("bin").getChildFile("bash.exe")).quoted() #endif + " GCC_PATH=" + gccPath + " PROJECT_NAME=" + name; - Toolchain::startShellScript(buildScript, this); + startShellScript(buildScript); waitForProcessToFinish(-1); exportingView->flushConsole(); @@ -416,8 +421,7 @@ class DaisyExporter final : public ExporterBase { String testBootloaderScript = "export PATH=\"" + bin.getFullPathName() + ":$PATH\"\n" + dfuUtil.getFullPathName() + " -l "; - Toolchain runTest; - auto output = runTest.startShellScriptWithOutput(testBootloaderScript); + auto output = startShellScriptWithOutput(testBootloaderScript); if (output.contains("alt=1")) { exportingView->logToConsole("Bootloader not found...\n"); bootloaderExitCode = flashBootloader(bin, sourceDir, make, gccPath); @@ -434,7 +438,7 @@ class DaisyExporter final : public ExporterBase { + " GCC_PATH=" + gccPath + " PROJECT_NAME=" + name; - Toolchain::startShellScript(flashScript, this); + startShellScript(flashScript); waitForProcessToFinish(-1); exportingView->flushConsole(); @@ -456,7 +460,7 @@ class DaisyExporter final : public ExporterBase { } else { auto outputFile = File(outdir); - auto libDaisy = Toolchain::dir.getChildFile("lib").getChildFile("libdaisy"); + auto libDaisy = toolchainDir.getChildFile("lib").getChildFile("libdaisy"); libDaisy.copyDirectoryTo(outputFile.getChildFile("libdaisy")); outputFile.getChildFile("ir").deleteRecursively(); diff --git a/Source/Heavy/ExporterBase.h b/Source/Heavy/ExporterBase.h index 420cbe704..be4f131bb 100644 --- a/Source/Heavy/ExporterBase.h +++ b/Source/Heavy/ExporterBase.h @@ -22,13 +22,16 @@ struct ExporterBase : public Component bool blockDialog = false; #if JUCE_WINDOWS - inline static String const exeSuffix = ".exe"; + static inline File const toolchainDir = ProjectInfo::appDataDir.getChildFile("Toolchain").getChildFile("usr"); + static inline String const exeSuffix = ".exe"; #else - inline static String const exeSuffix = ""; + static inline File const toolchainDir = ProjectInfo::appDataDir.getChildFile("Toolchain"); + static inline String const exeSuffix = ""; #endif - inline static File heavyExecutable = Toolchain::dir.getChildFile("bin").getChildFile("Heavy").getChildFile("Heavy" + exeSuffix); - + static inline File heavyExecutable = toolchainDir.getChildFile("bin").getChildFile("Heavy").getChildFile("Heavy" + exeSuffix); + static inline SmallArray tempFilesToDelete; + bool validPatchSelected = false; bool canvasDirty = false; bool isTempFile = false; @@ -45,6 +48,8 @@ struct ExporterBase : public Component Label unsavedLabel = Label("", "Warning: patch has unsaved changes"); PluginEditor* editor; + + ExporterBase(PluginEditor* pluginEditor, ExportingProgressView* exportView) : ThreadPool(1, Thread::osDefaultStackSize, Thread::Priority::highest) @@ -86,7 +91,7 @@ struct ExporterBase : public Component if (auto const* cnv = editor->getCurrentCanvas()) { openedPatchFile = File::createTempFile(".pd"); - Toolchain::deleteTempFileLater(openedPatchFile); + deleteTempFileLater(openedPatchFile); patchFile = cnv->patch.getCurrentFile(); if (!patchFile.existsAsFile()) { openedPatchFile.replaceWithText(cnv->patch.getCanvasContent(), false, false, "\n"); @@ -150,6 +155,67 @@ struct ExporterBase : public Component return file.getFullPathName(); #endif } + + static void deleteTempFileLater(File const& script) + { + tempFilesToDelete.add(script); + } + + static void deleteTempFiles() + { + for (auto& file : tempFilesToDelete) { + if (file.existsAsFile()) + file.deleteFile(); + if (file.isDirectory()) + file.deleteRecursively(); + } + } + + String startShellScriptWithOutput(String const& scriptText) + { + exportingView->logToConsole("\n\x1b[1;92m> " + scriptText + " \x1b[0m \n\n"); + + File scriptFile = File::createTempFile(".sh"); + deleteTempFileLater(scriptFile); + + auto const bash = String("#!/bin/bash\n"); + scriptFile.replaceWithText(bash + scriptText, false, false, "\n"); + + ChildProcess process; +#if JUCE_WINDOWS + auto sh = toolchainDir.getChildFile("bin").getChildFile("sh.exe"); + auto arguments = StringArray { sh.getFullPathName(), "--login", scriptFile.getFullPathName().replaceCharacter('\\', '/') }; +#else + scriptFile.setExecutePermission(true); + auto arguments = scriptFile.getFullPathName(); +#endif + process.start(arguments, ChildProcess::wantStdOut | ChildProcess::wantStdErr); + return process.readAllProcessOutput(); + } + + void startShellScript(String const& scriptText) + { + exportingView->logToConsole("\n\x1b[1;92m> " + scriptText + " \x1b[0m \n\n"); + + File scriptFile = File::createTempFile(".sh"); + deleteTempFileLater(scriptFile); + +#if JUCE_WINDOWS + auto const gccColourFlags = String("export CFLAGS=\"-fdiagnostics-color=always\"\nexport CXXFLAGS=\"-fdiagnostics-color=always\"\n "); +#else + auto const gccColourFlags = String("export TERM=xterm-256color\nexport GCC_URLS=no\n"); +#endif + auto const bash = String("#!/bin/bash\n"); + scriptFile.replaceWithText(bash + gccColourFlags + scriptText, false, false, "\n"); + +#if JUCE_WINDOWS + auto sh = toolchainDir.getChildFile("bin").getChildFile("sh.exe"); + start(StringArray { sh.getFullPathName(), "--login", scriptFile.getFullPathName().replaceCharacter('\\', '/') }); +#else + scriptFile.setExecutePermission(true); + start(scriptFile.getFullPathName(), ChildProcess::wantStdOut | ChildProcess::wantStdErr | ChildProcess::wantTtyOut); +#endif + } void startExport(File const& outDir) { @@ -245,7 +311,7 @@ struct ExporterBase : public Component static File createMetaJson(DynamicObject::Ptr const& metaJson) { auto const metadata = File::createTempFile(".json"); - Toolchain::deleteTempFileLater(metadata); + deleteTempFileLater(metadata); String const metaString = JSON::toString(var(metaJson.get())); metadata.replaceWithText(metaString, false, false, "\n"); return metadata; diff --git a/Source/Heavy/ExportingProgressView.h b/Source/Heavy/ExportingProgressView.h index 7e5f6e90a..066a449e9 100644 --- a/Source/Heavy/ExportingProgressView.h +++ b/Source/Heavy/ExportingProgressView.h @@ -5,11 +5,516 @@ */ #pragma once +class ExporterConsole : public Component +{ +public: + ExporterConsole() + { + viewport.setViewedComponent(this, false); + viewport.setScrollBarsShown(true, false, false, false); + setVisible(true); + setWantsKeyboardFocus(true); + setMouseCursor(MouseCursor::IBeamCursor); + } + + void clear() + { + string.clear(); + plainText.clear(); + glyphPositions.clear(); + + layout.createLayout(string, viewport.getWidth() - 8); + viewport.setViewPositionProportionately(0.0f, 0.0f); + selectionStart = selectionEnd = 0; + + layout.createLayout(string, viewport.getWidth() - 8); + setSize(viewport.getWidth(), layout.getHeight() + 4); + + repaint(); + } + + void append(String const& text) + { + auto shouldAutoScroll = viewport.getViewPositionY() + viewport.getViewHeight() > getHeight() - 10; + + parseAnsiText(text); + layout.createLayout(string, viewport.getWidth() - 8); + setSize(viewport.getWidth(), layout.getHeight() + 4); + + if(shouldAutoScroll) + viewport.setViewPositionProportionately(0.0f, 1.0f); + } + + void paint(Graphics& g) override + { + // Draw selection highlight first + if (hasSelection()) + { + g.setColour(findColour(TextEditor::highlightColourId)); + + auto selStart = jmin(selectionStart, selectionEnd); + auto selEnd = jmax(selectionStart, selectionEnd); + + for (const auto& rect : getSelectionRectangles(selStart, selEnd)) + { + g.fillRect(rect); + } + } + + layout.draw(g, getLocalBounds().reduced(4, 0).translated(0, -12).toFloat()); + } + + void mouseDown(const MouseEvent& e) override + { + updateGlyphPositions(); + + if(e.mods.isRightButtonDown()) + { + copySelectionToClipboard(); + return; + } + if(e.mods.isShiftDown()) + { + selectionEnd = getCharacterIndexAt(e.position); + repaint(); + return; + } + + selectionStart = selectionEnd = getCharacterIndexAt(e.position); + repaint(); + } + + void mouseDrag(const MouseEvent& e) override + { + selectionEnd = getCharacterIndexAt(e.position); + repaint(); + } + + void mouseDoubleClick(const MouseEvent& e) override + { + int index = getCharacterIndexAt(e.position); + selectWord(index); + } + + bool keyPressed(const KeyPress& key) override + { + if (key == KeyPress('c', ModifierKeys::commandModifier, 0)) { + if (hasSelection()) + { + copySelectionToClipboard(); + return true; + } + } + else if (key == KeyPress('a', ModifierKeys::commandModifier, 0)) { + updateGlyphPositions(); + + selectionStart = 0; + selectionEnd = plainText.length(); + repaint(); + return true; + } + + return false; + } + + Viewport& getViewport() + { + return viewport; + } + +private: + struct GlyphInfo + { + Rectangle bounds; + int charIndex; + }; + + void parseAnsiText(const String& text) + { + String fullText = ansiBuffer + text; + ansiBuffer.clear(); + + String currentSegment; + Colour currentColour = findColour(PlugDataColour::panelTextColourId); + Font currentFont = Fonts::getMonospaceFont(); + + for (int i = 0; i < fullText.length(); ++i) + { + // Check for ANSI escape sequence start + if (fullText[i] == '\x1b' && i + 1 < fullText.length() && fullText[i + 1] == '[') + { + // Append any text before this escape sequence + if (currentSegment.isNotEmpty()) + { + appendWithWordWrap(currentSegment, currentFont, currentColour); + currentSegment = ""; + } + + // Find the end of the escape sequence + int sequenceStart = i + 2; + int sequenceEnd = sequenceStart; + + if(sequenceStart >= fullText.length()) + { + ansiBuffer = fullText.substring(i); + break; + } + + while (sequenceEnd < fullText.length() && + fullText[sequenceEnd] >= 0x30 && fullText[sequenceEnd] <= 0x3F) + { + ++sequenceEnd; + } + + if (sequenceEnd < fullText.length() && + fullText[sequenceEnd] >= 0x40 && fullText[sequenceEnd] <= 0x7E) + { + char command = fullText[sequenceEnd]; + + if (command == 'm') // SGR (Select Graphic Rendition) + { + auto params = fullText.substring(sequenceStart, sequenceEnd); + parseAnsiSGR(params, currentColour, currentFont); + } + + i = sequenceEnd; // Skip past the entire sequence + } + else { + ansiBuffer = fullText.substring(i); + break; + } + } + else + { + currentSegment += fullText[i]; + } + } + + if (currentSegment.isNotEmpty()) + { + appendWithWordWrap(currentSegment, currentFont, currentColour); + } + + plainText = string.getText(); + needsGlyphPositionUpdate = true; + } + + void parseAnsiSGR(const String& params, Colour& currentColour, Font& currentFont) + { + auto defaultTextColour = findColour(PlugDataColour::panelTextColourId); + currentColour = defaultTextColour; + currentFont = Fonts::getMonospaceFont(); + + StringArray codes; + codes.addTokens(params, ";", ""); + + for (const auto& code : codes) + { + int value = code.getIntValue(); + switch (value) + { + case 0: + currentColour = findColour(PlugDataColour::panelTextColourId); + break; + case 1: + currentFont = Fonts::getMonospaceBoldFont(); + break; + case 30: + currentColour = defaultTextColour.interpolatedWith(Colours::black, 0.5); + break; + case 31: + currentColour = defaultTextColour.interpolatedWith(Colours::red, 0.5); + break; + case 32: + currentColour = defaultTextColour.interpolatedWith(Colours::green, 0.5); + break; + case 33: + currentColour = defaultTextColour.interpolatedWith(Colours::yellow, 0.5); + break; + case 34: + currentColour = defaultTextColour.interpolatedWith(Colours::blue, 0.5); + break; + case 35: + currentColour = defaultTextColour.interpolatedWith(Colours::magenta, 0.5); + break; + case 36: + currentColour = defaultTextColour.interpolatedWith(Colours::cyan, 0.5); + break; + case 37: + currentColour = defaultTextColour.interpolatedWith(Colours::white, 0.5); + break; + + case 90: + currentColour = defaultTextColour.interpolatedWith(Colours::darkgrey, 0.7); + break; + case 91: + currentColour = defaultTextColour.interpolatedWith(Colours::red, 0.7); + break; + case 92: + currentColour = defaultTextColour.interpolatedWith(Colours::green, 0.7); + break; + case 93: + currentColour = defaultTextColour.interpolatedWith(Colours::yellow, 0.7); + break; + case 94: + currentColour = defaultTextColour.interpolatedWith(Colours::blue, 0.7); + break; + case 95: + currentColour = defaultTextColour.interpolatedWith(Colours::magenta, 0.7); + break; + case 96: + currentColour = defaultTextColour.interpolatedWith(Colours::cyan, 0.7); + break; + case 97: + currentColour = defaultTextColour.interpolatedWith(Colours::white, 0.7); + break; + default: + break; + } + } + } + + void appendWithWordWrap(const String& text, Font const& font, Colour const& colour) + { + StringArray words; + + // Split on spaces while preserving the spaces + int lastPos = 0; + for (int i = 0; i < text.length(); ++i) + { + if (text[i] == ' ' || text[i] == '\t' || text[i] == '\n') + { + if (i > lastPos) + { + words.add(text.substring(lastPos, i)); + } + words.add(String::charToString(text[i])); + lastPos = i + 1; + } + } + + // Add remaining text + if (lastPos < text.length()) + { + words.add(text.substring(lastPos)); + } + + float maxWidth = viewport.getWidth() - 10; + + for (int wordIdx = 0; wordIdx < words.size(); ++wordIdx) + { + const auto& word = words[wordIdx]; + + if (word == "\n") + { + string.append(word, font, colour); + plainText += word; + currentLineWidth = 0; + continue; + } + + float wordWidth = font.getStringWidthFloat(word); + + // Look ahead: if this is whitespace, check if the next word would fit + if ((word == " " || word == "\t") && wordIdx + 1 < words.size()) + { + float nextWordWidth = font.getStringWidthFloat(words[wordIdx + 1]); + + // If current line + space + next word exceeds width, break NOW + if (currentLineWidth + wordWidth + nextWordWidth > maxWidth && currentLineWidth > 0) + { + string.append("\n", font, colour); + plainText += "\n"; + currentLineWidth = 0; + continue; // Skip the space + } + } + + // If adding this word would exceed the width, insert a newline + if (currentLineWidth + wordWidth > maxWidth && currentLineWidth > 0 && word != " " && word != "\t") + { + string.append("\n", font, colour); + plainText += "\n"; + currentLineWidth = 0; + } + + string.append(word, font, colour); + plainText += word; + currentLineWidth += wordWidth; + } + } + + void updateGlyphPositions() + { + if(!needsGlyphPositionUpdate) return; + + glyphPositions.clear(); + int charIndex = 0; + for (auto& line : layout) { + // TextLayout on macOS/iOS considers whitespace as a character, but on Windows/Linux it does not +#if JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD + float lastX = 4.0f; + for (auto* run : line.runs) { + auto const runText = string.getText().substring(run->stringRange.getStart(), run->stringRange.getEnd()); + int glyphIndex = 0; + for (int i = 0; i < runText.length(); ++i) { + if (CharacterFunctions::isWhitespace(runText[i])) { + GlyphInfo info; + info.bounds = line.getLineBounds().withX(lastX).withWidth(run->font.getStringWidthFloat(runText.substring(i, i + 1))).translated(0, -12); + info.charIndex = charIndex++; + glyphPositions.add(info); + lastX = info.bounds.getRight(); + continue; + } + while (glyphIndex < run->glyphs.size() && +#if JUCE_WINDOWS + run->glyphs.getReference(glyphIndex).glyphCode == 1 +#else + run->glyphs.getReference(glyphIndex).glyphCode == 32 +#endif + ) + glyphIndex++; + + if (glyphIndex < run->glyphs.size()) { + auto const& glyph = run->glyphs.getReference(glyphIndex); + auto const position = glyph.anchor + line.lineOrigin; + GlyphInfo info; + info.bounds = Rectangle(position.x + 4, position.y - run->font.getAscent() - 12, glyph.width, run->font.getHeight()); + info.charIndex = charIndex++; + glyphPositions.add(info); + glyphIndex++; + lastX = info.bounds.getRight(); + } + } + } +#else // JUCE_MAC or JUCE_IOS + for (auto* run : line.runs) { + for (auto& glyph : run->glyphs) { + GlyphInfo info; + auto position = glyph.anchor + line.lineOrigin; + info.bounds = Rectangle(position.x + 4, position.y - run->font.getAscent() - 12, glyph.width, run->font.getHeight()); + info.charIndex = charIndex++; + glyphPositions.add(info); + } + } +#endif + } + + needsGlyphPositionUpdate = false; + } + + int getCharacterIndexAt(Point position) + { + int closestIndex = 0; + for (const auto& glyph : glyphPositions) + { + bool pastCharacter = position.x > (glyph.bounds.getX() - 2); + bool sameLine = glyph.bounds.withX(position.x - 1).withWidth(2).contains(position); + + if (sameLine && pastCharacter) + { + closestIndex = glyph.charIndex; + } + } + + return jlimit(0, plainText.length(), closestIndex); + } + + SmallArray> getSelectionRectangles(int start, int end) + { + SmallArray> rectangles; + + if (glyphPositions.empty()) + return rectangles; + + float currentY = -1; + float lineLeft = std::numeric_limits::max(); + float lineRight = 0; + float glyphHeight = 0.0f; + + for (int i = start; i < end && i < glyphPositions.size(); ++i) + { + const auto& glyph = glyphPositions[i]; + auto const glyphY = glyph.bounds.getY(); + glyphHeight = glyph.bounds.getHeight(); + + if (std::abs(glyphY - currentY) > glyphHeight * 0.5f) + { + rectangles.add(Rectangle(lineLeft, currentY, + lineRight - lineLeft, glyphHeight)); + lineLeft = std::numeric_limits::max(); + lineRight = 0; + } + + currentY = glyphY; + lineLeft = jmin(lineLeft, glyph.bounds.getX()); + lineRight = jmax(lineRight, glyph.bounds.getRight()); + } + + if (currentY >= 0) + { + rectangles.add(Rectangle(lineLeft, currentY, + lineRight - lineLeft, glyphHeight)); + } + + return rectangles; + } + + bool hasSelection() const + { + return selectionStart != selectionEnd; + } + + void selectWord(int index) + { + if (index < 0 || index >= plainText.length()) + return; + + int start = index; + int end = index; + + while (start > 0 && !CharacterFunctions::isWhitespace(plainText[start - 1])) + --start; + + while (end < plainText.length() && !CharacterFunctions::isWhitespace(plainText[end])) + ++end; + + selectionStart = start; + selectionEnd = end; + repaint(); + } + + void copySelectionToClipboard() + { + if (!hasSelection()) + return; + + int start = jmin(selectionStart, selectionEnd); + int end = jmax(selectionStart, selectionEnd); + + String selectedText = plainText.substring(start, end); + SystemClipboard::copyTextToClipboard(selectedText); + } + + Viewport viewport; + AttributedString string; + TextLayout layout; + String plainText; + String ansiBuffer; + HeapArray glyphPositions; + + int selectionStart = 0; + int selectionEnd = 0; + float currentLineWidth = 0; + + bool needsGlyphPositionUpdate = false; +}; + class ExportingProgressView final : public Component , public Thread , public Timer { - TextEditor console; - + + ExporterConsole console; ChildProcess* processToMonitor; public: @@ -29,7 +534,7 @@ class ExportingProgressView final : public Component String userInteractionMessage; - static constexpr int maxLength = 512; + static constexpr int maxLength = 8192; char processOutput[maxLength]; ExportingProgressView() @@ -37,24 +542,11 @@ class ExportingProgressView final : public Component { setVisible(false); addChildComponent(continueButton); - addAndMakeVisible(console); + addAndMakeVisible(console.getViewport()); continueButton.onClick = [this] { showState(NotExporting); }; - - console.setColour(TextEditor::backgroundColourId, Colours::transparentBlack); - console.setColour(TextEditor::outlineColourId, Colours::transparentBlack); - - console.setScrollbarsShown(true); - console.setMultiLine(true); - console.setReadOnly(true); - console.setWantsKeyboardFocus(true); - - // To ensure custom LnF got assigned... - MessageManager::callAsync([this] { - console.setFont(Fonts::getMonospaceFont()); - }); } // For the spinning animation @@ -106,7 +598,7 @@ class ExportingProgressView final : public Component setVisible(state < NotExporting); continueButton.setVisible(state >= Success); if (state == Exporting || state == Flashing) - console.setText(""); + console.clear(); if (console.isShowing()) { console.grabKeyboardFocus(); } @@ -123,9 +615,7 @@ class ExportingProgressView final : public Component if (!_this) return; - _this->console.setText(_this->console.getText() + text); - _this->console.moveCaretToEnd(); - _this->console.setScrollToShowCursor(true); + _this->console.append(text); }); } } @@ -144,7 +634,7 @@ class ExportingProgressView final : public Component g.strokePath(background, PathStrokeType(1.0f)); g.setColour(findColour(PlugDataColour::sidebarBackgroundColourId)); - g.fillRoundedRectangle(console.getBounds().expanded(2).toFloat(), Corners::defaultCornerRadius); + g.fillRoundedRectangle(console.getViewport().getBounds().expanded(6).toFloat(), Corners::defaultCornerRadius); if (state == Exporting) { Fonts::drawStyledText(g, "Exporting...", 0, 25, getWidth(), 40, findColour(PlugDataColour::panelTextColourId), Bold, 32, Justification::centred); @@ -167,7 +657,7 @@ class ExportingProgressView final : public Component } void resized() override { - console.setBounds(proportionOfWidth(0.05f), 80, proportionOfWidth(0.9f), getHeight() - 172); + console.getViewport().setBounds(proportionOfWidth(0.05f), 80, proportionOfWidth(0.9f), getHeight() - 172); continueButton.setBounds(proportionOfWidth(0.42f), getHeight() - 60, proportionOfWidth(0.12f), 24); } }; diff --git a/Source/Heavy/HeavyExportDialog.cpp b/Source/Heavy/HeavyExportDialog.cpp index 49d1e9a49..40d2d4345 100644 --- a/Source/Heavy/HeavyExportDialog.cpp +++ b/Source/Heavy/HeavyExportDialog.cpp @@ -15,7 +15,7 @@ #include "Components/PropertiesPanel.h" #include "Utility/OSUtils.h" -#include "Toolchain.h" +#include "ToolchainInstaller.h" #include "ExportingProgressView.h" #include "ExporterBase.h" #include "CppExporter.h" @@ -196,7 +196,7 @@ HeavyExportDialog::HeavyExportDialog(Dialog* dialog) , exporterPanel(new ExporterSettingsPanel(dynamic_cast(dialog->parentComponent), exportingView.get())) , infoButton(new MainToolbarButton(Icons::Help)) { - hasToolchain = Toolchain::dir.exists(); + hasToolchain = ExporterBase::toolchainDir.exists(); // Don't do this relative to toolchain variable, that won't work on Windows auto const versionFile = ProjectInfo::appDataDir.getChildFile("Toolchain").getChildFile("VERSION"); @@ -261,7 +261,7 @@ HeavyExportDialog::~HeavyExportDialog() Dialogs::dismissFileDialog(); // Clean up temp files - Toolchain::deleteTempFiles(); + ExporterBase::deleteTempFiles(); } void HeavyExportDialog::paint(Graphics& g) diff --git a/Source/Heavy/OWLExporter.h b/Source/Heavy/OWLExporter.h index b8e092fc6..4bd6448cb 100644 --- a/Source/Heavy/OWLExporter.h +++ b/Source/Heavy/OWLExporter.h @@ -45,7 +45,7 @@ class OWLExporter final : public ExporterBase { flashButton.onClick = [this] { auto const tempFolder = File::getSpecialLocation(File::tempDirectory).getChildFile("Heavy-" + Uuid().toString().substring(10)); - Toolchain::deleteTempFileLater(tempFolder); + deleteTempFileLater(tempFolder); startExport(tempFolder); }; } @@ -120,8 +120,7 @@ class OWLExporter final : public ExporterBase { } auto const command = args.joinIntoString(" "); - exportingView->logToConsole("Command: " + command + "\n"); - Toolchain::startShellScript(command, this); + startShellScript(command); waitForProcessToFinish(-1); exportingView->flushConsole(); @@ -142,10 +141,9 @@ class OWLExporter final : public ExporterBase { if (compile) { auto const workingDir = File::getCurrentWorkingDirectory(); - auto const bin = Toolchain::dir.getChildFile("bin"); - auto const OWL = Toolchain::dir.getChildFile("lib").getChildFile("OwlProgram"); + auto const bin = toolchainDir.getChildFile("bin"); + auto const OWL = toolchainDir.getChildFile("lib").getChildFile("OwlProgram"); auto make = bin.getChildFile("make" + exeSuffix); - auto compiler = bin.getChildFile("arm-none-eabi-gcc" + exeSuffix); OWL.copyDirectoryTo(outputFile.getChildFile("OwlProgram")); @@ -166,7 +164,7 @@ class OWLExporter final : public ExporterBase { buildScript += pathToString(make) + " -j4" #if JUCE_WINDOWS - + " SHELL=" + pathToString(Toolchain::dir.getChildFile("bin").getChildFile("bash.exe")).quoted() + + " SHELL=" + pathToString(toolchainDir.getChildFile("bin").getChildFile("bash.exe")).quoted() #endif + " TOOLROOT=" + pathToString(gccPath) + "/" + " BUILD=../" @@ -188,7 +186,7 @@ class OWLExporter final : public ExporterBase { buildScript += " patch"; } - Toolchain::startShellScript(buildScript, this); + startShellScript(buildScript); waitForProcessToFinish(-1); exportingView->flushConsole(); @@ -217,11 +215,15 @@ class OWLExporter final : public ExporterBase { // rename binary outputFile.getChildFile("patch.bin").moveFileTo(outputFile.getChildFile(name + ".bin")); + if(!compileExitCode) { + exportingView->logToConsole("Compilation finished"); + } + return heavyExitCode && compileExitCode; } else { auto const outputFile = File(outdir); - auto const OWL = Toolchain::dir.getChildFile("lib").getChildFile("OwlProgram"); + auto const OWL = toolchainDir.getChildFile("lib").getChildFile("OwlProgram"); OWL.copyDirectoryTo(outputFile.getChildFile("OwlProgram")); outputFile.getChildFile("ir").deleteRecursively(); diff --git a/Source/Heavy/PdExporter.h b/Source/Heavy/PdExporter.h index 58f304977..4b24ca365 100644 --- a/Source/Heavy/PdExporter.h +++ b/Source/Heavy/PdExporter.h @@ -87,8 +87,7 @@ class PdExporter final : public ExporterBase { return true; auto const command = args.joinIntoString(" "); - exportingView->logToConsole("Command: " + command + "\n"); - Toolchain::startShellScript(command, this); + startShellScript(command); waitForProcessToFinish(-1); exportingView->flushConsole(); @@ -110,12 +109,12 @@ class PdExporter final : public ExporterBase { outputFile.setAsCurrentWorkingDirectory(); - auto const bin = Toolchain::dir.getChildFile("bin"); + auto const bin = toolchainDir.getChildFile("bin"); auto make = bin.getChildFile("make" + exeSuffix); auto makefile = outputFile.getChildFile("Makefile"); #if JUCE_MAC - Toolchain::startShellScript("make -j4 suppress-wunused=1", this); + startShellScript("make -j4 suppress-wunused=1"); #elif JUCE_WINDOWS File pdDll; if (ProjectInfo::isStandalone) { @@ -124,22 +123,22 @@ class PdExporter final : public ExporterBase { pdDll = File::getSpecialLocation(File::globalApplicationsDirectory).getChildFile("plugdata"); } - auto path = "export PATH=\"$PATH:" + pathToString(Toolchain::dir.getChildFile("bin")) + "\"\n"; - auto cc = "CC=" + pathToString(Toolchain::dir.getChildFile("bin").getChildFile("gcc.exe")) + " "; - auto cxx = "CXX=" + pathToString(Toolchain::dir.getChildFile("bin").getChildFile("g++.exe")) + " "; + auto path = "export PATH=\"$PATH:" + pathToString(toolchainDir.getChildFile("bin")) + "\"\n"; + auto cc = "CC=" + pathToString(toolchainDir.getChildFile("bin").getChildFile("gcc.exe")) + " "; + auto cxx = "CXX=" + pathToString(toolchainDir.getChildFile("bin").getChildFile("g++.exe")) + " "; auto pdbindir = "PDBINDIR=\"" + pathToString(pdDll) + "\" "; - auto shell = " SHELL=" + pathToString(Toolchain::dir.getChildFile("bin").getChildFile("bash.exe")).quoted(); + auto shell = " SHELL=" + pathToString(toolchainDir.getChildFile("bin").getChildFile("bash.exe")).quoted(); - Toolchain::startShellScript(path + cc + cxx + pdbindir + pathToString(make) + " -j4 suppress-wunused=1" + shell, this); + startShellScript(path + cc + cxx + pdbindir + pathToString(make) + " -j4 suppress-wunused=1" + shell); #else // Linux or BSD - auto prepareEnvironmentScript = Toolchain::dir.getChildFile("scripts").getChildFile("anywhere-setup.sh").getFullPathName() + "\n"; + auto prepareEnvironmentScript = toolchainDir.getChildFile("scripts").getChildFile("anywhere-setup.sh").getFullPathName() + "\n"; auto buildScript = prepareEnvironmentScript + make.getFullPathName() + " -j4 suppress-wunused=1"; - Toolchain::startShellScript(buildScript, this); + startShellScript(buildScript); #endif waitForProcessToFinish(-1); diff --git a/Source/Heavy/Toolchain.h b/Source/Heavy/ToolchainInstaller.h similarity index 75% rename from Source/Heavy/Toolchain.h rename to Source/Heavy/ToolchainInstaller.h index b0a55b325..5374fe152 100644 --- a/Source/Heavy/Toolchain.h +++ b/Source/Heavy/ToolchainInstaller.h @@ -12,83 +12,6 @@ #include "Utility/Decompress.h" #include "Constants.h" -struct Toolchain { -#if JUCE_WINDOWS - static inline File const dir = ProjectInfo::appDataDir.getChildFile("Toolchain").getChildFile("usr"); -#else - static inline File const dir = ProjectInfo::appDataDir.getChildFile("Toolchain"); -#endif - - static void deleteTempFileLater(File const& script) - { - tempFilesToDelete.add(script); - } - - static void deleteTempFiles() - { - for (auto& file : tempFilesToDelete) { - if (file.existsAsFile()) - file.deleteFile(); - if (file.isDirectory()) - file.deleteRecursively(); - } - } - - static void startShellScript(String const& scriptText, ChildProcess* processToUse = nullptr) - { - File scriptFile = File::createTempFile(".sh"); - Toolchain::deleteTempFileLater(scriptFile); - - auto const bash = String("#!/bin/bash\n"); - scriptFile.replaceWithText(bash + scriptText, false, false, "\n"); - -#if JUCE_WINDOWS - auto sh = Toolchain::dir.getChildFile("bin").getChildFile("sh.exe"); - - if (processToUse) { - processToUse->start(StringArray { sh.getFullPathName(), "--login", scriptFile.getFullPathName().replaceCharacter('\\', '/') }); - } else { - ChildProcess process; - process.start(StringArray { sh.getFullPathName(), "--login", scriptFile.getFullPathName().replaceCharacter('\\', '/') }); - process.waitForProcessToFinish(-1); - } -#else - scriptFile.setExecutePermission(true); - - if (processToUse) { - processToUse->start(scriptFile.getFullPathName()); - } else { - ChildProcess process; - process.start(scriptFile.getFullPathName()); - process.waitForProcessToFinish(-1); - } -#endif - } - - static String startShellScriptWithOutput(String const& scriptText) - { - File scriptFile = File::createTempFile(".sh"); - Toolchain::deleteTempFileLater(scriptFile); - - auto const bash = String("#!/bin/bash\n"); - scriptFile.replaceWithText(bash + scriptText, false, false, "\n"); - - ChildProcess process; -#if JUCE_WINDOWS - auto sh = Toolchain::dir.getChildFile("bin").getChildFile("sh.exe"); - auto arguments = StringArray { sh.getFullPathName(), "--login", scriptFile.getFullPathName().replaceCharacter('\\', '/') }; -#else - scriptFile.setExecutePermission(true); - auto arguments = scriptFile.getFullPathName(); -#endif - process.start(arguments, ChildProcess::wantStdOut | ChildProcess::wantStdErr); - return process.readAllProcessOutput(); - } - -private: - inline static SmallArray tempFilesToDelete; -}; - class ToolchainInstaller final : public Component , public Thread , public Timer { @@ -283,8 +206,8 @@ class ToolchainInstaller final : public Component } #if JUCE_WINDOWS - File usbDriverInstaller = Toolchain::dir.getChildFile("etc").getChildFile("usb_driver").getChildFile("install-filter.exe"); - File driverSpec = Toolchain::dir.getChildFile("etc").getChildFile("usb_driver").getChildFile("DFU_in_FS_Mode.inf"); + File usbDriverInstaller = toolchainDir.getChildFile("etc").getChildFile("usb_driver").getChildFile("install-filter.exe"); + File driverSpec = toolchainDir.getChildFile("etc").getChildFile("usb_driver").getChildFile("DFU_in_FS_Mode.inf"); // Since we interact with ComponentPeer, better call it from the message thread MessageManager::callAsync([this, usbDriverInstaller, driverSpec]() mutable { @@ -297,8 +220,8 @@ class ToolchainInstaller final : public Component // This makes sure we can use dfu-util without admin privileges // Kinda sucks that we need to sudo this, but there's no other way AFAIK - auto askpassScript = Toolchain::dir.getChildFile("scripts").getChildFile("askpass.sh"); - auto udevInstallScript = Toolchain::dir.getChildFile("scripts").getChildFile("install_udev_rule.sh"); + auto askpassScript = toolchainDir.getChildFile("scripts").getChildFile("askpass.sh"); + auto udevInstallScript = toolchainDir.getChildFile("scripts").getChildFile("install_udev_rule.sh"); askpassScript.setExecutePermission(true); udevInstallScript.setExecutePermission(true); @@ -308,7 +231,9 @@ class ToolchainInstaller final : public Component } #elif JUCE_MAC - Toolchain::startShellScript("xcode-select --install"); + ChildProcess process; + process.start("xcode-select --install"); + process.waitForProcessToFinish(-1); #endif installProgress = 0.0f; diff --git a/Source/Heavy/WASMExporter.h b/Source/Heavy/WASMExporter.h index b6cb23dad..0e89f2ee5 100644 --- a/Source/Heavy/WASMExporter.h +++ b/Source/Heavy/WASMExporter.h @@ -85,7 +85,6 @@ class WASMExporter final : public ExporterBase { return true; auto compileString = args.joinIntoString(" "); - exportingView->logToConsole("Command: " + compileString + "\n"); #if JUCE_WINDOWS auto buildScript = "source " + emsdkPath.replaceCharacter('\\', '/') + "/emsdk_env.sh; " + compileString; @@ -93,7 +92,7 @@ class WASMExporter final : public ExporterBase { auto buildScript = "source " + emsdkPath + "/emsdk_env.sh; " + compileString; #endif - Toolchain::startShellScript(buildScript, this); + startShellScript(buildScript); waitForProcessToFinish(-1); exportingView->flushConsole(); diff --git a/Source/Pd/Instance.h b/Source/Pd/Instance.h index b1ae1bb31..ddd8c2997 100644 --- a/Source/Pd/Instance.h +++ b/Source/Pd/Instance.h @@ -287,7 +287,7 @@ class Instance : public AsyncUpdater { void* printReceiver = nullptr; void* dataBufferReceiver = nullptr; - inline static String const defaultPatch = "#N canvas 827 239 734 565 12;"; + static inline String const defaultPatch = "#N canvas 827 239 734 565 12;"; bool initialiseIntoPluginmode = false; bool isPerformingGlobalSync = false; diff --git a/Source/Utility/Fonts.h b/Source/Utility/Fonts.h index 12df3d128..b4a4afa08 100644 --- a/Source/Utility/Fonts.h +++ b/Source/Utility/Fonts.h @@ -73,6 +73,7 @@ struct Fonts { semiBoldTypeface = Typeface::createSystemTypefaceFor(BinaryData::InterSemiBold_ttf, BinaryData::InterSemiBold_ttfSize); iconTypeface = Typeface::createSystemTypefaceFor(BinaryData::IconFont_ttf, BinaryData::IconFont_ttfSize); monoTypeface = Typeface::createSystemTypefaceFor(BinaryData::RobotoMono_Regular_ttf, BinaryData::RobotoMono_Regular_ttfSize); + monoBoldTypeface = Typeface::createSystemTypefaceFor(BinaryData::RobotoMono_Bold_ttf, BinaryData::RobotoMono_Bold_ttfSize); variableTypeface = Typeface::createSystemTypefaceFor(BinaryData::InterVariable_ttf, BinaryData::InterVariable_ttfSize); tabularTypeface = Typeface::createSystemTypefaceFor(BinaryData::InterTabular_ttf, BinaryData::InterTabular_ttfSize); @@ -85,6 +86,7 @@ struct Fonts { static Font getSemiBoldFont() { return Font(instance->semiBoldTypeface); } static Font getIconFont() { return Font(instance->iconTypeface); } static Font getMonospaceFont() { return Font(instance->monoTypeface); } + static Font getMonospaceBoldFont() { return Font(instance->monoBoldTypeface); } static Font getVariableFont() { return Font(instance->variableTypeface); } static Font getTabularNumbersFont() { return Font(instance->tabularTypeface); } @@ -239,6 +241,7 @@ struct Fonts { Typeface::Ptr semiBoldTypeface; Typeface::Ptr iconTypeface; Typeface::Ptr monoTypeface; + Typeface::Ptr monoBoldTypeface; Typeface::Ptr variableTypeface; Typeface::Ptr tabularTypeface;