1db5b5dfaSStefano Ceccherini/*
2e633e9efSHumdinger * Copyright 2014-2017, Haiku, Inc. All rights reserved.
3db5b5dfaSStefano Ceccherini * Distributed under the terms of the MIT License.
4db5b5dfaSStefano Ceccherini */
5db5b5dfaSStefano Ceccherini
6db5b5dfaSStefano Ceccherini#include "MidiSettingsView.h"
7db5b5dfaSStefano Ceccherini
8d6039d2bSStefano Ceccherini#include <MidiSettings.h>
9d6039d2bSStefano Ceccherini
10db5b5dfaSStefano Ceccherini#include <Box.h>
11db5b5dfaSStefano Ceccherini#include <Catalog.h>
12db5b5dfaSStefano Ceccherini#include <Directory.h>
13db5b5dfaSStefano Ceccherini#include <Entry.h>
14db5b5dfaSStefano Ceccherini#include <FindDirectory.h>
15db5b5dfaSStefano Ceccherini#include <GridView.h>
16db5b5dfaSStefano Ceccherini#include <LayoutBuilder.h>
17db5b5dfaSStefano Ceccherini#include <ListView.h>
18db5b5dfaSStefano Ceccherini#include <Locale.h>
19db5b5dfaSStefano Ceccherini#include <Node.h>
20db5b5dfaSStefano Ceccherini#include <NodeInfo.h>
219874150aSHumdinger#include <NodeMonitor.h>
22db5b5dfaSStefano Ceccherini#include <Path.h>
23f262f1b6SStefano Ceccherini#include <PathFinder.h>
24db5b5dfaSStefano Ceccherini#include <ScrollView.h>
25f262f1b6SStefano Ceccherini#include <StringList.h>
26873a8ad9SStefano Ceccherini#include <StringView.h>
27db5b5dfaSStefano Ceccherini
28db5b5dfaSStefano Ceccherini#include <stdio.h>
29f262f1b6SStefano Ceccherini
30db5b5dfaSStefano Ceccherini
31db5b5dfaSStefano Ceccherini#undef B_TRANSLATION_CONTEXT
32db5b5dfaSStefano Ceccherini#define B_TRANSLATION_CONTEXT "Midi View"
33db5b5dfaSStefano Ceccherini
34db5b5dfaSStefano Ceccheriniconst static uint32 kSelectSoundFont = 'SeSf';
359874150aSHumdingerconst static uint32 kDoubleClick = 'DClk';
36db5b5dfaSStefano Ceccherini
37db5b5dfaSStefano Ceccherini
38db5b5dfaSStefano CeccheriniMidiSettingsView::MidiSettingsView()
39db5b5dfaSStefano Ceccherini	:
40db5b5dfaSStefano Ceccherini	SettingsView()
41db5b5dfaSStefano Ceccherini{
429874150aSHumdinger	BBox* defaultsBox = new BBox("SoundFonts");
439874150aSHumdinger	defaultsBox->SetLabel(B_TRANSLATE("SoundFonts"));
44db5b5dfaSStefano Ceccherini	BGridView* defaultsGridView = new BGridView();
45db5b5dfaSStefano Ceccherini
46db5b5dfaSStefano Ceccherini	fListView = new BListView(B_SINGLE_SELECTION_LIST);
47db5b5dfaSStefano Ceccherini	fListView->SetSelectionMessage(new BMessage(kSelectSoundFont));
489874150aSHumdinger	fListView->SetInvocationMessage(new BMessage(kDoubleClick));
49db5b5dfaSStefano Ceccherini
509874150aSHumdinger	BScrollView* scrollView = new BScrollView("ScrollView", fListView,
51db5b5dfaSStefano Ceccherini			0, false, true);
52db5b5dfaSStefano Ceccherini	BLayoutBuilder::Grid<>(defaultsGridView)
53db5b5dfaSStefano Ceccherini		.SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING,
54db5b5dfaSStefano Ceccherini				B_USE_DEFAULT_SPACING)
55db5b5dfaSStefano Ceccherini		.Add(scrollView, 0, 0);
56db5b5dfaSStefano Ceccherini
57db5b5dfaSStefano Ceccherini	defaultsBox->AddChild(defaultsGridView);
589874150aSHumdinger	fSoundFontStatus = new BStringView("SoundFontStatus", "");
59db5b5dfaSStefano Ceccherini
60db5b5dfaSStefano Ceccherini	BLayoutBuilder::Group<>(this)
61db5b5dfaSStefano Ceccherini		.SetInsets(0, 0, 0, 0)
62db5b5dfaSStefano Ceccherini		.Add(defaultsBox)
639874150aSHumdinger		.AddGroup(B_HORIZONTAL)
649874150aSHumdinger			.AddGlue()
659874150aSHumdinger			.Add(fSoundFontStatus)
669874150aSHumdinger			.AddGlue()
679874150aSHumdinger			.End()
68db5b5dfaSStefano Ceccherini		.AddGlue();
69db5b5dfaSStefano Ceccherini}
70db5b5dfaSStefano Ceccherini
71db5b5dfaSStefano Ceccherini
72db5b5dfaSStefano Ceccherini/* virtual */
73db5b5dfaSStefano Ceccherinivoid
74db5b5dfaSStefano CeccheriniMidiSettingsView::AttachedToWindow()
75db5b5dfaSStefano Ceccherini{
76db5b5dfaSStefano Ceccherini	SettingsView::AttachedToWindow();
77db5b5dfaSStefano Ceccherini
78db5b5dfaSStefano Ceccherini	fListView->SetTarget(this);
79db5b5dfaSStefano Ceccherini	_LoadSettings();
809874150aSHumdinger	_RetrieveSoundFontList();
819874150aSHumdinger	_SelectActiveSoundFont();
829874150aSHumdinger	_UpdateSoundFontStatus();
839874150aSHumdinger	_WatchFolders();
849874150aSHumdinger}
859874150aSHumdinger
869874150aSHumdinger
879874150aSHumdinger/* virtual */
889874150aSHumdingervoid
899874150aSHumdingerMidiSettingsView::DetachedFromWindow()
909874150aSHumdinger{
919874150aSHumdinger	SettingsView::DetachedFromWindow();
929874150aSHumdinger
939874150aSHumdinger	stop_watching(this);
94db5b5dfaSStefano Ceccherini}
95db5b5dfaSStefano Ceccherini
96db5b5dfaSStefano Ceccherini
97db5b5dfaSStefano Ceccherini/* virtual */
98db5b5dfaSStefano Ceccherinivoid
99db5b5dfaSStefano CeccheriniMidiSettingsView::MessageReceived(BMessage* message)
100db5b5dfaSStefano Ceccherini{
101db5b5dfaSStefano Ceccherini	switch (message->what) {
1029874150aSHumdinger		case B_NODE_MONITOR:
103fa3f84b7SStefano Ceccherini		{
1049874150aSHumdinger			int32 selected = fListView->CurrentSelection();
1059874150aSHumdinger			BStringItem* olditem = (BStringItem*)fListView->ItemAt(selected);
1069874150aSHumdinger
1079874150aSHumdinger			_RetrieveSoundFontList();
1089874150aSHumdinger
1099874150aSHumdinger			int32 count = fListView->CountItems();
1109874150aSHumdinger			if (count == 1) {
1119874150aSHumdinger				fListView->Select(0);
112fa3f84b7SStefano Ceccherini				_SaveSettings();
1139874150aSHumdinger			} else if (olditem != NULL) {
1149874150aSHumdinger				for (int32 i = 0; i < fListView->CountItems(); i++) {
1159874150aSHumdinger					BStringItem* item = (BStringItem*)fListView->ItemAt(i);
116e633e9efSHumdinger					if (strcmp(item->Text(), olditem->Text()) == 0) {
1179874150aSHumdinger						fListView->Select(i);
1189874150aSHumdinger						break;
1199874150aSHumdinger					}
1209874150aSHumdinger				}
121fa3f84b7SStefano Ceccherini			}
1229874150aSHumdinger			_UpdateSoundFontStatus();
1239874150aSHumdinger			break;
1249874150aSHumdinger		}
1259874150aSHumdinger		case kSelectSoundFont:
1269874150aSHumdinger		{
1279874150aSHumdinger			int selection = fListView->CurrentSelection();
1289874150aSHumdinger			if (selection < 0)
1299874150aSHumdinger				_SelectActiveSoundFont();
1309874150aSHumdinger			else
1319874150aSHumdinger				_SaveSettings();
1329874150aSHumdinger
1339874150aSHumdinger			_UpdateSoundFontStatus();
1349874150aSHumdinger			break;
1359874150aSHumdinger		}
1369874150aSHumdinger		case kDoubleClick:
1379874150aSHumdinger		{
1389874150aSHumdinger			int selection = fListView->CurrentSelection();
139dd3732bbSHumdinger			if (selection < 0)
140dd3732bbSHumdinger				break;
141dd3732bbSHumdinger
1429874150aSHumdinger			BStringItem* item = (BStringItem*)fListView->ItemAt(selection);
1439874150aSHumdinger
1449874150aSHumdinger			BEntry entry(item->Text());
1459874150aSHumdinger			BEntry parent;
1469874150aSHumdinger			entry.GetParent(&parent);
1479874150aSHumdinger			entry_ref folderRef;
1489874150aSHumdinger			parent.GetRef(&folderRef);
1499874150aSHumdinger			BMessenger msgr("application/x-vnd.Be-TRAK");
1509874150aSHumdinger			BMessage refMsg(B_REFS_RECEIVED);
1519874150aSHumdinger			refMsg.AddRef("refs",&folderRef);
1529874150aSHumdinger			msgr.SendMessage(&refMsg);
153db5b5dfaSStefano Ceccherini			break;
154873a8ad9SStefano Ceccherini		}
155db5b5dfaSStefano Ceccherini
156db5b5dfaSStefano Ceccherini		default:
157db5b5dfaSStefano Ceccherini			SettingsView::MessageReceived(message);
158db5b5dfaSStefano Ceccherini			break;
159db5b5dfaSStefano Ceccherini	}
160db5b5dfaSStefano Ceccherini}
161db5b5dfaSStefano Ceccherini
162db5b5dfaSStefano Ceccherini
163db5b5dfaSStefano Ceccherinivoid
1649874150aSHumdingerMidiSettingsView::_RetrieveSoundFontList()
165db5b5dfaSStefano Ceccherini{
166a6fb27a3SStefano Ceccherini	// TODO: Duplicated code between here
167a6fb27a3SStefano Ceccherini	// and BSoftSynth::SetDefaultInstrumentsFile
168f262f1b6SStefano Ceccherini	BStringList paths;
169f262f1b6SStefano Ceccherini	status_t status = BPathFinder::FindPaths(B_FIND_PATH_DATA_DIRECTORY,
170f262f1b6SStefano Ceccherini			"synth", paths);
171db5b5dfaSStefano Ceccherini	if (status != B_OK)
172db5b5dfaSStefano Ceccherini		return;
173db5b5dfaSStefano Ceccherini
174db5b5dfaSStefano Ceccherini	fListView->MakeEmpty();
175db5b5dfaSStefano Ceccherini
176f262f1b6SStefano Ceccherini	for (int32 i = 0; i < paths.CountStrings(); i++) {
177f262f1b6SStefano Ceccherini		BDirectory directory(paths.StringAt(i).String());
178db5b5dfaSStefano Ceccherini		BEntry entry;
179db5b5dfaSStefano Ceccherini		if (directory.InitCheck() != B_OK)
180db5b5dfaSStefano Ceccherini			continue;
181db5b5dfaSStefano Ceccherini		while (directory.GetNextEntry(&entry) == B_OK) {
182db5b5dfaSStefano Ceccherini			BNode node(&entry);
183db5b5dfaSStefano Ceccherini			BNodeInfo nodeInfo(&node);
184db5b5dfaSStefano Ceccherini			char mimeType[B_MIME_TYPE_LENGTH];
185a6fb27a3SStefano Ceccherini			// TODO: For some reason the mimetype check fails.
186a6fb27a3SStefano Ceccherini			// maybe because the file hasn't yet been sniffed and recognized?
187db5b5dfaSStefano Ceccherini			if (nodeInfo.GetType(mimeType) == B_OK
188a6fb27a3SStefano Ceccherini				/*&& !strcmp(mimeType, "audio/x-soundfont")*/) {
189f262f1b6SStefano Ceccherini				BPath fullPath = paths.StringAt(i).String();
190db5b5dfaSStefano Ceccherini				fullPath.Append(entry.Name());
191db5b5dfaSStefano Ceccherini				fListView->AddItem(new BStringItem(fullPath.Path()));
192db5b5dfaSStefano Ceccherini			}
193db5b5dfaSStefano Ceccherini		}
194db5b5dfaSStefano Ceccherini	}
195db5b5dfaSStefano Ceccherini}
196db5b5dfaSStefano Ceccherini
197db5b5dfaSStefano Ceccherini
198db5b5dfaSStefano Ceccherinivoid
199db5b5dfaSStefano CeccheriniMidiSettingsView::_LoadSettings()
200db5b5dfaSStefano Ceccherini{
201d6039d2bSStefano Ceccherini	struct BPrivate::midi_settings settings;
2029874150aSHumdinger	if (BPrivate::read_midi_settings(&settings) == B_OK)
203e633e9efSHumdinger		fActiveSoundFont.SetTo(settings.soundfont_file);
204db5b5dfaSStefano Ceccherini}
205db5b5dfaSStefano Ceccherini
206db5b5dfaSStefano Ceccherini
207db5b5dfaSStefano Ceccherinivoid
208db5b5dfaSStefano CeccheriniMidiSettingsView::_SaveSettings()
209db5b5dfaSStefano Ceccherini{
210e633e9efSHumdinger	fActiveSoundFont = _SelectedSoundFont();
211e633e9efSHumdinger	if (fActiveSoundFont.Length() > 0) {
212873a8ad9SStefano Ceccherini		struct BPrivate::midi_settings settings;
213e633e9efSHumdinger		strlcpy(settings.soundfont_file, fActiveSoundFont.String(),
2149874150aSHumdinger			sizeof(settings.soundfont_file));
215873a8ad9SStefano Ceccherini		BPrivate::write_midi_settings(settings);
216873a8ad9SStefano Ceccherini	}
217873a8ad9SStefano Ceccherini}
218959051f8SJackBurton
219db5b5dfaSStefano Ceccherini
2209874150aSHumdingervoid
2219874150aSHumdingerMidiSettingsView::_SelectActiveSoundFont()
2229874150aSHumdinger{
2239874150aSHumdinger	int32 count = fListView->CountItems();
2249874150aSHumdinger	if (count == 1) {
2259874150aSHumdinger		fListView->Select(0);
2269874150aSHumdinger		_SaveSettings();
2279874150aSHumdinger		return;
2289874150aSHumdinger	}
2299874150aSHumdinger	for (int32 i = 0; i < fListView->CountItems(); i++) {
2309874150aSHumdinger		BStringItem* item = (BStringItem*)fListView->ItemAt(i);
231e633e9efSHumdinger		if (strcmp(item->Text(), fActiveSoundFont.String()) == 0) {
2329874150aSHumdinger			fListView->Select(i);
2339874150aSHumdinger			break;
2349874150aSHumdinger		}
2359874150aSHumdinger	}
2369874150aSHumdinger}
2379874150aSHumdinger
2389874150aSHumdinger
239873a8ad9SStefano CeccheriniBString
240873a8ad9SStefano CeccheriniMidiSettingsView::_SelectedSoundFont() const
241873a8ad9SStefano Ceccherini{
242873a8ad9SStefano Ceccherini	BString string;
243873a8ad9SStefano Ceccherini	int32 selection = fListView->CurrentSelection();
244873a8ad9SStefano Ceccherini	if (selection >= 0) {
245873a8ad9SStefano Ceccherini		BStringItem* item = (BStringItem*)fListView->ItemAt(selection);
246873a8ad9SStefano Ceccherini		if (item != NULL)
247873a8ad9SStefano Ceccherini			string = item->Text();
248873a8ad9SStefano Ceccherini	}
249db5b5dfaSStefano Ceccherini
250873a8ad9SStefano Ceccherini	return string;
251873a8ad9SStefano Ceccherini}
2529874150aSHumdinger
2539874150aSHumdinger
2549874150aSHumdingervoid
2559874150aSHumdingerMidiSettingsView::_UpdateSoundFontStatus()
2569874150aSHumdinger{
2579874150aSHumdinger	if (fListView->IsEmpty()) {
2589874150aSHumdinger		fSoundFontStatus->SetText(
259bc622f6bSHumdinger			B_TRANSLATE("There are no SoundFonts installed."));
2609874150aSHumdinger		return;
2619874150aSHumdinger	}
2629874150aSHumdinger	int32 selection = fListView->CurrentSelection();
2639874150aSHumdinger	if (selection < 0) {
2649874150aSHumdinger		fSoundFontStatus->SetText(
2659874150aSHumdinger			B_TRANSLATE("Please select a SoundFont."));
2669874150aSHumdinger		return;
2679874150aSHumdinger	}
2689874150aSHumdinger	fSoundFontStatus->SetText("");
2699874150aSHumdinger}
2709874150aSHumdinger
2719874150aSHumdinger
2729874150aSHumdingervoid
2739874150aSHumdingerMidiSettingsView::_WatchFolders()
2749874150aSHumdinger{
2759874150aSHumdinger	BStringList paths;
2769874150aSHumdinger	BPathFinder().FindPaths(B_FIND_PATH_DATA_DIRECTORY, "synth", paths);
2779874150aSHumdinger	for (int32 i = 0; i < paths.CountStrings(); i++) {
2789874150aSHumdinger		BEntry entry(paths.StringAt(i));
2799874150aSHumdinger		node_ref nref;
2809874150aSHumdinger		entry.GetNodeRef(&nref);
2819874150aSHumdinger
2829874150aSHumdinger		watch_node(&nref, B_WATCH_ALL, this);
2839874150aSHumdinger	}
2849874150aSHumdinger}
285