Page MenuHomePhorge

No OneTemporary

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -1,21 +1,22 @@
__pycache__
.*\.swp$
.*\.bak$
.*\.old$
.*\.orig$
test/
old/
+venv/
^a/
^d/
^p/
^r/
^chaos\.db
^zips$
^zipver\.txt$
^_commands_.txt$
diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,112 +1,114 @@
@%@~LICENSE:OK~@%@
+saw_051923_1 - [lex] The last for the /2 series.
+
saw_060522_1 - [(crickets)] New Wiggle tool icon. More art.
saw_060122_10- [(crickets)] More art and fixes.
saw_060122_9 - [(crickets)] Art.
saw_060122_8 - [(crickets)] Bug fix (ack color tool).
saw_060122_7 - [(crickets)] Fix ack+player bug!
saw_060122_6 - [(crickets)] ...include replay capture (PRAC).
saw_060122_5 - [(crickets)] ...double that (Player Rack Ack Chaos).
saw_060122_4 - [(crickets)] Include the test drawings as included samples (ack).
saw_060122_3 - [(crickets)] Randomly use ack saves in player rack chaos panel.
saw_060122_2 - [opeth] Bug fix.
saw_060122_1 - [opeth] Ack tool cursors.
saw_053122_2 - [opeth] Ack: all tools basically working (no text or group yet).
saw_053122_1 - [opeth] Fixing ack tooling: color, rect, and ellipse so far.
saw_053022_1 - [kaczynski] Color palette for ack.
saw_052822_1 - [ledzeppelin] More ack work.
saw_052722_3 - [ledzeppelin] Ack copy/paste (requires xclip system utility).
saw_052722_2 - [gojira] Ack save.
saw_052722_1 - [bach] A little bit of cleanup in ack classes.
saw_052622_5 - [bach] Implement ack Rect and Ellipse tools and Delete function.
saw_052622_4 - [bach] Add some color choices to ack.
saw_052622_3 - [bach] Begin to implement tools and objects in ack.
saw_052622_2 - [beethoven] Now have working captions filter in player rack.
saw_052622_1 - [beethoven] Implement keywords and labels in player rack. Add
ability to hide labels globally.
saw_052522_3 - [labyrinth] Improved confirmation/error dialogs.
saw_052522_2 - [labyrinth] Implemented a "list all" function for HotKeys.
saw_052522_1 - [labyrinth] Finished HotKeys panel for player.
saw_052422_1 - [labyrinth] Starting to implement HotKeys panel.
saw_052322_2 - [polog] More work on player rack. Starting to implement ack
(blackboard). Minor UI tweaks such as new status modes and
cursors. Improved escape key handling.
saw_052322_1 - [polog] Starting to implement player rack.
saw_052122_2 - [yelawolf] Remove the UNIQUE constraint on caption start time
because some files are actually marked with multiple captions
occurring at the same time. Add some more deferred downloads.
saw_052122_1 - [yelawolf] Implemented deferred downloads and seeded the database
with some videos. Beginning of a label system for tagging videos.
Channels, videos, and labels added by the user now start at
id=1000 to leave room for seeded entries. Database now enforces
foreign key constraints and patches use transactions. We now
perform a VACUUM operation on the database after patching or
application exit. Player explicitly disables key repeat on key
press. Debug DIP switch has been changed to the plus sign (+).
saw_051622_2 - [nin] Partial implementation of full-screen mode without meta.
saw_051622_1 - [nin] Improve database performance. Moved audio extraction step
to the main video download routine so we no longer have to wait
for audio extraction upon first play.
saw_051522_1 - [nin] Add switch.py to easily start with DIP switches set.
saw_042422_1 - [controldenied] Beginning to get replay captures to play.
saw_042222_1 - [controldenied] Reworking the replay system so we can now
capture keyboard and mouse actions. The command-line options
(dip switches) should now be specified as the first option only
and without spaces.
saw_041222_1 - [theprodigy] Minor changes wrap up this series.
saw_040822_1 - [theprodigy] Just a little bit better.
saw_040722_1 - [theprodigy] Introducing: ImageEngine (imagine)! Add more
command-line options (see README). Status bar now with separate
UIManager (sui). Player NUM-pad key improvements. Get FPS/avg
score readouts with TAB key.
saw_040422_1 - We now have a working sequence/segment editor.
saw_040222_1 - Implemented replay system. Improved player performance.
saw_033022_2 - Fix kush prompt paint (cursor overlap problem).
saw_033022_1 - Migration to the media/fragment system and versioned database.
saw_032622_2 - Rename directories.
saw_032622_1 - First commit.
diff --git a/k/__init__.py b/k/__init__.py
--- a/k/__init__.py
+++ b/k/__init__.py
@@ -1,822 +1,822 @@
''' Operating (oK) System '''
from k.ui import *
print('YO '+c.Style.BRIGHT+'[esc]'+c.Style.NORMAL+'APE QUITS and ' \
+ c.Style.BRIGHT+'<ctrl-c>'+c.Style.NORMAL+' to exit')
import k.cmd
import k.db as kdb
import k.imagine as kimg
import k.home as home
import k.video as video
#import k.game as game
import k.project as project
import k.replay as replay
from k.replay.ops import *
import k.online as online
import k.ack as ack
import k.player as player
from k.player.ops import Commands
import sys
from datetime import datetime
import traceback
import time
from html import escape
class OS:
def __init__(self):
self.init_start = datetime.now()
self.go = False
self.testing = False
self.imagine = True
self.local = False
self.clock = Clock()
self.square = False
self.replays = True
self.fullscreen = False
if OS.dip('+'):
print('THIS IS A TEST')
self.testing = True
if OS.dip('1'):
print('no imagination')
self.imagine = None
if OS.dip('2'):
print('stay local')
self.local = True
if OS.dip('3'):
print('fps//no limits')
self.clock = NullClock()
if OS.dip('4'):
print('square up')
self.square = True
if OS.dip('6'):
print('replay nix')
self.replays = False
if OS.dip('9'):
print('full-screen')
self.fullscreen = True
#self.peeking = False
pygame.mixer.pre_init(SAMPLE_RATE, -16, 1)
pygame.init()
pygame.display.set_caption('k-os')
if self.imagine:
self.imagine = kimg.ImageEngine()
self.imagine.start()
self.init_stop = datetime.now()
@staticmethod
def dip(switch):
if len(sys.argv) < 2:
return False
return switch in sys.argv[1]
def chaos(self):
self.init()
try:
while self.go:
for event in pygame.event.get():
with self.rate_kick:
self.kick(event)
with self.rate_tick:
self.tick()
if self.imagine:
with self.rate_burn:
ie = self.imagine.burn(self.screen,
pygame.image.frombuffer)
if ie:
self.lit.append(ie)
self.see()
if not self.clock.ready():
self.clock.wait()
# self.update_status()
#if self.player.players and self.player.players[-1].playing:
# time.sleep(1)
except KeyboardInterrupt:
print('got keyboard interrupt')
#self.go = False
finally:
self.kill()
def init(self, screen=None):
if screen is None:
if not self.fullscreen:
screen = pygame.display.set_mode((WIDTH, HEIGHT))
else:
screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
pygame.scrap.init()
pygame.scrap.set_mode(pygame.SCRAP_CLIPBOARD)
self.screen = screen
self.gui = KGUI((WIDTH, HEIGHT - STATUS))
self.sui = KGUI((WIDTH, STATUS))
self.lit = [ ]
self.bg = pygame.Surface((WIDTH, HEIGHT-STATUS))
self.bg.fill(BLACK)
pygame.draw.line(self.bg, WHITE,
(WIDTH-PWIDTH-1, 0), (WIDTH-PWIDTH-1, HEIGHT-STATUS-1))
pygame.draw.line(self.bg, WHITE,
(0, HEIGHT-STATUS-1), (WIDTH, HEIGHT-STATUS-1))
self.bglit = None
self.btn_home = pygame_gui.elements.UIButton(
text='?!',
manager=self.gui,
relative_rect=SPACER)
self.panel_home = home.Panel(self,
target(self.btn_home, 'top'))
self.cur_btn = self.btn_home
self.cur_btn.disable()
self.cur_panel = self.panel_home
self.cur_panel.show()
self.jobs = [ ]
self.status_updated = self.init_start
self.status('B')
self.btn_video = pygame_gui.elements.UIButton(
text='Video',
anchors=target(self.btn_home),
manager=self.gui,
relative_rect=SPACER)
self.panel_video = video.Panel(self,
target(self.btn_video, 'top'))
#self.btn_game = pygame_gui.elements.UIButton(text='Game',
# anchors=target(self.btn_video),
# manager=self.gui, relative_rect=SPACER)
#self.panel_game = game.Panel(self,
# target(self.btn_replay, 'top'))
self.btn_project = pygame_gui.elements.UIButton(
text='Project',
#anchors=target(self.btn_game),
anchors=target(self.btn_video),
manager=self.gui,
relative_rect=SPACER)
self.panel_project = project.Panel(self,
target(self.btn_project, 'top'))
if self.replays:
self.btn_replay = pygame_gui.elements.UIButton(
text='Replay',
anchors=target(self.btn_project),
manager=self.gui,
relative_rect=SPACER)
self.panel_replay = replay.Panel(self,
target(self.btn_replay, 'top'))
if not self.local:
self.panel_online = online.Panel(self,
target(self.btn_project, 'top'))
self.btn_ack = pygame_gui.elements.UIButton(
text='', # blank slate (blackboard)
manager=self.gui,
relative_rect=pygame.Rect((WIDTH/2-15, 0), (30, 40)))
self.ack = None
#self.lbl_pstatus = pygame_gui.elements.UILabel(
# text='',
# manager=self.gui,
# relative_rect=pygame.Rect((200, HEIGHT-30), (-1, -1)))
self.confirming = None
self.player = player.Stack(self)
k.cmd.install('player', Commands(self))
self.rate_kick = Counter()
self.rate_tick = Counter()
self.rate_burn = Counter()
self.rate_lit = Counter()
self.status('N')
self.clicked = False
self.hovering = None
self.closing = False
self.escaping = False
self.shifting = False
self.control = False
#if self.replays:
# self.gui.update(0)
# self.paint()
# self.replay_screen()
self.init_stop = datetime.now()
self.go = True
def tick(self, gui=True):
#print('.', end='')
#sys.stdout.flush()
tdelta = self.clock.tick()
if self.replays:
self.panel_replay.tick()
if self.player.big or self.ack:
gui = False
if gui:
#studio = self.panel_project.panel_studio
#if studio.project_id is None:
# self.lbl_pstatus.set_text("NO PROJECT")
#elif studio.started:
# self.lbl_pstatus.set_text(str(datetime.now()-studio.started))
#else:
# self.lbl_pstatus.set_text('PAUSED')
self.gui.update(tdelta)
self.paint()
completed = 0
for job in self.jobs:
self.see()
self.status(job[2])
try:
if job[1] is None:
job[0]()
else:
job[0](*job[1])
if not self.confirming:
self.status('N')
except Exception as e:
self.bug(e)
#self.status('E')
tdelta = self.clock.tick()
self.gui.update(tdelta)
self.paint()
completed += 1
if self.confirming:
break
del self.jobs[:completed]
if self.confirming is False:
self.player.resume()
self.confirming = None
if not self.local:
self.panel_online.tick()
if not self.confirming:
self.player.tick()
if self.ack and not self.player.big:
self.ack.tick()
#self.paint()
if self.clicked:
self.clicked = False
self.replay_screen()
def kick(self, event):
#print(event)
#debug_event(event)
if event.type == pygame.QUIT:
#self.go = False
self.kill()
elif event.type == pygame.WINDOWEXPOSED:
self.status()
#self.peek()
elif event.type == pygame.WINDOWENTER:
pass
elif event.type == pygame.WINDOWLEAVE:
pass
elif event.type == pygame.WINDOWFOCUSGAINED:
##self.peek()
pass
elif event.type == pygame.WINDOWFOCUSLOST:
#self.peek(False, 500)
pass
elif event.type == pygame.KEYDOWN:
self.replay_op(KeyDown(event.scancode))
alt = event.mod & pygame.KMOD_ALT
ctrl = event.mod & pygame.KMOD_CTRL
shift = event.mod & pygame.KMOD_SHIFT \
or event.mod & pygame.KMOD_LSHIFT \
or event.mod & pygame.KMOD_RSHIFT
nomod = not alt and not ctrl and not shift
if self.panel_home.panel_keys.discover:
self.panel_home.panel_keys.keydown(event.key, event.mod)
elif event.key == pygame.K_ESCAPE:
if self.player.big:
self.player.size_normal()
elif self.ack:
self.ack.kill()
self.ack = None
self.status('N')
elif self.confirming:
self.confirming[0].kill()
self.confirming = None
self.status('N')
self.player.resume()
elif self.player.is_playing(True):
self.player.pause()
self.closing = True
else:
self.escaping = True
self.status('Q')
elif not self.confirming:
if self.escaping:
self.escaping = False
self.status('N')
elif self.closing:
self.closing = False
elif event.key == pygame.K_BREAK:
if nomod and self.replays:
self.replay_break()
self.job(self.panel_replay.refresh)
elif event.key == pygame.K_TAB:
if shift:
self.score()
else:
self.player.keydown(event.key, event.mod)
if not self.ack and not self.player.big:
self.cur_panel.keydown(event.key, event.mod)
if event.key == pygame.K_LSHIFT \
or event.key == pygame.K_RSHIFT:
self.shifting = True
elif event.key == pygame.K_LCTRL \
or event.key == pygame.K_RCTRL:
self.control = True
elif event.type == pygame.KEYUP:
self.replay_op(KeyUp(event.scancode))
if self.panel_home.panel_keys.discover:
self.panel_home.panel_keys.keyup(event.key, event.mod)
elif event.key == pygame.K_ESCAPE:
if self.escaping:
#self.go = False
self.kill()
elif self.closing:
self.player.killall()
elif not self.confirming:
self.player.keyup(event.key, event.mod)
if not self.ack and not self.player.big:
self.cur_panel.keyup(event.key, event.mod)
if event.key == pygame.K_LSHIFT \
or event.key == pygame.K_RSHIFT:
self.shifting = False
elif event.key == pygame.K_LCTRL \
or event.key == pygame.K_RCTRL:
self.control = False
elif event.type == pygame.MOUSEMOTION:
self.replay_op(MouseMove(event.pos[0], event.pos[1]))
elif event.type == pygame.MOUSEBUTTONDOWN:
self.replay_op(MouseDown(event.button))
self.player.mouse_down(event)
if not self.local:
self.panel_online.mouse_button_down(event)
elif event.type == pygame.MOUSEBUTTONUP:
self.replay_op(MouseUp(event.button))
self.player.mouse_up(event)
if event.button == pygame.BUTTON_RIGHT:
self.replay_capture_toggle()
elif event.button == pygame.BUTTON_WHEELUP \
or event.button == pygame.BUTTON_WHEELDOWN:
self.clicked = True
elif event.type == pygame_gui.UI_BUTTON_ON_HOVERED:
if not self.hovering is event.ui_element:
self.hovering = event.ui_element
self.replay_screen()
elif event.type == pygame_gui.UI_BUTTON_ON_UNHOVERED:
if self.hovering is event.ui_element:
self.hovering = None
self.replay_screen()
elif event.type == pygame_gui.UI_BUTTON_START_PRESS:
self.replay_screen()
elif event.type == pygame_gui.UI_BUTTON_PRESSED:
if not self.player.big:
if event.ui_element is self.btn_home:
self.panel_swap(self.btn_home, self.panel_home)
elif event.ui_element is self.btn_video:
self.panel_swap(self.btn_video, self.panel_video)
#elif event.ui_element is self.btn_game:
# self.panel_swap(self.btn_game, self.panel_game)
elif event.ui_element is self.btn_project:
self.panel_swap(self.btn_project, self.panel_project)
elif self.replays and event.ui_element is self.btn_replay:
self.panel_swap(self.btn_replay, self.panel_replay)
elif event.ui_element is self.btn_ack:
self.ack = ack.Blackboard(self)
self.status('A')
else:
self.cur_panel.click(event.ui_element)
self.player.click(event.ui_element)
self.clicked = True
elif event.type == pygame_gui.UI_TEXT_ENTRY_CHANGED:
self.replay_screen()
elif event.type == pygame_gui.UI_TEXT_BOX_LINK_CLICKED:
if event.link_target.lower().startswith('http://') \
or event.link_target.lower().startswith('https://'):
self.click_link(event.link_target)
else:
self.cur_panel.click(event.ui_element, event.link_target)
self.player.click(event.ui_element, event.link_target)
elif event.type == pygame_gui.UI_WINDOW_CLOSE:
if self.confirming and event.ui_element == self.confirming[0]:
self.confirming[0].kill()
self.confirming = None
self.status('N')
self.player.resume()
elif event.type == pygame_gui.UI_CONFIRMATION_DIALOG_CONFIRMED:
if self.confirming and event.ui_element == self.confirming[0]:
self.confirming[0].kill()
fn = self.confirming[1]
self.confirming = False
self.job(fn)
if self.ack:
self.ack.kick(event)
elif not self.player.big:
self.gui.process_events(event)
def paint(self):
lit = self.screen.blit(self.bg, (0, 0))
if self.bglit:
self.lit.extend(self.bglit)
else:
self.lit.append(pygame.Rect(lit))
if not self.ack:
self.gui.draw_ui(self.screen)
def blit(self, surface, position, area=None):
lit = self.screen.blit(surface, position, area)
self.lit.append(pygame.Rect(lit))
def see(self):
if self.lit or self.confirming:
with self.rate_lit:
if self.confirming: pygame.display.flip()
else: pygame.display.update(self.lit)
self.lit = [ ]
def status(self, mode=None):
update = datetime.now()
if mode != 'K' and self.panel_home.panel_keys.discover:
self.panel_home.panel_keys.toggle_discover()
if mode == 'N':
pygame.mouse.set_cursor(*pygame.cursors.arrow)
elif mode == 'B':
#pygame.mouse.set_cursor(*pygame.cursors.tri_left)
pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_WAITARROW)
elif mode == 'D':
#pygame.mouse.set_cursor(*pygame.cursors.tri_right)
pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_WAIT)
elif mode == 'E':
#pygame.mouse.set_cursor(*pygame.cursors.broken_x)
pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_NO)
#elif mode == 'A':
# #pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_HAND)
# pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_CROSSHAIR)
elif mode == 'K':
pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_HAND)
elif mode == 'C':
pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_HAND)
if mode is not None:
for status in self.panel_home.status:
self.panel_home.status[status].hide()
self.panel_home.status[mode].show()
self.sui.update((update - self.status_updated).total_seconds())
self.status_updated = update
bar = pygame.Surface((WIDTH, STATUS))
self.sui.draw_ui(bar)
lit = self.screen.blit(bar, (0, HEIGHT-STATUS))
pygame.display.update(lit)
def panel_swap(self, btn, panel):
self.status('B')
#if self.cur_panel == self.panel_project:
# if self.panel_project.cur_panel == self.panel_project.panel_studio:
# self.panel_project.panel_studio.suspend()
if self.cur_btn:
self.cur_btn.enable()
self.cur_btn = btn
if self.cur_btn:
self.cur_btn.disable()
self.cur_panel.hide()
self.cur_panel = panel
self.cur_panel.show()
self.status('N')
def click_link(self, link):
print(f'LINK CLICK: {link}')
llink = link.lower()
start = llink.index('://') + 3
llink = llink[start:]
if llink.startswith('www.'):
llink = llink[4:]
if llink.startswith('youtube.com/watch?v=') \
or llink.startswith('youtu.be/'):
self.panel_swap(self.btn_video, self.panel_video)
panel = self.panel_video
panel.panel_swap(panel.btn_youtube, panel.panel_youtube)
panel = panel.panel_youtube
panel.clear_results()
panel.input.set_text(link)
panel.btn_video.disable()
self.job(panel.get_video, 'D')
def bug(self, e):
print('*!*!* UNCAUGHT EXCEPTION *!*!*')
print(e)
formatted = traceback.format_exc()
print(formatted)
formatted = f'<b>{e}</b><br><br>' \
+ escape(formatted).replace('\n', '<br>')
self.confirm(self.kill, 'Error Occurred', 'Quit', formatted,
(200, 100), (WIDTH-400, HEIGHT-STATUS-200))
self.status('E')
def score(self):
print(' '+c.Style.DIM+'[ ]'+c.Style.NORMAL \
+ ' scores are fps/% in 1s, 5s, 15s increments:')
score = ' '+c.Style.DIM+'[OK]'+c.Style.NORMAL \
+ ' '+c.Fore.WHITE+c.Back.BLACK+c.Style.BRIGHT+'tick' \
+ c.Style.RESET_ALL+f' {self.rate_tick}' \
+ ' '+c.Fore.WHITE+c.Back.BLACK+c.Style.BRIGHT+'kick' \
+ c.Style.RESET_ALL+f' {self.rate_kick}'
if self.imagine:
score += ' '+c.Fore.WHITE+c.Back.BLACK+c.Style.BRIGHT+'burn' \
+ c.Style.RESET_ALL+f' {self.rate_burn}'
score += ' '+c.Fore.WHITE+c.Back.BLACK+c.Style.BRIGHT+'lit' \
+ c.Style.RESET_ALL+f' {self.rate_lit}'
print(score)
if self.imagine:
self.imagine.score()
self.status()
def confirm(self, fn, title, ok, descr='', pos=(250, 200), size=(350, 250)):
if self.confirming:
self.confirming[0].kill()
self.player.size_normal()
if self.player.is_playing:
self.player.suspend()
self.confirming = (
pygame_gui.windows.UIConfirmationDialog(
window_title=title,
manager=self.gui,
action_short_name=ok,
action_long_desc=descr,
blocking = True,
rect=pygame.Rect(pos, size)),
fn
)
# resizable window interferes with our chosen mouse cursor
self.confirming[0].resizable = False
self.status('C')
def job(self, fn, mode='B'):
self.jobs.append((fn, None, mode))
def jab(self, fn, args, mode='B'):
self.jobs.append((fn, args, mode))
def focus_video(self, video_id):
video = self.panel_video
library = video.panel_library
library.refresh_video(video_id)
video.panel_swap(video.btn_library, library)
self.panel_swap(self.btn_video, video)
def focus_keyword(self, keyword):
video = self.panel_video
library = video.panel_library
library.inp_search.set_text(keyword)
library.refresh_videos(search_keyword=keyword)
video.panel_swap(video.btn_library, library)
self.panel_swap(self.btn_video, video)
def project(self):
return self.panel_project.panel_studio.init_project()
def frag(self, media, source, begin=None, end=None):
project = self.project()
return kdb.insert_frag(project, media, source, begin, end)
def clip(self, frag, loop, loop_begin, loop_end, jumps):
loop = '1' if loop else '0'
loop += f',{loop_begin}'
loop += f',{loop_end}'
jumps = ','.join([str(j) for j in jumps])
kdb.insert_clip(frag, loop, jumps)
self.panel_project.panel_studio.panel_clip.add_clip(frag)
def clip_naked(self, frag):
kdb.insert_clip(frag, None, None)
self.panel_project.panel_studio.panel_clip.add_clip(frag)
def focus_clip(self, clip):
self.panel_swap(self.btn_project, self.panel_project)
panel = self.panel_project
panel.panel_swap(panel.btn_studio, panel.panel_studio)
panel = panel.panel_studio
panel.panel_swap(panel.btn_clip, panel.panel_clip)
def seq(self):
return self.panel_project.panel_studio.panel_seq.panel_editor.init_seq()
def seg(self, frag):
seq = self.seq()
idx = kdb.get_last_segment_idx(seq)
if idx is None:
idx = 0
else:
idx += 1
kdb.insert_segment(seq, idx, frag)
self.panel_project.panel_studio.panel_seq.panel_editor.add_seg(idx)
return idx
def focus_seg(self, seg):
self.panel_swap(self.btn_project, self.panel_project)
panel = self.panel_project
panel.panel_swap(panel.btn_studio, panel.panel_studio)
panel = panel.panel_studio
panel.panel_swap(panel.btn_seq, panel.panel_seq)
panel = panel.panel_seq
panel.panel_swap(panel.btn_editor, panel.panel_editor)
def replay_op(self, op):
if self.replays:
self.panel_replay.op(op)
def replay_screen(self):
if self.replays:
self.panel_replay.screen()
def replay_capture_toggle(self):
if self.replays:
if self.panel_replay.toggle_capture():
self.panel_replay.init_replay()
self.clicked = True
else:
self.panel_replay.screen()
self.panel_replay.op(StopCapture())
self.panel_replay.update_timer()
def replay_break(self):
if self.replays:
self.panel_replay.break_replay()
'''
def peek(self, me=True, delay=None):
if self.player.is_playing():
return
if self.peeking and self.peeking.poll() is None:
# previous peek() process is still running
return
self.peeking = media.focus_peek(me=me, delay=delay)
'''
def kill(self):
if not self.go: return
self.go = False
self.replay_break()
if not self.local:
self.panel_online.go_offline()
''' Nope: bad idea... '''
#for job in self.jobs:
# self.status(job[1])
# try:
# job[0]()
# except Exception as e:
# self.bug(e)
if self.imagine:
print('choke image engine... ', end='')
sys.stdout.flush()
self.imagine.choke()
self.imagine.join()
- print('clean up database... ', end='')
+ print('clean up base... ', end='')
sys.stdout.flush()
kdb.close()
print('done')
#pygame.quit()
print('graceful death')
diff --git a/k/db.py b/k/db.py
--- a/k/db.py
+++ b/k/db.py
@@ -1,1511 +1,1512 @@
import sqlite3
from datetime import datetime
VERSION = 7
DATABASE = 'chaos.db'
# meta table entries
META_VERSION = 'db_version'
# media table entries
MEDIA_VIDEO = 10
-print(f'databasing "{DATABASE}" ...')
+print(f'base "{DATABASE}" ...')
con = sqlite3.connect(DATABASE, isolation_level=None,
detect_types=sqlite3.PARSE_DECLTYPES)
con.row_factory = sqlite3.Row
sqlite3.register_adapter(bool, int)
sqlite3.register_converter('BOOLEAN', lambda v: bool(int(v)))
cur = con.cursor()
#cur.execute('.dbconfig defensive on')
cur.execute('PRAGMA journal_mode=WAL')
cur.execute('PRAGMA synchronous=NORMAL')
cur.execute('PRAGMA temp_store=MEMORY')
#cur.execute('PRAGMA locking_mode=EXCLUSIVE')
cur.execute('PRAGMA foreign_keys=ON')
def cur_fetch():
for row in cur:
return row # returns first row only
return None # if there were no rows
def cur_fetchcol(name):
row = cur_fetch()
if not row:
return None
return row[name]
def cur_fetchall():
rows = [ ]
for row in cur:
rows.append(row)
return rows
def close():
cur.execute('VACUUM')
con.close()
###
### META
###
def _is_version_zero_():
''' The original database had no meta table, so this function checks for a
table known to have existed at the time (i.e. channel) and for the lack
of the meta table. This is done in order to differentiate between a
brand new database versus an existing pre-meta database.'''
try:
cur.execute('SELECT id FROM channel WHERE id < 0')
except sqlite3.OperationalError:
return False
try:
cur.execute('SELECT name FROM meta WHERE name = 1')
return False
except sqlite3.OperationalError:
return True
_version_zero_ = _is_version_zero_()
cur.execute('''
CREATE TABLE IF NOT EXISTS meta (
name TEXT PRIMARY KEY,
value TEXT
)
''')
cur.executemany('''
INSERT OR IGNORE INTO meta (
name,
value
)
VALUES (
?, ?
)
''', [
(META_VERSION, VERSION if not _version_zero_ else 0),
])
def get_meta(name):
cur.execute('''
SELECT value
FROM meta
WHERE name = ?
''', (
name,
))
return cur_fetchcol('value')
def set_meta(name, value):
cur.execute('''
UPDATE meta
SET value = ?
WHERE name = ?
''', (
value,
name
))
def _upgrade_if_needed_():
v = int(get_meta(META_VERSION))
if v < VERSION:
from k.patch import upgrade
- upgrade(DATABASE, cur, cur_fetchall, set_meta, META_VERSION, v, VERSION)
+ upgrade(DATABASE, close, cur, cur_fetchall,
+ set_meta, META_VERSION, v, VERSION)
_upgrade_if_needed_() # pause here and patch the db before continuing
###
### CHANNEL
###
cur.execute('''
CREATE TABLE IF NOT EXISTS channel (
id INTEGER PRIMARY KEY,
ytid TEXT NOT NULL UNIQUE,
name TEXT,
url TEXT
)
''')
cur.executemany('''
INSERT OR IGNORE INTO channel (
id,
ytid,
name
)
VALUES (
?, ?, ?
)
''', [
(10, 'UCk9H1u4QMFNbBOj96A9DGHw', 'Marcel'),
(20, 'UCTdw38Cw6jcm0atBPA39a0Q', 'NDC Conferences'),
(30, 'UCMXjSvsqlx1CMoNY-i7Pmyw', 'Space Feather'),
(40, 'UCpwvZwUam-URkxB7g4USKpg', 'RT'),
(50, 'UCfAOh2t5DpxVrgS9NQKjC7A', 'The Onion'),
(100, 'UCqFzWxSCi39LnW1JKFR3efg', 'Saturday Night Live'),
(999, 'UC604kMqi2n6y47YLHQ2a8mg', "mix'd k-os")
])
def insert_channel(channel):
cur.execute('''
INSERT INTO channel (
ytid,
name,
url
) VALUES (
?, ?, ?
)
''', (
channel.channel_id,
channel.channel_name,
channel.vanity_url
))
return cur.lastrowid
def update_channel(channel_id, channel):
cur.execute('''
UPDATE channel
SET
name = ?,
url = ?
WHERE id = ?
''', (
channel.channel_name,
channel.vanity_url,
channel_id
))
def get_channel(channel_id):
cur.execute('''
SELECT *
FROM channel
WHERE id = ?
''', (
channel_id,
))
return cur_fetch()
def id_channel(ytid):
cur.execute('''
SELECT id
FROM channel
WHERE ytid = ?
''', (
ytid,
))
return cur_fetchcol('id')
def list_channels():
cur.execute('''
SELECT *
FROM channel
ORDER BY name COLLATE NOCASE
''')
return cur_fetchall()
LIST_CHANNELS_SQL = '''
SELECT
c.id AS 'id',
c.ytid AS 'ytid',
c.name AS 'name',
c.url AS 'url'
FROM video v
LEFT JOIN channel c ON c.id = v.channel
'''
LIST_CHANNELS_SQL_GROUP_BY = '''
GROUP BY c.id
ORDER BY c.name COLLATE NOCASE
'''
def list_channels_by_label(hidden=None, labels=None):
sql = LIST_CHANNELS_SQL
sep = ' WHERE '
args = [ ]
if labels:
for i in range(len(labels)):
sql += f' LEFT JOIN label_video l{i}'
sql += f' ON l{i}.video = v.id AND l{i}.label = ?'
args.append(labels[i])
for i in range(len(labels)):
sql += sep + f'l{i}.video IS NOT NULL'
sep = ' AND '
if hidden:
sql += sep + 'v.id NOT IN (' + ','.join('?'*len(hidden)) + ')'
sep = ' AND '
args.extend(hidden)
sql += LIST_CHANNELS_SQL_GROUP_BY
cur.execute(sql, tuple(args))
return cur_fetchall()
###
### VIDEO
###
cur.execute('''
CREATE TABLE IF NOT EXISTS video (
id INTEGER PRIMARY KEY,
channel INTEGER NOT NULL,
ytid TEXT NOT NULL UNIQUE,
author TEXT,
title TEXT,
description TEXT,
length INTEGER,
published TIMESTAMP,
thumb_url TEXT,
retrieved TIMESTAMP,
FOREIGN KEY (channel) REFERENCES channel (id)
)
''')
cur.executemany('''
INSERT OR IGNORE INTO video (
id,
channel,
ytid,
title
)
VALUES (
?, ?, ?, ?
)
''', [
(10, 10, 'yJDv-zdhzMY',
'The Mother of All Demos, presented by Douglas Engelbart (1968)'),
(20, 20, '6avJHaC3C2U', 'The Art of Code - Dylan Beattie'),
(30, 30, 'GsDrXc94NGU',
'On Max Headroom: The Most Misunderstood Joke on TV'),
(40, 40, 'D95LqdndUM8',
'‘There Will Be No Winners’ If War Breaks Out - Putin'),
(50, 50, 'vm1U5E44W90',
'Putin Learns Putin Behind Plot To Assassinate Putin'),
(100, 100, 'gaoQ5mMRDhg', 'Shud the Mermaid - SNL'),
(101, 100, 'XD66suMp3J4', 'Billionaire Star Trek - SNL'),
(997, 999, 'I7t1bTgFlyU', 'image engine idles | pygame/k-os'),
(998, 999, 'm004JwfzCK4',
'"The sun is gradually expanding" feat. Elex Muscman'),
(999, 999, 'LpnFGAo3oXs', 'gen-z fidget spinner... a work in progress')
])
def insert_video(channel_id, video):
cur.execute('''
INSERT INTO video (
channel,
ytid,
author,
title,
description,
length,
published,
thumb_url,
retrieved
)
VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?
)
''', (
channel_id,
video.video_id,
video.author,
video.title,
video.description,
video.length,
video.publish_date,
video.thumbnail_url,
datetime.now()
))
return cur.lastrowid
def update_video(video_id, video):
cur.execute('''
UPDATE video
SET
author = ?,
title = ?,
description = ?,
length = ?,
published = ?,
thumb_url = ?,
retrieved = ?
WHERE id = ?
''', (
video.author,
video.title,
video.description,
video.length,
video.publish_date,
video.thumbnail_url,
datetime.now(),
video_id
))
def get_video(video_id):
cur.execute('''
SELECT *
FROM video
WHERE id = ?
''', (
video_id,
))
return cur_fetch()
def id_video(ytid):
cur.execute('''
SELECT id
FROM video
WHERE ytid = ?
''', (
ytid,
))
return cur_fetchcol('id')
LIST_VIDEOS_SQL = '''
SELECT
v.id AS 'id',
ch.ytid AS 'cytid',
v.ytid AS 'ytid',
v.title AS 'title',
v.retrieved AS 'retrieved'
FROM video v
LEFT JOIN channel ch ON ch.id = v.channel
'''
LIST_VIDEOS_SQL_JOIN_EXTRA = '''
LEFT JOIN captions cap ON cap.video = v.id
LEFT JOIN keyword k ON k.video = v.id
'''
LIST_VIDEOS_SQL_GROUP_BY = '''
GROUP BY v.id
ORDER BY v.title COLLATE NOCASE
'''
def list_video(video_id):
sql = LIST_VIDEOS_SQL
sql += ' WHERE v.id = ?'
cur.execute(sql, (video_id,))
return cur_fetch()
def list_videos(hidden=None, labels=None, channel_id=None, search_title=None,
search_description=None, search_keyword=None,
search_captions=None):
sql = LIST_VIDEOS_SQL + LIST_VIDEOS_SQL_JOIN_EXTRA
if labels:
for i in range(len(labels)):
sql += f' LEFT JOIN label_video l{i}'
sql += f' ON l{i}.video = v.id AND l{i}.label = {labels[i]}'
sep = ' WHERE '
args = [ ]
if hidden:
sql += sep + 'v.id NOT IN (' + ','.join('?'*len(hidden)) + ')'
sep = ' AND '
args.extend(hidden)
if labels:
for i in range(len(labels)):
sql += sep + f'l{i}.video IS NOT NULL'
sep = ' AND '
sep = ' AND '
if channel_id is not None:
sql += sep + 'v.channel = ?'
sep = ' AND '
args.append(channel_id)
if search_title is not None:
sql += sep + 'v.title LIKE ?'
sep = ' AND '
args.append('%' + search_title + '%')
if search_description is not None:
sql += sep + 'v.description LIKE ?'
sep = ' AND '
args.append('%' + search_description + '%')
if search_keyword is not None:
sql += sep + 'k.keyword LIKE ?'
sep = ' AND '
args.append('%' + search_keyword + '%')
if search_captions is not None:
sql += sep + 'cap.txt LIKE ?'
sep = ' AND '
args.append('%' + search_captions + '%')
sql += LIST_VIDEOS_SQL_GROUP_BY
cur.execute(sql, tuple(args))
return cur_fetchall()
def list_videos_hidden():
cur.execute('''
SELECT lv.video AS id
FROM label_video lv
LEFT JOIN label l ON l.id = lv.label
WHERE l.hide = 1
''')
return cur_fetchall()
###
### KEYWORD
###
cur.execute('''
CREATE TABLE IF NOT EXISTS keyword (
id INTEGER PRIMARY KEY,
video INTEGER NOT NULL,
keyword TEXT NOT NULL,
FOREIGN KEY (video) REFERENCES video (id),
UNIQUE (video, keyword)
)
''')
def insert_keyword(video_id, keyword):
cur.execute('''
INSERT INTO keyword (
video,
keyword
)
VALUES (
?, ?
)
''', (
video_id,
keyword
))
return cur.lastrowid
def list_keywords(video_id):
cur.execute('''
SELECT id, keyword
FROM keyword
WHERE video = ?
ORDER BY keyword COLLATE NOCASE
''', (video_id,))
return cur_fetchall()
###
### STREAM
###
cur.execute('''
CREATE TABLE IF NOT EXISTS stream (
id INTEGER PRIMARY KEY,
video INTEGER NOT NULL,
itag INTEGER NOT NULL,
type TEXT,
subtype TEXT,
vcodec TEXT,
acodec TEXT,
resolution TEXT,
fps INTEGER,
bitrate INTEGER,
is_otf BOOLEAN,
is_dash BOOLEAN,
is_prog BOOLEAN,
is_3d BOOLEAN,
is_hdr BOOLEAN,
is_live BOOLEAN,
FOREIGN KEY (video) REFERENCES video (id),
UNIQUE (video, itag)
)
''')
def insert_stream(video_id, stream):
cur.execute('''
INSERT INTO stream (
video,
itag,
type,
subtype,
vcodec,
acodec,
resolution,
fps,
bitrate,
is_otf,
is_dash,
is_prog,
is_3d,
is_hdr,
is_live
)
VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
)
''', (
video_id,
stream.itag,
stream.type,
stream.subtype,
stream.video_codec,
stream.audio_codec,
stream.resolution,
stream.fps,
stream.bitrate,
stream.is_otf,
stream.is_dash,
stream.is_progressive,
stream.is_3d,
stream.is_hdr,
stream.is_live
))
return cur.lastrowid
def list_video_streams(video_id):
cur.execute('''
SELECT *
FROM stream
WHERE video = ? AND type = 'video'
ORDER BY resolution
''', (
video_id,
))
return cur_fetchall()
###
### CAPTIONS
###
cur.execute('''
CREATE TABLE IF NOT EXISTS captions (
id INTEGER PRIMARY KEY,
video INTEGER NOT NULL,
lang INTEGER NOT NULL,
txt TEXT,
FOREIGN KEY (video) REFERENCES video (id),
UNIQUE (video, lang)
)
''')
def insert_captions(video_id, captions, text):
cur.execute('''
INSERT INTO captions (
video,
lang,
txt
)
VALUES (
?, ?, ?
)
''', (
video_id,
captions.code,
#captions.xml_captions
text
))
return cur.lastrowid
def get_captions(video_id):
cur.execute('''
SELECT *
FROM captions
WHERE video = ?
''', (
video_id,
))
return cur_fetch()
def id_captions(video_id):
cur.execute('''
SELECT id
FROM captions
WHERE video = ?
''', (
video_id,
))
return cur_fetchcol('id')
cur.execute('''
CREATE TABLE IF NOT EXISTS caption (
id INTEGER PRIMARY KEY,
captions INTEGER NOT NULL,
start INTEGER NOT NULL,
txt TEXT,
FOREIGN KEY (captions) REFERENCES captions (id)
)
''')
INSERT_CAPTION_SQL = '''
INSERT INTO caption (
captions,
start,
txt
)
VALUES (
?, ?, ?
)
'''
def insert_caption(captions_id, start, text):
cur.execute(INSERT_CAPTION_SQL, (
captions_id,
start,
text
))
return cur.lastrowid
def insert_caption_list(caps):
cur.executemany(INSERT_CAPTION_SQL, caps)
return cur.rowcount
def list_captions(captions_id):
cur.execute('''
SELECT *
FROM caption
WHERE captions = ?
ORDER BY start, id
''', (
captions_id,
))
return cur_fetchall()
def match_captions(captions_id, word):
sql = '''
SELECT *
FROM caption
WHERE captions = ?
'''
rep = '''
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(txt,
',', ' '),
'/', ' '),
';', ' '),
':', ' '),
'(', ' '),
')', ' '),
'?', ' '),
'!', ' '),
'.', ' ')
'''
sql += f' AND ({rep} = ?'
sql += 3 * f' OR {rep} LIKE ?'
sql += ') ORDER BY start, id'
cur.execute(sql, (
captions_id,
word,
f'{word} %',
f'% {word}',
f'% {word} %'
))
return cur_fetchall()
###
### PROJECT
###
cur.execute('''
CREATE TABLE IF NOT EXISTS project (
id INTEGER PRIMARY KEY,
name TEXT,
created TIMESTAMP,
updated TIMESTAMP
)
''')
def insert_project():
t = datetime.now()
cur.execute('''
INSERT INTO project (
created,
updated
) VALUES (
?, ?
)
''', (
t, t
))
return cur.lastrowid
def get_project(project_id):
cur.execute('''
SELECT *
FROM project
WHERE id = ?
''', (
project_id,
))
return cur_fetch()
def list_projects():
cur.execute('''
SELECT *
FROM project
ORDER BY name COLLATE NOCASE, updated DESC
''')
return cur_fetchall()
def set_project_name(project_id, name):
cur.execute('''
UPDATE project
SET name = ?, updated = ?
WHERE id = ?
''', (
name,
datetime.now(),
project_id
))
def touch_project(project_id):
cur.execute('''
UPDATE project
SET updated = ?
WHERE id = ?
''', (
datetime.now(),
project_id
))
#def delete_project(project_id):
# cur.execute('''
# DELETE
# FROM clip
# WHERE project = ?
# ''', (
# project_id,
# ))
#
# cur.execute('''
# DELETE
# FROM project
# WHERE id = ?
# ''', (
# project_id,
# ))
###
### MEDIA FRAGMENT
###
cur.execute('''
CREATE TABLE IF NOT EXISTS media (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
)
''')
cur.executemany('''
INSERT OR IGNORE INTO media (
id,
name
)
VALUES (
?, ?
)
''', [
(MEDIA_VIDEO, 'video'),
])
cur.execute('''
CREATE TABLE IF NOT EXISTS fragment (
id INTEGER PRIMARY KEY,
project INTEGER NOT NULL,
media INTEGER NOT NULL,
source INTEGER NOT NULL,
start INTEGER,
stop INTEGER,
FOREIGN KEY (project) REFERENCES project (id),
FOREIGN KEY (media) REFERENCES media (id)
)
''')
def insert_frag(project_id, media_id, source_id, start, stop):
cur.execute('''
INSERT INTO fragment (
project,
media,
source,
start,
stop
)
VALUES (
?, ?, ?, ?, ?
)
''', (
project_id,
media_id,
source_id,
start,
stop
))
return cur.lastrowid
def get_frag(frag_id):
cur.execute('''
SELECT *
FROM fragment
WHERE id = ?
''', (
frag_id,
))
return cur_fetch()
###
### CLIP
###
cur.execute('''
CREATE TABLE IF NOT EXISTS clip (
fragment INTEGER PRIMARY KEY,
name TEXT,
key INTEGER,
loop TEXT,
jumps TEXT,
created TIMESTAMP,
updated TIMESTAMP,
FOREIGN KEY (fragment) REFERENCES fragment (id)
)
''')
def insert_clip(frag_id, loop, jumps):
t = datetime.now()
cur.execute('''
INSERT INTO clip (
fragment,
loop,
jumps,
created,
updated
)
VALUES (
?, ?, ?, ?, ?
)
''', (
frag_id,
loop,
jumps,
t, t
))
return cur.lastrowid
def get_clip(frag_id):
cur.execute('''
SELECT *
FROM clip
WHERE fragment = ?
''', (
frag_id,
))
return cur_fetch()
CLIP_LIST_SQL = '''
SELECT
f.id AS 'id',
f.project AS 'project',
f.start AS 'start',
f.stop AS 'stop',
c.name AS 'name',
c.key AS 'key',
c.loop AS 'loop',
c.jumps AS 'jumps'
FROM clip c
LEFT JOIN fragment f ON f.id = c.fragment
'''
CLIP_LIST_SQL_ORDER = '''
ORDER BY c.name COLLATE NOCASE, c.updated DESC
'''
def get_clip_listing(frag_id):
cur.execute(
CLIP_LIST_SQL + 'WHERE c.fragment = ?',
(frag_id,))
return cur_fetch()
def list_clips(project_id):
cur.execute(
CLIP_LIST_SQL + 'WHERE f.project = ?' + CLIP_LIST_SQL_ORDER,
(project_id,))
return cur_fetchall()
def set_clip_name(frag_id, name):
cur.execute('''
UPDATE clip
SET name = ?
WHERE fragment = ?
''', (
name,
frag_id
))
def set_clip_key(frag_id, key):
cur.execute('''
UPDATE clip
SET key = ?
WHERE fragment = ?
''', (
key,
frag_id
))
def set_clip_loop(frag_id, loop):
cur.execute('''
UPDATE clip
SET loop = ?
WHERE fragment = ?
''', (
loop,
frag_id
))
def set_clip_jumps(frag_id, jumps):
cur.execute('''
UPDATE clip
SET jumps = ?
WHERE fragment = ?
''', (
jumps,
frag_id
))
def touch_clip(frag_id):
cur.execute('''
UPDATE clip
SET updated = ?
WHERE fragment = ?
''', (
datetime.now(),
frag_id
))
#def delete_clip(clip_id):
# cur.execute('''
# DELETE
# FROM clip
# WHERE fragment = ?
# ''', (
# clip_id,
# ))
###
### SEQUENCE SEGMENT
###
cur.execute('''
CREATE TABLE IF NOT EXISTS sequence (
id INTEGER PRIMARY KEY,
project INTEGER NOT NULL,
name TEXT,
created TIMESTAMP,
updated TIMESTAMP,
FOREIGN KEY (project) REFERENCES project (id)
)
''')
def insert_sequence(project_id):
t = datetime.now()
cur.execute('''
INSERT INTO sequence (
project,
created,
updated
)
VALUES (
?, ?, ?
)
''', (
project_id,
t, t
))
return cur.lastrowid
def get_sequence(seq_id):
cur.execute('''
SELECT *
FROM sequence
WHERE id = ?
''', (
seq_id,
))
return cur_fetch()
def list_sequences(project_id):
cur.execute('''
SELECT *
FROM sequence
WHERE project = ?
ORDER BY name COLLATE NOCASE, updated DESC
''', (
project_id,
))
return cur_fetchall()
def set_sequence_name(seq_id, name):
cur.execute('''
UPDATE sequence
SET name = ?
WHERE id = ?
''', (
name,
seq_id
))
def touch_sequence(seq_id):
cur.execute('''
UPDATE sequence
SET updated = ?
WHERE id = ?
''', (
datetime.now(),
seq_id
))
cur.execute('''
CREATE TABLE IF NOT EXISTS segment (
sequence INTEGER NOT NULL,
idx INTEGER NOT NULL,
fragment INTEGER NOT NULL,
PRIMARY KEY (sequence, idx),
FOREIGN KEY (sequence) REFERENCES sequence (id),
FOREIGN KEY (fragment) REFERENCES fragment (id)
)
''')
def insert_segment(seq_id, idx, frag_id):
cur.execute('''
INSERT INTO segment (
sequence,
idx,
fragment
)
VALUES (
?, ?, ?
)
''', (
seq_id,
idx,
frag_id
))
return cur.lastrowid
def get_segment(seq_id, idx):
cur.execute('''
SELECT *
FROM segment
WHERE sequence = ? AND idx = ?
''', (
seq_id,
idx
))
return cur_fetch()
SEGMENT_LIST_SQL = '''
SELECT
s.sequence AS 'sequence',
s.idx AS 'idx',
s.fragment AS 'fragment',
f.project AS 'project',
f.start AS 'start',
f.stop AS 'stop'
FROM segment s
LEFT JOIN fragment f ON f.id = s.fragment
'''
SEGMENT_LIST_SQL_ORDER = '''
ORDER BY s.idx
'''
def get_segment_listing(seq_id, idx):
cur.execute(
SEGMENT_LIST_SQL + 'WHERE s.sequence = ? AND s.idx = ?',
(seq_id, idx))
return cur_fetch()
def list_segments(seq_id):
cur.execute(
SEGMENT_LIST_SQL + 'WHERE s.sequence = ?' + SEGMENT_LIST_SQL_ORDER,
(seq_id,))
return cur_fetchall()
def get_last_segment_idx(seq_id):
cur.execute('''
SELECT idx
FROM segment
WHERE sequence = ?
ORDER BY idx DESC
LIMIT 1
''', (
seq_id,
))
return cur_fetchcol('idx')
def set_segment_idx(seq_id, old_idx, new_idx):
cur.execute('''
UPDATE segment
SET idx = ?
WHERE sequence = ? AND idx = ?
''', (
new_idx,
seq_id,
old_idx
))
###
### REPLAY
###
cur.execute('''
CREATE TABLE IF NOT EXISTS replay (
id INTEGER PRIMARY KEY,
name TEXT,
start INTEGER,
stop INTEGER,
data TEXT
)
''')
def insert_replay(start):
cur.execute('''
INSERT INTO replay (
start
) VALUES (
?
)
''', (
start,
))
return cur.lastrowid
def get_replay(replay_id):
cur.execute('''
SELECT *
FROM replay
WHERE id = ?
''', (
replay_id,
))
return cur_fetch()
def list_replays():
cur.execute('''
SELECT
id,
name,
start,
stop
FROM replay
ORDER BY name COLLATE NOCASE, start DESC
''')
return cur_fetchall()
def finish_replay(replay_id, stop, data):
cur.execute('''
UPDATE replay
SET stop = ?, data = ?
WHERE id = ?
''', (
stop,
data,
replay_id
))
def set_replay_name(replay_id, name):
cur.execute('''
UPDATE replay
SET name = ?
WHERE id = ?
''', (
name,
replay_id
))
cur.execute('''
CREATE TABLE IF NOT EXISTS replay_video (
replay INTEGER NOT NULL,
video INTEGER NOT NULL,
PRIMARY KEY (replay, video),
FOREIGN KEY (replay) REFERENCES replay (id),
FOREIGN KEY (video) REFERENCES video (id)
)
''')
def insert_replay_video(replay, video):
cur.execute('''
INSERT INTO replay_video (
replay,
video
) VALUES (
?, ?
)
''', (
replay,
video
))
return cur.lastrowid
def list_replay_videos(replay_id):
cur.execute('''
SELECT *
FROM replay_video
WHERE replay = ?
''', (
replay_id,
))
return cur_fetchall()
###
### LABEL
###
cur.execute('''
CREATE TABLE IF NOT EXISTS label (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL COLLATE NOCASE UNIQUE,
hide BOOLEAN
)
''')
cur.executemany('''
INSERT OR IGNORE INTO label (
id,
name
)
VALUES (
?, ?
)
''', [
(9, 'LANNOCC'),
(420, 'funny'),
(999, 'k-os')
])
def insert_label(name):
cur.execute('''
INSERT INTO label (
name
)
VALUES (
?
)
''', (
name,
))
return cur.lastrowid
def get_label(label_id):
cur.execute('''
SELECT *
FROM label
WHERE id = ?
''', (
label_id,
))
return cur_fetch()
def list_labels(hidden=False):
sql = '''
SELECT *
FROM label
'''
if not hidden:
sql += ' WHERE hide = 0 OR hide IS NULL'
sql += ' ORDER BY name COLLATE NOCASE'
cur.execute(sql)
return cur_fetchall()
def set_label_hide(label_id, hide):
cur.execute('''
UPDATE label
SET hide = ?
WHERE id = ?
''', (
hide,
label_id
))
def delete_label(label_id):
cur.execute('''
DELETE
FROM label_video
WHERE label = ?
''', (
label_id,
))
cur.execute('''
DELETE
FROM label
WHERE id = ?
''', (
label_id,
))
cur.execute('''
CREATE TABLE IF NOT EXISTS label_video (
label INTEGER NOT NULL,
video INTEGER NOT NULL,
PRIMARY KEY (label, video),
FOREIGN KEY (label) REFERENCES label (id),
FOREIGN KEY (video) REFERENCES video (id)
)
''')
cur.executemany('''
INSERT OR IGNORE INTO label_video (
label,
video
)
VALUES (
?, ?
)
''', [
(9, 10),
(9, 20),
(9, 30),
(9, 40),
(9, 50),
(9, 100),
(9, 101),
(9, 997),
(420, 50),
(420, 100),
(420, 101),
(420, 998),
(420, 999),
(999, 997),
(999, 998),
(999, 999)
])
def count_label_videos(label_id):
cur.execute('''
SELECT COUNT(*)
FROM label_video
WHERE label = ?
''', (
label_id,
))
return cur_fetch()[0]
def insert_label_video(label_id, video_id):
cur.execute('''
INSERT INTO label_video (
label,
video
) VALUES (
?, ?
)
''', (label_id, video_id))
def list_video_labels(video_id):
cur.execute('''
SELECT label
FROM label_video
WHERE video = ?
''', (video_id,))
return cur_fetchall()
def delete_label_video(label_id, video_id):
cur.execute('''
DELETE FROM label_video
WHERE label = ? AND video = ?
''', (label_id, video_id))
print('db ready :-)')
diff --git a/k/home.py b/k/home.py
--- a/k/home.py
+++ b/k/home.py
@@ -1,115 +1,115 @@
from k.ui import *
from version import *
import k.storage as media
from k.labels import Panel as Labels
from k.keys import Panel as Keys
INFO = '''ORDER IN CHAOS
This is the "K" Operating System. K in this context stands in for many things such as keyframe or knife, or ken, but also generically.
Purpose:
- make art
- play video
- hack python
-- perform musicly
+- perform musically
- train logic (AI)
- grow fun community
'''
EXTRA='''
-From a complete and fully-formed object / idea to noise, randomness, or the absense of anything... there are those points where change occurs and entropy is added; that is K.
+From a complete and fully-formed object / idea to noise, randomness, or the absence of anything... there are those points where change occurs and entropy is added; that is K.
_________
'''
SIGNED='THANK YOU for running this program.\n' \
+ 'Email ' + SAW + ' @ ' + THEY + ' if you want to help...\n' \
+ ' --' + ME
IMAGE=media.get_gfx('title.png')
class Panel(KPanel):
def __init__(self, k, anchors):
super().__init__(k, anchors)
self.image = pygame_gui.elements.UIImage(
image_surface=IMAGE,
manager=k.gui,
container=self.container,
relative_rect=pygame.Rect((10, 10), (180, 180)))
self.tagline = pygame_gui.elements.UILabel(
text='> Disorderly Conduct ^',
manager=k.gui,
container=self.container,
anchors=target(self.image, 'top'),
relative_rect=SPACER)
if self.k.testing:
self.btn_testing = pygame_gui.elements.UIButton(
text='TEST ME',
manager=k.gui,
container=self.container,
relative_rect=pygame.Rect((250, 111), (-1, -1)))
else:
self.btn_testing = None
self.btn_keys = pygame_gui.elements.UIButton(
text='HotKeys',
manager=k.gui,
container=self.container,
relative_rect=pygame.Rect((420, 175), (90, 25)))
self.panel_keys = Keys(k, target(k.btn_home, 'top'))
self.btn_labels = pygame_gui.elements.UIButton(
text='Labels',
manager=k.gui,
container=self.container,
relative_rect=pygame.Rect((420, 200), (90, 25)))
self.panel_labels = Labels(k, target(k.btn_home, 'top'))
self.info = pygame_gui.elements.UITextBox(
html_text=(INFO+EXTRA+SIGNED).replace('\n', '<br>'),
manager=k.gui,
container=self.container,
relative_rect=pygame.Rect((9, 234), (WIDTH-PWIDTH-36, 333)))
self.version = pygame_gui.elements.UILabel(
text=f'v/{VVHEN}',
#manager=k.gui,
#relative_rect=pygame.Rect((WIDTH/2 - 125, HEIGHT-30), (250, -1)))
manager=k.sui,
relative_rect=pygame.Rect((WIDTH/2 - 125, 3), (250, -1)))
#self.status_rect = pygame.Rect((5, HEIGHT-27), (152, 20))
self.status_rect = pygame.Rect((5, 5), (152, 20))
self.status = {}
for mode in MODES:
status = pygame_gui.elements.UIImage(
image_surface=media.get_gfx(MODES[mode]),
manager=k.sui,
relative_rect=self.status_rect)
status.hide()
self.status[mode] = status
def click(self, element, target=None):
if self.btn_testing and element is self.btn_testing:
from k.player.testing import Player
self.k.player.open(Player(self.k))
elif element is self.btn_keys:
self.k.panel_swap(None, self.panel_keys)
elif element is self.btn_labels:
self.k.panel_swap(None, self.panel_labels)
else:
return False
return True
diff --git a/k/patch/__init__.py b/k/patch/__init__.py
--- a/k/patch/__init__.py
+++ b/k/patch/__init__.py
@@ -1,66 +1,68 @@
import sys
-def upgrade(dbfile, cur, fetchall, set_meta, meta_version, from_ver, to_ver):
+def upgrade(dbfile, close, cur, fetchall,
+ set_meta, meta_version, from_ver, to_ver):
print()
print()
print('#################################')
print(' DATABASE UPGRADE REQUIRED')
print('---------------------------------')
print(f' database file: {dbfile}')
print(f' your version: {from_ver}')
print(f' needed version: {to_ver}')
print('---------------------------------')
print('The database must be patched')
print('before it can be used by this')
print('release.')
print()
print('! WARNING: It is recommended that')
print('you make a backup copy of the')
print('database file before continuing!!')
print()
print('Patches will apply incrementally.')
print('---------------------------------')
print(' USE <CTRL>-C TO EXIT')
print('#################################')
v = from_ver
while v < to_ver:
v += 1
try:
apply_patch(cur, fetchall, v)
set_meta(meta_version, v)
print('SUCCESS')
except KeyboardInterrupt:
print('ANCELLED BY USER') # not a typo (piggy back off ^C)
+ close()
sys.exit(1)
except Exception as e:
print('FAILED')
raise RuntimeError(f'Failed to apply version {v} patch', e)
def apply_patch(cur, fetchall, version):
print()
print(f'Hit <ENTER> to apply version {version}...')
input()
- exec(f'from k.patch.v{version} import patch as patch_v{version}')
+ exec(f'from .v{version} import patch as patch_v{version}')
cur.execute('PRAGMA foreign_keys=OFF')
cur.execute('BEGIN')
exec(f'patch_v{version}(cur)')
cur.execute('PRAGMA foreign_key_check')
fails = fetchall()
if fails:
print('!!! FOREIGN KEY FAILURE !!!')
for fail in fails:
print(f' table={fail[0]}, id={fail[1]}, column={fail[2]}')
raise RuntimeError('one or more foreign key constraints failed')
cur.execute('COMMIT')
cur.execute('PRAGMA foreign_keys=ON')
cur.execute('VACUUM')
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,6 @@
+pygame_gui
+colorama
+opencv-python
+pytube
+ffpyplayer
+
diff --git a/version.py b/version.py
--- a/version.py
+++ b/version.py
@@ -1,8 +1,8 @@
-VVHEN="6.05 (crickets) 13+20/2"
+VVHEN="6.05 lex 13+22/2"
THEY="yahoo.com"
SAW="LANNOCC"
ME="shawn"
print(VVHEN+' --'+SAW)
'''can you help?'''

File Metadata

Mime Type
text/x-diff
Expires
Sun, Sep 20, 4:24 PM (1 d, 1 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3510
Default Alt Text
(67 KB)

Event Timeline