Linux Window Managers and Distributions

Last Updated or created 2023-10-05

Linux OSses I currently use : Ubuntu, Centos/Rocky/Fedora, Raspbian
(and msdos lol)
Have used:
Slackware,Gentoo, Kali, ELive, Suse,Debian,Mint,Puppy,Lubuntu

Window managers I currently use

  • Xmonad – Tiling window manager
  • Gnome
Xmonad with clusterssh on 14 servers. (Using my serverpath identify trick)

See also :

Screenshots from old desktops

I have to add some recent screenshots.

Fluxbox, Compiz, Xfwm4, Ratpoison

Identifying asian languages

Last Updated or created 2023-10-05

My girlfriend sometimes asks me what country/language is that?
(When seeing written text or hearing people talk)

I’ve studied japanese a long time ago, and I still can read some characters. Sometimes the western words are translated using katakana.
Those are easier. ( For years i had a little card in my wallet with katakana, written a large japanese scroll on ricepaper, a computer demo and terminal tools)

Modern Japanese is written in a mixture of three basic scripts: Kanji — which are Chinese ideographic symbols — as well as Hiragana and Katakana — two phonetic alphabets (syllables). There are a few thousand Kanji characters, while Hiragana and Katakana have 46 each

Katakana chart
ア a イ i ウ u エ e オ o
カ ka キ ki ク ku ケ ke コ ko
サ sa シ shi ス su セ se ソ so
タ ta チ chi ツ tsu テ te ト to
ナ na ニ ni ヌ nu ネ ne ノ no
ハ ha ヒ hi フ fu ヘ he ホ ho
マ ma ミ mi ム mu メ me モ mo
ヤ ya ユ yu ヨ yo
ラ ra リ ri ル ru レ re ロ ro
ワ wa
ン n

So mostly a consonant combined with a vowel.
A dash – for a dubble vowel, and a u can be silent.

My name is ヘンリ

In my mind i use below to identify languages.

  • Indian: Lines with things hanging from it
  • Thai: round stuff with circles
  • Korean: straight lines with circles
  • Chinese: Very busy lines (blocks filled with lines)
  • Japanese: Blocks with lines alternated with simple characters
  • Vietnamese: They borrow chinese characters, rest “western” with dots and ^ ‘ stuff

Spoken language is difficult to explain, but these guys nail it.

Movie stabilisation and music suggestions

Last Updated or created 2023-10-05

Some suggestions/answers for some friends.

Movie stabilisation from action cams:

Mostly I use kdenlive, but if you have an actioncam which also records movement (pan, tilt, zoom, and rotation) use a tool like Gyroflow!
This will use the motion data to correct the movement!

https://userbase.kde.org/Kdenlive/Manual/Clip_Menu/Stabilize

I’ve tried Davinci Resolve also. But I’m not sure which i’ve used for below movies.

Using blender : https://www.youtube.com/watch?v=oCHjdEODrpM
OR https://www.youtube.com/watch?v=982RL4a899g

Me flying a Cessna 172
Arja on the Death Road in Bolivia (8x speed and stabilzed)

If you want even an easier way, upload to YT, stabilise and download you movie. 🙂

Something else, what music to listen to? Any suggestions?

I had to name some (most by heart), I will edit/alter this list.
The folk/pipes artists will be in a next post.

Heavier stuff:
The prodigy, nightwish, in extremo, tanzwut, after forever, faun, gathering, therion, withintemptation

Folky
Trolska polska, dervish, gaelic storm, lunasa, michael mcgoldrick, peatbog faeries, beoga

Jazzy folk
Borne and mcleod, Bees Knees (Hamish moore and dick lee)

Film music
Akira, Vangelis (bladerunner), Kill Bill music (all kinds of sources)

Electro
Junky-xl, Trentemoller, Alt-j, Avcii

Classical
Einaudi, ennio morricone, Paganini,Rondò Veneziano

Easy listening
Aereda, Andreas Vollenweider,Anuna, Clannad, Dead can danve, enya, Era, Lais, kitaro, Moya Brennan,omnia

Blues
BB King

Divers
Alva Noto and Ryuichi Sakamoto, Buddha bar, Buena Vista Social Club, Cafe del mar, Mark Knopfler, Easy Alohas

Indie
Kensington, Imagine Dragons, 77 bombay street, Mumford and Sons, Lumineers, Of monsters and men,

Scottish Rock
Runrig

Find other music/genre’s

NFO creator with poster art generator

Last Updated or created 2023-10-05

Created this for usage with Kodi, for our own personal movies, which can’t be scraped by movie scrapers obviously.
(dvd-rip,digital video, mobile movies, OBS, Vuze and Nikon movies for example)

UPDATE V2 added functions

This is a followup on:

Works on Windows also!

Needed libraries: (install with pip)
pathlib, Pillow, pymediainfo,PySimpleGUI,python-vlc

NFO created

Title – editable (generated from filename)
Duration – mediainfo data in seconds
Plot – Single line type it yourself
Actors – Predefined
Tags – Predefined checkboxes
Country – Pulldown ( I use this as location, Scotland, Asia, Garden)
Year – default 2023, copy button from mobile phone metadata year
Genre – Pulldown

Works

  • File select and loaded
  • Play movie, scrub thretro movie
  • Create snapshot
  • Play/Mute/Pause
  • Playtimer
  • Auto update NFO text field with selectable options
  • Poster art – rotate
  • Poster art – brightness
  • Reload Thumb after snapshotting
  • Year extracted from filename
  • add tag field
  • Next file (button AND functionality)
  • checkboxes from text list
  • Read NFO from file into fields
  • Poster art – aspect ratio

Needs work

Wish list

  • Poster art – contrast?
  • Low – more mediainfo?
  • Low – Media rotate??

The GUI in action (V1)

Kodi example

CODE ( WIP ) V2
I place this python script in every library directory. So i can change the checkboxes and the NFO being generated.
I fill the directory with symlinks for every movie I want to have included in this directory, but this is not needed. (thats the way I like to do things)
(This is the directory I scrape into Kodi)

from pathlib import Path
from sys import platform as PLATFORM
import os
import re
import PySimpleGUI as sg
import vlc
from pymediainfo import MediaInfo
from PIL import Image, ImageEnhance, ImageTk, ImageOps, ImageFilter
from xml.etree import ElementTree as ET


'''
WARNING, NFO overwrites previous!!



'''

alltags = ["music", "pipes", "computer","bbq","fun","art","travel","hobby","family","retro","compilation","retro","vuze"]

#------- WINDOWS FIX --------#
if PLATFORM.startswith('linux'):
    print("yeah linux baby!")
else:
    os.add_dll_directory(r'E:\VLC')

duration=0
tmptag=""

def nextFile(currentfile,dir):
        newfile=""
        dirpath = os.path.dirname(dir)
        fileList = []
        for f in os.listdir(dirpath):
            #fpath = os.path.join(dirpath, f)
            fpath = f
            if os.path.isfile(fpath) and f.endswith(('.mp4', '.mov', '.mpg','.avi','.mkv','.3gp')):
                fileList.append(fpath)
        fileList.sort()
        for i in range(len(fileList)):
#            print("fileList[i] " + fileList[i])
            try:
                if (fileList[i]) == currentfile:
                    newfile=fileList[i+1]
                    break
            except:
                newfile=fileList
        return newfile

def loadthumb(thumbfile):
    # IF exists
    path_to_file = thumbfile
    path = Path(path_to_file)

    if path.is_file():
        im = Image.open(thumbfile)
        im=ImageOps.contain(im, (640,640)) 
        thumbimage = ImageTk.PhotoImage(image=im)
        window['thumb'].update(data=thumbimage)
    else:
        window['thumb'].update("")

def loadnfo(file):

    #LOAD NFO
    nfo=file + ".nfo"
    path = Path(nfo)

    if path.is_file():
            f = open(nfo, "r")
            innfo=f.read()
            f.close()
#            print ("file : " + nfo)
            innfo="".join([s for s in innfo.strip().splitlines(True) if s.strip()])

# Clear some fields
            window['year'].update("")
            window['plot'].update("")

            # Update fields test
            if ET.fromstring(innfo).find('country') is not None:
                nfolocation = ET.fromstring(innfo).find('country')
                window['location'].update(value=nfolocation.text)
            if ET.fromstring(innfo).find('year') is not None:
                nfoyear = ET.fromstring(innfo).find('year')
                window['year'].update(nfoyear.text)
            if ET.fromstring(innfo).find('plot') is not None:
                nfoplot = ET.fromstring(innfo).find('plot')
                window['plot'].update(nfoplot.text)
            if ET.fromstring(innfo).find('title') is not None:
                nfotitle = ET.fromstring(innfo).find('title')
                window['-NM-'].update(nfotitle.text)
            if ET.fromstring(innfo).find('genre') is not None:
                nfogenre = ET.fromstring(innfo).find('genre')
                window['genre'].update(value=nfogenre.text)

            window['coline'].update(False)
            window['henri'].update(False)
            window['monique'].update(False)
            for actor in ET.fromstring(innfo).findall('actor'):
                name = actor.find('role').text
                if name == "Coline":
                    window['coline'].update(True)
                if name == "Henri":
                    window['henri'].update(True)
                if name == "Monique":
                    window['monique'].update(True)
            for alltag in alltags:
                window[alltag].update(False)

            if ET.fromstring(innfo).find('tag') is not None:
                for tag in ET.fromstring(innfo).findall('tag'):
                    if tag.text in window.AllKeysDict:
                        window[tag.text].update(True)

            window['coline'].update(False)
            window['henri'].update(False)
            window['monique'].update(False)
            for actor in ET.fromstring(innfo).findall('actor'):
                name = actor.find('role').text
                if name == "Coline":
                    window['coline'].update(True)
                if name == "Henri":
                    window['henri'].update(True)
                if name == "Monique":
                    window['monique'].update(True)
            for alltag in alltags:
                window[alltag].update(False)

            if ET.fromstring(innfo).find('tag') is not None:
                for tag in ET.fromstring(innfo).find('tag'):
                    window[tag.text].update(True)

    else:
        innfo=""
    window['LOADNFO'].update(innfo)





#------- Button definition --------#
def btn(name):  
    return sg.Button(name, size=(6, 2), pad=(1, 1))

#def tag(name):  
#    return sg.Checkbox(name, enable_events=True)

#------- GUI definition & setup --------#
sg.theme('SystemDefaultForReal')


l1=sg.Text("New title")
l2=sg.Multiline(" ", expand_x=True, key='-OUT-', expand_y=True,justification='left', size=(20,15))
l3=sg.Multiline(" ", expand_x=True, key='LOADNFO', expand_y=True,justification='left', size=(20,15))
l4=sg.Text("Plot")
t1=sg.Input("", key='-NM-')
t2=sg.Input("", key='plot',enable_events=True)
cb=[]

for alltag in alltags:
    cb.append(sg.Checkbox(alltag, key=alltag, enable_events=True))




cb.append(sg.Input("", key='addtag',size=(5, 1), enable_events=True))
cb.append(sg.Combo(["Lab","Datacenter","home","Outside","Outside","Lloydwebber","Steenweg","Enschede","Netherlands","Germany","Italy","Scotland","Canada","Egypt","Belgium","Sweden","Ireland","Asia","NewZealand","Hilversum"],default_value='Lab',key='location'))
cb.append(sg.Combo(["Storage","Funny","Vacation","Music","Relation"],default_value='Storage',key='genre'))
nameyear=[]
nameyear.append(sg.Checkbox("Coline", key='coline', enable_events=True,default=True))
nameyear.append(sg.Checkbox("Henri", key='henri', enable_events=True,default=True))
nameyear.append(sg.Checkbox("Monique", key='monique', enable_events=True,default=False))
nameyear.append(sg.Input("2023",key='year',size=(5, 1), enable_events=True))
nameyear.append(sg.Button("copyyear\nmetadata", key='copymeta', size=(20, 1), pad=(1, 1), enable_events=True))
nameyear.append(sg.Input("",key='metayear',size=(5, 1), enable_events=True))
nameyear.append(sg.Button("copyyear\nfilename", key='copyname', size=(20, 1), pad=(1, 1), enable_events=True))
nameyear.append(sg.Input("",key='fileyear',size=(5, 1), enable_events=True))
b1=sg.Button("WRITE NFO", key='write', enable_events=True)
b2=sg.Button("Exit", key='exit', enable_events=True)

#------- Layout total --------#

layout = [[sg.Input(key='-VIDEO_LOCATION-', visible=False, enable_events=True),
          sg.FileBrowse(file_types=(("Video files", "*.mkv *.mov *.mp4 *3gp *avi *mpg"),)),btn('next')],
          [sg.Text('Load media to start', key='-MESSAGE_AREA-')],
          [sg.Image('', size=(600, 480), key='-VID_OUT-', pad=(1, 1)),sg.Image('', size=(600, 480), key='thumb', pad=(1, 1))],
          [btn('mute'), btn('play'), btn('pause'), btn('stop'), btn('snap'), btn('snaprot'), btn('lighten'), btn('darken'), sg.Combo(["4:3","16:9","9:16"],key='aspect',enable_events=True)],
          [sg.Slider(range=(0, 1000), default_value=1, expand_x=True, enable_events=True, orientation='horizontal', key='-SL-')],
          [sg.Text('org title', key='orgtitle')],
          [l1, t1, l4, t2],[cb],[nameyear],[b1, l2, l3, b2],
          [sg.Text('GENERATED                            -= mini nfo writer =-                              PREVIOUS', key='footer')]
          ]

#------- Set window --------#
window = sg.Window('Mini NFO generator', layout, element_justification='center', finalize=True, resizable=True)
#------- VID out window --------#
window['-VID_OUT-'].expand(True, True)               
#------------ Media Player Setup ---------#
inst = vlc.Instance()
list_player = inst.media_list_player_new()
media_list = inst.media_list_new([])
list_player.set_media_list(media_list)
player = list_player.get_media_player()
if PLATFORM.startswith('linux'):
    player.set_xwindow(window['-VID_OUT-'].Widget.winfo_id())
else:
    player.set_hwnd(window['-VID_OUT-'].Widget.winfo_id())

#------------ I Want default mute ---------#
player.audio_set_mute(True)

#------------ The Event Loop ------------#
while True:
    event, values = window.read(timeout=1000)       # run with a timeout so that current location can be updated
    if event == sg.WIN_CLOSED:
        break



    if event == 'mute':
        mutevalue = player.audio_get_mute()
        if mutevalue==0:
            player.audio_set_mute(True)
        if mutevalue==1:
            player.audio_set_mute(False)
    if event == 'play':
        list_player.play()
    if event == 'pause':
        list_player.pause()
    if event == 'stop':
        list_player.stop()
    if event == 'snap':
        list_player.pause()
        filename = values['-VIDEO_LOCATION-']
        shortfilename = filename.rsplit( ".", 1 )[ 0 ] 
        newname = shortfilename + "-poster.png"
        player.video_take_snapshot(0, newname, 0, 0)
        loadthumb(newname)
    if event == 'snaprot':
        list_player.pause()
        filename = values['-VIDEO_LOCATION-']
        shortfilename = filename.rsplit( ".", 1 )[ 0 ] 
        newname = shortfilename + "-poster.png"
        im1 = Image.open(newname)
        im1 = im1.rotate(90, Image.NEAREST, expand = 1)
        im1 = im1.save(newname)
        loadthumb(newname)

    if event == 'lighten':
        list_player.pause()
        filename = values['-VIDEO_LOCATION-']
        shortfilename = filename.rsplit( ".", 1 )[ 0 ] 
        newname = shortfilename + "-poster.png"
        im1 = Image.open(newname)
        im1 = ImageEnhance.Brightness(im1)
        im1 = im1.enhance(1.2)
        im1 = im1.save(newname)
        loadthumb(newname)
        
    if event == 'darken':
        list_player.pause()
        filename = values['-VIDEO_LOCATION-']
        shortfilename = filename.rsplit( ".", 1 )[ 0 ] 
        newname = shortfilename + "-poster.png"
        im1 = Image.open(newname)
        im1 = ImageEnhance.Brightness(im1)
        im1 = im1.enhance(0.8)
        im1 = im1.save(newname)
        loadthumb(newname)

    if event == 'aspect':
        filename = values['-VIDEO_LOCATION-']
        shortfilename = filename.rsplit( ".", 1 )[ 0 ] 
        newname = shortfilename + "-poster.png"
        if values['aspect'] == "4:3":
            im1 = Image.open(newname)
            im1 = im1.resize((1920 ,int(1920/4*3)), Image.ANTIALIAS)
            im1 = im1.save(newname)
            loadthumb(newname)
        if values['aspect'] == "16:9":
            im1 = Image.open(newname)
            im1 = im1.resize((1920 ,int(1920/16*9)), Image.ANTIALIAS)
            im1 = im1.save(newname)
            loadthumb(newname)
        if values['aspect'] == "9:16":
            im1 = Image.open(newname)
            im1 = im1.resize((int(1920/16*9),1080), Image.ANTIALIAS)
            im1 = im1.save(newname)
            loadthumb(newname)


    if event == 'write':
        filename = values['-VIDEO_LOCATION-']
        shortfilename = filename.rsplit( ".", 1 )[ 0 ] 
        newname = shortfilename + ".nfo"
        f = open(newname, "w")
        f.write(out)
        f.close()
        loadnfo(shortfilename)

    if event == 'copymeta':
        if datefromfile is not None:
            window['year'].update(datefromfile)

    if event == 'copyname':
        if fileyear is not None:
            window['year'].update(fileyear)


    if event == '-SL-':
        pos=int(values['-SL-'])
        player.set_position(pos/ 1000.0)

        
    if values['coline'] == False:
         colinetext = ""
    if values['coline'] == True:
        colinetext = """<actor>
  <name>Coline Lastname</name>
  <role>Coline</role>
</actor>"""
    if values['henri'] == False:
         henritext = ""
    if values['henri'] == True:
        henritext = """<actor>
  <name>Henri Aanstoot</name>
  <role>Henri</role>
</actor>"""
    if values['monique'] == False:
            moniquetext = ""
    if values['monique'] == True:
        moniquetext = """<actor>
  <name>Monique Lastname</name>
  <role>Monique</role>
</actor>"""

        
    if event == '-VIDEO_LOCATION-':
        if values['-VIDEO_LOCATION-'] and not 'Video URL' in values['-VIDEO_LOCATION-']:
            media_list.remove_index(0)
            media_list.add_media(values['-VIDEO_LOCATION-'])
            list_player.set_media_list(media_list)
            shortname = values['-VIDEO_LOCATION-']
            shortname = shortname.rsplit( "/", 1 )[ 1 ] 
            nextfile=nextFile(shortname,"./")
            shortname = shortname.rsplit( ".", 1 )[ 0 ] 
            window['-NM-'].update(shortname) # only add a legit submit
            list_player.stop()
            list_player.next()
            thumbname=shortname + "-poster.png"
            loadthumb(thumbname)

            #Print org title
            window['orgtitle'].update(values['-VIDEO_LOCATION-'])


            loadnfo(shortname)


            #DURATION
            mi = MediaInfo.parse(values['-VIDEO_LOCATION-'])
            duration=int(mi.tracks[0].duration/1000)
            
            #DATE FROM media
            metadate=mi.tracks[0].encoded_date
            if metadate is not None:
                datefromfile=next(iter(re.findall(r"[1][9][8-9][0-9]|[2][0][0-9]{2}", metadate)), None)
                window['metayear'].update(datefromfile)

            # YEAR FROM FILENAME 
            fileyear=next(iter(re.findall(r"[1][9][8-9][0-9]|[2][0][0-9]{2}", shortname)), None)
            # year from filename
            if fileyear is not None:
                window['fileyear'].update(fileyear)


    if event == 'next':
        
        values['-VIDEO_LOCATION-'] = nextfile
        window['-VIDEO_LOCATION-'].update(nextfile)

        if values['-VIDEO_LOCATION-'] and not 'Video URL' in values['-VIDEO_LOCATION-']:
            media_list.remove_index(0)
            media_list.add_media(values['-VIDEO_LOCATION-'])
            list_player.set_media_list(media_list)
            shortname = values['-VIDEO_LOCATION-']
 #           shortname = shortname.rsplit( "/", 1 )[ 1 ] 
            nextfile=nextFile(shortname,"./")
            #print(nextfile)
            shortname = shortname.rsplit( ".", 1 )[ 0 ] 
            window['-NM-'].update(shortname) # only add a legit submit
            list_player.stop()
            list_player.next()
            thumbname=shortname + "-poster.png"
            loadthumb(thumbname)

            #Print org title
            window['orgtitle'].update(values['-VIDEO_LOCATION-'])
            

            loadnfo(shortname)

            #DURATION
            mi = MediaInfo.parse(values['-VIDEO_LOCATION-'])
            duration=int(mi.tracks[0].duration/1000)
            
            #DATE FROM media
            metadate=mi.tracks[0].encoded_date
            if metadate is not None:
                datefromfile=next(iter(re.findall(r"[1][9][8-9][0-9]|[2][0][0-9]{2}", metadate)), None)
                window['metayear'].update(datefromfile)

            # YEAR FROM FILENAME 
            fileyear=next(iter(re.findall(r"[1][9][8-9][0-9]|[2][0][0-9]{2}", shortname)), None)
            # year from filename
            if fileyear is not None:
                window['fileyear'].update(fileyear)
#        media_list.add_media(nextfile)
##        shortname = nextfile.rsplit( ".", 1 )[ 0 ] 
##        window['-NM-'].update(shortname) # only add a legit submit
#        print(nextfile)
#        window['-VIDEO_LOCATION-'].update(nextfile)
#        list_player.next()
# hier moeten wat update dingen bij!




    # Add tag
    if event == 'addtag':
        tmptag="<tag>" + values['addtag'] + "</tag>"

#------------ exit ---------#

    if event=='exit':
         exit()
#------------ TAGS ---------#
    
    subs=[x.Text for x in cb if x.get()==True]
    for idx, x in enumerate(subs):
        subs[idx]="<tag>" + subs[idx] + "</tag>"


    if values['year'] == False:
        year=str(2023)
    else:
        year=values['year']
    if values['location'] == False:
        location="Lab"
    else:
        location=values['location']
    if values['plot'] == False:
        plot=""
    else:
        plot=values['plot']
    if values['genre'] == False:
        genre="Storage"
    else:
        genre=values['genre']
#------------ NFO TEXT FIELD ---------#

    out="""<movie>
<title>{}</title>
<plot>{}</plot>
<genre>{}</genre>
<duration>{}</duration>
<year>{}</year>
<country>{}</country>
{}
{}
{}
{}
{}
</movie>
""".format(values['-NM-'],plot,genre,duration,year,location,colinetext,henritext,moniquetext,tmptag, "\n".join(subs))
    out="".join([s for s in out.strip().splitlines(True) if s.strip()])
    window['-OUT-'].update(out)

#------------ Messages and timer ---------#

    # update elapsed time if there is a video loaded and the player is playing
    if player.is_playing():
        window['-MESSAGE_AREA-'].update("{:02d}:{:02d} / {:02d}:{:02d}".format(*divmod(player.get_time()//1000, 60),
                                                                     *divmod(player.get_length()//1000, 60)))
    else:
        window['-MESSAGE_AREA-'].update('Load media to start' if media_list.count() == 0 else 'Ready to play media' )

window.close()

Musescore bagpipe music workaround

Last Updated or created 2023-08-22

I really like musescore, and mainly I use it for multistaff typesetting.
(In the past i’ve been using Cakewalk for this)

https://www.henriaanstoot.nl/2023/05/04/planxty-irwin-concertina-notation/

https://www.henriaanstoot.nl/2023/02/02/eleanor-plunkett-for-harp/

I still use ABC notation and Bagpipe Music Writer.
In abc multistaff can be done, but not perfect, the latter can’t.

So i was playing with Musescore to import BWW files and make it multistaff.

But Musescore kept messing things up, let me explain.

Part 1 – importing the bww file

Import works, but in the mixer part you don’t see an instrument.

Part 2 – try changing the instrument (fails)

Now i’ve got the instrument, but i’ve got 4 sharps, the notes are messed up.
(Tried transposing and turning on/off concert pitch)

Part 3 – creating empty sheet with two staffs and setting the instrument then copy paste the notes (fails)

Incorrectly pasted the b in the wrong octave.

I could not find anything helpful online. Maybe it can be fixed? But how?

My workaround

  • Import bww file, export as musicXML
  • Import harmony, export also
  • Create new sheet, with two staffs
    (file new, assign instrument, press F7 and add staff)
  • Open exported musicXML in a new file
  • Select all with ctrl-a OR first note and ctrl-end
  • Copy with ctrl-c and past into newly created score.
  • Same with harmony part
Instrument/staff add line

Example of this workaround

Python pysimplegui with VLC example

Last Updated or created 2023-08-24

A work in progress – see followup

pip3 install python-vlc && pip3 install PySimpleGUI

Kodi movie NFO file editor test

And a player in python

Some example code

from pathlib import Path

import PySimpleGUI as sg
import vlc
from sys import platform as PLATFORM


sg.theme('DarkBlue')

def btn(name):  
    return sg.Button(name, size=(6, 1), pad=(1, 1))

b1=sg.Button("WRITE NFO")
b2=sg.Button("Exit")

layout = [[sg.Input(key='-VIDEO_LOCATION-', visible=False, enable_events=True),
          sg.FileBrowse(file_types=(("MP4 Files", "*.mp4"),))],
          [sg.Image('', size=(600, 480), key='-VID_OUT-')],
          [btn('mute'), btn('play'), btn('skip 5sec'), btn('pause'), btn('stop'), btn('snap')],
          [sg.Text('Load media to start', key='-MESSAGE_AREA-')],
          [sg.Slider(range=(0, 100), default_value=5, expand_x=True, enable_events=True, orientation='horizontal', key='-SL-')],
          [[b1, b2]]]

window = sg.Window('Mini NFO generator', layout, element_justification='center', finalize=True, resizable=True)

window['-VID_OUT-'].expand(True, True)                

inst = vlc.Instance()
list_player = inst.media_list_player_new()
media_list = inst.media_list_new([])
list_player.set_media_list(media_list)
player = list_player.get_media_player()
if PLATFORM.startswith('linux'):
    player.set_xwindow(window['-VID_OUT-'].Widget.winfo_id())
else:
    player.set_hwnd(window['-VID_OUT-'].Widget.winfo_id())

player.audio_set_mute(True)
while True:
    event, values = window.read(timeout=1000)       
    if event == sg.WIN_CLOSED:
        break

    if event == 'play':
        list_player.play()
    if event == 'pause':
        list_player.pause()
    if event == 'stop':
        list_player.stop()
    if event == 'snap':
        list_player.pause()
        newname = values['-VIDEO_LOCATION-'] + ".png"
        player.video_take_snapshot(0, newname, 400, 300)
    if event == 'next':
        player.set_position(0.5)
        list_player.play()
    if event == 'mute':
        player.audio_set_mute(True)
    if event == '-SL-':
        player.set_position(int(values['-SL-']/100))
    if event == '-VIDEO_LOCATION-':
        if values['-VIDEO_LOCATION-'] and not 'Video URL' in values['-VIDEO_LOCATION-']:
            media_list.add_media(values['-VIDEO_LOCATION-'])
            list_player.set_media_list(media_list)
            window['-VIDEO_LOCATION-'].update('Video URL or Local Path:') 
            list_player.next()

    if player.is_playing():
        window['-MESSAGE_AREA-'].update("{:02d}:{:02d} / {:02d}:{:02d}".format(*divmod(player.get_time()//1000, 60),
                                                                     *divmod(player.get_length()//1000, 60)))
    else:
        window['-MESSAGE_AREA-'].update('Load media to start' if media_list.count() == 0 else 'Ready to play media' )

window.close()

My dosbox assembly directory

Last Updated or created 2023-08-21

Below you can find the files in a zip for writing assemby machine code in dosbox.

I’ve got mine extracted in ~/projects/dos

To automount this i’ve edited

~/.dosbox/dosbox-*.conf
;-------- bottom part
[autoexec]
# Lines in this section will be run at startup.
# You can put your MOUNT lines here.

mount c: /home/myusername/projects/dos
c:

The files

  • A.BAT – Runs editor, masm,linker (start with a<space>progname
  • DEBUG.COM – msdos debugger
  • EXE2BIN.EXE – exe to com (if segments allow)
  • GFX.ASM – example template (see below)
  • LINK.EXE – masm linker
  • MASM.EXE – masm compiler
  • Q* – editor stuff
  • Q.EXE – editor
  • SR.EXE – sourcer
  • SYMDEB.EXE
  • TASM.EXE – turbo assembler
  • TD.EXE – turbo debugger
  • TLINK.EXE – turbo linker

Template

; everything in 64k CS, DS, and SS are the same
.model small
; start pointer
.stack 100h
.code
start:
	; set mode 13 (320x200 * 265 colors palette)
    mov ah,0	
    mov al,13h
    int 10h

    ; set pixel in the middle color 2 (cyan)
    mov ah,0ch
    mov al,2
    mov cx,160
    mov dx,100
    int 10h

	; wait key input
    mov ah,0
    int 16h

	; set mode back to text
    mov ah,0
    mov al,3
    int 10h

	; exit to dos
    mov ax,4c00h
    int 21h
end start

Usage

start dosbox
a gfx (edit gfx.asm example)
esc, q, e
gfx (run program)

Music for movies

Last Updated or created 2023-08-30

We like to listen to movie scores. Those are underappreciated most of the times.

That’s why we go to concerts like

  • Evening of the Film Music
  • Hans Zimmer in Concert
  • The Star Wars Suite

We also do a quizes on YT, general movie knowledge, guess the movie by the scene, and guess the movie by musical scores.

We have a spotify playlist with random movie music. Sometimes very hard.

But sometimes we know the movie by its track before we had seen the movie. (Requiem of a Dream)

A lot of the time we make mistakes with Spielberg movies, there are a lot similar sounding moviescores!

See also John Williams remark at
https://www.henriaanstoot.nl/2022/12/07/i-admire-people-who-excel-at-things-they-do/

I’ve got some 5.1 surround music from movies, very nice to hear another dimension.

Some original soundtracks I have in mp3

  • Akira !
  • Interstellar
  • Pirates of the Caribbean
  • Ghost in the Shell
  • Appleseed
  • Titanic
  • Lord of the Rings
  • Blade Runner (Vangelis)
  • Godfather – ( although i’m not a fan of the movies )
  • Lawrence of Arabia
  • Amélie
  • Requiem for a Dream

Ludovico Einaudi – Composer of amazing piano music
https://www.henriaanstoot.nl/2019/08/31/best-of-einaudi-lying-down/
Ennio Morricone – Composer of many Spaghetti westerns

Although not original music written for the movie, because Tarantino likes to pick out tunes to fit the scenes.
3/4 Of the music of Kill Bill is amazing!

The rest is on streaming services

By the scene example

Soundtrack guessing game

Enjoying music

Last Updated or created 2023-08-18

I will add to this in time

Folk:

  • Shooglenifty – Celtic Fusion
    ( The recordings with Angus )
  • The Sidh
  • Ross Ainsley
    Partners in Crime (with Jarlath Henderson)
  • Fred Morrison
    All of his CD’s
    His tunes played others
    Breizh by Claymore pipes and Drums, I will put my version online also.
  • Gordon Duncan
    Thunderstruck, bellydancer, fourth floor, Pressed for time, Sleeping tune and many more
  • Manran
  • Kyle Warren
    Sampled
  • Fraser Shaw
    Air Chall (I play this one on tinwhistle)
  • Martyn Bennett
    Mackay’s Memoirs (Based around the theme and first variation of the piobaireachd ‘Lament For Mary MacLeod’)
  • Callum Armstrong ( Branschke/Armstrong Duo )
    Like his tune Burrito Hurricane on a Triple Chanter!

Tunes:

  • Jutland by Tommy O’Sullivan (We play this one with our Folkband, I play this on Uilleann)
    Versions I like:
    Paddy Keenan and Tommy O’Sullivan
    Michael McGoldrick and John McSherry
  • Bellydancer by Gordon Duncan
    Tape on B and F sound holes to produce the Middle-Easterny, B-flat phrygian scale.
    Gordon Duncan – Thunderstruck CD
    Session A9

Balalaika
https://www.youtube.com/watch?v=41_d4D7T6uI&pp=ygUJQmFsYWxhaWth

Some old skool CD’s

I’ve got many, some can’t be found online in a streaming service

(Maybe i’ll add some track info)

One of the first I bought because I had some cassette tapes with the Corries. Legends in Scottish Folk

PM of the Shotts and Dykehead. I’ve met the guy on a contest on the mainland, and got to speak to him and his mate Jimmy Killpatrick.
Liked his melodies, some easy to play but always interesting.
On of the first tunes I played with a natural C was Ebb-Tide.

Great piper, one of the most brilliant technical pipers. Met the guy in Scotland 1992. Got his autograph on this CD.
Mostly of his March, Strathspey and Reel playing.
(Got his MSR book somewhere)
https://pipetunesearch.henriaanstoot.nl/?select=listbook&book=ALGI

One of the gold old oldies folk.

I fell in love with this CD (got this somewhere in ’93-94)
Amazing fusion of pipes mixed with other styles and instruments.
I still play Death of a space piper.
https://www.henriaanstoot.nl/2006/12/09/death-of-a-space-piper/

Another amazing composer

This CD made me fall in love with “Cauld wind pipes”
(Not mouth blown)
There are many kinds of pipes on this CD.
It made me want to have a set of smallpipes.

Dick Lee’s Book

Again amazing stuff, fusion of instruments and styles.
Dick Lee plays clarinets, saxes and melodicas. But composed as a non-piper amazing tunes!
With the amazing playing of Hamish Moore, a joy for your ears!
https://pipetunesearch.henriaanstoot.nl/?select=listbook&book=DICKLEE

He died far to young, this amazing musical wonder.
Hard to explain his style. From Classical piping to electronical music.