Bassix GTK3 webkit browser Wiki
A very small gtk3-webkit browser that runs well on the raspberry pi3
Brought to you by:
big-bass

Example code:bassix-radio-player.bac
place radio2.cfg in your home directory
install dependencies
sudo apt-get install mpg123
tested on linux mint 20.1 64 bit xfce
'--- bigbass GTK3 with FIXED placement and some new macros
'--- for the lack of a name we can call it gtk3 bassix
'--- a simple 'HUG' looking syntax idea but include only what you need as you go
'--- June 25 2020 --- UPDATED MAY 1 2021
'--- added dynamic combobox
'--- added songtrack automatically as a label
'--- added timeout and refresh July 12
OPTION PARSE FALSE
PRAGMA INCLUDE <gtk-3.0/gtk/gtk.h>
PRAGMA OPTIONS `pkg-config --cflags gtk+-3.0`
PRAGMA LDFLAGS `pkg-config --libs gtk+-3.0`
PRAGMA OPTIONS -Wno-deprecated-declarations
'--- new signal handlers to simplify the callbacks
DEF FN CONNECT( widget, event,cb) = g_signal_connect_data(widget,event,cb, 0, 0, 0)
DEF FN CONNECT_DATA( widget, event,cb,t) = g_signal_connect_data(G_OBJECT (widget),event,G_CALLBACK (cb),(gpointer) t, 0, 0)
DEF FN WINDOW_ADD() = gtk_window_new(GTK_WINDOW_TOPLEVEL)
DEF FN NEW(widget,...) = g_object_new(widget, __VA_ARGS__,NULL)
DEF FN PLACE( widget, name,wid,high) = gtk_fixed_put(GTK_FIXED(widget), GTK_WIDGET(name),wid,high)
DEF FN ADD_FIXED( widget, name) = gtk_container_add(GTK_CONTAINER(widget), GTK_WIDGET(name))
DEF FN SET(widget, name, ...) = g_object_set(GTK_WIDGET(widget), name, __VA_ARGS__, NULL)
DEF FN GET( widget, name, ...) = g_object_get(widget, name, __VA_ARGS__, NULL)
DEF FN SHOW( widget) = gtk_widget_show_all(GTK_WIDGET(widget))
DEF FN HIDE( widget) = gtk_widget_hide(GTK_WIDGET(widget))
DEF FN INIT() = gtk_init(0,0)
DEF FN LABEL_ADD(t) = gtk_label_new(t)
DEF FN BUTTON_ADD(t) = gtk_button_new_with_label(t)
DEF FN TEXT_VIEW() = gtk_text_view_new ()
DEF FN FIXED() = gtk_fixed_new()
DEF FN DISPLAY() = gtk_main()
DEF FN ATTACH() = gtk_container_add()
DEF FN SCROLLED_WINDOW() = gtk_scrolled_window_new (NULL, NULL)
DEF FN STREAM(im) = g_memory_input_stream_new_from_data(im, -1, g_free)
DEF FN PIXBUF_MEM(stm) = gdk_pixbuf_new_from_stream(stm, NULL, NULL)
DEF FN PIXBUFF(p) = gtk_image_new_from_pixbuf (p )
DEF FN SET_IMAGE(widget,im) = gtk_button_set_image (GTK_BUTTON (widget), im)
DEF FN IMAGE_FILE(f) = gtk_image_new_from_file(f)
DEF FN COMBO() = gtk_combo_box_text_new ()
DEF FN COMBO_GET(c) = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT(c))
DEF FN COMBO_ACTIVE(c) = gtk_combo_box_get_active (GTK_COMBO_BOX(c))
DEF FN COMBO_ADD(widget,arr) = gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), arr)
DEF FN VOLUME_GET(widget) = gtk_scale_button_get_value(GTK_SCALE_BUTTON(widget))
DEF FN VOLUME() = gtk_volume_button_new()
DEF FN TIMEOUT_ADD(n,cb) = g_timeout_add(n,(GSourceFunc) cb, NULL)
DEF FN REMOVE_TIMEOUT(id) = g_source_remove(id)
ALIAS GTK_TYPE_WINDOW TO WINDOW
ALIAS GTK_TYPE_BUTTON TO BUTTON
ALIAS GTK_WIDGET TO WIDGET
ALIAS GTK_CONTAINER TO CONTAINER
ALIAS g_free TO FREE
DECLARE window, scrolled_win ,exit_btn ,image ,label2 TYPE GtkWidget*
DECLARE fixed TYPE GtkWidget*
DECLARE image2 TYPE GtkWidget*
DECLARE VOLUME2 TYPE GtkWidget*
DECLARE combo_box TYPE GtkWidget*
'=====================
SUB exit_prog
'=====================
CLEAR
SYSTEM(" killall mpg123 ")
SLEEP 100
DELETE FILE "/tmp/MPG123_file.txt"
END
END SUB
'=====================
SUB exit_clicked ()
'=====================
CLEAR
SYSTEM(" killall mpg123 ")
SLEEP 100
DELETE FILE "/tmp/MPG123_file.txt"
END
END SUB
SUB song_title_cb
HIDE(label2)
count = 0
REPEAT
SLEEP 200
LIVE_DATA$ = EXEC$("tail -n 1 /tmp/MPG123_file.txt &")
'---now we will use bacon to parse for StreamTitle
track$ = INBETWEEN$(LIVE_DATA$ , "StreamTitle='", "';")
INCR count
UNTIL LEN(track$) !=0 OR count > 35
'PRINT "live data test:",LIVE_DATA$
'---if no track is found in 3.5 seconds give up on the title
'--- offer a visual aid if found + not found - as the icon
IF LEN(track$) !=0 THEN
SET(window, "icon-name","gtk-add")
IF LEN(track$) > 70 THEN
track$ = ALIGN$(track$, 70, 0)
END IF
'SET(label2, "label", track$)
label2 = LABEL_ADD(track$)
PLACE(fixed ,label2,5,45)
SHOW(label2)
ELSE
SET(window, "icon-name","gtk-remove")
END IF
END SUB
'======================================================
SUB on_changed (GtkComboBox *widget, void* user_data)
'======================================================
IF FILEEXISTS( "/tmp/MPG123_file.txt") THEN
DELETE FILE "/tmp/MPG123_file.txt"
END IF
'LOCAL combo_box TYPE GtkComboBox*
'combo_box = widget
CLEAR
'--- we dont want more than one station playing at a time
SYSTEM(" killall mpg123 & ")
LOCAL distro TYPE STRING
'---get matching url is the index_num
index_num = COMBO_ACTIVE(combo_box)
distro = COMBO_GET(combo_box)
HIDE(label2)
PRINT distro FORMAT "%s\n"
PRINT url$[index_num] FORMAT "%s\n"
SETENVIRON "result_selected",url$[index_num]
SYSTEM("mpg123 $result_selected 2> /tmp/MPG123_file.txt&")
TIMEOUT_ADD(500,song_title_cb)
END SUB
' ==============================
SUB VOLUME2_CB(long widget, void* user_data)
' ==============================
PRINT "VOLUME2_CB"
'---we use strings to set env
LOCAL audio_level_bacon$ TYPE STRING
LOCAL audio_level_bacon TYPE double
PRINT VOLUME_GET(VOLUME2) FORMAT "%.1f\n"
audio_level_bacon = VOLUME_GET(VOLUME2)
'---a hack to get scale 1-100
audio_level_bacon = audio_level_bacon * 100
audio_level_bacon$= STR$(audio_level_bacon)
SETENVIRON "audio_level_bacon",audio_level_bacon$
'---debug whats happenning in the low level
sys_vol$ = EXEC$("echo $audio_level_bacon")
PRINT "sys volume: ",sys_vol$
SYSTEM "amixer -D pulse sset Master $audio_level_bacon% &"
END SUB
'---main code
INIT
'--- you could place all properties in the NEW() or use SET
'--- and add what you need as you go
window = WINDOW_ADD()
'--- widget ,property , value or string
SET(window, "icon-name", "media-record")
SET(window, "title", "Internet Radio auto title Bassix ")
SET(window, "resizable", TRUE)
SET(window, "border-width", 10, "default-width", 590)
SET(window, "default-height", 30)
'--- place window into the fixed container
fixed = FIXED()
ADD_FIXED(window, fixed)
'---new button and label
exit_btn = BUTTON_ADD ("Exit")
SET(exit_btn, "width_request", 80 ,"height_request",30)
SET(exit_btn, "tooltip-text", "EXIT")
'---make sure the image is visible
SET(exit_btn, "always_show_image",TRUE)
SET(exit_btn, "label","gtk-quit","use_stock",TRUE)
'---placement inside fixed,widget,X,Y
PLACE (fixed, exit_btn, 550, 5)
SET(exit_btn, "width_request", 80 ,"height_request",30)
SET(exit_btn, "tooltip-text", "refresh")
refresh_btn = BUTTON_ADD ("Refresh")
'---make sure the image is visible
SET(refresh_btn, "always_show_image",TRUE)
SET(refresh_btn, "label","gtk-refresh","use_stock",TRUE)
'---placement inside fixed,widget,X,Y
PLACE (fixed, refresh_btn, 390, 5)
'---volume button , settings and placement
VOLUME2 = VOLUME()
SET(VOLUME2, "size", GTK_ICON_SIZE_DND)
PLACE (fixed, VOLUME2, 500, 5)
'--- handle callbacks widget,event,sub or function
CONNECT(window, "delete-event", exit_prog)
CONNECT(exit_btn, "clicked" ,exit_clicked )
'---DYNAMIC COMBO BOX read in a file
LOCAL i TYPE int
LOCAL view TYPE GtkWidget*
'--- Create the combo box and append your string values to it.
combo_box = COMBO()
SET(combo_box, "height_request",10)
SET(combo_box, "width_request", 80)
'--- make a dynamic combobox read in any type of file
'--- get names of station left side of pipe
result_input$ = CHOP$(EXEC$("cat ~/radio2.cfg | cut -d'|' -f1"))
'--- get urls right side of pipe
result_input2$ = CHOP$(EXEC$("cat ~/radio2.cfg | cut -d'|' -f2"))
SPLIT result_input$ BY NL$ TO words$ SIZE dim
FOR i = 0 TO dim - 1
COMBO_ADD(combo_box,words$[i])
NEXT
'--- a 2D array split in two parts station and url
SPLIT result_input2$ BY NL$ TO url$ SIZE dim2
'---second url
FOR i = 0 TO dim2 -1
IF NOT(INSTR(url$[i],"cannot access")) THEN
PRINT url$[i] TO SIZE 8098
CLEAR
'--- going to save the url part in memory
ENDIF
NEXT
'--- Choose to set the first option as the active one by default
SET(combo_box, "active",0)
CONNECT_DATA(combo_box, "changed",on_changed,NULL)
CONNECT_DATA(VOLUME2, "value-changed",VOLUME2_CB ,NULL)
CONNECT_DATA(refresh_btn, "clicked",song_title_cb ,NULL)
label2 = LABEL_ADD("")
PLACE (fixed, combo_box, 5, 5)
SHOW(window)
HIDE(label2)
'---got the g_timeout working for bassix
DISPLAY