Skip to content

Instantly share code, notes, and snippets.

@Kefta
Last active September 3, 2019 16:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kefta/b1d058b3420e4bd41164729d06da1c20 to your computer and use it in GitHub Desktop.
Save Kefta/b1d058b3420e4bd41164729d06da1c20 to your computer and use it in GitHub Desktop.
Lua program for planning my radio show
--[=[
// 2019-09-03 - 2:48:49 //
[1] Ghettotech/Juke/Footwork - 24:18
1.Feelin - DJ Rashad feat. DJ Spinn & Taso - Double Cup - 4:31
2.Feelin' - DJ Rashad - TEKLIFE Vol. 1: Welcome to the Chi - 4:02
3.Move Da Booty - D.J. Funk - Booty House Anthems 2 - 0:28
4.Have'n Sex ???? Hell Yea!!!!! - D.J. Funk - Booty House Anthems 2 - 1:15
5.Footworkin on Air - Traxman - Da Mind of Traxman - 4:01
6.Itz Crack - Traxman - Da Mind of Traxman - 3:02
7.Sound Filed - Traxman - Da Mind of Traxman - 2:51
8.Double Cup - DJ Rashad feat. DJ Spinn - Double Cup - 4:08
[2] Ambient Techno - 35:10
1.Session Add - Skee Mask - Compro - 6:20
2.Quadrant Dub I - Basic Channel - Quadrant Dub I - 15:36
3.Phylyps Trak Ii/Ii - Basic Channel - Phylyps Trak II - 13:14
[3] Nu Disco/Future Funk/Synth Funk - 23:13
1.A Different Feeling - The Avalanches - Since I Left You - 4:23
2.Black Hole - Kelley Polar - Love Songs of the Hanging Gardens - 4:50
3.Vocalise (From Here To Polarity - Kelley Polar - Love Songs of the Hanging Gardens - 3:55
4.Feelings of Sentimentality Due to Getting Curved - Flamingosis - Bright Moments - 3:16
5.Strange - DJ Screw & Cameo - Chapter 214: Old School - 6:49
[4] UK Garage/Future Garage - 25:45
1.Raver - Burial - Untrue - 5:00
2.White Noise - Disclosure feat. AlunaGeorge - Seattle - 4:38
3.Sincere - Re-Cue'D - MJ Cole feat. Nova Casper & Jay Dee - Sincere - 5:39
4.Right Thing to Do - SBTRKT feat. Jessie Ware - SBTRKT - 3:23
5.Unluck - James Blake - James Blake - 3:00
6.Flatline - Vacant - Origins - 4:05
[5] Instrumental Hip Hop/Lo-fi Hip Hop/Glitch Hop - 25:58
1.Falling 4 U - SwuM & Jinsang - Blossoms - 2:05
2.chief. - who knows - 2:16
3.HORIZONTAL - YAYAYI - YAYAYI - 11:19
4.Ice $ Cold $ Ocean - NxxxxxS - Fujita Scale - 5:09
5.[][][][][][][][][]][[][][][][][[]?[[[][]][[][][][][]][]][][][][][]][][][][][][][][]][]][[][][]. 333% - ATIVAN COREA - 5:09
[6] Industrial Techno/Breaks/EBM - 34:25
1.Fuck Da Police - Anne KGB - 15:00
2.Hidden Power (Phase d) - Machine Girl - WLFGRL - 8:39
3.Splitter - Fixmer / McCarthy - Between the Devil - 6:01
4.Meat Beat Manifesto - Psyche-Out - 99% - 4:45
]=]
local Show = (dofile or include)("show_planner.lua").Show
print(Show("2019-09-03", {{
Title = "Ghettotech/Juke/Footwork",
Tracks = {
{"Feelin", "DJ Rashad feat. DJ Spinn & Taso", "Double Cup", "4:31"},
{"Feelin'", "DJ Rashad", "TEKLIFE Vol. 1: Welcome to the Chi", "4:02"},
{"Move Da Booty", "D.J. Funk", "Booty House Anthems 2", "0:28"},
{"Have'n Sex ???? Hell Yea!!!!!", "D.J. Funk", "Booty House Anthems 2", "1:15"},
{"Footworkin on Air", "Traxman", "Da Mind of Traxman", "4:01"},
{"Itz Crack", "Traxman", "Da Mind of Traxman", "3:02"},
{"Sound Filed", "Traxman", "Da Mind of Traxman", "2:51"},
{"Double Cup", "DJ Rashad feat. DJ Spinn", "Double Cup", "4:08"}
}
},{
Title = "Ambient Techno",
Tracks = {
{"Session Add", "Skee Mask", "Compro", "6:20"},
{"Quadrant Dub I", "Basic Channel", "Quadrant Dub I", "15:36"},
{"Phylyps Trak Ii/Ii", "Basic Channel", "Phylyps Trak II", "13:14"}
}
},{
Title = "Nu Disco/Future Funk/Synth Funk",
Tracks = {
{"A Different Feeling", "The Avalanches", "Since I Left You", "4:23"},
{"Black Hole", "Kelley Polar", "Love Songs of the Hanging Gardens", "4:50"},
{"Vocalise (From Here To Polarity", "Kelley Polar", "Love Songs of the Hanging Gardens", "3:55"},
{"Feelings of Sentimentality Due to Getting Curved", "Flamingosis", "Bright Moments", "3:16"},
{"Strange", "DJ Screw & Cameo", "Chapter 214: Old School", "6:49"}
}
},{
Title = "UK Garage/Future Garage",
Tracks = {
{"Raver", "Burial", "Untrue", "5:00"},
{"White Noise", "Disclosure feat. AlunaGeorge", "Seattle", "4:38"},
{"Sincere - Re-Cue'D", "MJ Cole feat. Nova Casper & Jay Dee", "Sincere", "5:39"},
{"Right Thing to Do", "SBTRKT feat. Jessie Ware", "SBTRKT", "3:23"},
{"Unluck", "James Blake", "James Blake", "3:00"},
{"Flatline", "Vacant", "Origins", "4:05"}
}
},{
Title = "Instrumental Hip Hop/Lo-fi Hip Hop/Glitch Hop",
Tracks = {
{"Falling 4 U", "SwuM & Jinsang", "Blossoms", "2:05"},
{"chief.", "who knows", nil, "2:16"},
{"HORIZONTAL", "YAYAYI", "YAYAYI", "11:19"},
{"Ice $ Cold $ Ocean", "NxxxxxS", "Fujita Scale", "5:09"},
{"[][][][][][][][][]][[][][][][][[]­[[[][]][[][][][][]][]][][][][][]][][][][][][][][]][]][[][][]. 333%", "ATIVAN COREA", nil, "5:09"}
}
},{
Title = "Industrial Techno/Breaks/EBM",
Tracks = {
{"Fuck Da Police", "Anne KGB", nil, "15:00"},
{"Hidden Power (Phase d)", "Machine Girl", "WLFGRL", "8:39"},
{"Splitter", "Fixmer / McCarthy", "Between the Devil", "6:01"},
{"Meat Beat Manifesto", "Psyche-Out", "99%", "4:45"}
}
}}))
local planner = {}
local function FormatSubTime(uSeconds)
return uSeconds < 10 and "0" .. uSeconds or uSeconds
end
local function Time(uHours, uMinutes, uSeconds)
if (uSeconds == nil) then
if (uMinutes == nil) then
return "00:" .. FormatSubTime(uHours)
end
return uHours .. ":" .. FormatSubTime(uMinutes)
end
if (uHours == 0) then
return uMinutes .. ":" .. FormatSubTime(uSeconds)
end
return uHours .. ":" .. FormatSubTime(uMinutes) .. ":" .. FormatSubTime(uSeconds)
end
local function AddTime(uHours, uMinutes, uSeconds, uTotalHours, uTotalMinutes, uTotalSeconds)
uTotalSeconds = uTotalSeconds + uSeconds
if (uTotalSeconds > 60) then
uTotalMinutes = uTotalMinutes + 1
uTotalSeconds = uTotalSeconds - 60
end
uTotalMinutes = uTotalMinutes + uMinutes
if (uTotalMinutes > 60) then
uTotalHours = uTotalHours + 1
uTotalMinutes = uTotalMinutes - 60
end
return uTotalHours + uHours, uTotalMinutes, uTotalSeconds
end
local function GetTime(sTime)
local uSep = string.find(sTime, ":")
if (uSep == nil) then
local uSeconds = tonumber(sTime)
if (uSeconds == nil) then
return nil, nil, nil
end
local uHours = math.floor(uSeconds / 3600)
uSeconds = uSeconds % 3600
return uHours, math.floor(uSeconds / 60), uSeconds % 60
end
local uSep2 = string.find(sTime, ":", uSep + 1)
local uHours, uMinutes, uSeconds
if (uSep2 == nil) then
uMinutes = tonumber(string.sub(sTime, 1, uSep - 1))
if (uMinutes == nil) then
return nil, nil, nil
end
uSeconds = tonumber(string.sub(sTime, uSep + 1))
if (uSeconds == nil) then
return nil, nil, nil
end
uHours = 0
else
uHours = tonumber(string.sub(sTime, 1, uSep - 1))
if (uHours == nil) then
return nil, nil, nil
end
uMinutes = tonumber(string.sub(sTime, uSep + 1, uSep2 - 1))
if (uMinutes == nil) then
return nil, nil, nil
end
uSeconds = tonumber(string.sub(sTime, uSep2 + 1))
if (uSeconds == nil) then
return nil, nil, nil
end
end
uHours = uHours + math.floor(uSeconds / 3600)
uSeconds = uSeconds % 3600
return uHours + math.floor(uMinutes / 60), uMinutes % 60 + math.floor(uSeconds / 60), uSeconds % 60
end
local SHOW = {__newindex = function() end, __tostring = function(self) return self:ToString() end}
function planner.Show(sTitle --[[= "Show"]], tBlockConstructors --[[= {}]])
if (sTitle == nil) then
sTitle = "Show"
end
local tShow = {}
local tBlocks = {}
local uBlocks
if (tBlockConstructors == nil) then
uBlocks = 0
else
uBlocks = #tBlockConstructors
for i = 1, uBlocks do
local tBlock = tBlockConstructors[i]
tBlocks[i] = planner.Block(tBlock.Title, tBlock.Tracks)
end
end
function tShow:GetTitle()
return sTitle
end
function tShow:SetTitle(sNewTitle)
sTitle = sNewTitle
end
function tShow:GetBlock(uBlockPos)
return tBlocks[uBlockPos]
end
function tShow:SetBlock(uBlockPos, block)
for i = uBlocks + 1, uBlockPos - 1 do
uBlocks = uBlocks + 1
tBlocks[i] = planner.Block()
end
uBlocks = uBlocks + 1
tBlocks[uBlockPos] = block
end
-- function tShow:AddBlock(block) - also supported where uBlockPos will default to tShow:GetBlockCount()
function tShow:AddBlock(uBlockPos, block)
uBlocks = uBlocks + 1
if (block == nil) then
block = uBlockPos
uBlockPos = uBlocks
end
tBlocks[uBlockPos] = block
end
function tShow:RemoveBlock(uBlockPos --[[= tShow:GetBlockCount()]])
if (uBlocks > 0) then
if (uBlockPos == nil) then
uBlockPos = uBlocks
end
uBlocks = uBlocks - 1
tBlocks[uBlocks] = nil
end
end
function tShow:GetBlockCount()
return uBlocks
end
function tShow:GetTime()
local uTotalHours, uTotalMinutes, uTotalSeconds = 0, 0, 0
for i = 1, uBlocks do
local uHours, uMinutes, uSeconds = tBlocks[i]:GetTime()
uTotalHours, uTotalMinutes, uTotalSeconds = AddTime(uHours, uMinutes, uSeconds, uTotalHours, uTotalMinutes, uTotalSeconds)
end
return uTotalHours, uTotalMinutes, uTotalSeconds
end
function tShow:ToString()
local tStringBuffer = {string.format("// %s - %s //\n", sTitle, Time(self:GetTime()))}
for i = 2, uBlocks + 1 do
tStringBuffer[i] = string.format("\n[%u] %s", i - 1, tBlocks[i - 1]:ToString())
end
return table.concat(tStringBuffer)
end
return setmetatable(tShow, SHOW)
end
function planner.IsShow(v)
return getmetatable(v) == SHOW
end
local BLOCK = {__newindex = function() end, __tostring = function(self) return self:ToString() end}
function planner.Block(sTitle --[["Block"]], tTrackConstructors --[[{}]])
local tBlock = {}
local tTracks = {}
local uTracks
if (tTrackConstructors == nil) then
uTracks = 0
else
uTracks = #tTrackConstructors
for i = 1, uTracks do
local tTrack = tTrackConstructors[i]
tTracks[i] = planner.Track(tTrack.Title or tTrack[1], tTrack.Artist or tTrack[2], tTrack.Album or tTrack[3], tTrack.Time or tTrack[4])
end
end
function tBlock:GetTitle()
return sTitle
end
function tBlock:SetTitle(sNewTitle)
sTitle = sNewTitle
end
function tBlock:GetTrack(uTrackPos)
return tTracks[uTrackPos]
end
function tBlock:SetTrack(uTrackPos, track)
for i = uTracks + 1, uTrackPos - 1 do
uTracks = uTracks + 1
tTracks[i] = planner.Track()
end
uTracks = uTracks + 1
tTracks[uTrackPos] = track
end
-- function tBlock:AddTrack(track) - also supported where uTrackPos will default to tBlock:GetTrackCount()
function tBlock:AddTrack(uTrackPos, track)
uTracks = uTracks + 1
if (track == nil) then
track = uTrackPos
uTrackPos = uTracks
end
tTracks[uTrackPos] = track
end
function tBlock:RemoveTrack(uTrackPos --[[= tBlock:GetTrackCount()]])
if (uTracks > 0) then
if (uTrackPos == nil) then
uTrackPos = uTracks
end
uTracks = uTracks - 1
tTracks[uTracks] = nil
end
end
function tBlock:GetTrackCount()
return uTracks
end
function tBlock:GetTime()
local uTotalHours, uTotalMinutes, uTotalSeconds = 0, 0, 0
for i = 1, uTracks do
local uHours, uMinutes, uSeconds = tTracks[i]:GetTime()
uTotalHours, uTotalMinutes, uTotalSeconds = AddTime(uHours, uMinutes, uSeconds, uTotalHours, uTotalMinutes, uTotalSeconds)
end
return uTotalHours, uTotalMinutes, uTotalSeconds
end
function tBlock:ToString()
local tStringBuffer = {sTitle .. " - " .. Time(self:GetTime()) .. "\n"}
for i = 2, uTracks + 1 do
tStringBuffer[i] = string.format("\t%u.%s\n", i - 1, tTracks[i - 1]:ToString())
end
return table.concat(tStringBuffer)
end
return setmetatable(tBlock, BLOCK)
end
function planner.IsBlock(v)
return getmetatable(v) == BLOCK
end
local TRACK = {__newindex = function() end, __tostring = function(self) return self:ToString() end}
function planner.Track(sTitle --[[= ""]], sArtist --[[= ""]], sAlbum --[[= ""]], sTime --[[= ""]])
if (sTitle == nil) then
sTitle = ""
end
if (sArtist == nil) then
sArtist = ""
end
if (sAlbum == nil) then
sAlbum = ""
end
if (sTime == nil) then
sTime = ""
end
local tTrack = {}
local uHours, uMinutes, uSeconds = GetTime(sTime)
function tTrack:GetTitle()
return sTitle
end
function tTrack:SetTitle(sNewTitle)
sTitle = sNewTitle
end
function tTrack:GetArtist()
return sArtist
end
function tTrack:SetArtist(sNewArtist)
sArtist = sNewArtist
end
function tTrack:GetAlbum()
return sAlbum
end
function tTrack:SetAlbum(sNewAlbum)
sAlbum = sNewAlbum
end
function tTrack:GetTime()
return uHours or 0, uMinutes or 0, uSeconds or 0
end
function tTrack:ToString()
local tStringBuffer = {sTitle}
local uBufferPos = 2
if (sArtist ~= "") then
tStringBuffer[uBufferPos] = " - " .. sArtist
uBufferPos = uBufferPos + 1
end
if (sAlbum ~= "") then
tStringBuffer[uBufferPos] = " - " .. sAlbum
uBufferPos = uBufferPos + 1
end
if (uHours ~= nil) then
tStringBuffer[uBufferPos] = " - " .. Time(uHours, uMinutes, uSeconds)
uBufferPos = uBufferPos + 1
end
return table.concat(tStringBuffer)
end
return setmetatable(tTrack, TRACK)
end
function planner.IsTrack(v)
return getmetatable(v) == TRACK
end
return planner
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment