Add linux bass
This commit is contained in:
parent
c46545401e
commit
ca6a819267
289 changed files with 10933 additions and 0 deletions
315
bass-sys/linux/bass24/3dtest/3dtest.c
Normal file
315
bass-sys/linux/bass24/3dtest/3dtest.c
Normal file
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
BASS 3D test
|
||||
Copyright (c) 1999-2012 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glade/glade.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <regex.h>
|
||||
#include "bass.h"
|
||||
|
||||
// path to glade file
|
||||
#ifndef GLADE_PATH
|
||||
#define GLADE_PATH ""
|
||||
#endif
|
||||
|
||||
GladeXML *glade;
|
||||
GtkWidget *win = 0;
|
||||
GtkWidget *filesel;
|
||||
|
||||
// channel (sample/music) info structure
|
||||
typedef struct {
|
||||
DWORD channel; // the channel
|
||||
BASS_3DVECTOR pos, vel; // position,velocity
|
||||
} Channel;
|
||||
|
||||
Channel *chans = NULL; // the channels
|
||||
int chanc = 0, chan = -1; // number of channels, current channel
|
||||
|
||||
#define TIMERPERIOD 50 // timer period (ms)
|
||||
#define MAXDIST 50 // maximum distance of the channels (m)
|
||||
#define SPEED 12 // speed of the channels' movement (m/s)
|
||||
|
||||
// display error messages
|
||||
void Error(const char *es)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s\n(error code: %d)", es, BASS_ErrorGetCode());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
#define GetWidget(id) glade_xml_get_widget(glade,id)
|
||||
|
||||
void WindowDestroy(GtkObject *obj, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
// Update the button states
|
||||
void UpdateButtons()
|
||||
{
|
||||
gtk_widget_set_sensitive(GetWidget("remove"), chan == -1 ? FALSE : TRUE);
|
||||
gtk_widget_set_sensitive(GetWidget("play"), chan == -1 ? FALSE : TRUE);
|
||||
gtk_widget_set_sensitive(GetWidget("stop"), chan == -1 ? FALSE : TRUE);
|
||||
gtk_widget_set_sensitive(GetWidget("movex"), chan == -1 ? FALSE : TRUE);
|
||||
gtk_widget_set_sensitive(GetWidget("movez"), chan == -1 ? FALSE : TRUE);
|
||||
gtk_widget_set_sensitive(GetWidget("movereset"), chan == -1 ? FALSE : TRUE);
|
||||
if (chan != -1) {
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(GetWidget("movex")), fabs(chans[chan].vel.x));
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(GetWidget("movez")), fabs(chans[chan].vel.z));
|
||||
}
|
||||
}
|
||||
|
||||
gboolean ListSelectionChange(GtkTreeView *treeview, gpointer data)
|
||||
{ // the selected channel has (probably) changed
|
||||
GtkTreeSelection *ts;
|
||||
GtkTreeModel *tm;
|
||||
GtkTreeIter it;
|
||||
ts = gtk_tree_view_get_selection(GTK_TREE_VIEW(GetWidget("channels")));
|
||||
if (gtk_tree_selection_get_selected(ts, &tm, &it)) {
|
||||
char *rows = gtk_tree_model_get_string_from_iter(tm, &it);
|
||||
chan = atoi(rows);
|
||||
g_free(rows);
|
||||
} else
|
||||
chan = -1;
|
||||
UpdateButtons();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean FileExtensionFilter(const GtkFileFilterInfo *info, gpointer data)
|
||||
{
|
||||
return !regexec((regex_t*)data, info->filename, 0, NULL, 0);
|
||||
}
|
||||
|
||||
void AddClicked(GtkButton *obj, gpointer data)
|
||||
{ // add a channel
|
||||
int resp = gtk_dialog_run(GTK_DIALOG(filesel));
|
||||
gtk_widget_hide(filesel);
|
||||
if (resp == GTK_RESPONSE_ACCEPT) {
|
||||
char *file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel));
|
||||
DWORD newchan;
|
||||
// Load a music or sample from "file"
|
||||
if ((newchan = BASS_MusicLoad(FALSE, file, 0, 0, BASS_MUSIC_RAMP | BASS_SAMPLE_LOOP | BASS_SAMPLE_3D, 1))
|
||||
|| (newchan = BASS_SampleLoad(FALSE, file, 0, 0, 1, BASS_SAMPLE_LOOP | BASS_SAMPLE_3D | BASS_SAMPLE_MONO))) {
|
||||
Channel *c;
|
||||
chanc++;
|
||||
chans = (Channel*)realloc((void*)chans, chanc * sizeof(Channel));
|
||||
c = chans + chanc - 1;
|
||||
memset(c, 0, sizeof(Channel));
|
||||
c->channel = newchan;
|
||||
BASS_SampleGetChannel(newchan, FALSE); // initialize sample channel
|
||||
{ // add it to the list
|
||||
GtkTreeView *tree = GTK_TREE_VIEW(GetWidget("channels"));
|
||||
GtkListStore *tm = GTK_LIST_STORE(gtk_tree_view_get_model(tree));
|
||||
GtkTreeIter it;
|
||||
gtk_list_store_append(tm, &it);
|
||||
gtk_list_store_set(tm, &it, 0, strrchr(file, '/') + 1, -1);
|
||||
}
|
||||
} else
|
||||
Error("Can't load file (note samples must be mono)");
|
||||
g_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveClicked(GtkButton *obj, gpointer data)
|
||||
{ // remove a channel
|
||||
GtkTreeModel *tm = gtk_tree_view_get_model(GTK_TREE_VIEW(GetWidget("channels")));
|
||||
GtkTreeIter it;
|
||||
if (gtk_tree_model_iter_nth_child(tm, &it, NULL, chan)) {
|
||||
Channel *c = chans + chan;
|
||||
// free both MOD and stream, it must be one of them! :)
|
||||
BASS_SampleFree(c->channel);
|
||||
BASS_MusicFree(c->channel);
|
||||
chanc--;
|
||||
memmove(c, c + 1, (chanc - chan) * sizeof(Channel));
|
||||
gtk_list_store_remove(GTK_LIST_STORE(tm), &it);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
BASS_ChannelPlay(chans[chan].channel, FALSE);
|
||||
}
|
||||
|
||||
void StopClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
BASS_ChannelPause(chans[chan].channel);
|
||||
}
|
||||
|
||||
void MoveXChanged(GtkSpinButton *spinbutton, gpointer data)
|
||||
{ // X velocity
|
||||
float value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(GetWidget("movex")));
|
||||
if (fabs(chans[chan].vel.x) != value) chans[chan].vel.x = value;
|
||||
}
|
||||
|
||||
void MoveZChanged(GtkSpinButton *spinbutton, gpointer data)
|
||||
{ // Y velocity
|
||||
float value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(GetWidget("movez")));
|
||||
if (fabs(chans[chan].vel.z) != value) chans[chan].vel.z = value;
|
||||
}
|
||||
|
||||
void MoveResetClicked(GtkButton *obj, gpointer data)
|
||||
{ // reset the position and velocity to 0
|
||||
memset(&chans[chan].pos, 0, sizeof(chans[chan].pos));
|
||||
memset(&chans[chan].vel, 0, sizeof(chans[chan].vel));
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
void RolloffChanged(GtkRange *range, gpointer data)
|
||||
{
|
||||
// change the rolloff factor
|
||||
double value = gtk_range_get_value(range);
|
||||
BASS_Set3DFactors(-1, pow(2, (value - 10) / 5.0), -1);
|
||||
}
|
||||
|
||||
void DopplerChanged(GtkRange *range, gpointer data)
|
||||
{
|
||||
// change the doppler factor
|
||||
double value = gtk_range_get_value(range);
|
||||
BASS_Set3DFactors(-1, -1, pow(2, (value - 10) / 5.0));
|
||||
}
|
||||
|
||||
gboolean Update(gpointer data)
|
||||
{
|
||||
int c, x, y, cx, cy;
|
||||
GtkWidget *dc = GetWidget("drawingarea1");
|
||||
GdkGC *gc = dc->style->fg_gc[GTK_WIDGET_STATE(dc)];
|
||||
GdkGCValues gcsave;
|
||||
|
||||
gdk_gc_get_values(gc, &gcsave);
|
||||
|
||||
cx = dc->allocation.width / 2;
|
||||
cy = dc->allocation.height / 2;
|
||||
|
||||
{ // clear the display
|
||||
GdkColor c = { 0,0xffff,0xffff,0xffff };
|
||||
gdk_gc_set_rgb_fg_color(gc, &c);
|
||||
gdk_draw_rectangle(dc->window, gc, TRUE, 0, 0, dc->allocation.width, dc->allocation.height);
|
||||
}
|
||||
|
||||
{ // Draw the listener
|
||||
GdkColor c = { 0,0x8000,0x8000,0x8000 };
|
||||
gdk_gc_set_rgb_fg_color(gc, &c);
|
||||
gdk_draw_arc(dc->window, gc, TRUE, cx - 4, cy - 4, 8, 8, 0, 360 * 64);
|
||||
}
|
||||
|
||||
for (c = 0; c < chanc; c++) {
|
||||
// If the channel's playing then update it's position
|
||||
if (BASS_ChannelIsActive(chans[c].channel) == BASS_ACTIVE_PLAYING) {
|
||||
// Check if channel has reached the max distance
|
||||
if (chans[c].pos.z >= MAXDIST || chans[c].pos.z <= -MAXDIST)
|
||||
chans[c].vel.z = -chans[c].vel.z;
|
||||
if (chans[c].pos.x >= MAXDIST || chans[c].pos.x <= -MAXDIST)
|
||||
chans[c].vel.x = -chans[c].vel.x;
|
||||
// Update channel position
|
||||
chans[c].pos.z += chans[c].vel.z * TIMERPERIOD / 1000;
|
||||
chans[c].pos.x += chans[c].vel.x * TIMERPERIOD / 1000;
|
||||
BASS_ChannelSet3DPosition(chans[c].channel, &chans[c].pos, NULL, &chans[c].vel);
|
||||
}
|
||||
{ // Draw the channel position indicator
|
||||
static GdkColor cols[2] = { {0,0xffff,0xc000,0xc000},{0,0xffff,0,0} };
|
||||
gdk_gc_set_rgb_fg_color(gc, &cols[chan == c]);
|
||||
x = cx + (int)((cx - 10) * chans[c].pos.x / MAXDIST);
|
||||
y = cy - (int)((cy - 10) * chans[c].pos.z / MAXDIST);
|
||||
gdk_draw_arc(dc->window, gc, TRUE, x - 4, y - 4, 8, 8, 0, 360 * 64);
|
||||
}
|
||||
}
|
||||
// Apply the 3D changes
|
||||
BASS_Apply3D();
|
||||
|
||||
gdk_gc_set_values(gc, &gcsave, GDK_GC_FOREGROUND);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
regex_t fregex[2];
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
Error("An incorrect version of BASS was loaded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Initialize the output device with 3D support
|
||||
if (!BASS_Init(-1, 44100, BASS_DEVICE_3D, NULL, NULL)) {
|
||||
Error("Can't initialize device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
BASS_INFO i;
|
||||
BASS_GetInfo(&i);
|
||||
if (i.speakers > 2) {
|
||||
GtkWidget *dialog = gtk_message_dialog_new(NULL, 0,
|
||||
GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "Multiple speakers were detected. Would you like to use them?");
|
||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_NO)
|
||||
BASS_SetConfig(BASS_CONFIG_3DALGORITHM, BASS_3DALG_OFF);
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
// Use meters as distance unit, real world rolloff, real doppler effect
|
||||
BASS_Set3DFactors(1, 1, 1);
|
||||
|
||||
// initialize GUI
|
||||
glade = glade_xml_new(GLADE_PATH"3dtest.glade", NULL, NULL);
|
||||
if (!glade) return 0;
|
||||
win = GetWidget("window1");
|
||||
if (!win) return 0;
|
||||
glade_xml_signal_autoconnect(glade);
|
||||
g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(GetWidget("channels"))), "changed", G_CALLBACK(ListSelectionChange), NULL);
|
||||
|
||||
{ // setup list
|
||||
GtkTreeView *list = GTK_TREE_VIEW(GetWidget("channels"));
|
||||
GtkTreeViewColumn *col = gtk_tree_view_column_new();
|
||||
gtk_tree_view_append_column(list, col);
|
||||
GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
|
||||
gtk_tree_view_column_pack_start(col, renderer, TRUE);
|
||||
gtk_tree_view_column_add_attribute(col, renderer, "text", 0);
|
||||
GtkListStore *liststore = gtk_list_store_new(1, G_TYPE_STRING);
|
||||
gtk_tree_view_set_model(list, GTK_TREE_MODEL(liststore));
|
||||
g_object_unref(liststore);
|
||||
}
|
||||
|
||||
{ // initialize file selector
|
||||
GtkFileFilter *filter;
|
||||
filesel = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "Streamable files (wav/aif/mp3/mp2/mp1/ogg)");
|
||||
regcomp(&fregex[0], "\\.(mp[1-3]|ogg|wav|aif)$", REG_ICASE | REG_NOSUB | REG_EXTENDED);
|
||||
gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, FileExtensionFilter, &fregex[0], NULL);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "MOD music files (mo3/xm/mod/s3m/it/mtm/umx)");
|
||||
regcomp(&fregex[1], "\\.(mo3|xm|mod|s3m|it|umx)$", REG_ICASE | REG_NOSUB | REG_EXTENDED);
|
||||
gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, FileExtensionFilter, &fregex[1], NULL);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "All files");
|
||||
gtk_file_filter_add_pattern(filter, "*");
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
}
|
||||
|
||||
g_timeout_add(TIMERPERIOD, Update, NULL);
|
||||
|
||||
UpdateButtons();
|
||||
|
||||
gtk_main();
|
||||
|
||||
gtk_widget_destroy(filesel);
|
||||
regfree(&fregex[0]);
|
||||
regfree(&fregex[1]);
|
||||
|
||||
BASS_Free(); // close output
|
||||
|
||||
return 0;
|
||||
}
|
334
bass-sys/linux/bass24/3dtest/3dtest.glade
Normal file
334
bass-sys/linux/bass24/3dtest/3dtest.glade
Normal file
|
@ -0,0 +1,334 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<glade-interface>
|
||||
<widget class="GtkWindow" id="window1">
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">BASS - 3D test</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">GTK_WIN_POS_CENTER</property>
|
||||
<signal name="destroy" handler="WindowDestroy"/>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="bottom_padding">5</property>
|
||||
<property name="left_padding">5</property>
|
||||
<property name="right_padding">5</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="channels">
|
||||
<property name="height_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<property name="headers_clickable">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="add">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Add...</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="AddClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="remove">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Remove</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="RemoveClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="play">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Play</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="PlayClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="stop">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Stop</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="StopClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Channels</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment2">
|
||||
<property name="visible">True</property>
|
||||
<property name="bottom_padding">5</property>
|
||||
<property name="left_padding">5</property>
|
||||
<property name="right_padding">5</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">x:</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSpinButton" id="movex">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">0 0 100 1 10 0</property>
|
||||
<property name="numeric">True</property>
|
||||
<signal name="value_changed" handler="MoveXChanged"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label7">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">z:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSpinButton" id="movez">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">0 0 100 1 10 0</property>
|
||||
<property name="numeric">True</property>
|
||||
<signal name="value_changed" handler="MoveZChanged"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="movereset">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Reset</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="MoveResetClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Movement</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment5">
|
||||
<property name="visible">True</property>
|
||||
<property name="bottom_padding">5</property>
|
||||
<property name="left_padding">5</property>
|
||||
<property name="right_padding">5</property>
|
||||
<child>
|
||||
<widget class="GtkDrawingArea" id="drawingarea1">
|
||||
<property name="width_request">200</property>
|
||||
<property name="height_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label6">
|
||||
<property name="visible">True</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment3">
|
||||
<property name="visible">True</property>
|
||||
<property name="bottom_padding">5</property>
|
||||
<property name="left_padding">5</property>
|
||||
<property name="right_padding">5</property>
|
||||
<child>
|
||||
<widget class="GtkHScale" id="rolloff">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">10 0 20 1 10 0</property>
|
||||
<property name="draw_value">False</property>
|
||||
<signal name="value_changed" handler="RolloffChanged"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Rolloff factor</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment4">
|
||||
<property name="visible">True</property>
|
||||
<property name="bottom_padding">5</property>
|
||||
<property name="left_padding">5</property>
|
||||
<property name="right_padding">5</property>
|
||||
<child>
|
||||
<widget class="GtkHScale" id="doppler">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">10 0 20 1 10 0</property>
|
||||
<property name="draw_value">False</property>
|
||||
<signal name="value_changed" handler="DopplerChanged"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Doppler factor</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
9
bass-sys/linux/bass24/3dtest/makefile
Normal file
9
bass-sys/linux/bass24/3dtest/makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
TARGET = 3dtest
|
||||
PACKAGES = gtk+-2.0 libglade-2.0
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
294
bass-sys/linux/bass24/basstest/basstest.c
Normal file
294
bass-sys/linux/bass24/basstest/basstest.c
Normal file
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
BASS simple playback test
|
||||
Copyright (c) 1999-2012 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glade/glade.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
#include "bass.h"
|
||||
|
||||
// path to glade file
|
||||
#ifndef GLADE_PATH
|
||||
#define GLADE_PATH ""
|
||||
#endif
|
||||
|
||||
GladeXML *glade;
|
||||
GtkWidget *win = 0;
|
||||
GtkWidget *filesel;
|
||||
|
||||
// display error messages
|
||||
void Error(const char *es)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s\n(error code: %d)", es, BASS_ErrorGetCode());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
#define GetWidget(id) glade_xml_get_widget(glade,id)
|
||||
|
||||
void AddListEntry(const char *list, DWORD handle, const char *text)
|
||||
{
|
||||
GtkTreeView *tree = GTK_TREE_VIEW(GetWidget(list));
|
||||
GtkListStore *tm = GTK_LIST_STORE(gtk_tree_view_get_model(tree));
|
||||
GtkTreeIter it;
|
||||
gtk_list_store_append(tm, &it);
|
||||
gtk_list_store_set(tm, &it, 0, text, 1, handle, -1);
|
||||
}
|
||||
|
||||
DWORD GetSelectedHandle(int mode)
|
||||
{
|
||||
DWORD handle;
|
||||
char list[10];
|
||||
GtkTreeSelection *ts;
|
||||
GtkTreeModel *tm;
|
||||
GtkTreeIter it;
|
||||
sprintf(list, "list%d", mode);
|
||||
ts = gtk_tree_view_get_selection(GTK_TREE_VIEW(GetWidget(list)));
|
||||
if (!gtk_tree_selection_get_selected(ts, &tm, &it)) return 0;
|
||||
gtk_tree_model_get(tm, &it, 1, &handle, -1);
|
||||
return handle;
|
||||
}
|
||||
|
||||
void WindowDestroy(GtkObject *obj, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
gboolean FileExtensionFilter(const GtkFileFilterInfo *info, gpointer data)
|
||||
{
|
||||
return !regexec((regex_t*)data, info->filename, 0, NULL, 0);
|
||||
}
|
||||
|
||||
void AddClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
int resp = gtk_dialog_run(GTK_DIALOG(filesel));
|
||||
gtk_widget_hide(filesel);
|
||||
if (resp == GTK_RESPONSE_ACCEPT) {
|
||||
char *file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel));
|
||||
const gchar *objname = gtk_widget_get_name(GTK_WIDGET(obj));
|
||||
int mode = atoi(objname + 3); // get mode from button name ("addX")
|
||||
switch (mode) {
|
||||
case 1: // add a stream
|
||||
{
|
||||
HSTREAM handle;
|
||||
if (handle = BASS_StreamCreateFile(FALSE, file, 0, 0, 0))
|
||||
AddListEntry("list1", handle, strrchr(file, '/') + 1);
|
||||
else
|
||||
Error("Can't open stream");
|
||||
}
|
||||
break;
|
||||
case 2: // add a music
|
||||
{
|
||||
HMUSIC handle;
|
||||
if (handle = BASS_MusicLoad(FALSE, file, 0, 0, BASS_MUSIC_RAMP, 1))
|
||||
AddListEntry("list2", handle, strrchr(file, '/') + 1);
|
||||
else
|
||||
Error("Can't load music");
|
||||
}
|
||||
break;
|
||||
case 3: // add a sample
|
||||
{
|
||||
HSAMPLE sam;
|
||||
/* load a sample from "file" and give it a max of 3 simultaneous
|
||||
playings using playback position as override decider */
|
||||
if (sam = BASS_SampleLoad(FALSE, file, 0, 0, 3, BASS_SAMPLE_OVER_POS))
|
||||
AddListEntry("list3", sam, strrchr(file, '/') + 1);
|
||||
else
|
||||
Error("Can't load sample");
|
||||
}
|
||||
break;
|
||||
}
|
||||
g_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
const gchar *objname = gtk_widget_get_name(GTK_WIDGET(obj));
|
||||
int mode = atoi(objname + 6); // get mode from button name ("removeX")
|
||||
char list[10];
|
||||
sprintf(list, "list%d", mode); // associated list name
|
||||
GtkTreeView *tree = GTK_TREE_VIEW(GetWidget(list));
|
||||
GtkTreeSelection *ts = gtk_tree_view_get_selection(tree);
|
||||
GtkTreeModel *tm;
|
||||
GtkTreeIter it;
|
||||
if (gtk_tree_selection_get_selected(ts, &tm, &it)) {
|
||||
DWORD handle;
|
||||
gtk_tree_model_get(tm, &it, 1, &handle, -1);
|
||||
switch (mode) {
|
||||
case 1:
|
||||
BASS_StreamFree(handle); // free stream
|
||||
break;
|
||||
case 2:
|
||||
BASS_MusicFree(handle); // free MOD music
|
||||
break;
|
||||
case 3:
|
||||
BASS_SampleFree(handle); // free sample
|
||||
break;
|
||||
}
|
||||
gtk_list_store_remove(GTK_LIST_STORE(tm), &it); // remove list entry
|
||||
}
|
||||
}
|
||||
|
||||
void PlayClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
DWORD handle;
|
||||
const gchar *objname = gtk_widget_get_name(GTK_WIDGET(obj));
|
||||
int mode = atoi(objname + 4); // get mode from button name ("playX")
|
||||
handle = GetSelectedHandle(mode); // get selected stream/music/sample handle
|
||||
if (mode == 3) { // sample: get a channel and set volume=50% and pan=random
|
||||
handle = BASS_SampleGetChannel(handle, FALSE);
|
||||
BASS_ChannelSetAttribute(handle, BASS_ATTRIB_VOL, 0.5f);
|
||||
BASS_ChannelSetAttribute(handle, BASS_ATTRIB_PAN, ((rand() % 201) - 100) / 100.f);
|
||||
}
|
||||
if (!BASS_ChannelPlay(handle, FALSE)) // play it
|
||||
Error("Can't play channel");
|
||||
}
|
||||
|
||||
void StopClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
DWORD handle;
|
||||
const gchar *objname = gtk_widget_get_name(GTK_WIDGET(obj));
|
||||
int mode = atoi(objname + 4); // get mode from button name ("playX")
|
||||
handle = GetSelectedHandle(mode); // get selected stream/music/sample handle
|
||||
BASS_ChannelStop(handle); // stop it
|
||||
}
|
||||
|
||||
void RestartClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
DWORD handle;
|
||||
const gchar *objname = gtk_widget_get_name(GTK_WIDGET(obj));
|
||||
int mode = atoi(objname + 7); // get mode from button name ("restartX")
|
||||
handle = GetSelectedHandle(mode); // get selected stream/music/sample handle
|
||||
if (!BASS_ChannelPlay(handle, TRUE)) // restart it
|
||||
Error("Can't play channel");
|
||||
}
|
||||
|
||||
void GVolumeChanged(GtkRange *range, gpointer data)
|
||||
{
|
||||
const gchar *objname = gtk_widget_get_name(GTK_WIDGET(range));
|
||||
int mode = atoi(objname + 7); // get mode from name ("gvolumeX")
|
||||
double value = gtk_range_get_value(range);
|
||||
switch (mode) {
|
||||
case 1:
|
||||
BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, value * 100); // global stream volume (0-10000)
|
||||
break;
|
||||
case 2:
|
||||
BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, value * 100); // global MOD volume (0-10000)
|
||||
break;
|
||||
case 3:
|
||||
BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, value * 100); // global sample volume (0-10000)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VolumeChanged(GtkRange *range, gpointer data)
|
||||
{
|
||||
double value = gtk_range_get_value(range);
|
||||
BASS_SetVolume(value / 100.f); // output volume (0-1)
|
||||
}
|
||||
|
||||
void StopAllClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
BASS_Pause(); // pause output
|
||||
}
|
||||
|
||||
void ResumeAllClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
BASS_Start(); // resume output
|
||||
}
|
||||
|
||||
void ThreadsToggled(GtkToggleButton *obj, gpointer data)
|
||||
{
|
||||
BASS_SetConfig(BASS_CONFIG_UPDATETHREADS, obj->active ? 2 : 1); // set 1 or 2 update threads
|
||||
}
|
||||
|
||||
gboolean TimerProc(gpointer data)
|
||||
{ // update the CPU usage % display
|
||||
char text[16];
|
||||
sprintf(text, "CPU%% %.2f", BASS_GetCPU());
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("cpu")), text);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
regex_t fregex[2];
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
Error("An incorrect version of BASS was loaded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize default output device
|
||||
if (!BASS_Init(-1, 44100, 0, NULL, NULL)) {
|
||||
Error("Can't initialize device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize GUI
|
||||
glade = glade_xml_new(GLADE_PATH"basstest.glade", NULL, NULL);
|
||||
if (!glade) return 0;
|
||||
win = GetWidget("window1");
|
||||
if (!win) return 0;
|
||||
glade_xml_signal_autoconnect(glade);
|
||||
|
||||
{ // setup lists
|
||||
int a;
|
||||
for (a = 1; a <= 3; a++) {
|
||||
char name[8];
|
||||
sprintf(name, "list%d", a);
|
||||
GtkTreeView *list = GTK_TREE_VIEW(GetWidget(name));
|
||||
GtkTreeViewColumn *col = gtk_tree_view_column_new();
|
||||
gtk_tree_view_append_column(list, col);
|
||||
GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
|
||||
gtk_tree_view_column_pack_start(col, renderer, TRUE);
|
||||
gtk_tree_view_column_add_attribute(col, renderer, "text", 0);
|
||||
GtkListStore *liststore = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
|
||||
gtk_tree_view_set_model(list, GTK_TREE_MODEL(liststore));
|
||||
g_object_unref(liststore);
|
||||
}
|
||||
}
|
||||
|
||||
// initialize volume slider
|
||||
gtk_range_set_value(GTK_RANGE(GetWidget("volume")), BASS_GetVolume() * 100);
|
||||
|
||||
{ // initialize file selector
|
||||
GtkFileFilter *filter;
|
||||
filesel = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "Streamable files (wav/aif/mp3/mp2/mp1/ogg)");
|
||||
regcomp(&fregex[0], "\\.(mp[1-3]|ogg|wav|aif)$", REG_ICASE | REG_NOSUB | REG_EXTENDED);
|
||||
gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, FileExtensionFilter, &fregex[0], NULL);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "MOD music files (mo3/xm/mod/s3m/it/mtm/umx)");
|
||||
regcomp(&fregex[1], "\\.(mo3|xm|mod|s3m|it|umx)$", REG_ICASE | REG_NOSUB | REG_EXTENDED);
|
||||
gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, FileExtensionFilter, &fregex[1], NULL);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "All files");
|
||||
gtk_file_filter_add_pattern(filter, "*");
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
}
|
||||
|
||||
g_timeout_add(500, TimerProc, NULL);
|
||||
|
||||
gtk_main();
|
||||
|
||||
gtk_widget_destroy(filesel);
|
||||
regfree(&fregex[0]);
|
||||
regfree(&fregex[1]);
|
||||
|
||||
BASS_Free(); // close output
|
||||
|
||||
return 0;
|
||||
}
|
580
bass-sys/linux/bass24/basstest/basstest.glade
Normal file
580
bass-sys/linux/bass24/basstest/basstest.glade
Normal file
|
@ -0,0 +1,580 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<glade-interface>
|
||||
<widget class="GtkWindow" id="window1">
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">BASS - simple playback test</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">GTK_WIN_POS_CENTER</property>
|
||||
<signal name="destroy" handler="WindowDestroy"/>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="bottom_padding">5</property>
|
||||
<property name="left_padding">5</property>
|
||||
<property name="right_padding">5</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="list1">
|
||||
<property name="height_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<property name="headers_clickable">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="play1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Play</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="PlayClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="stop1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Stop</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="StopClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="restart1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Restart</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="RestartClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="add1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Add..</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="AddClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="remove1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Remove</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="RemoveClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox3">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">global volume:</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHScale" id="gvolume1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">100 0 100 1 10 0</property>
|
||||
<property name="draw_value">False</property>
|
||||
<signal name="value_changed" handler="GVolumeChanged"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Stream</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment2">
|
||||
<property name="visible">True</property>
|
||||
<property name="bottom_padding">5</property>
|
||||
<property name="left_padding">5</property>
|
||||
<property name="right_padding">5</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="list2">
|
||||
<property name="height_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<property name="headers_clickable">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="play2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Play</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="PlayClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="stop2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Stop</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="StopClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="restart2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Restart</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="RestartClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox5">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="add2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Add..</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="AddClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="remove2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Remove</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="RemoveClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox5">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">global volume:</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHScale" id="gvolume2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">100 0 100 1 10 0</property>
|
||||
<property name="draw_value">False</property>
|
||||
<signal name="value_changed" handler="GVolumeChanged"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">MOD Music</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment3">
|
||||
<property name="visible">True</property>
|
||||
<property name="bottom_padding">5</property>
|
||||
<property name="left_padding">5</property>
|
||||
<property name="right_padding">5</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox6">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="list3">
|
||||
<property name="height_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<property name="headers_clickable">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox6">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="play3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Play</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="PlayClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox7">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="add3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Add..</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="AddClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="remove3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Remove</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="RemoveClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox7">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label5">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">global volume:</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHScale" id="gvolume3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">100 0 100 1 10 0</property>
|
||||
<property name="draw_value">False</property>
|
||||
<signal name="value_changed" handler="GVolumeChanged"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label6">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Sample</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox8">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox9">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="stop">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Stop Output</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="StopAllClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="resume">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Resume</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="ResumeAllClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox9">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label7">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">volume:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHScale" id="volume">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">0 0 100 1 10 0</property>
|
||||
<property name="draw_value">False</property>
|
||||
<signal name="value_changed" handler="VolumeChanged"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox10">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="threads">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">2 update threads</property>
|
||||
<property name="response_id">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="ThreadsToggled"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="cpu">
|
||||
<property name="visible">True</property>
|
||||
<property name="wrap_mode">PANGO_WRAP_WORD_CHAR</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_END</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
9
bass-sys/linux/bass24/basstest/makefile
Normal file
9
bass-sys/linux/bass24/basstest/makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
TARGET = basstest
|
||||
PACKAGES = gtk+-2.0 libglade-2.0
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
8
bass-sys/linux/bass24/contest/makefile
Normal file
8
bass-sys/linux/bass24/contest/makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
TARGET = contest
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
271
bass-sys/linux/bass24/custloop/custloop.c
Normal file
271
bass-sys/linux/bass24/custloop/custloop.c
Normal file
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
BASS custom looping example
|
||||
Copyright (c) 2004-2014 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib/gthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
#include <math.h>
|
||||
#include "bass.h"
|
||||
|
||||
#define WIDTH 600 // display width
|
||||
#define HEIGHT 201 // height (odd number for centre line)
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
BYTE rgbRed, rgbGreen, rgbBlue;
|
||||
} RGB;
|
||||
#pragma pack()
|
||||
|
||||
GtkWidget *win = 0;
|
||||
GThread *scanthread = 0;
|
||||
BOOL killscan = FALSE;
|
||||
|
||||
DWORD chan;
|
||||
DWORD bpp; // bytes per pixel
|
||||
QWORD loop[2] = { 0 }; // loop start & end
|
||||
HSYNC lsync; // looping sync
|
||||
|
||||
GtkWidget *waveda;
|
||||
GdkPixbuf *wavepb;
|
||||
RGB palette[HEIGHT / 2 + 1];
|
||||
|
||||
// display error messages
|
||||
void Error(const char *es)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s\n(error code: %d)", es, BASS_ErrorGetCode());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
void WindowDestroy(GtkObject *obj, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
void CALLBACK LoopSyncProc(HSYNC handle, DWORD channel, DWORD data, void *user)
|
||||
{
|
||||
if (!BASS_ChannelSetPosition(channel, loop[0], BASS_POS_BYTE)) // try seeking to loop start
|
||||
BASS_ChannelSetPosition(channel, 0, BASS_POS_BYTE); // failed, go to start of file instead
|
||||
}
|
||||
|
||||
void SetLoopStart(QWORD pos)
|
||||
{
|
||||
loop[0] = pos;
|
||||
}
|
||||
|
||||
void SetLoopEnd(QWORD pos)
|
||||
{
|
||||
loop[1] = pos;
|
||||
BASS_ChannelRemoveSync(chan, lsync); // remove old sync
|
||||
lsync = BASS_ChannelSetSync(chan, BASS_SYNC_POS | BASS_SYNC_MIXTIME, loop[1], LoopSyncProc, 0); // set new sync
|
||||
}
|
||||
|
||||
// scan the peaks
|
||||
void *ScanPeaks(void *p)
|
||||
{
|
||||
DWORD decoder = (uintptr_t)p;
|
||||
RGB *wavebuf = (RGB*)gdk_pixbuf_get_pixels(wavepb);
|
||||
DWORD pos = 0;
|
||||
float spp = BASS_ChannelBytes2Seconds(decoder, bpp); // seconds per pixel
|
||||
while (!killscan) {
|
||||
float peak[2];
|
||||
if (spp > 1) { // more than 1 second per pixel, break it down...
|
||||
float todo = spp;
|
||||
peak[1] = peak[0] = 0;
|
||||
do {
|
||||
float level[2], step = (todo < 1 ? todo : 1);
|
||||
BASS_ChannelGetLevelEx(decoder, level, step, BASS_LEVEL_STEREO); // scan peaks
|
||||
if (peak[0] < level[0]) peak[0] = level[0];
|
||||
if (peak[1] < level[1]) peak[1] = level[1];
|
||||
todo -= step;
|
||||
} while (todo > 0);
|
||||
} else
|
||||
BASS_ChannelGetLevelEx(decoder, peak, spp, BASS_LEVEL_STEREO); // scan peaks
|
||||
{
|
||||
DWORD a;
|
||||
for (a = 0; a < peak[0] * (HEIGHT / 2); a++)
|
||||
wavebuf[(HEIGHT / 2 - 1 - a) * WIDTH + pos] = palette[1 + a]; // draw left peak
|
||||
for (a = 0; a < peak[1] * (HEIGHT / 2); a++)
|
||||
wavebuf[(HEIGHT / 2 + 1 + a) * WIDTH + pos] = palette[1 + a]; // draw right peak
|
||||
}
|
||||
pos++;
|
||||
if (pos >= WIDTH) break; // reached end of display
|
||||
if (!BASS_ChannelIsActive(decoder)) break; // reached end of channel
|
||||
}
|
||||
if (!killscan) {
|
||||
DWORD size;
|
||||
BASS_ChannelSetPosition(decoder, (QWORD)-1, BASS_POS_BYTE | BASS_POS_SCAN); // build seek table (scan to end)
|
||||
size = BASS_ChannelGetAttributeEx(decoder, BASS_ATTRIB_SCANINFO, 0, 0); // get seek table size
|
||||
if (size) { // got it
|
||||
void *info = malloc(size); // allocate a buffer
|
||||
BASS_ChannelGetAttributeEx(decoder, BASS_ATTRIB_SCANINFO, info, size); // get the seek table
|
||||
BASS_ChannelSetAttributeEx(chan, BASS_ATTRIB_SCANINFO, info, size); // apply it to the playback channel
|
||||
free(info);
|
||||
}
|
||||
}
|
||||
BASS_StreamFree(decoder); // free the decoder
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean FileExtensionFilter(const GtkFileFilterInfo *info, gpointer data)
|
||||
{
|
||||
return !regexec((regex_t*)data, info->filename, 0, NULL, 0);
|
||||
}
|
||||
|
||||
// select a file to play, and start scanning it
|
||||
BOOL PlayFile()
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
regex_t fregex;
|
||||
GtkWidget *filesel; // file selector
|
||||
GtkFileFilter *filter;
|
||||
filesel = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "Playable files");
|
||||
regcomp(&fregex, "\\.(mo3|xm|mod|s3m|it|umx|mp[1-3]|ogg|wav|aif)$", REG_ICASE | REG_NOSUB | REG_EXTENDED);
|
||||
gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, FileExtensionFilter, &fregex, NULL);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "All files");
|
||||
gtk_file_filter_add_pattern(filter, "*");
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
if (gtk_dialog_run(GTK_DIALOG(filesel)) == GTK_RESPONSE_ACCEPT) {
|
||||
char *file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel));
|
||||
gtk_widget_hide(filesel);
|
||||
if (!(chan = BASS_StreamCreateFile(FALSE, file, 0, 0, 0))
|
||||
&& !(chan = BASS_MusicLoad(FALSE, file, 0, 0, BASS_MUSIC_RAMP | BASS_MUSIC_POSRESET | BASS_MUSIC_PRESCAN, 1))) {
|
||||
Error("Can't play file");
|
||||
} else {
|
||||
// create the bitmap
|
||||
wavepb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, WIDTH, HEIGHT);
|
||||
{ // setup palette
|
||||
RGB *pal = (RGB*)palette;
|
||||
int a;
|
||||
memset(palette, 0, sizeof(palette));
|
||||
for (a = 1; a <= HEIGHT / 2; a++) {
|
||||
pal[a].rgbRed = (255 * a) / (HEIGHT / 2);
|
||||
pal[a].rgbGreen = 255 - pal[a].rgbRed;
|
||||
}
|
||||
}
|
||||
bpp = BASS_ChannelGetLength(chan, BASS_POS_BYTE) / WIDTH; // bytes per pixel
|
||||
{
|
||||
DWORD bpp1 = BASS_ChannelSeconds2Bytes(chan, 0.001); // minimum 1ms per pixel
|
||||
if (bpp < bpp1) bpp = bpp1;
|
||||
}
|
||||
BASS_ChannelSetSync(chan, BASS_SYNC_END | BASS_SYNC_MIXTIME, 0, LoopSyncProc, 0); // set sync to loop at end
|
||||
BASS_ChannelPlay(chan, FALSE); // start playing
|
||||
{ // create another channel to scan
|
||||
DWORD chan2 = BASS_StreamCreateFile(FALSE, file, 0, 0, BASS_STREAM_DECODE);
|
||||
if (!chan2) chan2 = BASS_MusicLoad(FALSE, file, 0, 0, BASS_MUSIC_DECODE, 1);
|
||||
#if GLIB_CHECK_VERSION(2,32,0)
|
||||
scanthread = g_thread_new(NULL, ScanPeaks, (void*)(uintptr_t)chan2); // start scanning in a new thread
|
||||
#else
|
||||
scanthread = g_thread_create(ScanPeaks, (void*)(uintptr_t)chan2, TRUE, NULL); // start scanning in a new thread
|
||||
#endif
|
||||
}
|
||||
ret = TRUE;
|
||||
}
|
||||
g_free(file);
|
||||
}
|
||||
gtk_widget_destroy(filesel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WindowButtonRelease(GtkWidget *obj, GdkEventButton *event, gpointer data)
|
||||
{
|
||||
if (event->type == GDK_BUTTON_RELEASE) {
|
||||
if (event->button == 1) // set loop start
|
||||
SetLoopStart(event->x * bpp);
|
||||
else if (event->button == 3) // set loop end
|
||||
SetLoopEnd(event->x * bpp);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTimeLine(QWORD pos, DWORD col, DWORD y)
|
||||
{
|
||||
GdkGC *gc = waveda->style->fg_gc[GTK_WIDGET_STATE(waveda)];
|
||||
DWORD wpos = pos / bpp;
|
||||
GdkColor c = { 0,(col & 0xff) << 8,col & 0xff00,(col >> 8) & 0xff00 };
|
||||
gdk_gc_set_rgb_fg_color(gc, &c);
|
||||
gdk_draw_line(waveda->window, gc, wpos, 0, wpos, HEIGHT);
|
||||
}
|
||||
|
||||
gboolean AreaExpose(GtkWidget *widget, GdkEventExpose *event, gpointer user)
|
||||
{
|
||||
GdkGC *gc = widget->style->fg_gc[GTK_WIDGET_STATE(waveda)];
|
||||
GdkGCValues gcsave;
|
||||
gdk_gc_get_values(gc, &gcsave);
|
||||
gdk_draw_pixbuf(widget->window, gc, wavepb, 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
|
||||
DrawTimeLine(loop[0], 0xffff00, 12); // loop start
|
||||
DrawTimeLine(loop[1], 0x00ffff, 24); // loop end
|
||||
DrawTimeLine(BASS_ChannelGetPosition(chan, BASS_POS_BYTE), 0xffffff, 0); // current pos
|
||||
gdk_gc_set_values(gc, &gcsave, GDK_GC_FOREGROUND);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean TimerProc(gpointer data)
|
||||
{
|
||||
// refresh window
|
||||
gtk_widget_queue_draw(waveda);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
#if !GLIB_CHECK_VERSION(2,32,0)
|
||||
g_thread_init(NULL);
|
||||
#endif
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
Error("An incorrect version of BASS was loaded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize BASS
|
||||
if (!BASS_Init(-1, 44100, 0, win, NULL)) {
|
||||
Error("Can't initialize device");
|
||||
return 0;
|
||||
}
|
||||
if (!PlayFile()) { // start a file playing
|
||||
BASS_Free();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// create the window
|
||||
win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER);
|
||||
gtk_window_set_resizable(GTK_WINDOW(win), FALSE);
|
||||
gtk_window_set_title(GTK_WINDOW(win), "BASS custom looping example (left-click to set loop start, right-click to set end)");
|
||||
g_signal_connect(win, "destroy", GTK_SIGNAL_FUNC(WindowDestroy), NULL);
|
||||
|
||||
GtkWidget *ebox = gtk_event_box_new();
|
||||
gtk_container_add(GTK_CONTAINER(win), ebox);
|
||||
g_signal_connect(ebox, "button-release-event", GTK_SIGNAL_FUNC(WindowButtonRelease), NULL);
|
||||
|
||||
waveda = gtk_drawing_area_new();
|
||||
gtk_widget_set_size_request(waveda, WIDTH, HEIGHT);
|
||||
gtk_container_add(GTK_CONTAINER(ebox), waveda);
|
||||
g_signal_connect(waveda, "expose-event", GTK_SIGNAL_FUNC(AreaExpose), NULL);
|
||||
|
||||
// setup update timer (10hz)
|
||||
g_timeout_add(100, TimerProc, NULL);
|
||||
|
||||
gtk_widget_show_all(win);
|
||||
gtk_main();
|
||||
|
||||
killscan = TRUE;
|
||||
g_thread_join(scanthread); // wait for the scan thread
|
||||
|
||||
g_object_unref(wavepb);
|
||||
|
||||
BASS_Free();
|
||||
return 0;
|
||||
}
|
9
bass-sys/linux/bass24/custloop/makefile
Normal file
9
bass-sys/linux/bass24/custloop/makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
TARGET = custloop
|
||||
PACKAGES = gtk+-2.0 gthread-2.0
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
8
bass-sys/linux/bass24/devlist/makefile
Normal file
8
bass-sys/linux/bass24/devlist/makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
TARGET = devlist
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
250
bass-sys/linux/bass24/dsptest/dsptest.c
Normal file
250
bass-sys/linux/bass24/dsptest/dsptest.c
Normal file
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
BASS simple DSP test
|
||||
Copyright (c) 2000-2017 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glade/glade.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
#include <math.h>
|
||||
#include "bass.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
// path to glade file
|
||||
#ifndef GLADE_PATH
|
||||
#define GLADE_PATH ""
|
||||
#endif
|
||||
|
||||
GladeXML *glade;
|
||||
GtkWidget *win = 0;
|
||||
GtkWidget *filesel;
|
||||
|
||||
DWORD chan; // the channel... HMUSIC or HSTREAM
|
||||
|
||||
// display error messages
|
||||
void Error(const char *es)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s\n(error code: %d)", es, BASS_ErrorGetCode());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
// "rotate"
|
||||
HDSP rotdsp = 0; // DSP handle
|
||||
float rotpos; // cur.pos
|
||||
void CALLBACK Rotate(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user)
|
||||
{
|
||||
float *d = (float*)buffer;
|
||||
DWORD a;
|
||||
|
||||
for (a = 0; a < length / 4; a += 2) {
|
||||
d[a] *= fabs(sin(rotpos));
|
||||
d[a + 1] *= fabs(cos(rotpos));
|
||||
rotpos += 0.00003;
|
||||
}
|
||||
rotpos = fmod(rotpos, 2 * M_PI);
|
||||
}
|
||||
|
||||
// "echo"
|
||||
HDSP echdsp = 0; // DSP handle
|
||||
#define ECHBUFLEN 1200 // buffer length
|
||||
float echbuf[ECHBUFLEN][2]; // buffer
|
||||
int echpos; // cur.pos
|
||||
void CALLBACK Echo(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user)
|
||||
{
|
||||
float *d = (float*)buffer;
|
||||
DWORD a;
|
||||
|
||||
for (a = 0; a < length / 4; a += 2) {
|
||||
float l = d[a] + (echbuf[echpos][1] / 2);
|
||||
float r = d[a + 1] + (echbuf[echpos][0] / 2);
|
||||
#if 1 // 0=echo, 1=basic "bathroom" reverb
|
||||
echbuf[echpos][0] = d[a] = l;
|
||||
echbuf[echpos][1] = d[a + 1] = r;
|
||||
#else
|
||||
echbuf[echpos][0] = d[a];
|
||||
echbuf[echpos][1] = d[a + 1];
|
||||
d[a] = l;
|
||||
d[a + 1] = r;
|
||||
#endif
|
||||
echpos++;
|
||||
if (echpos == ECHBUFLEN) echpos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// "flanger"
|
||||
HDSP fladsp = 0; // DSP handle
|
||||
#define FLABUFLEN 350 // buffer length
|
||||
float flabuf[FLABUFLEN][2]; // buffer
|
||||
int flapos; // cur.pos
|
||||
float flas, flasinc; // sweep pos/increment
|
||||
void CALLBACK Flange(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user)
|
||||
{
|
||||
float *d = (float*)buffer;
|
||||
DWORD a;
|
||||
|
||||
for (a = 0; a < length / 4; a += 2) {
|
||||
int p1 = (flapos + (int)flas) % FLABUFLEN;
|
||||
int p2 = (p1 + 1) % FLABUFLEN;
|
||||
float f = flas - (int)flas;
|
||||
float s;
|
||||
|
||||
s = (d[a] + ((flabuf[p1][0] * (1 - f)) + (flabuf[p2][0] * f))) * 0.7;
|
||||
flabuf[flapos][0] = d[a];
|
||||
d[a] = s;
|
||||
|
||||
s = (d[a + 1] + ((flabuf[p1][1] * (1 - f)) + (flabuf[p2][1] * f))) * 0.7;
|
||||
flabuf[flapos][1] = d[a + 1];
|
||||
d[a + 1] = s;
|
||||
|
||||
flapos++;
|
||||
if (flapos == FLABUFLEN) flapos = 0;
|
||||
flas += flasinc;
|
||||
if (flas<0 || flas>FLABUFLEN - 1) {
|
||||
flasinc = -flasinc;
|
||||
flas += flasinc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define GetWidget(id) glade_xml_get_widget(glade,id)
|
||||
|
||||
void WindowDestroy(GtkObject *obj, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
void RotateToggled(GtkToggleButton *obj, gpointer data)
|
||||
{ // toggle "rotate"
|
||||
if (obj->active) {
|
||||
rotpos = M_PI / 4;
|
||||
rotdsp = BASS_ChannelSetDSP(chan, &Rotate, 0, 2);
|
||||
} else
|
||||
BASS_ChannelRemoveDSP(chan, rotdsp);
|
||||
}
|
||||
|
||||
void EchoToggled(GtkToggleButton *obj, gpointer data)
|
||||
{ // toggle "echo"
|
||||
if (obj->active) {
|
||||
memset(echbuf, 0, sizeof(echbuf));
|
||||
echpos = 0;
|
||||
echdsp = BASS_ChannelSetDSP(chan, &Echo, 0, 1);
|
||||
} else
|
||||
BASS_ChannelRemoveDSP(chan, echdsp);
|
||||
}
|
||||
|
||||
void FlangerToggled(GtkToggleButton *obj, gpointer data)
|
||||
{ // toggle "flanger"
|
||||
if (obj->active) {
|
||||
memset(flabuf, 0, sizeof(flabuf));
|
||||
flapos = 0;
|
||||
flas = FLABUFLEN / 2;
|
||||
flasinc = 0.002f;
|
||||
fladsp = BASS_ChannelSetDSP(chan, &Flange, 0, 0);
|
||||
} else
|
||||
BASS_ChannelRemoveDSP(chan, fladsp);
|
||||
}
|
||||
|
||||
gboolean FileExtensionFilter(const GtkFileFilterInfo *info, gpointer data)
|
||||
{
|
||||
return !regexec((regex_t*)data, info->filename, 0, NULL, 0);
|
||||
}
|
||||
|
||||
void OpenClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
int resp = gtk_dialog_run(GTK_DIALOG(filesel));
|
||||
gtk_widget_hide(filesel);
|
||||
if (resp == GTK_RESPONSE_ACCEPT) {
|
||||
char *file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel));
|
||||
// free both MOD and stream, it must be one of them! :)
|
||||
BASS_MusicFree(chan);
|
||||
BASS_StreamFree(chan);
|
||||
if (!(chan = BASS_StreamCreateFile(FALSE, file, 0, 0, BASS_SAMPLE_LOOP | BASS_SAMPLE_FLOAT))
|
||||
&& !(chan = BASS_MusicLoad(FALSE, file, 0, 0, BASS_MUSIC_RAMPS | BASS_SAMPLE_LOOP | BASS_SAMPLE_FLOAT, 1))) {
|
||||
// whatever it is, it ain't playable
|
||||
gtk_button_set_label(obj, "click here to open a file...");
|
||||
Error("Can't play the file");
|
||||
} else {
|
||||
BASS_CHANNELINFO info;
|
||||
BASS_ChannelGetInfo(chan, &info);
|
||||
if (info.chans != 2) { // the DSP expects stereo
|
||||
gtk_button_set_label(obj, "click here to open a file...");
|
||||
BASS_MusicFree(chan);
|
||||
BASS_StreamFree(chan);
|
||||
Error("only stereo sources are supported");
|
||||
} else {
|
||||
gtk_button_set_label(obj, file);
|
||||
// setup DSPs on new channel and play it
|
||||
RotateToggled(GTK_TOGGLE_BUTTON(GetWidget("rotate")), 0);
|
||||
EchoToggled(GTK_TOGGLE_BUTTON(GetWidget("echo")), 0);
|
||||
FlangerToggled(GTK_TOGGLE_BUTTON(GetWidget("flanger")), 0);
|
||||
BASS_ChannelPlay(chan, FALSE);
|
||||
}
|
||||
}
|
||||
g_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
regex_t fregex;
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
Error("An incorrect version of BASS was loaded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check for floating-point capability
|
||||
if (!BASS_GetConfig(BASS_CONFIG_FLOAT)) {
|
||||
Error("This example requires floating-point support");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// enable floating-point DSP (not really necessary as the channels will be floating-point anyway)
|
||||
BASS_SetConfig(BASS_CONFIG_FLOATDSP, TRUE);
|
||||
|
||||
// initialize default device
|
||||
if (!BASS_Init(-1, 44100, 0, NULL, NULL)) {
|
||||
Error("Can't initialize device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize GUI
|
||||
glade = glade_xml_new(GLADE_PATH"dsptest.glade", NULL, NULL);
|
||||
if (!glade) return 0;
|
||||
win = GetWidget("window1");
|
||||
if (!win) return 0;
|
||||
glade_xml_signal_autoconnect(glade);
|
||||
|
||||
{ // initialize file selector
|
||||
GtkFileFilter *filter;
|
||||
filesel = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "Playable files");
|
||||
regcomp(&fregex, "\\.(mo3|xm|mod|s3m|it|umx|mp[1-3]|ogg|wav|aif)$", REG_ICASE | REG_NOSUB | REG_EXTENDED);
|
||||
gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, FileExtensionFilter, &fregex, NULL);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "All files");
|
||||
gtk_file_filter_add_pattern(filter, "*");
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
}
|
||||
|
||||
gtk_main();
|
||||
|
||||
gtk_widget_destroy(filesel);
|
||||
regfree(&fregex);
|
||||
|
||||
BASS_Free();
|
||||
|
||||
return 0;
|
||||
}
|
82
bass-sys/linux/bass24/dsptest/dsptest.glade
Normal file
82
bass-sys/linux/bass24/dsptest/dsptest.glade
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<glade-interface>
|
||||
<widget class="GtkWindow" id="window1">
|
||||
<property name="width_request">400</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">BASS simple DSP test</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">GTK_WIN_POS_CENTER</property>
|
||||
<signal name="destroy" handler="WindowDestroy"/>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="open">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">click here to open a file...</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="OpenClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="rotate">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">rotate</property>
|
||||
<property name="response_id">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="RotateToggled"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="echo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">echo</property>
|
||||
<property name="response_id">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="EchoToggled" after="yes"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="flanger">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">flanger</property>
|
||||
<property name="response_id">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="FlangerToggled"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
9
bass-sys/linux/bass24/dsptest/makefile
Normal file
9
bass-sys/linux/bass24/dsptest/makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
TARGET = dsptest
|
||||
PACKAGES = gtk+-2.0 libglade-2.0
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
191
bass-sys/linux/bass24/fxtest/fxtest.c
Normal file
191
bass-sys/linux/bass24/fxtest/fxtest.c
Normal file
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
BASS DX8 effects test
|
||||
Copyright (c) 2001-2017 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glade/glade.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
#include <math.h>
|
||||
#include "bass.h"
|
||||
|
||||
// path to glade file
|
||||
#ifndef GLADE_PATH
|
||||
#define GLADE_PATH ""
|
||||
#endif
|
||||
|
||||
GladeXML *glade;
|
||||
GtkWidget *win = 0;
|
||||
GtkWidget *filesel;
|
||||
|
||||
DWORD floatable = BASS_SAMPLE_FLOAT; // floating-point channel support?
|
||||
|
||||
DWORD chan; // channel handle
|
||||
DWORD fxchan = 0; // output stream handle
|
||||
HFX fx[4]; // 3 eq bands + reverb
|
||||
|
||||
// display error messages
|
||||
void Error(const char *es)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s\n(error code: %d)", es, BASS_ErrorGetCode());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
#define GetWidget(id) glade_xml_get_widget(glade,id)
|
||||
|
||||
void WindowDestroy(GtkObject *obj, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
void UpdateFX(const char *id)
|
||||
{
|
||||
GtkRange *obj = GTK_RANGE(GetWidget(id));
|
||||
double v = gtk_range_get_value(obj);
|
||||
int b = atoi(id + 2) - 1;
|
||||
if (b < 3) {
|
||||
BASS_DX8_PARAMEQ p;
|
||||
BASS_FXGetParameters(fx[b], &p);
|
||||
p.fGain = v;
|
||||
BASS_FXSetParameters(fx[b], &p);
|
||||
} else {
|
||||
BASS_DX8_REVERB p;
|
||||
BASS_FXGetParameters(fx[3], &p);
|
||||
p.fReverbMix = (v ? log(v / 20.0) * 20 : -96);
|
||||
BASS_FXSetParameters(fx[3], &p);
|
||||
}
|
||||
}
|
||||
|
||||
void SetupFX()
|
||||
{
|
||||
// setup the effects
|
||||
BASS_DX8_PARAMEQ p;
|
||||
DWORD ch = fxchan ? fxchan : chan; // set on output stream if enabled, else file stream
|
||||
fx[0] = BASS_ChannelSetFX(ch, BASS_FX_DX8_PARAMEQ, 0);
|
||||
fx[1] = BASS_ChannelSetFX(ch, BASS_FX_DX8_PARAMEQ, 0);
|
||||
fx[2] = BASS_ChannelSetFX(ch, BASS_FX_DX8_PARAMEQ, 0);
|
||||
fx[3] = BASS_ChannelSetFX(ch, BASS_FX_DX8_REVERB, 0);
|
||||
p.fGain = 0;
|
||||
p.fBandwidth = 18;
|
||||
p.fCenter = 125;
|
||||
BASS_FXSetParameters(fx[0], &p);
|
||||
p.fCenter = 1000;
|
||||
BASS_FXSetParameters(fx[1], &p);
|
||||
p.fCenter = 8000;
|
||||
BASS_FXSetParameters(fx[2], &p);
|
||||
UpdateFX("fx1");
|
||||
UpdateFX("fx2");
|
||||
UpdateFX("fx3");
|
||||
UpdateFX("fx4");
|
||||
}
|
||||
|
||||
gboolean FileExtensionFilter(const GtkFileFilterInfo *info, gpointer data)
|
||||
{
|
||||
return !regexec((regex_t*)data, info->filename, 0, NULL, 0);
|
||||
}
|
||||
|
||||
void OpenClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
int resp = gtk_dialog_run(GTK_DIALOG(filesel));
|
||||
gtk_widget_hide(filesel);
|
||||
if (resp == GTK_RESPONSE_ACCEPT) {
|
||||
char *file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel));
|
||||
// free both MOD and stream, it must be one of them! :)
|
||||
BASS_MusicFree(chan);
|
||||
BASS_StreamFree(chan);
|
||||
if (!(chan = BASS_StreamCreateFile(FALSE, file, 0, 0, BASS_SAMPLE_LOOP | floatable))
|
||||
&& !(chan = BASS_MusicLoad(FALSE, file, 0, 0, BASS_MUSIC_RAMPS | BASS_SAMPLE_LOOP | floatable, 1))) {
|
||||
// whatever it is, it ain't playable
|
||||
gtk_button_set_label(obj, "click here to open a file...");
|
||||
Error("Can't play the file");
|
||||
} else {
|
||||
gtk_button_set_label(obj, file);
|
||||
if (!fxchan) SetupFX(); // set effects on file if not using output stream
|
||||
BASS_ChannelPlay(chan, FALSE);
|
||||
}
|
||||
g_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean FXChange(GtkRange *range, GtkScrollType scroll, gdouble value, gpointer data)
|
||||
{
|
||||
UpdateFX(gtk_widget_get_name(GTK_WIDGET(range)));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void OutputToggled(GtkToggleButton *obj, gpointer data)
|
||||
{
|
||||
// remove current effects
|
||||
DWORD ch = fxchan ? fxchan : chan;
|
||||
BASS_ChannelRemoveFX(ch, fx[0]);
|
||||
BASS_ChannelRemoveFX(ch, fx[1]);
|
||||
BASS_ChannelRemoveFX(ch, fx[2]);
|
||||
BASS_ChannelRemoveFX(ch, fx[3]);
|
||||
if (obj->active)
|
||||
fxchan = BASS_StreamCreate(0, 0, 0, STREAMPROC_DEVICE, 0); // get device output stream
|
||||
else
|
||||
fxchan = 0; // stop using device output stream
|
||||
SetupFX();
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
regex_t fregex;
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
Error("An incorrect version of BASS was loaded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check for floating-point capability
|
||||
if (!BASS_GetConfig(BASS_CONFIG_FLOAT)) {
|
||||
// no floating-point channel support
|
||||
floatable = 0;
|
||||
// enable floating-point (8.24 fixed-point in this case) DSP instead
|
||||
BASS_SetConfig(BASS_CONFIG_FLOATDSP, TRUE);
|
||||
}
|
||||
|
||||
// initialize default device
|
||||
if (!BASS_Init(-1, 44100, 0, NULL, NULL)) {
|
||||
Error("Can't initialize device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize GUI
|
||||
glade = glade_xml_new(GLADE_PATH"fxtest.glade", NULL, NULL);
|
||||
if (!glade) return 0;
|
||||
win = GetWidget("window1");
|
||||
if (!win) return 0;
|
||||
glade_xml_signal_autoconnect(glade);
|
||||
|
||||
{ // initialize file selector
|
||||
GtkFileFilter *filter;
|
||||
filesel = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "Playable files");
|
||||
regcomp(&fregex, "\\.(mo3|xm|mod|s3m|it|umx|mp[1-3]|ogg|wav|aif)$", REG_ICASE | REG_NOSUB | REG_EXTENDED);
|
||||
gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, FileExtensionFilter, &fregex, NULL);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "All files");
|
||||
gtk_file_filter_add_pattern(filter, "*");
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
}
|
||||
|
||||
gtk_main();
|
||||
|
||||
gtk_widget_destroy(filesel);
|
||||
regfree(&fregex);
|
||||
|
||||
BASS_Free();
|
||||
|
||||
return 0;
|
||||
}
|
194
bass-sys/linux/bass24/fxtest/fxtest.glade
Normal file
194
bass-sys/linux/bass24/fxtest/fxtest.glade
Normal file
|
@ -0,0 +1,194 @@
|
|||
<?xml version="1.0"?>
|
||||
<glade-interface>
|
||||
<!-- interface-requires gtk+ 2.12 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<widget class="GtkWindow" id="window1">
|
||||
<property name="width_request">400</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">BASS "DX8" effects test</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">center</property>
|
||||
<signal name="destroy" handler="WindowDestroy"/>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="open">
|
||||
<property name="label" translatable="yes">click here to open a file...</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="OpenClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkVScale" id="fx1">
|
||||
<property name="height_request">100</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="adjustment">0 -10 10 1 10 0</property>
|
||||
<property name="inverted">True</property>
|
||||
<property name="restrict_to_fill_level">False</property>
|
||||
<property name="fill_level">0</property>
|
||||
<property name="draw_value">False</property>
|
||||
<signal name="change_value" handler="FXChange"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">125 hz</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkVScale" id="fx2">
|
||||
<property name="height_request">100</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="adjustment">0 -10 10 1 10 0</property>
|
||||
<property name="inverted">True</property>
|
||||
<property name="restrict_to_fill_level">False</property>
|
||||
<property name="fill_level">0</property>
|
||||
<property name="draw_value">False</property>
|
||||
<signal name="change_value" handler="FXChange"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">1 khz</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkVScale" id="fx3">
|
||||
<property name="height_request">100</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="adjustment">0 -10 10 1 10 0</property>
|
||||
<property name="inverted">True</property>
|
||||
<property name="restrict_to_fill_level">False</property>
|
||||
<property name="draw_value">False</property>
|
||||
<signal name="change_value" handler="FXChange"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">8 khz</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox5">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkVScale" id="fx4">
|
||||
<property name="height_request">100</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="adjustment">0 0 20 1 10 0</property>
|
||||
<property name="inverted">True</property>
|
||||
<property name="restrict_to_fill_level">False</property>
|
||||
<property name="draw_value">False</property>
|
||||
<signal name="change_value" handler="FXChange"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">reverb</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="output">
|
||||
<property name="label" translatable="yes">Apply effects to final output instead of file</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="OutputToggled"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
9
bass-sys/linux/bass24/fxtest/makefile
Normal file
9
bass-sys/linux/bass24/fxtest/makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
TARGET = fxtest
|
||||
PACKAGES = gtk+-2.0 libglade-2.0
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
BIN
bass-sys/linux/bass24/libbass.so
Normal file
BIN
bass-sys/linux/bass24/libbass.so
Normal file
Binary file not shown.
229
bass-sys/linux/bass24/livespec/livespec.c
Normal file
229
bass-sys/linux/bass24/livespec/livespec.c
Normal file
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
BASS spectrum analyser example
|
||||
Copyright (c) 2002-2010 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
#include <math.h>
|
||||
#include "bass.h"
|
||||
|
||||
#define SPECWIDTH 368 // display width (should be multiple of 4)
|
||||
#define SPECHEIGHT 127 // height (changing requires palette adjustments too)
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
BYTE rgbRed, rgbGreen, rgbBlue;
|
||||
} RGB;
|
||||
#pragma pack()
|
||||
|
||||
GtkWidget *win = 0;
|
||||
|
||||
HRECORD chan;
|
||||
|
||||
GtkWidget *speci, *textarea;
|
||||
GdkPixbuf *specpb;
|
||||
RGB palette[256];
|
||||
|
||||
int specmode = 0, specpos = 0; // spectrum mode (and marker pos for 2nd mode)
|
||||
|
||||
// display error messages
|
||||
void Error(const char *es)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s\n(error code: %d)", es, BASS_ErrorGetCode());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
void WindowDestroy(GtkObject *obj, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
void WindowButtonRelease(GtkWidget *obj, GdkEventButton *event, gpointer data)
|
||||
{
|
||||
if (event->type == GDK_BUTTON_RELEASE) {
|
||||
RGB *specbuf = (RGB*)gdk_pixbuf_get_pixels(specpb);
|
||||
specmode = (specmode + 1) % 4; // next spectrum mode
|
||||
memset(specbuf, 0, SPECWIDTH * SPECHEIGHT * sizeof(*specbuf)); // clear display
|
||||
}
|
||||
}
|
||||
|
||||
gboolean FileExtensionFilter(const GtkFileFilterInfo *info, gpointer data)
|
||||
{
|
||||
return !regexec((regex_t*)data, info->filename, 0, NULL, 0);
|
||||
}
|
||||
|
||||
// update the spectrum display - the interesting bit :)
|
||||
gboolean UpdateSpectrum(gpointer data)
|
||||
{
|
||||
static DWORD quietcount = 0;
|
||||
int x, y, y1;
|
||||
RGB *specbuf = (RGB*)gdk_pixbuf_get_pixels(specpb);
|
||||
|
||||
if (specmode == 3) { // waveform
|
||||
int c;
|
||||
float *buf;
|
||||
BASS_CHANNELINFO ci;
|
||||
memset(specbuf, 0, SPECWIDTH * SPECHEIGHT * sizeof(*specbuf));
|
||||
BASS_ChannelGetInfo(chan, &ci); // get number of channels
|
||||
buf = alloca(ci.chans * SPECWIDTH * sizeof(float)); // allocate buffer for data
|
||||
BASS_ChannelGetData(chan, buf, (ci.chans * SPECWIDTH * sizeof(float)) | BASS_DATA_FLOAT); // get the sample data (floating-point to avoid 8 & 16 bit processing)
|
||||
for (c = 0; c < ci.chans; c++) {
|
||||
for (x = 0; x < SPECWIDTH; x++) {
|
||||
int v = (1 - buf[x * ci.chans + c]) * SPECHEIGHT / 2; // invert and scale to fit display
|
||||
if (v < 0) v = 0;
|
||||
else if (v >= SPECHEIGHT) v = SPECHEIGHT - 1;
|
||||
if (!x) y = v;
|
||||
do { // draw line from previous sample...
|
||||
if (y < v) y++;
|
||||
else if (y > v) y--;
|
||||
specbuf[y * SPECWIDTH + x] = palette[c & 1 ? 127 : 1]; // left=green, right=red (could add more colours to palette for more chans)
|
||||
} while (y != v);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
float fft[1024];
|
||||
BASS_ChannelGetData(chan, fft, BASS_DATA_FFT2048); // get the FFT data
|
||||
|
||||
if (!specmode) { // "normal" FFT
|
||||
memset(specbuf, 0, SPECWIDTH * SPECHEIGHT * sizeof(*specbuf));
|
||||
for (x = 0; x < SPECWIDTH / 2; x++) {
|
||||
#if 1
|
||||
y = sqrt(fft[x + 1]) * 3 * SPECHEIGHT - 4; // scale it (sqrt to make low values more visible)
|
||||
#else
|
||||
y = fft[x + 1] * 10 * SPECHEIGHT; // scale it (linearly)
|
||||
#endif
|
||||
if (y > SPECHEIGHT) y = SPECHEIGHT; // cap it
|
||||
if (x && (y1 = (y + y1) / 2)) // interpolate from previous to make the display smoother
|
||||
while (--y1 >= 0) specbuf[(SPECHEIGHT - 1 - y1) * SPECWIDTH + x * 2 - 1] = palette[y1 + 1];
|
||||
y1 = y;
|
||||
while (--y >= 0) specbuf[(SPECHEIGHT - 1 - y) * SPECWIDTH + x * 2] = palette[y + 1]; // draw level
|
||||
}
|
||||
} else if (specmode == 1) { // logarithmic, acumulate & average bins
|
||||
int b0 = 0;
|
||||
memset(specbuf, 0, SPECWIDTH * SPECHEIGHT * sizeof(*specbuf));
|
||||
#define BANDS 28
|
||||
for (x = 0; x < BANDS; x++) {
|
||||
float peak = 0;
|
||||
int b1 = pow(2, x * 10.0 / (BANDS - 1));
|
||||
if (b1 > 1023) b1 = 1023;
|
||||
if (b1 <= b0) b1 = b0 + 1; // make sure it uses at least 1 FFT bin
|
||||
for (; b0 < b1; b0++)
|
||||
if (peak < fft[1 + b0]) peak = fft[1 + b0];
|
||||
y = sqrt(peak) * 3 * SPECHEIGHT - 4; // scale it (sqrt to make low values more visible)
|
||||
if (y > SPECHEIGHT) y = SPECHEIGHT; // cap it
|
||||
while (--y >= 0)
|
||||
for (y1 = 0; y1 < SPECWIDTH / BANDS - 2; y1++)
|
||||
specbuf[(SPECHEIGHT - 1 - y) * SPECWIDTH + x * (SPECWIDTH / BANDS) + y1] = palette[y + 1]; // draw bar
|
||||
}
|
||||
} else { // "3D"
|
||||
for (x = 0; x < SPECHEIGHT; x++) {
|
||||
y = sqrt(fft[x + 1]) * 3 * 127; // scale it (sqrt to make low values more visible)
|
||||
if (y > 127) y = 127; // cap it
|
||||
specbuf[(SPECHEIGHT - 1 - x) * SPECWIDTH + specpos] = palette[128 + y]; // plot it
|
||||
}
|
||||
// move marker onto next position
|
||||
specpos = (specpos + 1) % SPECWIDTH;
|
||||
for (x = 0; x < SPECHEIGHT; x++) specbuf[x * SPECWIDTH + specpos] = palette[255];
|
||||
}
|
||||
}
|
||||
|
||||
if (LOWORD(BASS_ChannelGetLevel(chan)) < 500) { // check if it's quiet
|
||||
quietcount++;
|
||||
if (quietcount > 40) // it's been quiet for over a second
|
||||
gtk_label_set(GTK_LABEL(textarea), quietcount & 16 ? "make some noise!" : "");
|
||||
} else { // not quiet
|
||||
quietcount = 0;
|
||||
gtk_label_set(GTK_LABEL(textarea), "click to toggle mode");
|
||||
}
|
||||
|
||||
gtk_image_set_from_pixbuf(GTK_IMAGE(speci), specpb); // update the display
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Recording callback - not doing anything with the data
|
||||
BOOL CALLBACK DuffRecording(HRECORD handle, const void *buffer, DWORD length, void *user)
|
||||
{
|
||||
return TRUE; // continue recording
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
Error("An incorrect version of BASS was loaded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize BASS recording (default device)
|
||||
if (!BASS_RecordInit(-1)) {
|
||||
Error("Can't initialize device");
|
||||
return -1;
|
||||
}
|
||||
// start recording (44100hz mono 16-bit)
|
||||
if (!(chan = BASS_RecordStart(44100, 1, 0, &DuffRecording, 0))) {
|
||||
Error("Can't start recording");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// create the window
|
||||
win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER);
|
||||
gtk_window_set_resizable(GTK_WINDOW(win), FALSE);
|
||||
gtk_window_set_title(GTK_WINDOW(win), "BASS \"live\" spectrum");
|
||||
g_signal_connect(GTK_WINDOW(win), "destroy", GTK_SIGNAL_FUNC(WindowDestroy), NULL);
|
||||
|
||||
GtkWidget *ebox = gtk_event_box_new();
|
||||
gtk_container_add(GTK_CONTAINER(win), ebox);
|
||||
g_signal_connect(ebox, "button-release-event", GTK_SIGNAL_FUNC(WindowButtonRelease), NULL);
|
||||
|
||||
GtkWidget *box = gtk_vbox_new(FALSE, 2);
|
||||
gtk_container_add(GTK_CONTAINER(ebox), box);
|
||||
|
||||
// create the bitmap
|
||||
specpb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, SPECWIDTH, SPECHEIGHT);
|
||||
speci = gtk_image_new_from_pixbuf(specpb);
|
||||
gtk_container_add(GTK_CONTAINER(box), speci);
|
||||
|
||||
textarea = gtk_label_new("click to toggle mode");
|
||||
gtk_container_add(GTK_CONTAINER(box), textarea);
|
||||
|
||||
{ // setup palette
|
||||
RGB *pal = palette;
|
||||
int a;
|
||||
memset(palette, 0, sizeof(palette));
|
||||
for (a = 1; a < 128; a++) {
|
||||
pal[a].rgbGreen = 256 - 2 * a;
|
||||
pal[a].rgbRed = 2 * a;
|
||||
}
|
||||
for (a = 0; a < 32; a++) {
|
||||
pal[128 + a].rgbBlue = 8 * a;
|
||||
pal[128 + 32 + a].rgbBlue = 255;
|
||||
pal[128 + 32 + a].rgbRed = 8 * a;
|
||||
pal[128 + 64 + a].rgbRed = 255;
|
||||
pal[128 + 64 + a].rgbBlue = 8 * (31 - a);
|
||||
pal[128 + 64 + a].rgbGreen = 8 * a;
|
||||
pal[128 + 96 + a].rgbRed = 255;
|
||||
pal[128 + 96 + a].rgbGreen = 255;
|
||||
pal[128 + 96 + a].rgbBlue = 8 * a;
|
||||
}
|
||||
}
|
||||
|
||||
// setup update timer (40hz)
|
||||
g_timeout_add(25, UpdateSpectrum, NULL);
|
||||
|
||||
gtk_widget_show_all(win);
|
||||
gtk_main();
|
||||
|
||||
g_object_unref(specpb);
|
||||
|
||||
BASS_RecordFree();
|
||||
|
||||
return 0;
|
||||
}
|
9
bass-sys/linux/bass24/livespec/makefile
Normal file
9
bass-sys/linux/bass24/livespec/makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
TARGET = livespec
|
||||
PACKAGES = gtk+-2.0
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
11
bass-sys/linux/bass24/makefile
Normal file
11
bass-sys/linux/bass24/makefile
Normal file
|
@ -0,0 +1,11 @@
|
|||
EXAMPLES = 3dtest basstest contest custloop devlist dsptest fxtest livespec modtest multi netradio plugins rectest speakers spectrum synth writewav
|
||||
|
||||
.PHONY: all clean $(EXAMPLES)
|
||||
|
||||
all: $(EXAMPLES)
|
||||
|
||||
clean:
|
||||
@$(foreach x,$(EXAMPLES),$(MAKE) -C $(x) clean;)
|
||||
|
||||
$(EXAMPLES):
|
||||
$(MAKE) -C $@
|
12
bass-sys/linux/bass24/makefile.in
Normal file
12
bass-sys/linux/bass24/makefile.in
Normal file
|
@ -0,0 +1,12 @@
|
|||
FLAGS = -Os -I.. -L.. -L../x64 -lbass -lm -Wl,--no-warn-search-mismatch,-rpath,'$$ORIGIN/..:$$ORIGIN/../x64'
|
||||
FLAGS += $(foreach pkg,$(PACKAGES),`pkg-config $(pkg) --cflags --libs`)
|
||||
ifneq (,$(findstring libglade,$(PACKAGES)))
|
||||
FLAGS += -export-dynamic
|
||||
# path to glade file
|
||||
FLAGS += -D'GLADE_PATH="$(shell pwd)/"'
|
||||
endif
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
%: %.c
|
||||
$(CC) $*.c $(FLAGS) -o $@
|
9
bass-sys/linux/bass24/modtest/makefile
Normal file
9
bass-sys/linux/bass24/modtest/makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
TARGET = modtest
|
||||
PACKAGES = gtk+-2.0 libglade-2.0
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
208
bass-sys/linux/bass24/modtest/modtest.c
Normal file
208
bass-sys/linux/bass24/modtest/modtest.c
Normal file
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
BASS MOD music test
|
||||
Copyright (c) 1999-2014 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glade/glade.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
#include "bass.h"
|
||||
|
||||
// path to glade file
|
||||
#ifndef GLADE_PATH
|
||||
#define GLADE_PATH ""
|
||||
#endif
|
||||
|
||||
GladeXML *glade;
|
||||
GtkWidget *win = 0;
|
||||
GtkWidget *filesel;
|
||||
|
||||
DWORD music; // the HMUSIC channel
|
||||
|
||||
// display error messages
|
||||
void Error(const char *es)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s\n(error code: %d)", es, BASS_ErrorGetCode());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
#define GetWidget(id) glade_xml_get_widget(glade,id)
|
||||
|
||||
void WindowDestroy(GtkObject *obj, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
gboolean FileExtensionFilter(const GtkFileFilterInfo *info, gpointer data)
|
||||
{
|
||||
return !regexec((regex_t*)data, info->filename, 0, NULL, 0);
|
||||
}
|
||||
|
||||
DWORD GetFlags()
|
||||
{
|
||||
DWORD flags = BASS_MUSIC_POSRESET; // stop notes when seeking
|
||||
switch (gtk_combo_box_get_active(GTK_COMBO_BOX(GetWidget("interpolation")))) {
|
||||
case 0:
|
||||
flags |= BASS_MUSIC_NONINTER; // no interpolation
|
||||
break;
|
||||
case 2:
|
||||
flags |= BASS_MUSIC_SINCINTER; // sinc interpolation
|
||||
break;
|
||||
}
|
||||
switch (gtk_combo_box_get_active(GTK_COMBO_BOX(GetWidget("ramping")))) {
|
||||
case 1:
|
||||
flags |= BASS_MUSIC_RAMP; // ramping
|
||||
break;
|
||||
case 2:
|
||||
flags |= BASS_MUSIC_RAMPS; // "sensitive" ramping
|
||||
break;
|
||||
}
|
||||
switch (gtk_combo_box_get_active(GTK_COMBO_BOX(GetWidget("surround")))) {
|
||||
case 1:
|
||||
flags |= BASS_MUSIC_SURROUND; // surround
|
||||
break;
|
||||
case 2:
|
||||
flags |= BASS_MUSIC_SURROUND2; // "mode2"
|
||||
break;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
void OpenClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
int resp = gtk_dialog_run(GTK_DIALOG(filesel));
|
||||
gtk_widget_hide(filesel);
|
||||
if (resp == GTK_RESPONSE_ACCEPT) {
|
||||
char *file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel));
|
||||
BASS_MusicFree(music); // free the current music
|
||||
music = BASS_MusicLoad(FALSE, file, 0, 0, GetFlags(), 1); // load the new music
|
||||
if (music) { // success
|
||||
DWORD length = BASS_ChannelGetLength(music, BASS_POS_MUSIC_ORDER); // get the order length
|
||||
gtk_button_set_label(obj, file);
|
||||
{
|
||||
char text[100], *ctype = "";
|
||||
BASS_CHANNELINFO info;
|
||||
int channels = 0;
|
||||
while (BASS_ChannelGetAttributeEx(music, BASS_ATTRIB_MUSIC_VOL_CHAN + channels, 0, 0)) channels++; // count channels
|
||||
BASS_ChannelGetInfo(music, &info);
|
||||
switch (info.ctype & ~BASS_CTYPE_MUSIC_MO3) {
|
||||
case BASS_CTYPE_MUSIC_MOD:
|
||||
ctype = "MOD";
|
||||
break;
|
||||
case BASS_CTYPE_MUSIC_MTM:
|
||||
ctype = "MTM";
|
||||
break;
|
||||
case BASS_CTYPE_MUSIC_S3M:
|
||||
ctype = "S3M";
|
||||
break;
|
||||
case BASS_CTYPE_MUSIC_XM:
|
||||
ctype = "XM";
|
||||
break;
|
||||
case BASS_CTYPE_MUSIC_IT:
|
||||
ctype = "IT";
|
||||
break;
|
||||
}
|
||||
snprintf(text, sizeof(text), "name: %s, format: %dch %s%s", BASS_ChannelGetTags(music, BASS_TAG_MUSIC_NAME), channels, ctype, info.ctype & BASS_CTYPE_MUSIC_MO3 ? " (MO3)" : "");
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("info")), text);
|
||||
}
|
||||
gtk_range_set_range(GTK_RANGE(GetWidget("position")), 0, length - 1); // update scroller range
|
||||
BASS_ChannelPlay(music, FALSE); // start it
|
||||
} else { // failed
|
||||
gtk_button_set_label(obj, "click here to open a file...");
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("info")), "");
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("posdisplay")), "");
|
||||
Error("Can't play the file");
|
||||
}
|
||||
g_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
if (BASS_ChannelIsActive(music) == BASS_ACTIVE_PLAYING)
|
||||
BASS_ChannelPause(music);
|
||||
else
|
||||
BASS_ChannelPlay(music, FALSE);
|
||||
}
|
||||
|
||||
gboolean PositionChange(GtkRange *range, GtkScrollType scroll, gdouble value, gpointer data)
|
||||
{
|
||||
BASS_ChannelSetPosition(music, value, BASS_POS_MUSIC_ORDER); // set the position
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void FlagChanged(GtkComboBox *obj, gpointer data)
|
||||
{
|
||||
BASS_ChannelFlags(music, GetFlags(), -1); // update flags
|
||||
}
|
||||
|
||||
gboolean TimerProc(gpointer data)
|
||||
{
|
||||
char text[16];
|
||||
QWORD pos = BASS_ChannelGetPosition(music, BASS_POS_MUSIC_ORDER);
|
||||
if (pos != (QWORD)-1) {
|
||||
gtk_range_set_value(GTK_RANGE(GetWidget("position")), LOWORD(pos));
|
||||
sprintf(text, "%03d.%03d", LOWORD(pos), HIWORD(pos));
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("posdisplay")), text);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
regex_t fregex;
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
Error("An incorrect version of BASS was loaded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize default output device
|
||||
if (!BASS_Init(-1, 44100, 0, NULL, NULL)) {
|
||||
Error("Can't initialize device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize GUI
|
||||
glade = glade_xml_new(GLADE_PATH"modtest.glade", NULL, NULL);
|
||||
if (!glade) return 0;
|
||||
win = GetWidget("window1");
|
||||
if (!win) return 0;
|
||||
glade_xml_signal_autoconnect(glade);
|
||||
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(GetWidget("interpolation")), 1);
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(GetWidget("ramping")), 2);
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(GetWidget("surround")), 0);
|
||||
|
||||
{ // initialize file selector
|
||||
GtkFileFilter *filter;
|
||||
filesel = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "mo3/it/xm/s3m/mtm/mod/umx");
|
||||
regcomp(&fregex, "\\.(mo3|it|xm|s3m|mtm|mod|umx)$", REG_ICASE | REG_NOSUB | REG_EXTENDED);
|
||||
gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, FileExtensionFilter, &fregex, NULL);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "All files");
|
||||
gtk_file_filter_add_pattern(filter, "*");
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
}
|
||||
|
||||
g_timeout_add(100, TimerProc, NULL);
|
||||
|
||||
gtk_main();
|
||||
|
||||
gtk_widget_destroy(filesel);
|
||||
regfree(&fregex);
|
||||
|
||||
BASS_Free();
|
||||
|
||||
return 0;
|
||||
}
|
183
bass-sys/linux/bass24/modtest/modtest.glade
Normal file
183
bass-sys/linux/bass24/modtest/modtest.glade
Normal file
|
@ -0,0 +1,183 @@
|
|||
<?xml version="1.0"?>
|
||||
<glade-interface>
|
||||
<!-- interface-requires gtk+ 2.12 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<widget class="GtkWindow" id="window1">
|
||||
<property name="width_request">400</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">BASS MOD music test</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">center</property>
|
||||
<signal name="destroy" handler="WindowDestroy"/>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="open">
|
||||
<property name="label" translatable="yes">click here to open a file...</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="OpenClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="info">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">100</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="posdisplay">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="play">
|
||||
<property name="label" translatable="yes">Play / Pause</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="PlayClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHScale" id="position">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">0 0 0 1 10 0</property>
|
||||
<property name="draw_value">False</property>
|
||||
<signal name="change_value" handler="PositionChange"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Interpolation</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkComboBox" id="interpolation">
|
||||
<property name="visible">True</property>
|
||||
<property name="items" translatable="yes">off
|
||||
linear
|
||||
sinc</property>
|
||||
<signal name="changed" handler="FlagChanged"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Ramping</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkComboBox" id="ramping">
|
||||
<property name="visible">True</property>
|
||||
<property name="items" translatable="yes">off
|
||||
normal
|
||||
sensitive</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Surround</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkComboBox" id="surround">
|
||||
<property name="visible">True</property>
|
||||
<property name="items" translatable="yes">off
|
||||
mode 1
|
||||
mode 2</property>
|
||||
<signal name="changed" handler="FlagChanged"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
BIN
bass-sys/linux/bass24/mp3-free/libbass.so
Normal file
BIN
bass-sys/linux/bass24/mp3-free/libbass.so
Normal file
Binary file not shown.
9
bass-sys/linux/bass24/multi/makefile
Normal file
9
bass-sys/linux/bass24/multi/makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
TARGET = multi
|
||||
PACKAGES = gtk+-2.0 libglade-2.0
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
255
bass-sys/linux/bass24/multi/multi.c
Normal file
255
bass-sys/linux/bass24/multi/multi.c
Normal file
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
BASS multiple output example
|
||||
Copyright (c) 2001-2008 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glade/glade.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
#include <math.h>
|
||||
#include "bass.h"
|
||||
|
||||
// path to glade file
|
||||
#ifndef GLADE_PATH
|
||||
#define GLADE_PATH ""
|
||||
#endif
|
||||
|
||||
GladeXML *glade;
|
||||
GtkWidget *win = 0;
|
||||
GtkWidget *filesel;
|
||||
|
||||
DWORD outdev[2]; // output devices
|
||||
DWORD latency[2]; // latencies
|
||||
HSTREAM chan[2]; // the streams
|
||||
|
||||
// display error messages
|
||||
void Error(const char *es)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s\n(error code: %d)", es, BASS_ErrorGetCode());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
#define GetWidget(id) glade_xml_get_widget(glade,id)
|
||||
|
||||
void WindowDestroy(GtkObject *obj, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
gboolean FileExtensionFilter(const GtkFileFilterInfo *info, gpointer data)
|
||||
{
|
||||
return !regexec((regex_t*)data, info->filename, 0, NULL, 0);
|
||||
}
|
||||
|
||||
void OpenClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
int resp = gtk_dialog_run(GTK_DIALOG(filesel));
|
||||
gtk_widget_hide(filesel);
|
||||
if (resp == GTK_RESPONSE_ACCEPT) {
|
||||
char *file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel));
|
||||
const gchar *objname = gtk_widget_get_name(GTK_WIDGET(obj));
|
||||
int devn = atoi(objname + 4) - 1; // get device number from button name ("openX")
|
||||
BASS_StreamFree(chan[devn]); // free old stream before opening new
|
||||
BASS_SetDevice(outdev[devn]); // set the device to create stream on
|
||||
if (!(chan[devn] = BASS_StreamCreateFile(FALSE, file, 0, 0, BASS_SAMPLE_LOOP))) {
|
||||
gtk_button_set_label(obj, "click here to open a file...");
|
||||
Error("Can't play the file");
|
||||
} else {
|
||||
gtk_button_set_label(obj, file);
|
||||
BASS_ChannelPlay(chan[devn], FALSE);
|
||||
}
|
||||
g_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
// Cloning DSP function
|
||||
void CALLBACK CloneDSP(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user)
|
||||
{
|
||||
BASS_StreamPutData((uintptr_t)user, buffer, length); // user = clone
|
||||
}
|
||||
|
||||
void CloneClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
const gchar *objname = gtk_widget_get_name(GTK_WIDGET(obj));
|
||||
int devn = atoi(objname + 5) - 1; // get device number from button name ("cloneX")
|
||||
BASS_CHANNELINFO i;
|
||||
if (!BASS_ChannelGetInfo(chan[devn ^ 1], &i)) {
|
||||
Error("Nothing to clone");
|
||||
} else {
|
||||
BASS_StreamFree(chan[devn]); // free old stream
|
||||
BASS_SetDevice(outdev[devn]); // set the device to create stream on
|
||||
if (!(chan[devn] = BASS_StreamCreate(i.freq, i.chans, i.flags, STREAMPROC_PUSH, 0))) { // create a "push" stream
|
||||
char oname[10];
|
||||
sprintf(oname, "open%d", devn + 1);
|
||||
gtk_button_set_label(GTK_BUTTON(GetWidget(oname)), "click here to open a file...");
|
||||
Error("Can't create clone");
|
||||
} else {
|
||||
BASS_ChannelLock(chan[devn ^ 1], TRUE); // lock source stream to synchonise buffer contents
|
||||
BASS_ChannelSetDSP(chan[devn ^ 1], CloneDSP, (void*)(uintptr_t)chan[devn], 0); // set DSP to feed data to clone
|
||||
{ // copy buffered data to clone
|
||||
DWORD d = BASS_ChannelSeconds2Bytes(chan[devn], latency[devn] / 1000.f); // playback delay
|
||||
DWORD c = BASS_ChannelGetData(chan[devn ^ 1], 0, BASS_DATA_AVAILABLE);
|
||||
BYTE *buf = (BYTE*)malloc(c);
|
||||
c = BASS_ChannelGetData(chan[devn ^ 1], buf, c);
|
||||
if (c > d) BASS_StreamPutData(chan[devn], buf + d, c - d);
|
||||
free(buf);
|
||||
}
|
||||
BASS_ChannelLock(chan[devn ^ 1], FALSE); // unlock source stream
|
||||
BASS_ChannelPlay(chan[devn], FALSE); // play clone
|
||||
{
|
||||
char oname[10];
|
||||
sprintf(oname, "open%d", devn + 1);
|
||||
gtk_button_set_label(GTK_BUTTON(GetWidget(oname)), "clone");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SwapClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
{ // swap handles
|
||||
HSTREAM temp = chan[0];
|
||||
chan[0] = chan[1];
|
||||
chan[1] = temp;
|
||||
}
|
||||
{ // swap text
|
||||
GtkButton *open1 = GTK_BUTTON(GetWidget("open1")), *open2 = GTK_BUTTON(GetWidget("open2"));
|
||||
char *temp = strdup(gtk_button_get_label(open1));
|
||||
gtk_button_set_label(open1, gtk_button_get_label(open2));
|
||||
gtk_button_set_label(open2, temp);
|
||||
free(temp);
|
||||
}
|
||||
// update the channel devices
|
||||
BASS_ChannelSetDevice(chan[0], outdev[0]);
|
||||
BASS_ChannelSetDevice(chan[1], outdev[1]);
|
||||
}
|
||||
|
||||
// Simple device selector dialog stuff begins here
|
||||
void ListRowActivated(GtkTreeView *obj, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data)
|
||||
{
|
||||
int sel = 1 + *gtk_tree_path_get_indices(path); // get selection
|
||||
gtk_dialog_response(GTK_DIALOG(GetWidget("dialog1")), sel);
|
||||
}
|
||||
|
||||
int SelectDevice(const char *title)
|
||||
{
|
||||
int sel = 0;
|
||||
GtkWidget *win = GetWidget("dialog1");
|
||||
gtk_window_set_title(GTK_WINDOW(win), title);
|
||||
|
||||
GtkTreeView *list = GTK_TREE_VIEW(GetWidget("list"));
|
||||
if (!gtk_tree_view_get_column(list, 0)) { // no column yet, so add one...
|
||||
GtkTreeViewColumn *col = gtk_tree_view_column_new();
|
||||
gtk_tree_view_append_column(list, col);
|
||||
GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
|
||||
gtk_tree_view_column_pack_start(col, renderer, TRUE);
|
||||
gtk_tree_view_column_add_attribute(col, renderer, "text", 0);
|
||||
}
|
||||
|
||||
GtkListStore *liststore = gtk_list_store_new(1, G_TYPE_STRING);
|
||||
{
|
||||
BASS_DEVICEINFO i;
|
||||
int c;
|
||||
for (c = 1; BASS_GetDeviceInfo(c, &i); c++) { // device 1 = 1st real device
|
||||
if (i.flags & BASS_DEVICE_ENABLED) { // enabled, so add it...
|
||||
GtkTreeIter it;
|
||||
gtk_list_store_append(liststore, &it);
|
||||
gtk_list_store_set(liststore, &it, 0, i.name, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
gtk_tree_view_set_model(list, GTK_TREE_MODEL(liststore));
|
||||
g_object_unref(liststore);
|
||||
{ // pre-select 1st entry
|
||||
GtkTreeSelection *tsel = gtk_tree_view_get_selection(list);
|
||||
GtkTreePath *tpath = gtk_tree_path_new_first();
|
||||
gtk_tree_selection_select_path(tsel, tpath);
|
||||
gtk_tree_path_free(tpath);
|
||||
}
|
||||
|
||||
sel = gtk_dialog_run(GTK_DIALOG(win));
|
||||
gtk_widget_hide(win);
|
||||
|
||||
return sel;
|
||||
}
|
||||
// Simple device selector dialog stuff ends here
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
regex_t fregex;
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
Error("An incorrect version of BASS was loaded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize GUI
|
||||
glade = glade_xml_new(GLADE_PATH"multi.glade", NULL, NULL);
|
||||
if (!glade) return 0;
|
||||
win = GetWidget("window1");
|
||||
if (!win) return 0;
|
||||
glade_xml_signal_autoconnect(glade);
|
||||
|
||||
// Let the user choose the output devices
|
||||
outdev[0] = SelectDevice("Select output device #1");
|
||||
outdev[1] = SelectDevice("Select output device #2");
|
||||
|
||||
{ // setup output devices
|
||||
BASS_INFO info;
|
||||
if (!BASS_Init(outdev[0], 44100, 0, NULL, NULL)) {
|
||||
Error("Can't initialize device 1");
|
||||
return 0;
|
||||
}
|
||||
BASS_GetInfo(&info);
|
||||
latency[0] = info.latency;
|
||||
if (!BASS_Init(outdev[1], 44100, 0, NULL, NULL)) {
|
||||
Error("Can't initialize device 2");
|
||||
return 0;
|
||||
}
|
||||
BASS_GetInfo(&info);
|
||||
latency[1] = info.latency;
|
||||
}
|
||||
{
|
||||
BASS_DEVICEINFO i;
|
||||
BASS_GetDeviceInfo(outdev[0], &i);
|
||||
gtk_frame_set_label(GTK_FRAME(GetWidget("device1")), i.name);
|
||||
BASS_GetDeviceInfo(outdev[1], &i);
|
||||
gtk_frame_set_label(GTK_FRAME(GetWidget("device2")), i.name);
|
||||
}
|
||||
|
||||
{ // initialize file selector
|
||||
GtkFileFilter *filter;
|
||||
filesel = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "Playable files");
|
||||
regcomp(&fregex, "\\.(mo3|xm|mod|s3m|it|umx|mp[1-3]|ogg|wav|aif)$", REG_ICASE | REG_NOSUB | REG_EXTENDED);
|
||||
gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, FileExtensionFilter, &fregex, NULL);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "All files");
|
||||
gtk_file_filter_add_pattern(filter, "*");
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
}
|
||||
|
||||
gtk_widget_show(win);
|
||||
gtk_main();
|
||||
|
||||
gtk_widget_destroy(filesel);
|
||||
regfree(&fregex);
|
||||
|
||||
// release both devices
|
||||
BASS_SetDevice(outdev[0]);
|
||||
BASS_Free();
|
||||
BASS_SetDevice(outdev[1]);
|
||||
BASS_Free();
|
||||
|
||||
return 0;
|
||||
}
|
203
bass-sys/linux/bass24/multi/multi.glade
Normal file
203
bass-sys/linux/bass24/multi/multi.glade
Normal file
|
@ -0,0 +1,203 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<glade-interface>
|
||||
<widget class="GtkWindow" id="window1">
|
||||
<property name="width_request">450</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">BASS multiple output example</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">GTK_WIN_POS_CENTER</property>
|
||||
<signal name="destroy" handler="WindowDestroy"/>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="device1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">6</property>
|
||||
<property name="bottom_padding">10</property>
|
||||
<property name="left_padding">10</property>
|
||||
<property name="right_padding">10</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="open1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">click here to open a file...</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="OpenClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="clone1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">clone #2</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="CloneClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="swap">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">swap</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="SwapClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="padding">10</property>
|
||||
<property name="pack_type">GTK_PACK_END</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="device2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment2">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">6</property>
|
||||
<property name="bottom_padding">10</property>
|
||||
<property name="left_padding">10</property>
|
||||
<property name="right_padding">10</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="open2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">click here to open a file...</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="OpenClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="clone2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">clone #1</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="CloneClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<widget class="GtkDialog" id="dialog1">
|
||||
<property name="width_request">300</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
|
||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
||||
<property name="has_separator">False</property>
|
||||
<child internal-child="vbox">
|
||||
<widget class="GtkVBox" id="dialog-vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="list">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<property name="headers_clickable">True</property>
|
||||
<signal name="row_activated" handler="ListRowActivated"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child internal-child="action_area">
|
||||
<widget class="GtkHButtonBox" id="dialog-action_area1">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">GTK_BUTTONBOX_END</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="pack_type">GTK_PACK_END</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
9
bass-sys/linux/bass24/netradio/makefile
Normal file
9
bass-sys/linux/bass24/netradio/makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
TARGET = netradio
|
||||
PACKAGES = gtk+-2.0 libglade-2.0 gthread-2.0
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
283
bass-sys/linux/bass24/netradio/netradio.c
Normal file
283
bass-sys/linux/bass24/netradio/netradio.c
Normal file
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
BASS internet radio example
|
||||
Copyright (c) 2002-2019 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glade/glade.h>
|
||||
#include <glib/gthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bass.h"
|
||||
|
||||
// HLS definitions (copied from BASSHLS.H)
|
||||
#define BASS_SYNC_HLS_SEGMENT 0x10300
|
||||
#define BASS_TAG_HLS_EXTINF 0x14000
|
||||
|
||||
// path to glade file
|
||||
#ifndef GLADE_PATH
|
||||
#define GLADE_PATH ""
|
||||
#endif
|
||||
|
||||
GladeXML *glade;
|
||||
GtkWidget *win = 0;
|
||||
DWORD req = 0; // request number/counter
|
||||
HSTREAM chan;
|
||||
guint buftimer = 0;
|
||||
|
||||
const char *urls[10] = { // preset stream URLs
|
||||
"http://stream-dc1.radioparadise.com/rp_192m.ogg", "http://www.radioparadise.com/m3u/mp3-32.m3u",
|
||||
"http://network.absoluteradio.co.uk/core/audio/mp3/live.pls?service=a8bb", "http://network.absoluteradio.co.uk/core/audio/aacplus/live.pls?service=a8",
|
||||
"http://somafm.com/secretagent.pls", "http://somafm.com/secretagent32.pls",
|
||||
"http://somafm.com/suburbsofgoa.pls", "http://somafm.com/suburbsofgoa32.pls",
|
||||
"http://ai-radio.org/256.ogg", "http://ai-radio.org/48.aacp"
|
||||
};
|
||||
|
||||
// display error messages
|
||||
void Error(const char *es)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s\n(error code: %d)", es, BASS_ErrorGetCode());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
#define GetWidget(id) glade_xml_get_widget(glade,id)
|
||||
|
||||
void WindowDestroy(GtkObject *obj, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
void gtk_label_set_text_8859(GtkLabel *label, const gchar *text)
|
||||
{
|
||||
gsize s;
|
||||
char *utf = g_convert(text, -1, "UTF-8", "ISO-8859-1", NULL, &s, NULL);
|
||||
if (utf) {
|
||||
gtk_label_set_text(label, utf);
|
||||
g_free(utf);
|
||||
} else
|
||||
gtk_label_set_text(label, text);
|
||||
}
|
||||
|
||||
// update stream title from metadata
|
||||
void DoMeta()
|
||||
{
|
||||
GtkLabel *label = GTK_LABEL(GetWidget("status1"));
|
||||
const char *meta = BASS_ChannelGetTags(chan, BASS_TAG_META);
|
||||
if (meta) { // got Shoutcast metadata
|
||||
char *p = strstr(meta, "StreamTitle='");
|
||||
if (p) {
|
||||
p = strdup(p + 13);
|
||||
strchr(p, ';')[-1] = 0;
|
||||
gtk_label_set_text_8859(label, p);
|
||||
free(p);
|
||||
}
|
||||
} else {
|
||||
meta = BASS_ChannelGetTags(chan, BASS_TAG_OGG);
|
||||
if (meta) { // got Icecast/OGG tags
|
||||
const char *artist = NULL, *title = NULL, *p = meta;
|
||||
for (; *p; p += strlen(p) + 1) {
|
||||
if (!strncasecmp(p, "artist=", 7)) // found the artist
|
||||
artist = p + 7;
|
||||
if (!strncasecmp(p, "title=", 6)) // found the title
|
||||
title = p + 6;
|
||||
}
|
||||
if (title) {
|
||||
if (artist) {
|
||||
char text[100];
|
||||
snprintf(text, sizeof(text), "%s - %s", artist, title);
|
||||
gtk_label_set_text(label, text);
|
||||
} else
|
||||
gtk_label_set_text(label, title);
|
||||
}
|
||||
} else {
|
||||
meta = BASS_ChannelGetTags(chan, BASS_TAG_HLS_EXTINF);
|
||||
if (meta) { // got HLS segment info
|
||||
const char *p = strchr(meta, ',');
|
||||
if (p) gtk_label_set_text(label, p + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CALLBACK MetaSync(HSYNC handle, DWORD channel, DWORD data, void *user)
|
||||
{
|
||||
gdk_threads_enter();
|
||||
DoMeta();
|
||||
gdk_threads_leave();
|
||||
}
|
||||
|
||||
gboolean BufferTimerProc(gpointer data)
|
||||
{ // monitor buffering progress
|
||||
if (BASS_ChannelIsActive(chan) == BASS_ACTIVE_PLAYING) {
|
||||
buftimer = 0;
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("status2")), "playing");
|
||||
{ // get the broadcast name and URL
|
||||
const char *icy = BASS_ChannelGetTags(chan, BASS_TAG_ICY);
|
||||
if (!icy) icy = BASS_ChannelGetTags(chan, BASS_TAG_HTTP); // no ICY tags, try HTTP
|
||||
if (icy) {
|
||||
for (; *icy; icy += strlen(icy) + 1) {
|
||||
if (!strncasecmp(icy, "icy-name:", 9))
|
||||
gtk_label_set_text_8859(GTK_LABEL(GetWidget("status2")), icy + 9);
|
||||
if (!strncasecmp(icy, "icy-url:", 8))
|
||||
gtk_label_set_text_8859(GTK_LABEL(GetWidget("status3")), icy + 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
// get the stream title
|
||||
DoMeta();
|
||||
return FALSE; // stop monitoring
|
||||
} else {
|
||||
char text[32];
|
||||
sprintf(text, "buffering... %d%%", 100 - (int)BASS_StreamGetFilePosition(chan, BASS_FILEPOS_BUFFERING));
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("status2")), text);
|
||||
return TRUE; // continue monitoring
|
||||
}
|
||||
}
|
||||
|
||||
void CALLBACK StallSync(HSYNC handle, DWORD channel, DWORD data, void *user)
|
||||
{
|
||||
if (!data) { // stalled
|
||||
if (!buftimer) buftimer = g_timeout_add(50, BufferTimerProc, NULL); // start buffer monitoring
|
||||
}
|
||||
}
|
||||
|
||||
void CALLBACK EndSync(HSYNC handle, DWORD channel, DWORD data, void *user)
|
||||
{
|
||||
if (buftimer) {
|
||||
g_source_remove(buftimer); // stop buffer monitoring
|
||||
buftimer = 0;
|
||||
}
|
||||
gdk_threads_enter();
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("status1")), "");
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("status2")), "not playing");
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("status3")), "");
|
||||
gdk_threads_leave();
|
||||
}
|
||||
|
||||
void CALLBACK StatusProc(const void *buffer, DWORD length, void *user)
|
||||
{
|
||||
if (buffer && !length && (uintptr_t)user == req) { // got HTTP/ICY tags, and this is still the current request
|
||||
gdk_threads_enter();
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("status3")), buffer); // display connection status
|
||||
gdk_threads_leave();
|
||||
}
|
||||
}
|
||||
|
||||
void *OpenURL(void *url)
|
||||
{
|
||||
G_LOCK_DEFINE_STATIC(req);
|
||||
DWORD c, r;
|
||||
G_LOCK(req); // make sure only 1 thread at a time can do the following
|
||||
r = ++req; // increment the request counter for this request
|
||||
G_UNLOCK(req);
|
||||
if (buftimer) {
|
||||
g_source_remove(buftimer); // stop buffer monitoring
|
||||
buftimer = 0;
|
||||
}
|
||||
BASS_StreamFree(chan); // close old stream
|
||||
gdk_threads_enter();
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("status1")), "");
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("status2")), "connecting...");
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("status3")), "");
|
||||
gdk_threads_leave();
|
||||
c = BASS_StreamCreateURL(url, 0, BASS_STREAM_BLOCK | BASS_STREAM_STATUS | BASS_STREAM_AUTOFREE, StatusProc, (void*)(uintptr_t)r);
|
||||
free(url); // free temp URL buffer
|
||||
G_LOCK(req);
|
||||
if (r != req) { // there is a newer request, discard this stream
|
||||
G_UNLOCK(req);
|
||||
if (c) BASS_StreamFree(c);
|
||||
return NULL;
|
||||
}
|
||||
chan = c; // this is now the current stream
|
||||
G_UNLOCK(req);
|
||||
if (!chan) {
|
||||
gdk_threads_enter();
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("status2")), "not playing");
|
||||
Error("Can't play the stream");
|
||||
gdk_threads_leave();
|
||||
} else {
|
||||
// start buffer monitoring
|
||||
buftimer = g_timeout_add(50, BufferTimerProc, NULL);
|
||||
// set syncs for stream title updates
|
||||
BASS_ChannelSetSync(chan, BASS_SYNC_META, 0, MetaSync, 0); // Shoutcast
|
||||
BASS_ChannelSetSync(chan, BASS_SYNC_OGG_CHANGE, 0, MetaSync, 0); // Icecast/OGG
|
||||
BASS_ChannelSetSync(chan, BASS_SYNC_HLS_SEGMENT, 0, MetaSync, 0); // HLS
|
||||
// set sync for stalling/buffering
|
||||
BASS_ChannelSetSync(chan, BASS_SYNC_STALL, 0, StallSync, 0);
|
||||
// set sync for end of stream
|
||||
BASS_ChannelSetSync(chan, BASS_SYNC_END, 0, EndSync, 0);
|
||||
// play it!
|
||||
BASS_ChannelPlay(chan, FALSE);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void PresetClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
const char *url;
|
||||
const gchar *objname = gtk_widget_get_name(GTK_WIDGET(obj));
|
||||
if (!strcmp(objname, "customopen")) { // play a custom URL
|
||||
url = gtk_entry_get_text(GTK_ENTRY(GetWidget("customurl"))); // get the URL
|
||||
} else { // play a preset
|
||||
int preset = atoi(objname + 6) - 1; // get preset from button name ("presetX")
|
||||
url = urls[preset];
|
||||
}
|
||||
if (GTK_TOGGLE_BUTTON(GetWidget("proxydirect"))->active)
|
||||
BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY, NULL); // disable proxy
|
||||
else
|
||||
BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY, gtk_entry_get_text(GTK_ENTRY(GetWidget("proxyurl")))); // set proxy server
|
||||
// open URL in a new thread (so that main thread is free)
|
||||
#if GLIB_CHECK_VERSION(2,32,0)
|
||||
{
|
||||
GThread *thread = g_thread_new(NULL, OpenURL, strdup(url));
|
||||
g_thread_unref(thread);
|
||||
}
|
||||
#else
|
||||
g_thread_create(OpenURL, strdup(url), FALSE, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
#if !GLIB_CHECK_VERSION(2,32,0)
|
||||
g_thread_init(NULL);
|
||||
#endif
|
||||
gdk_threads_init();
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
Error("An incorrect version of BASS was loaded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize default output device
|
||||
if (!BASS_Init(-1, 44100, 0, NULL, NULL)) {
|
||||
Error("Can't initialize device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BASS_SetConfig(BASS_CONFIG_NET_PLAYLIST, 1); // enable playlist processing
|
||||
BASS_SetConfig(BASS_CONFIG_NET_PREBUF_WAIT, 0); // disable BASS_StreamCreateURL pre-buffering
|
||||
|
||||
BASS_PluginLoad("libbass_aac.so", 0); // load BASS_AAC (if present) for AAC support
|
||||
BASS_PluginLoad("libbassflac.so", 0); // load BASSFLAC (if present) for FLAC support
|
||||
BASS_PluginLoad("libbasshls.so", 0); // load BASSHLS (if present) for HLS support
|
||||
|
||||
// initialize GUI
|
||||
glade = glade_xml_new(GLADE_PATH"netradio.glade", NULL, NULL);
|
||||
if (!glade) return 0;
|
||||
win = GetWidget("window1");
|
||||
if (!win) return 0;
|
||||
glade_xml_signal_autoconnect(glade);
|
||||
|
||||
gdk_threads_enter();
|
||||
gtk_main();
|
||||
gdk_threads_leave();
|
||||
|
||||
BASS_Free();
|
||||
|
||||
return 0;
|
||||
}
|
432
bass-sys/linux/bass24/netradio/netradio.glade
Normal file
432
bass-sys/linux/bass24/netradio/netradio.glade
Normal file
|
@ -0,0 +1,432 @@
|
|||
<?xml version="1.0"?>
|
||||
<glade-interface>
|
||||
<!-- interface-requires gtk+ 2.6 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<widget class="GtkWindow" id="window1">
|
||||
<property name="width_request">450</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">BASS internet radio tuner</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">center</property>
|
||||
<signal name="destroy" handler="WindowDestroy"/>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">out</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">6</property>
|
||||
<property name="bottom_padding">10</property>
|
||||
<property name="left_padding">10</property>
|
||||
<property name="right_padding">10</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">High bitrate</property>
|
||||
<property name="ellipsize">end</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Low bitrate</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="preset1">
|
||||
<property name="label" translatable="yes">1</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="PresetClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="preset3">
|
||||
<property name="label" translatable="yes">2</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="PresetClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="preset5">
|
||||
<property name="label" translatable="yes">3</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="PresetClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="preset7">
|
||||
<property name="label" translatable="yes">4</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="PresetClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="preset9">
|
||||
<property name="label" translatable="yes">5</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="PresetClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="preset2">
|
||||
<property name="label" translatable="yes">1</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="PresetClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="preset4">
|
||||
<property name="label" translatable="yes">2</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="PresetClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="preset6">
|
||||
<property name="label" translatable="yes">3</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="PresetClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="preset8">
|
||||
<property name="label" translatable="yes">4</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="PresetClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="preset10">
|
||||
<property name="label" translatable="yes">5</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="PresetClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Presets</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">out</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment2">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">6</property>
|
||||
<property name="bottom_padding">10</property>
|
||||
<property name="left_padding">10</property>
|
||||
<property name="right_padding">10</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="customurl">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="text" translatable="yes">http://</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="customopen">
|
||||
<property name="label" translatable="yes">Open</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="PresetClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Custom</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame3">
|
||||
<property name="height_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">out</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment3">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">6</property>
|
||||
<property name="bottom_padding">10</property>
|
||||
<property name="left_padding">10</property>
|
||||
<property name="right_padding">10</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="status">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="status1">
|
||||
<property name="visible">True</property>
|
||||
<property name="wrap">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="status2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">not playing</property>
|
||||
<property name="wrap">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="status3">
|
||||
<property name="visible">True</property>
|
||||
<property name="wrap">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Currently playing</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">out</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment4">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">6</property>
|
||||
<property name="bottom_padding">10</property>
|
||||
<property name="left_padding">10</property>
|
||||
<property name="right_padding">10</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox5">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="proxyurl">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox5">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="proxydirect">
|
||||
<property name="label" translatable="yes">Direct connection</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label7">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">1</property>
|
||||
<property name="yalign">0</property>
|
||||
<property name="label" translatable="yes">[user:pass@]server:port</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label6">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">proxy</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
1043
bass-sys/linux/bass24/pascal/bass.pas
Normal file
1043
bass-sys/linux/bass24/pascal/bass.pas
Normal file
File diff suppressed because it is too large
Load diff
9
bass-sys/linux/bass24/plugins/makefile
Normal file
9
bass-sys/linux/bass24/plugins/makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
TARGET = plugins
|
||||
PACKAGES = gtk+-2.0 libglade-2.0
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
225
bass-sys/linux/bass24/plugins/plugins.c
Normal file
225
bass-sys/linux/bass24/plugins/plugins.c
Normal file
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
BASS plugin test
|
||||
Copyright (c) 2005-2009 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glade/glade.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <regex.h>
|
||||
#include <glob.h>
|
||||
#include "bass.h"
|
||||
|
||||
// path to glade file
|
||||
#ifndef GLADE_PATH
|
||||
#define GLADE_PATH ""
|
||||
#endif
|
||||
|
||||
GladeXML *glade;
|
||||
GtkWidget *win = 0;
|
||||
GtkWidget *filesel;
|
||||
|
||||
DWORD chan; // the channel... HMUSIC or HSTREAM
|
||||
|
||||
// display error messages
|
||||
void Error(const char *es)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s\n(error code: %d)", es, BASS_ErrorGetCode());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
// translate a CTYPE value to text
|
||||
const char *GetCTypeString(DWORD ctype, HPLUGIN plugin)
|
||||
{
|
||||
if (plugin) { // using a plugin
|
||||
const BASS_PLUGININFO *pinfo = BASS_PluginGetInfo(plugin); // get plugin info
|
||||
int a;
|
||||
for (a = 0; a < pinfo->formatc; a++) {
|
||||
if (pinfo->formats[a].ctype == ctype) // found a "ctype" match...
|
||||
return pinfo->formats[a].name; // return it's name
|
||||
}
|
||||
}
|
||||
// check built-in stream formats...
|
||||
if (ctype == BASS_CTYPE_STREAM_OGG) return "Ogg Vorbis";
|
||||
if (ctype == BASS_CTYPE_STREAM_MP1) return "MPEG layer 1";
|
||||
if (ctype == BASS_CTYPE_STREAM_MP2) return "MPEG layer 2";
|
||||
if (ctype == BASS_CTYPE_STREAM_MP3) return "MPEG layer 3";
|
||||
if (ctype == BASS_CTYPE_STREAM_AIFF) return "Audio IFF";
|
||||
if (ctype == BASS_CTYPE_STREAM_WAV_PCM) return "PCM WAVE";
|
||||
if (ctype == BASS_CTYPE_STREAM_WAV_FLOAT) return "Floating-point WAVE";
|
||||
if (ctype & BASS_CTYPE_STREAM_WAV) return "WAVE";
|
||||
return "?";
|
||||
}
|
||||
|
||||
#define GetWidget(id) glade_xml_get_widget(glade,id)
|
||||
|
||||
void WindowDestroy(GtkObject *obj, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
gboolean FileExtensionFilter(const GtkFileFilterInfo *info, gpointer data)
|
||||
{
|
||||
return !regexec((regex_t*)data, info->filename, 0, NULL, 0);
|
||||
}
|
||||
|
||||
void OpenClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
int resp = gtk_dialog_run(GTK_DIALOG(filesel));
|
||||
gtk_widget_hide(filesel);
|
||||
if (resp == GTK_RESPONSE_ACCEPT) {
|
||||
char *file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel));
|
||||
BASS_StreamFree(chan); // free old stream before opening new
|
||||
if (!(chan = BASS_StreamCreateFile(FALSE, file, 0, 0, BASS_SAMPLE_LOOP))) {
|
||||
gtk_button_set_label(obj, "click here to open a file...");
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("info")), "");
|
||||
gtk_range_set_range(GTK_RANGE(GetWidget("position")), 0, 0);
|
||||
Error("Can't play the file");
|
||||
} else {
|
||||
gtk_button_set_label(obj, file);
|
||||
{ // display the file type and length
|
||||
char text[100];
|
||||
QWORD bytes = BASS_ChannelGetLength(chan, BASS_POS_BYTE);
|
||||
DWORD time = BASS_ChannelBytes2Seconds(chan, bytes);
|
||||
BASS_CHANNELINFO info;
|
||||
BASS_ChannelGetInfo(chan, &info);
|
||||
sprintf(text, "channel type = %x (%s)\nlength = %llu (%u:%02u)",
|
||||
info.ctype, GetCTypeString(info.ctype, info.plugin), bytes, time / 60, time % 60);
|
||||
gtk_label_set_text(GTK_LABEL(GetWidget("info")), text);
|
||||
gtk_range_set_range(GTK_RANGE(GetWidget("position")), 0, time); // update scroller range
|
||||
}
|
||||
BASS_ChannelPlay(chan, FALSE);
|
||||
}
|
||||
g_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean PositionChange(GtkRange *range, GtkScrollType scroll, gdouble value, gpointer data)
|
||||
{
|
||||
BASS_ChannelSetPosition(chan, BASS_ChannelSeconds2Bytes(chan, value), BASS_POS_BYTE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean TimerProc(gpointer data)
|
||||
{
|
||||
gtk_range_set_value(GTK_RANGE(GetWidget("position")), BASS_ChannelBytes2Seconds(chan, BASS_ChannelGetPosition(chan, BASS_POS_BYTE))); // update position
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
Error("An incorrect version of BASS was loaded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize default output device
|
||||
if (!BASS_Init(-1, 44100, 0, NULL, NULL)) {
|
||||
Error("Can't initialize device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize GUI
|
||||
glade = glade_xml_new(GLADE_PATH"plugins.glade", NULL, NULL);
|
||||
if (!glade) return 0;
|
||||
win = GetWidget("window1");
|
||||
if (!win) return 0;
|
||||
glade_xml_signal_autoconnect(glade);
|
||||
|
||||
{ // setup plugin list and file selector
|
||||
GtkTreeView *list = GTK_TREE_VIEW(GetWidget("plugins"));
|
||||
GtkTreeViewColumn *col = gtk_tree_view_column_new();
|
||||
gtk_tree_view_append_column(list, col);
|
||||
GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
|
||||
gtk_tree_view_column_pack_start(col, renderer, TRUE);
|
||||
gtk_tree_view_column_add_attribute(col, renderer, "text", 0);
|
||||
GtkListStore *liststore = gtk_list_store_new(1, G_TYPE_STRING);
|
||||
gtk_tree_view_set_model(list, GTK_TREE_MODEL(liststore));
|
||||
g_object_unref(liststore);
|
||||
gtk_tree_selection_set_mode(gtk_tree_view_get_selection(list), GTK_SELECTION_NONE);
|
||||
|
||||
GtkFileFilter *filter;
|
||||
regex_t *fregex;
|
||||
filesel = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "BASS built-in (*.wav;*.aif;*.mp3;*.mp2;*.mp1;*.ogg)");
|
||||
fregex = malloc(sizeof(*fregex));
|
||||
regcomp(fregex, "\\.(mp[1-3]|ogg|wav|aif)$", REG_ICASE | REG_NOSUB | REG_EXTENDED);
|
||||
gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, FileExtensionFilter, fregex, NULL);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
{ // look for plugins (in the executable's directory)
|
||||
glob_t g;
|
||||
char path[300];
|
||||
if (readlink("/proc/self/exe", path, 300) <= 0) {
|
||||
Error("Can't locate executable");
|
||||
return 0;
|
||||
}
|
||||
strcpy(strrchr(path, '/') + 1, "libbass*.so");
|
||||
if (!glob(path, 0, 0, &g)) {
|
||||
int a;
|
||||
for (a = 0; a < g.gl_pathc; a++) {
|
||||
HPLUGIN plug;
|
||||
if (plug = BASS_PluginLoad(g.gl_pathv[a], 0)) { // plugin loaded...
|
||||
// add it to the list
|
||||
char *file = strrchr(g.gl_pathv[a], '/') + 1;
|
||||
GtkTreeIter it;
|
||||
gtk_list_store_append(liststore, &it);
|
||||
gtk_list_store_set(liststore, &it, 0, file, -1);
|
||||
// get plugin info to add to the file selector filter
|
||||
const BASS_PLUGININFO *pinfo = BASS_PluginGetInfo(plug);
|
||||
int b;
|
||||
for (b = 0; b < pinfo->formatc; b++) {
|
||||
char buf[300], *p;
|
||||
filter = gtk_file_filter_new();
|
||||
sprintf(buf, "%s (%s) - %s", pinfo->formats[b].name, pinfo->formats[b].exts, file);
|
||||
gtk_file_filter_set_name(filter, buf);
|
||||
// build filter regex
|
||||
sprintf(buf, "\\.(%s)$", pinfo->formats[b].exts);
|
||||
while (p = strchr(buf, '*')) { // find an extension
|
||||
if (p[-1] == ';') // not the first...
|
||||
p[-1] = '|'; // add an alternation
|
||||
memmove(p, p + 2, strlen(p + 2) + 1); // remove the "*."
|
||||
}
|
||||
fregex = malloc(sizeof(*fregex));
|
||||
regcomp(fregex, buf, REG_ICASE | REG_NOSUB | REG_EXTENDED);
|
||||
gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, FileExtensionFilter, fregex, NULL);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
globfree(&g);
|
||||
}
|
||||
{
|
||||
GtkTreeIter it;
|
||||
if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(liststore), &it)) { // no plugins...
|
||||
gtk_list_store_append(liststore, &it);
|
||||
gtk_list_store_set(liststore, &it, 0, "no plugins - visit the BASS webpage to get some", -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "All files");
|
||||
gtk_file_filter_add_pattern(filter, "*");
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
}
|
||||
|
||||
g_timeout_add(500, TimerProc, NULL);
|
||||
|
||||
gtk_main();
|
||||
|
||||
gtk_widget_destroy(filesel);
|
||||
|
||||
// "free" the output device and all plugins
|
||||
BASS_Free();
|
||||
BASS_PluginFree(0);
|
||||
|
||||
return 0;
|
||||
}
|
89
bass-sys/linux/bass24/plugins/plugins.glade
Normal file
89
bass-sys/linux/bass24/plugins/plugins.glade
Normal file
|
@ -0,0 +1,89 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<glade-interface>
|
||||
<widget class="GtkWindow" id="window1">
|
||||
<property name="width_request">400</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">BASS plugin test</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">GTK_WIN_POS_CENTER</property>
|
||||
<signal name="destroy" handler="WindowDestroy"/>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">6</property>
|
||||
<property name="bottom_padding">10</property>
|
||||
<property name="left_padding">10</property>
|
||||
<property name="right_padding">10</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="plugins">
|
||||
<property name="height_request">100</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<property name="headers_clickable">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Loaded plugins</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="open">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">click here to open a file...</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="OpenClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="padding">10</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="info">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHScale" id="position">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">0 0 0 1 10 0</property>
|
||||
<property name="draw_value">False</property>
|
||||
<signal name="change_value" handler="PositionChange"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
9
bass-sys/linux/bass24/rectest/makefile
Normal file
9
bass-sys/linux/bass24/rectest/makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
TARGET = rectest
|
||||
PACKAGES = gtk+-2.0 libglade-2.0
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
276
bass-sys/linux/bass24/rectest/rectest.c
Normal file
276
bass-sys/linux/bass24/rectest/rectest.c
Normal file
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
BASS recording example
|
||||
Copyright (c) 2002-2019 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glade/glade.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <regex.h>
|
||||
#include "bass.h"
|
||||
|
||||
// path to glade file
|
||||
#ifndef GLADE_PATH
|
||||
#define GLADE_PATH ""
|
||||
#endif
|
||||
|
||||
GladeXML *glade;
|
||||
GtkWidget *win = 0;
|
||||
GtkWidget *filesel; // file selector
|
||||
|
||||
#define FREQ 44100
|
||||
#define CHANS 2
|
||||
#define BUFSTEP 200000 // memory allocation unit
|
||||
|
||||
int input; // current input source
|
||||
char *recbuf = NULL; // recording buffer
|
||||
DWORD reclen; // recording length
|
||||
|
||||
HRECORD rchan = 0; // recording channel
|
||||
HSTREAM chan = 0; // playback channel
|
||||
|
||||
// display error messages
|
||||
void Error(const char *es)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s\n(error code: %d)", es, BASS_ErrorGetCode());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
#define GetWidget(id) glade_xml_get_widget(glade,id)
|
||||
|
||||
void WindowDestroy(GtkObject *obj, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
// buffer the recorded data
|
||||
BOOL CALLBACK RecordingCallback(HRECORD handle, const void *buffer, DWORD length, void *user)
|
||||
{
|
||||
// increase buffer size if needed
|
||||
if ((reclen % BUFSTEP) + length >= BUFSTEP) {
|
||||
recbuf = realloc(recbuf, ((reclen + length) / BUFSTEP + 1) * BUFSTEP);
|
||||
if (!recbuf) {
|
||||
rchan = 0;
|
||||
Error("Out of memory!");
|
||||
gtk_button_set_label(GTK_BUTTON(GetWidget("record")), "Record");
|
||||
return FALSE; // stop recording
|
||||
}
|
||||
}
|
||||
// buffer the data
|
||||
memcpy(recbuf + reclen, buffer, length);
|
||||
reclen += length;
|
||||
return TRUE; // continue recording
|
||||
}
|
||||
|
||||
void StartRecording()
|
||||
{
|
||||
WAVEFORMATEX *wf;
|
||||
if (recbuf) { // free old recording
|
||||
BASS_StreamFree(chan);
|
||||
chan = 0;
|
||||
free(recbuf);
|
||||
recbuf = NULL;
|
||||
gtk_widget_set_sensitive(GetWidget("play"), FALSE);
|
||||
gtk_widget_set_sensitive(GetWidget("save"), FALSE);
|
||||
}
|
||||
// allocate initial buffer and make space for WAVE header
|
||||
recbuf = malloc(BUFSTEP);
|
||||
reclen = 44;
|
||||
// fill the WAVE header
|
||||
memcpy(recbuf, "RIFF\0\0\0\0WAVEfmt \20\0\0\0", 20);
|
||||
memcpy(recbuf + 36, "data\0\0\0\0", 8);
|
||||
wf = (WAVEFORMATEX*)(recbuf + 20);
|
||||
wf->wFormatTag = 1;
|
||||
wf->nChannels = CHANS;
|
||||
wf->wBitsPerSample = 16;
|
||||
wf->nSamplesPerSec = FREQ;
|
||||
wf->nBlockAlign = wf->nChannels * wf->wBitsPerSample / 8;
|
||||
wf->nAvgBytesPerSec = wf->nSamplesPerSec * wf->nBlockAlign;
|
||||
// start recording
|
||||
rchan = BASS_RecordStart(FREQ, CHANS, 0, RecordingCallback, 0);
|
||||
if (!rchan) {
|
||||
Error("Can't start recording");
|
||||
free(recbuf);
|
||||
recbuf = 0;
|
||||
return;
|
||||
}
|
||||
gtk_button_set_label(GTK_BUTTON(GetWidget("record")), "Stop");
|
||||
}
|
||||
|
||||
void StopRecording()
|
||||
{
|
||||
BASS_ChannelStop(rchan);
|
||||
rchan = 0;
|
||||
gtk_button_set_label(GTK_BUTTON(GetWidget("record")), "Record");
|
||||
// complete the WAVE header
|
||||
*(DWORD*)(recbuf + 4) = reclen - 8;
|
||||
*(DWORD*)(recbuf + 40) = reclen - 44;
|
||||
// enable "save" button
|
||||
gtk_widget_set_sensitive(GetWidget("save"), TRUE);
|
||||
// create a stream from the recording
|
||||
if (chan = BASS_StreamCreateFile(TRUE, recbuf, 0, reclen, 0))
|
||||
gtk_widget_set_sensitive(GetWidget("play"), TRUE); // enable "play" button
|
||||
}
|
||||
|
||||
gboolean FileExtensionFilter(const GtkFileFilterInfo *info, gpointer data)
|
||||
{
|
||||
return !regexec((regex_t*)data, info->filename, 0, NULL, 0);
|
||||
}
|
||||
|
||||
// write the recorded data to disk
|
||||
void WriteToDisk()
|
||||
{
|
||||
int resp = gtk_dialog_run(GTK_DIALOG(filesel));
|
||||
gtk_widget_hide(filesel);
|
||||
if (resp == GTK_RESPONSE_ACCEPT) {
|
||||
char *file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel));
|
||||
FILE *fp = fopen(file, "wb");
|
||||
if (fp) {
|
||||
fwrite(recbuf, reclen, 1, fp);
|
||||
fclose(fp);
|
||||
} else
|
||||
Error("Can't create the file");
|
||||
g_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateInputInfo()
|
||||
{
|
||||
float level;
|
||||
int r = BASS_RecordGetInput(input, &level); // get info on the input
|
||||
if (r == -1 || level < 0) { // failed
|
||||
r = BASS_RecordGetInput(-1, &level); // try master input instead
|
||||
if (r == -1 || level < 0) level = 1; // that failed too, just display 100%
|
||||
}
|
||||
gtk_range_set_value(GTK_RANGE(GetWidget("level")), level * 100); // set the level slider
|
||||
}
|
||||
|
||||
void RecordClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
if (!rchan)
|
||||
StartRecording();
|
||||
else
|
||||
StopRecording();
|
||||
}
|
||||
|
||||
void PlayClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
BASS_ChannelPlay(chan, TRUE); // play the recorded data
|
||||
}
|
||||
|
||||
void SaveClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
WriteToDisk();
|
||||
}
|
||||
|
||||
void InputChanged(GtkComboBox *obj, gpointer data)
|
||||
{
|
||||
int i;
|
||||
input = gtk_combo_box_get_active(obj); // get the selection
|
||||
// enable the selected input
|
||||
for (i = 0; BASS_RecordSetInput(i, BASS_INPUT_OFF, -1); i++); // 1st disable all inputs, then...
|
||||
BASS_RecordSetInput(input, BASS_INPUT_ON, -1); // enable the selected
|
||||
UpdateInputInfo(); // update info
|
||||
}
|
||||
|
||||
void LevelChanged(GtkRange *range, gpointer data)
|
||||
{
|
||||
double level = gtk_range_get_value(range) / 100;
|
||||
if (!BASS_RecordSetInput(input, 0, level)) // failed to set input level
|
||||
BASS_RecordSetInput(-1, 0, level); // try master level instead
|
||||
}
|
||||
|
||||
gboolean TimerProc(gpointer data)
|
||||
{ // update the recording/playback counter
|
||||
char text[30] = "";
|
||||
if (rchan) { // recording
|
||||
if (!BASS_ChannelIsActive(rchan)) { // the recording has stopped, eg. unplugged device
|
||||
StopRecording();
|
||||
Error("The recording stopped");
|
||||
return TRUE;
|
||||
}
|
||||
sprintf(text, "%d", reclen - 44);
|
||||
} else if (chan) {
|
||||
if (BASS_ChannelIsActive(chan)) // playing
|
||||
sprintf(text, "%lld / %lld", BASS_ChannelGetPosition(chan, BASS_POS_BYTE), BASS_ChannelGetLength(chan, BASS_POS_BYTE));
|
||||
else
|
||||
sprintf(text, "%lld", BASS_ChannelGetLength(chan, BASS_POS_BYTE));
|
||||
}
|
||||
gtk_label_set(GTK_LABEL(GetWidget("status")), text);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
regex_t fregex;
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
Error("An incorrect version of BASS was loaded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initalize default recording device
|
||||
if (!BASS_RecordInit(-1)) {
|
||||
Error("Can't initialize recording device");
|
||||
return 0;
|
||||
}
|
||||
// initialize default output device
|
||||
if (!BASS_Init(-1, FREQ, 0, NULL, NULL))
|
||||
Error("Can't initialize output device");
|
||||
|
||||
// initialize GUI
|
||||
glade = glade_xml_new(GLADE_PATH"rectest.glade", NULL, NULL);
|
||||
if (!glade) return 0;
|
||||
win = GetWidget("window1");
|
||||
if (!win) return 0;
|
||||
glade_xml_signal_autoconnect(glade);
|
||||
|
||||
{ // get list of inputs
|
||||
int c;
|
||||
const char *i;
|
||||
GtkComboBox *list = GTK_COMBO_BOX(GetWidget("input"));
|
||||
for (c = 0; i = BASS_RecordGetInputName(c); c++) {
|
||||
gtk_combo_box_append_text(list, i);
|
||||
if (!(BASS_RecordGetInput(c, NULL) & BASS_INPUT_OFF)) { // this 1 is currently "on"
|
||||
input = c;
|
||||
gtk_combo_box_set_active(list, input);
|
||||
UpdateInputInfo(); // display info
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // initialize file selector
|
||||
GtkFileFilter *filter;
|
||||
filesel = gtk_file_chooser_dialog_new("Save File", GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
|
||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(filesel), TRUE);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "WAV files");
|
||||
regcomp(&fregex, "\\.wav$", REG_ICASE | REG_NOSUB | REG_EXTENDED);
|
||||
gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, FileExtensionFilter, &fregex, NULL);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "All files");
|
||||
gtk_file_filter_add_pattern(filter, "*");
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
}
|
||||
|
||||
g_timeout_add(200, TimerProc, NULL);
|
||||
|
||||
gtk_main();
|
||||
|
||||
gtk_widget_destroy(filesel);
|
||||
regfree(&fregex);
|
||||
|
||||
// release all BASS stuff
|
||||
BASS_RecordFree();
|
||||
BASS_Free();
|
||||
|
||||
return 0;
|
||||
}
|
128
bass-sys/linux/bass24/rectest/rectest.glade
Normal file
128
bass-sys/linux/bass24/rectest/rectest.glade
Normal file
|
@ -0,0 +1,128 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<glade-interface>
|
||||
<widget class="GtkWindow" id="window1">
|
||||
<property name="width_request">400</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">BASS recording test</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">GTK_WIN_POS_CENTER</property>
|
||||
<signal name="destroy" handler="WindowDestroy"/>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkComboBox" id="input">
|
||||
<property name="visible">True</property>
|
||||
<property name="items" translatable="yes"></property>
|
||||
<signal name="changed" handler="InputChanged"/>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHScale" id="level">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">0 0 100 1 10 0</property>
|
||||
<property name="draw_value">False</property>
|
||||
<signal name="value_changed" handler="LevelChanged"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="record">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Record</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="RecordClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="play">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Play</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="PlayClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="save">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">Save</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="SaveClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="label_yalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="status">
|
||||
<property name="width_request">250</property>
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
9
bass-sys/linux/bass24/speakers/makefile
Normal file
9
bass-sys/linux/bass24/speakers/makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
TARGET = speakers
|
||||
PACKAGES = gtk+-2.0 libglade-2.0
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
158
bass-sys/linux/bass24/speakers/speakers.c
Normal file
158
bass-sys/linux/bass24/speakers/speakers.c
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
BASS multi-speaker example
|
||||
Copyright (c) 2003-2009 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glade/glade.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
#include "bass.h"
|
||||
|
||||
// path to glade file
|
||||
#ifndef GLADE_PATH
|
||||
#define GLADE_PATH ""
|
||||
#endif
|
||||
|
||||
GladeXML *glade;
|
||||
GtkWidget *win = 0;
|
||||
GtkWidget *filesel;
|
||||
|
||||
DWORD flags[4] = { BASS_SPEAKER_FRONT,BASS_SPEAKER_REAR,BASS_SPEAKER_CENLFE,BASS_SPEAKER_REAR2 };
|
||||
HSTREAM chan[4];
|
||||
|
||||
// display error messages
|
||||
void Error(const char *es)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s\n(error code: %d)", es, BASS_ErrorGetCode());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
#define GetWidget(id) glade_xml_get_widget(glade,id)
|
||||
|
||||
void WindowDestroy(GtkObject *obj, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
gboolean FileExtensionFilter(const GtkFileFilterInfo *info, gpointer data)
|
||||
{
|
||||
return !regexec((regex_t*)data, info->filename, 0, NULL, 0);
|
||||
}
|
||||
|
||||
void OpenClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
int resp = gtk_dialog_run(GTK_DIALOG(filesel));
|
||||
gtk_widget_hide(filesel);
|
||||
if (resp == GTK_RESPONSE_ACCEPT) {
|
||||
char *file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel));
|
||||
const gchar *objname = gtk_widget_get_name(GTK_WIDGET(obj));
|
||||
int speaker = atoi(objname + 4) - 1; // get speaker pair number from button name ("openX")
|
||||
BASS_StreamFree(chan[speaker]); // free old stream before opening new
|
||||
if (!(chan[speaker] = BASS_StreamCreateFile(FALSE, file, 0, 0, flags[speaker] | BASS_SAMPLE_LOOP))) {
|
||||
gtk_button_set_label(obj, "click here to open a file...");
|
||||
Error("Can't play the file");
|
||||
} else {
|
||||
gtk_button_set_label(obj, file);
|
||||
BASS_ChannelPlay(chan[speaker], FALSE);
|
||||
}
|
||||
g_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
void SwapClicked(GtkButton *obj, gpointer data)
|
||||
{
|
||||
const gchar *objname = gtk_widget_get_name(GTK_WIDGET(obj));
|
||||
int speaker = atoi(objname + 4) - 1; // get speaker pair number from button name ("swapX")
|
||||
{ // swap handles
|
||||
HSTREAM temp = chan[speaker];
|
||||
chan[speaker] = chan[speaker + 1];
|
||||
chan[speaker + 1] = temp;
|
||||
}
|
||||
{ // swap text
|
||||
GtkButton *open1, *open2;
|
||||
char bname[10], *temp;
|
||||
sprintf(bname, "open%d", 1 + speaker);
|
||||
open1 = GTK_BUTTON(GetWidget(bname));
|
||||
sprintf(bname, "open%d", 1 + speaker + 1);
|
||||
open2 = GTK_BUTTON(GetWidget(bname));
|
||||
temp = strdup(gtk_button_get_label(open1));
|
||||
gtk_button_set_label(open1, gtk_button_get_label(open2));
|
||||
gtk_button_set_label(open2, temp);
|
||||
free(temp);
|
||||
}
|
||||
// update the channel devices
|
||||
BASS_ChannelFlags(chan[speaker], flags[speaker], BASS_SPEAKER_FRONT);
|
||||
BASS_ChannelFlags(chan[speaker + 1], flags[speaker + 1], BASS_SPEAKER_FRONT);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
regex_t fregex;
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
Error("An incorrect version of BASS was loaded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize default device
|
||||
if (!BASS_Init(-1, 44100, 0, NULL, NULL)) {
|
||||
Error("Can't initialize device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize GUI
|
||||
glade = glade_xml_new(GLADE_PATH"speakers.glade", NULL, NULL);
|
||||
if (!glade) return 0;
|
||||
win = GetWidget("window1");
|
||||
if (!win) return 0;
|
||||
glade_xml_signal_autoconnect(glade);
|
||||
|
||||
{ // check how many speakers the device supports
|
||||
BASS_INFO i;
|
||||
BASS_GetInfo(&i);
|
||||
if (i.speakers < 8) {
|
||||
gtk_widget_set_sensitive(GetWidget("open4"), FALSE);
|
||||
gtk_widget_set_sensitive(GetWidget("swap3"), FALSE);
|
||||
}
|
||||
if (i.speakers < 6) {
|
||||
gtk_widget_set_sensitive(GetWidget("open3"), FALSE);
|
||||
gtk_widget_set_sensitive(GetWidget("swap2"), FALSE);
|
||||
}
|
||||
if (i.speakers < 4) {
|
||||
gtk_widget_set_sensitive(GetWidget("open2"), FALSE);
|
||||
gtk_widget_set_sensitive(GetWidget("swap1"), FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
{ // initialize file selector
|
||||
GtkFileFilter *filter;
|
||||
filesel = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "Playable files");
|
||||
regcomp(&fregex, "\\.(mo3|xm|mod|s3m|it|umx|mp[1-3]|ogg|wav|aif)$", REG_ICASE | REG_NOSUB | REG_EXTENDED);
|
||||
gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, FileExtensionFilter, &fregex, NULL);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "All files");
|
||||
gtk_file_filter_add_pattern(filter, "*");
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
}
|
||||
|
||||
gtk_widget_show(win);
|
||||
gtk_main();
|
||||
|
||||
gtk_widget_destroy(filesel);
|
||||
regfree(&fregex);
|
||||
|
||||
BASS_Free();
|
||||
|
||||
return 0;
|
||||
}
|
282
bass-sys/linux/bass24/speakers/speakers.glade
Normal file
282
bass-sys/linux/bass24/speakers/speakers.glade
Normal file
|
@ -0,0 +1,282 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<glade-interface>
|
||||
<widget class="GtkWindow" id="window1">
|
||||
<property name="width_request">450</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">BASS multi-speaker example</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">GTK_WIN_POS_CENTER</property>
|
||||
<signal name="destroy" handler="WindowDestroy"/>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">6</property>
|
||||
<property name="bottom_padding">10</property>
|
||||
<property name="left_padding">10</property>
|
||||
<property name="right_padding">10</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="open1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">click here to open a file...</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="OpenClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">1 - front</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="swap1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">swap</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="SwapClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="padding">10</property>
|
||||
<property name="pack_type">GTK_PACK_END</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment2">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">6</property>
|
||||
<property name="bottom_padding">10</property>
|
||||
<property name="left_padding">10</property>
|
||||
<property name="right_padding">10</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="open2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">click here to open a file...</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="OpenClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">2 - rear</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox4">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="swap2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">swap</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="SwapClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="padding">10</property>
|
||||
<property name="pack_type">GTK_PACK_END</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment3">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">6</property>
|
||||
<property name="bottom_padding">10</property>
|
||||
<property name="left_padding">10</property>
|
||||
<property name="right_padding">10</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox6">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="open3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">click here to open a file...</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="OpenClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">3 - center/FLE</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox5">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="swap3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">swap</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="SwapClicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="padding">10</property>
|
||||
<property name="pack_type">GTK_PACK_END</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">GTK_SHADOW_OUT</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment4">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">6</property>
|
||||
<property name="bottom_padding">10</property>
|
||||
<property name="left_padding">10</property>
|
||||
<property name="right_padding">10</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox7">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="open4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">click here to open a file...</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="OpenClicked"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">4 - rear center</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
9
bass-sys/linux/bass24/spectrum/makefile
Normal file
9
bass-sys/linux/bass24/spectrum/makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
TARGET = spectrum
|
||||
PACKAGES = gtk+-2.0
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
241
bass-sys/linux/bass24/spectrum/spectrum.c
Normal file
241
bass-sys/linux/bass24/spectrum/spectrum.c
Normal file
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
BASS spectrum analyser example
|
||||
Copyright (c) 2002-2012 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
#include <math.h>
|
||||
#include "bass.h"
|
||||
|
||||
#define SPECWIDTH 368 // display width (should be multiple of 4)
|
||||
#define SPECHEIGHT 127 // height (changing requires palette adjustments too)
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
BYTE rgbRed, rgbGreen, rgbBlue;
|
||||
} RGB;
|
||||
#pragma pack()
|
||||
|
||||
GtkWidget *win = 0;
|
||||
|
||||
DWORD chan;
|
||||
|
||||
GtkWidget *speci;
|
||||
GdkPixbuf *specpb;
|
||||
RGB palette[256];
|
||||
|
||||
int specmode = 0, specpos = 0; // spectrum mode (and marker pos for 2nd mode)
|
||||
|
||||
// display error messages
|
||||
void Error(const char *es)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s\n(error code: %d)", es, BASS_ErrorGetCode());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
void WindowDestroy(GtkObject *obj, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
void WindowButtonRelease(GtkWidget *obj, GdkEventButton *event, gpointer data)
|
||||
{
|
||||
if (event->type == GDK_BUTTON_RELEASE) {
|
||||
RGB *specbuf = (RGB*)gdk_pixbuf_get_pixels(specpb);
|
||||
specmode = (specmode + 1) % 4; // next spectrum mode
|
||||
memset(specbuf, 0, SPECWIDTH * SPECHEIGHT * sizeof(*specbuf)); // clear display
|
||||
}
|
||||
}
|
||||
|
||||
gboolean FileExtensionFilter(const GtkFileFilterInfo *info, gpointer data)
|
||||
{
|
||||
return !regexec((regex_t*)data, info->filename, 0, NULL, 0);
|
||||
}
|
||||
|
||||
// select a file to play, and play it
|
||||
BOOL PlayFile()
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
regex_t fregex;
|
||||
GtkWidget *filesel; // file selector
|
||||
GtkFileFilter *filter;
|
||||
filesel = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "Playable files");
|
||||
regcomp(&fregex, "\\.(mo3|xm|mod|s3m|it|umx|mp[1-3]|ogg|wav|aif)$", REG_ICASE | REG_NOSUB | REG_EXTENDED);
|
||||
gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, FileExtensionFilter, &fregex, NULL);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "All files");
|
||||
gtk_file_filter_add_pattern(filter, "*");
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filesel), filter);
|
||||
if (gtk_dialog_run(GTK_DIALOG(filesel)) == GTK_RESPONSE_ACCEPT) {
|
||||
char *file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel));
|
||||
gtk_widget_hide(filesel);
|
||||
if (!(chan = BASS_StreamCreateFile(FALSE, file, 0, 0, BASS_SAMPLE_LOOP))
|
||||
&& !(chan = BASS_MusicLoad(FALSE, file, 0, 0, BASS_MUSIC_RAMP | BASS_SAMPLE_LOOP, 1))) {
|
||||
Error("Can't play file");
|
||||
} else {
|
||||
BASS_ChannelPlay(chan, FALSE);
|
||||
ret = TRUE;
|
||||
}
|
||||
g_free(file);
|
||||
}
|
||||
gtk_widget_destroy(filesel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// update the spectrum display - the interesting bit :)
|
||||
gboolean UpdateSpectrum(gpointer data)
|
||||
{
|
||||
int x, y, y1;
|
||||
RGB *specbuf = (RGB*)gdk_pixbuf_get_pixels(specpb);
|
||||
|
||||
if (specmode == 3) { // waveform
|
||||
int c;
|
||||
float *buf;
|
||||
BASS_CHANNELINFO ci;
|
||||
memset(specbuf, 0, SPECWIDTH * SPECHEIGHT * sizeof(*specbuf));
|
||||
BASS_ChannelGetInfo(chan, &ci); // get number of channels
|
||||
buf = alloca(ci.chans * SPECWIDTH * sizeof(float)); // allocate buffer for data
|
||||
BASS_ChannelGetData(chan, buf, (ci.chans * SPECWIDTH * sizeof(float)) | BASS_DATA_FLOAT); // get the sample data (floating-point to avoid 8 & 16 bit processing)
|
||||
for (c = 0; c < ci.chans; c++) {
|
||||
for (x = 0; x < SPECWIDTH; x++) {
|
||||
int v = (1 - buf[x * ci.chans + c]) * SPECHEIGHT / 2; // invert and scale to fit display
|
||||
if (v < 0) v = 0;
|
||||
else if (v >= SPECHEIGHT) v = SPECHEIGHT - 1;
|
||||
if (!x) y = v;
|
||||
do { // draw line from previous sample...
|
||||
if (y < v) y++;
|
||||
else if (y > v) y--;
|
||||
specbuf[y * SPECWIDTH + x] = palette[c & 1 ? 127 : 1]; // left=green, right=red (could add more colours to palette for more chans)
|
||||
} while (y != v);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
float fft[1024];
|
||||
BASS_ChannelGetData(chan, fft, BASS_DATA_FFT2048); // get the FFT data
|
||||
|
||||
if (!specmode) { // "normal" FFT
|
||||
memset(specbuf, 0, SPECWIDTH * SPECHEIGHT * sizeof(*specbuf));
|
||||
for (x = 0; x < SPECWIDTH / 2; x++) {
|
||||
#if 1
|
||||
y = sqrt(fft[x + 1]) * 3 * SPECHEIGHT - 4; // scale it (sqrt to make low values more visible)
|
||||
#else
|
||||
y = fft[x + 1] * 10 * SPECHEIGHT; // scale it (linearly)
|
||||
#endif
|
||||
if (y > SPECHEIGHT) y = SPECHEIGHT; // cap it
|
||||
if (x && (y1 = (y + y1) / 2)) // interpolate from previous to make the display smoother
|
||||
while (--y1 >= 0) specbuf[(SPECHEIGHT - 1 - y1) * SPECWIDTH + x * 2 - 1] = palette[y1 + 1];
|
||||
y1 = y;
|
||||
while (--y >= 0) specbuf[(SPECHEIGHT - 1 - y) * SPECWIDTH + x * 2] = palette[y + 1]; // draw level
|
||||
}
|
||||
} else if (specmode == 1) { // logarithmic, acumulate & average bins
|
||||
int b0 = 0;
|
||||
memset(specbuf, 0, SPECWIDTH * SPECHEIGHT * sizeof(*specbuf));
|
||||
#define BANDS 28
|
||||
for (x = 0; x < BANDS; x++) {
|
||||
float peak = 0;
|
||||
int b1 = pow(2, x * 10.0 / (BANDS - 1));
|
||||
if (b1 > 1023) b1 = 1023;
|
||||
if (b1 <= b0) b1 = b0 + 1; // make sure it uses at least 1 FFT bin
|
||||
for (; b0 < b1; b0++)
|
||||
if (peak < fft[1 + b0]) peak = fft[1 + b0];
|
||||
y = sqrt(peak) * 3 * SPECHEIGHT - 4; // scale it (sqrt to make low values more visible)
|
||||
if (y > SPECHEIGHT) y = SPECHEIGHT; // cap it
|
||||
while (--y >= 0)
|
||||
for (y1 = 0; y1 < SPECWIDTH / BANDS - 2; y1++)
|
||||
specbuf[(SPECHEIGHT - 1 - y) * SPECWIDTH + x * (SPECWIDTH / BANDS) + y1] = palette[y + 1]; // draw bar
|
||||
}
|
||||
} else { // "3D"
|
||||
for (x = 0; x < SPECHEIGHT; x++) {
|
||||
y = sqrt(fft[x + 1]) * 3 * 127; // scale it (sqrt to make low values more visible)
|
||||
if (y > 127) y = 127; // cap it
|
||||
specbuf[(SPECHEIGHT - 1 - x) * SPECWIDTH + specpos] = palette[128 + y]; // plot it
|
||||
}
|
||||
// move marker onto next position
|
||||
specpos = (specpos + 1) % SPECWIDTH;
|
||||
for (x = 0; x < SPECHEIGHT; x++) specbuf[x * SPECWIDTH + specpos] = palette[255];
|
||||
}
|
||||
}
|
||||
|
||||
gtk_image_set_from_pixbuf(GTK_IMAGE(speci), specpb); // update the display
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
Error("An incorrect version of BASS was loaded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize BASS
|
||||
if (!BASS_Init(-1, 44100, 0, NULL, NULL)) {
|
||||
Error("Can't initialize device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PlayFile()) { // start a file playing
|
||||
BASS_Free();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// create the window
|
||||
win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER);
|
||||
gtk_window_set_resizable(GTK_WINDOW(win), FALSE);
|
||||
gtk_window_set_title(GTK_WINDOW(win), "BASS spectrum example (click to toggle mode)");
|
||||
g_signal_connect(win, "destroy", GTK_SIGNAL_FUNC(WindowDestroy), NULL);
|
||||
|
||||
GtkWidget *ebox = gtk_event_box_new();
|
||||
gtk_container_add(GTK_CONTAINER(win), ebox);
|
||||
g_signal_connect(ebox, "button-release-event", GTK_SIGNAL_FUNC(WindowButtonRelease), NULL);
|
||||
|
||||
// create the bitmap
|
||||
specpb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, SPECWIDTH, SPECHEIGHT);
|
||||
speci = gtk_image_new_from_pixbuf(specpb);
|
||||
gtk_container_add(GTK_CONTAINER(ebox), speci);
|
||||
|
||||
{ // setup palette
|
||||
RGB *pal = palette;
|
||||
int a;
|
||||
memset(palette, 0, sizeof(palette));
|
||||
for (a = 1; a < 128; a++) {
|
||||
pal[a].rgbGreen = 256 - 2 * a;
|
||||
pal[a].rgbRed = 2 * a;
|
||||
}
|
||||
for (a = 0; a < 32; a++) {
|
||||
pal[128 + a].rgbBlue = 8 * a;
|
||||
pal[128 + 32 + a].rgbBlue = 255;
|
||||
pal[128 + 32 + a].rgbRed = 8 * a;
|
||||
pal[128 + 64 + a].rgbRed = 255;
|
||||
pal[128 + 64 + a].rgbBlue = 8 * (31 - a);
|
||||
pal[128 + 64 + a].rgbGreen = 8 * a;
|
||||
pal[128 + 96 + a].rgbRed = 255;
|
||||
pal[128 + 96 + a].rgbGreen = 255;
|
||||
pal[128 + 96 + a].rgbBlue = 8 * a;
|
||||
}
|
||||
}
|
||||
|
||||
// setup update timer (40hz)
|
||||
g_timeout_add(25, UpdateSpectrum, NULL);
|
||||
|
||||
gtk_widget_show_all(win);
|
||||
gtk_main();
|
||||
|
||||
g_object_unref(specpb);
|
||||
|
||||
BASS_Free();
|
||||
|
||||
return 0;
|
||||
}
|
9
bass-sys/linux/bass24/synth/makefile
Normal file
9
bass-sys/linux/bass24/synth/makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
TARGET = synth
|
||||
PACKAGES = gtk+-2.0 libglade-2.0
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
146
bass-sys/linux/bass24/synth/synth.c
Normal file
146
bass-sys/linux/bass24/synth/synth.c
Normal file
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
BASS simple synth
|
||||
Copyright (c) 2001-2017 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <glade/glade.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "bass.h"
|
||||
|
||||
// path to glade file
|
||||
#ifndef GLADE_PATH
|
||||
#define GLADE_PATH ""
|
||||
#endif
|
||||
|
||||
GladeXML *glade;
|
||||
GtkWidget *win = 0;
|
||||
|
||||
BASS_INFO info;
|
||||
HSTREAM stream; // the stream
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#define KEYS 20
|
||||
const guint keys[KEYS] = {
|
||||
'Q','2','W','3','E','R','5','T','6','Y','7','U',
|
||||
'I','9','O','0','P', GDK_bracketleft, GDK_equal, GDK_bracketright
|
||||
};
|
||||
#define MAXVOL 0.22
|
||||
#define DECAY (MAXVOL/4000)
|
||||
float vol[KEYS] = { 0 }, pos[KEYS]; // keys' volume and pos
|
||||
|
||||
const DWORD fxtype[5] = { BASS_FX_DX8_CHORUS,BASS_FX_DX8_DISTORTION,BASS_FX_DX8_ECHO,BASS_FX_DX8_FLANGER,BASS_FX_DX8_REVERB };
|
||||
HFX fx[5] = { 0 }; // effect handles
|
||||
|
||||
// display error messages
|
||||
void Error(const char *es)
|
||||
{
|
||||
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s\n(error code: %d)", es, BASS_ErrorGetCode());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
#define GetWidget(id) glade_xml_get_widget(glade,id)
|
||||
|
||||
void WindowDestroy(GtkObject *obj, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
DWORD CALLBACK WriteStream(HSTREAM handle, float *buffer, DWORD length, void *user)
|
||||
{
|
||||
int k, c;
|
||||
float omega, s;
|
||||
memset(buffer, 0, length);
|
||||
for (k = 0; k < KEYS; k++) {
|
||||
if (!vol[k]) continue;
|
||||
omega = 2 * M_PI * pow(2.0, (k + 3) / 12.0) * 440.0 / info.freq;
|
||||
for (c = 0; c < length / sizeof(float); c += 2) {
|
||||
buffer[c] += sin(pos[k]) * vol[k];
|
||||
buffer[c + 1] = buffer[c]; // left and right channels are the same
|
||||
pos[k] += omega;
|
||||
if (vol[k] < MAXVOL) {
|
||||
vol[k] -= DECAY;
|
||||
if (vol[k] <= 0) { // faded-out
|
||||
vol[k] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
pos[k] = fmod(pos[k], 2 * M_PI);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
void FXToggled(GtkToggleButton *obj, gpointer data)
|
||||
{ // toggle effects
|
||||
const gchar *objname = gtk_widget_get_name(GTK_WIDGET(obj));
|
||||
int n = atoi(objname + 2);
|
||||
if (fx[n]) {
|
||||
BASS_ChannelRemoveFX(stream, fx[n]);
|
||||
fx[n] = 0;
|
||||
} else
|
||||
fx[n] = BASS_ChannelSetFX(stream, fxtype[n], 0);
|
||||
}
|
||||
|
||||
gboolean KeyHandler(GtkWidget *grab_widget, GdkEventKey *event, gpointer data)
|
||||
{
|
||||
int key, kv = event->keyval;
|
||||
if (kv >= 'a' && kv <= 'z') kv -= 0x20;
|
||||
for (key = 0; key < KEYS; key++) {
|
||||
if (kv == keys[key]) {
|
||||
if (event->type == GDK_KEY_PRESS && vol[key] < MAXVOL) {
|
||||
pos[key] = 0;
|
||||
vol[key] = MAXVOL + DECAY / 2; // start key (setting "vol" slightly higher than MAXVOL to cover any rounding-down)
|
||||
} else if (event->type == GDK_KEY_RELEASE && vol[key])
|
||||
vol[key] -= DECAY; // trigger key fadeout
|
||||
break;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
Error("An incorrect version of BASS was loaded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize default output device
|
||||
if (!BASS_Init(-1, 44100, 0, NULL, NULL)) {
|
||||
Error("Can't initialize device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize GUI
|
||||
glade = glade_xml_new(GLADE_PATH"synth.glade", NULL, NULL);
|
||||
if (!glade) return 0;
|
||||
win = GetWidget("window1");
|
||||
if (!win) return 0;
|
||||
glade_xml_signal_autoconnect(glade);
|
||||
|
||||
BASS_GetInfo(&info);
|
||||
stream = BASS_StreamCreate(info.freq, 2, BASS_SAMPLE_FLOAT, (STREAMPROC*)WriteStream, 0); // create a stream (stereo for effects)
|
||||
BASS_ChannelSetAttribute(stream, BASS_ATTRIB_BUFFER, 0); // no buffering for minimum latency
|
||||
BASS_ChannelPlay(stream, FALSE); // start it
|
||||
|
||||
g_signal_connect(win, "key-press-event", G_CALLBACK(KeyHandler), NULL);
|
||||
g_signal_connect(win, "key-release-event", G_CALLBACK(KeyHandler), NULL);
|
||||
|
||||
gtk_main();
|
||||
|
||||
BASS_Free();
|
||||
|
||||
return 0;
|
||||
}
|
174
bass-sys/linux/bass24/synth/synth.glade
Normal file
174
bass-sys/linux/bass24/synth/synth.glade
Normal file
|
@ -0,0 +1,174 @@
|
|||
<?xml version="1.0"?>
|
||||
<glade-interface>
|
||||
<!-- interface-requires gtk+ 2.8 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<widget class="GtkWindow" id="window1">
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">BASS simple sinewave synth</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">center</property>
|
||||
<signal name="destroy" handler="WindowDestroy"/>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">out</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment2">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">6</property>
|
||||
<property name="bottom_padding">10</property>
|
||||
<property name="left_padding">20</property>
|
||||
<property name="right_padding">20</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="keys">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><big><tt> 2 3 5 6 7 9 0 =
|
||||
Q W ER T Y UI O P[ ]</tt></big></property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">center</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Press these keys to play</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">out</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment4">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">6</property>
|
||||
<property name="bottom_padding">10</property>
|
||||
<property name="left_padding">10</property>
|
||||
<property name="right_padding">10</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="fx4">
|
||||
<property name="label" translatable="yes">reverb</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="FXToggled"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="fx2">
|
||||
<property name="label" translatable="yes">echo</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="FXToggled"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="fx0">
|
||||
<property name="label" translatable="yes">chorus</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="FXToggled"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="fx3">
|
||||
<property name="label" translatable="yes">flanger</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="FXToggled"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="fx1">
|
||||
<property name="label" translatable="yes">distortion</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="FXToggled"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label6">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Effects</property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
8
bass-sys/linux/bass24/writewav/makefile
Normal file
8
bass-sys/linux/bass24/writewav/makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
TARGET = writewav
|
||||
|
||||
include ../makefile.in
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGET)
|
BIN
bass-sys/linux/bass24/x64/libbass.so
Normal file
BIN
bass-sys/linux/bass24/x64/libbass.so
Normal file
Binary file not shown.
BIN
bass-sys/linux/bass24/x64/mp3-free/libbass.so
Normal file
BIN
bass-sys/linux/bass24/x64/mp3-free/libbass.so
Normal file
Binary file not shown.
BIN
bass-sys/win/bass24/bass.chm
Normal file
BIN
bass-sys/win/bass24/bass.chm
Normal file
Binary file not shown.
2127
bass-sys/win/bass24/bass.txt
Normal file
2127
bass-sys/win/bass24/bass.txt
Normal file
File diff suppressed because it is too large
Load diff
1160
bass-sys/win/bass24/c/bass.h
Normal file
1160
bass-sys/win/bass24/c/bass.h
Normal file
File diff suppressed because it is too large
Load diff
163
bass-sys/win/bass24/c/contest/contest.c
Normal file
163
bass-sys/win/bass24/c/contest/contest.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
BASS simple console player
|
||||
Copyright (c) 1999-2019 Un4seen Developments Ltd.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "bass.h"
|
||||
|
||||
#ifdef _WIN32 // Windows
|
||||
#include <conio.h>
|
||||
#else // OSX/Linux
|
||||
#include <sys/time.h>
|
||||
#include <termios.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define Sleep(x) usleep(x*1000)
|
||||
|
||||
int _kbhit()
|
||||
{
|
||||
int r;
|
||||
fd_set rfds;
|
||||
struct timeval tv = { 0 };
|
||||
struct termios term, oterm;
|
||||
tcgetattr(0, &oterm);
|
||||
memcpy(&term, &oterm, sizeof(term));
|
||||
cfmakeraw(&term);
|
||||
tcsetattr(0, TCSANOW, &term);
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(0, &rfds);
|
||||
r = select(1, &rfds, NULL, NULL, &tv);
|
||||
tcsetattr(0, TCSANOW, &oterm);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
// display error messages
|
||||
void Error(const char *text)
|
||||
{
|
||||
printf("Error(%d): %s\n", BASS_ErrorGetCode(), text);
|
||||
BASS_Free();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void ListDevices()
|
||||
{
|
||||
BASS_DEVICEINFO di;
|
||||
int a;
|
||||
for (a = 0; BASS_GetDeviceInfo(a, &di); a++) {
|
||||
if (di.flags & BASS_DEVICE_ENABLED) // enabled output device
|
||||
printf("dev %d: %s\n", a, di.name);
|
||||
}
|
||||
}
|
||||
|
||||
void main(int argc, char **argv)
|
||||
{
|
||||
DWORD chan, act, time, level;
|
||||
BOOL ismod;
|
||||
QWORD pos;
|
||||
int a, filep, device = -1;
|
||||
|
||||
printf("BASS simple console player\n"
|
||||
"--------------------------\n");
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
|
||||
printf("An incorrect version of BASS was loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
for (filep = 1; filep < argc; filep++) {
|
||||
if (!strcmp(argv[filep], "-l")) {
|
||||
ListDevices();
|
||||
return;
|
||||
} else if (!strcmp(argv[filep], "-d") && filep + 1 < argc) device = atoi(argv[++filep]);
|
||||
else break;
|
||||
}
|
||||
if (filep == argc) {
|
||||
printf("\tusage: contest [-l] [-d #] <file>\n"
|
||||
"\t-l = list devices\n"
|
||||
"\t-d = device number\n");
|
||||
return;
|
||||
}
|
||||
|
||||
BASS_SetConfig(BASS_CONFIG_NET_PLAYLIST, 1); // enable playlist processing
|
||||
BASS_SetConfig(BASS_CONFIG_NET_PREBUF_WAIT, 0); // disable BASS_StreamCreateURL pre-buffering
|
||||
|
||||
// initialize output device
|
||||
if (!BASS_Init(device, 44100, 0, 0, NULL))
|
||||
Error("Can't initialize device");
|
||||
|
||||
// try streaming the file/url
|
||||
if ((chan = BASS_StreamCreateFile(FALSE, argv[filep], 0, 0, BASS_SAMPLE_LOOP))
|
||||
|| (chan = BASS_StreamCreateURL(argv[filep], 0, BASS_SAMPLE_LOOP, 0, 0))) {
|
||||
pos = BASS_ChannelGetLength(chan, BASS_POS_BYTE);
|
||||
if (BASS_StreamGetFilePosition(chan, BASS_FILEPOS_DOWNLOAD) != -1) {
|
||||
// streaming from the internet
|
||||
if (pos != -1)
|
||||
printf("streaming internet file [%lld bytes]", pos);
|
||||
else
|
||||
printf("streaming internet file");
|
||||
} else
|
||||
printf("streaming file [%lld bytes]", pos);
|
||||
ismod = FALSE;
|
||||
} else {
|
||||
// try loading the MOD (with looping, sensitive ramping, and calculate the duration)
|
||||
if (!(chan = BASS_MusicLoad(FALSE, argv[filep], 0, 0, BASS_SAMPLE_LOOP | BASS_MUSIC_RAMPS | BASS_MUSIC_PRESCAN, 1)))
|
||||
// not a MOD either
|
||||
Error("Can't play the file");
|
||||
{ // count channels
|
||||
float dummy;
|
||||
for (a = 0; BASS_ChannelGetAttribute(chan, BASS_ATTRIB_MUSIC_VOL_CHAN + a, &dummy); a++);
|
||||
}
|
||||
printf("playing MOD music \"%s\" [%u chans, %u orders]",
|
||||
BASS_ChannelGetTags(chan, BASS_TAG_MUSIC_NAME), a, (DWORD)BASS_ChannelGetLength(chan, BASS_POS_MUSIC_ORDER));
|
||||
pos = BASS_ChannelGetLength(chan, BASS_POS_BYTE);
|
||||
ismod = TRUE;
|
||||
}
|
||||
|
||||
// display the time length
|
||||
if (pos != -1) {
|
||||
time = (DWORD)BASS_ChannelBytes2Seconds(chan, pos);
|
||||
printf(" %u:%02u\n", time / 60, time % 60);
|
||||
} else // no time length available
|
||||
printf("\n");
|
||||
|
||||
BASS_ChannelPlay(chan, FALSE);
|
||||
|
||||
while (!_kbhit() && (act = BASS_ChannelIsActive(chan))) {
|
||||
// display some stuff and wait a bit
|
||||
level = BASS_ChannelGetLevel(chan);
|
||||
pos = BASS_ChannelGetPosition(chan, BASS_POS_BYTE);
|
||||
time = BASS_ChannelBytes2Seconds(chan, pos);
|
||||
printf("pos %09llu", pos);
|
||||
if (ismod) {
|
||||
pos = BASS_ChannelGetPosition(chan, BASS_POS_MUSIC_ORDER);
|
||||
printf(" (%03u:%03u)", LOWORD(pos), HIWORD(pos));
|
||||
}
|
||||
printf(" - %u:%02u - L ", time / 60, time % 60);
|
||||
if (act == BASS_ACTIVE_STALLED) { // playback has stalled
|
||||
printf("- buffering: %3u%% -", 100 - (DWORD)BASS_StreamGetFilePosition(chan, BASS_FILEPOS_BUFFERING));
|
||||
} else {
|
||||
for (a = 27204; a > 200; a = a * 2 / 3) putchar(LOWORD(level) >= a ? '*' : '-');
|
||||
putchar(' ');
|
||||
for (a = 210; a < 32768; a = a * 3 / 2) putchar(HIWORD(level) >= a ? '*' : '-');
|
||||
}
|
||||
printf(" R - cpu %.2f%% \r", BASS_GetCPU());
|
||||
fflush(stdout);
|
||||
Sleep(50);
|
||||
}
|
||||
printf(" \r");
|
||||
|
||||
// wind the frequency down...
|
||||
BASS_ChannelSlideAttribute(chan, BASS_ATTRIB_FREQ, 1000, 500);
|
||||
Sleep(400);
|
||||
// ...and fade-out to avoid a "click"
|
||||
BASS_ChannelSlideAttribute(chan, BASS_ATTRIB_VOL | BASS_SLIDE_LOG, -1, 100);
|
||||
// wait for slide to finish (could use BASS_SYNC_SLIDE instead)
|
||||
while (BASS_ChannelIsSliding(chan, 0)) Sleep(1);
|
||||
|
||||
BASS_Free();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue