mpogue2 / SquareDesk

Fully-featured music player and sequence designer, designed for square dance callers
10 stars 4 forks source link

Epic: Simple Sequence Designer using SD + File/Clipboard Import from CSDS Online or Taminations #752

Open mpogue2 opened 1 year ago

mpogue2 commented 1 year ago

I need a sequence playback thing of SOME kind, since I'm calling C1 for the first time in August. I've evaluated CSDS, CSDS Online, Callerama, Taminations, and SD. I won't repeat all of that analysis here, but my conclusion is that the best approach is probably hybrid: "Design: use CSDS Online or Taminations or SquareDesk's internal SD; Playback (while calling a C1 dance): use SquareDesk's SD".

I do like the "resolver" in CSDS Online (https://www.ceder.net/ws/) a LOT. But, the UI is very weak for designing (especially if you make a typo mistake), and it's really unusable for playback (during a dance). CSDS seems really good for playback, but it's Windows X86 only (and it's $200).

I think it's possible to make a minimally usable Design/Playback tab, using SD. This ticket describes some thoughts about what I think I need for August C1 calling:

Design in CSDS Online, Convert CSDS sequences to SD, use SD sequences or converted CSDS sequences: PROS: Nice resolution in CSDS Online Can still design in SquareDesk/SD SquareDesk has better music support CONS: have to write code:

                - NEW FEATURES IN SD TAB (or a new tab?):
                    - Fixed list of Frames to start (Unknown, Easy, Medium, Hard, Asymmetric, Used, etc)
                        - standard list created at startup in SD folder
                        - user can make more folders, if desired, and can move using Finder
                    - Save current sequence to Frame (folder)
                    - Import CSDS sequence (and convert to SD format) to Frame (NOTE: Export not needed now)
                    - Import SD sequence from text file to Frame
                    - Export SD sequence to text file (much better than "Save As HTML")
                    - Select frame (Keys: 1,2,3,4,5 = assigned to frames in Preferences, or maybe just alphabetical?
                            should these just be tabs, auto populated from the SD folder?)
                    - forward/back within frame (Keys: LEFT/RIGHT)
                    - USED key (move current to Used frame, Key: U, or should this just set a flag that this was used?
                        or maybe just add a file "Sequence.1.meta" containing "USED")
                    - REMOVE key (remove current sequence from current frame, Key: R, or just set a flag?)
                        (should flags be in the file system, or in the SQLite DB?)
                    - first sequence of frame (or "last viewed sequence in frame"?) is auto-loaded into SD
                    - first call is highlighted in the sequence
                    - scrub with UP/DOWN arrows in Current Sequence pane, changes the picture as keys are pressed
                    - TIME IN TIP needs to be somewhere on the page, maybe CLOCK, too?
                    - Mini playback controls (Keys: Stop, Play/Pause)?
                    - for Playback mode, we can lose the "Options, ? Completion, and Additional" tabs (replace with frame controls)
                        also the SD Output tab can go
                        also the little pictures in the Current Sequence tab can go, and the height of the rows reduced to be able
                            to see more calls at one time
                    - Right Click Menu in Current Sequence tab > Problem HERE
                    - Difficulty level can be selected, and that will mark USED AND will move to the other folder
                    - CANONICAL FORMAT FOR ALL SEQUENCES, AND PUBLISH THIS?
                        Canonical: BOYS Swing Thru while the GIRLS Trade
                        SD: BOYS (while the others) <NL> Swing Thru <NL> Trade
                        CSDS Online: Boys Swing Thru Girls Partner Trade
                        Taminations: BOYS Swing Thru while the GIRLS Trade
                    - MUST be able to assign names to each dancer, in place of numbers
                    - Zebra stripe the current sequence (perhaps every 3)

UPDATE

Here's what's implemented from the above list, as of 2023/03/12:

mpogue2 commented 1 year ago

Might be able to run CSDS Online in a Reference pane, and import directly from there. Or, could do COPY there, switch to SD tab and PASTE. Something simple might be good enough for August.

mpogue2 commented 1 year ago

Note sure I like the USED idea, where sequences get moved to a different folder. Might just want to mark them "used at this particular dance", which is what CSDS does.

mpogue2 commented 1 year ago

MILESTONE 1: To get started on this doesn't require much work, since some amount of basic infrastructure is needed first (and gives us a minimally-usable product):

I think this might be enough to be a very usable (though minimal) tool for calling C1. 80% of what is needed in a sequence designer (like CSDS), but with 10% of the work.

Hmmmmm:

mpogue2 commented 1 year ago

Good YouTube video: https://www.youtube.com/watch?v=0dpPa6f6-YA

Stuff that CSDS has:

mpogue2 commented 1 year ago

Current SD menu: image

We already have in the File menu:

We can add:

mpogue2 commented 1 year ago

Current SD tab: image

mpogue2 commented 1 year ago

We already have a way to turn off Formation Thumbnails, to hide the Options/? Completion/Additional panes, and to highlight individual calls in a sequence (although right now we can highlight more than one at a time, which we would turn off): image

We could add a new tab in the Options/?/Additional area called "Names", where we could type in names for each dancer, in a grid format:

  Boy     Girl
1 [Mark]  [Jane]
2 [Tony]  [Laurie]
3 [Todd]  [Cheryl]
4 [Jim]   [Gloria]

Perhaps with a [Default] button to go back to default (numbers, etc.).

mpogue2 commented 1 year ago

SD > [X] Show SD Output menu option would allow us to turn off the SD output tab entirely.

And, we can bring in the Frames idea in a similar way (perhaps to the LEFT of the Current Sequence window, or ABOVE/BELOW both the Current Sequence and Grid panes: View > SD > Frames

Then, a SET VIEW menu option for SD makes sense: SD > Set View > Design | Playback (mutually exclusive options)

Where Playback View:

and Design View:

Still can individually turn those on and off as desired. The PLAYBACK MODE is really not a "Playback Mode" then, it just sets up a particular set of View options, all of which are still in the SD menu.

mpogue2 commented 1 year ago

That gives us a unified single tab for designing sequences AND playing them back (dynamically selecting them) at a dance. It's pretty simple, a natural extension of what we have now, and although it doesn't have all the fancy stuff that CSDS has, I think it's a usable feature...

mpogue2 commented 1 year ago

Change SD > Numbers > Normal | Invisible to SD > Labels > None | [X] Numbers (note reordering) and then to SD > Labels > None | [X] Numbers | Names

mpogue2 commented 1 year ago

We have room for max of 3 characters on dancer icon labels right now. Looks like this:

image

I had to make the font a little smaller even for numbers, because I can't figure out how to change the font size for dancer label font on-the-fly (@danlyke, do you know how?).

7dd8e627f244bd615c22b1e3868f03b2085d03ed implements this:

mpogue2 commented 1 year ago

This is what Taminations does. They use more characters, and because their dancer frames (squares, circles) are not black, the black labels are actually readable. We might want to do this, too, at some point.

image

On the other hand, while Taminations names are more readable MOST of the time, Taminations output can also get VERY crowded, because the names are too wide:

image

By comparison, my initial cut at this looks like this:

image

mpogue2 commented 1 year ago

I do like the way Taminations colors each call by level:

image

and I like the Undo and Reset buttons at the bottom, too. I can live without the Copy and Paste buttons. I'd like to have a Redo button.

mpogue2 commented 1 year ago

d79026e7440c7a9fdabdf9c732e6d43eaaf5b441 adds support for naming dancers in SD.

New Names tab in SD lower right pane allows for setting 3-character names for each dancer. Tab order is set, so you can double-click on a name, type in a new name, and hit TAB to go to the next one in order CCW around the square.

mpogue2 commented 1 year ago

8341c164fe42fd82743fb836018b29cdacad5dc9 adds support for UI configuration. This config can be overridden manually via the usual menus. Note: these are not modes, they are just shortcuts for setting multiple view options all at once.

Sequence Designer:

Dance Arranger:

mpogue2 commented 1 year ago

TODO: Sequence Designer: allows multiple selections in the call list (no items selected at load time, double click on item to load) Dance Arranger: allows only single item selection in the call list (item 0 selected at load time, double click OR up/down arrow to load)

TODO: Load Sequence from File... Can I make the size of the Options/?/Additional/Names smaller at startup time? Stick an HTML Redirector (or just a link?) page into Reference for CSDS Online Stick an HTML Redirector (or just a link?) page into Reference for Taminations Online Allow SEQUENCE PASTE into SquareDesk/SD (failing that, in Import From Clipboard button) -- both CSDS Online and Taminations (offline/online) allow for SEQUENCE COPY with newlines as delimiters). This will allow us to use SD or CSDS Online or Taminations (offline/online) for sequence design (from within SquareDesk, too....)

mpogue2 commented 1 year ago

Current UX after selecting "Sequence Designer":

image

Current UX after selecting "Dance Arranger":

image
mpogue2 commented 1 year ago

f912e1111a582b030b5f633f7bd1d6203243ed50 does this:

TODO:

mpogue2 commented 1 year ago

Feature implemented by 4f1652ddbb6e5a1e47d956d39b4bee506d885a1a: In the Names tab, the background colors of the lineEdit fields should match the colors of the 4 couples.
This will make it easier when 3 characters is ambiguous, e.g. David E vs David Q both are "Dav".

Looks kinda nice, I think:

image

mpogue2 commented 1 year ago

TODO: Consider whether items in the Current Sequence window should be highlighted differently, e.g. with a line between cells, rather than highlighting the whole cell. Or, could be an arrow or something.

mpogue2 commented 1 year ago

TODO: Change status from "Kybd: Plus" to "SD: Plus" or "Level: Plus" or even "SD Level: Plus". There is no Voice input anymore, so distinguishing between "Kybd" and "Voice" input levels is no longer relevant.

Done: 08065a5004ac0a0514ffe9aaf7674806cbc53e6a

mpogue2 commented 1 year ago

TODO: In Dance Arranger mode, consider also hiding the SD Input line and the three tabs: Options/?/Additional. None of these are needed here, if we are just playing back an existing already-done sequence. Can always switch back to Designer mode with a single hotkey, if editing is needed.

Done: 826487103de7c83ec90f9e7508bc5b8d80b752a8

Current UX (Dance Arranger mode):

image
mpogue2 commented 1 year ago

TODO: In Dance Arranger mode, consider a status line for the current sequence ID, similar to CSDS (although I don't know what our Sequence ID should look like yet), perhaps above the Current Sequence tab. Or, consider getting rid of the Current Sequence title, and move the Current Sequence list up one level in the hierarchy. "Current Sequence" doesn't add much useful info. I suppose that the title of the tab ("Current Sequence") could be repurposed for this, too, although that feels a bit weird.

NOTE: Added the current level to the "Current Sequence" tab name. We'll see if it feels OK, after trying this a while.

mpogue2 commented 1 year ago

DONE: Consider changing Cmd-C (Copy Sequence) and modal Context Menu item ([X] Copy as HTML) to two separate shortcuts: Cmd-C (Copy as Plain Text) and Cmd-Shift-C (Copy as HTML).

DONE: Consider adding to the Current Sequence Context Menu, which already has Copy there. Add "Paste Sequence". Note that QtClipboard says that it can handle both plain text and HTML text, but SquareDesk's Copy As HTML is actually not recognized as HTML.

Taminations and CSDS Online are both Plain Text. Only SquareDesk has the Copy as HTML option. Also,change "Copy" to "Copy Sequence" at the same time, so that we end up with both "Copy Sequence" (Cmd-C) and "Paste Sequence" (Cmd-V).

Reorder Copy Sequence as HTML to be right below Copy Sequence.

Implementation is in: b645aaa040eab7875d39fa696da6f254493035f3

Context menu now looks like this:

image
mpogue2 commented 1 year ago

TODO: Some context menu items in Current Sequence context menu should be greyed out under some conditions, e.g. Copy Sequence, Copy Sequence to HTML, Paste Sequence (if clipboard is empty), Undo, Redo (if nothing on the redo stack), Go Back To Here (if no current selection).

mpogue2 commented 1 year ago

We can now copy sequences from either CSDS Online or from Taminations, and we can paste them successfully into SquareDesk's SD (into the Current Sequence pane, using Right Click > Paste Sequence).

Copy Sequence (Cmd-C) also works from within Squaredesk/SD, when focus is either in the SD Input field, OR in the Current Sequence pane.

TODO:

Commit: 672367dca44e6c5271cb299f2a5de3664e9441ed

mpogue2 commented 1 year ago

TODO BUG: Whenever switching switching levels, the new level is stuck with a "HEADS Square Thru 4" as the first item in the Current Sequence. This is wrong. But, it's coming from SDThread::finishAndShutdownSD(), which intentionally sticks this in, before it sends a "quit" to the SD thread. If I comment out the Heads start and square thru 4, then if I change levels and quit SquareDesk, it crashes for some reason. So, this stuff is needed, I just don't know why. (FIXED)

I'm not sure how to stop the new Current Sequence from picking this up either. It seems to be scanning the SD thread output, and it sees the "Heads Square Thru 4" from the OLD level, and it sticks it into the Current Sequence, thinking it's the NEW level. Maybe I can somehow clear out this buffer, when a finishAndShutdownSD() is done? But, where IS that buffer?? (FIXED)

mpogue2 commented 1 year ago

BUG: Changing levels continues to tack more level strings onto the output file name in SD, for example: "/Users/mpogue/Library/CloudStorage/Box-Box/__squareDanceMusic_Box/sd/sequence.Plus.A1.C1.A1"

Fixed by: b6946183b88ee9f2275ae78fee4720fb8238c812

This commit fixes several bugs when changing levels:

mpogue2 commented 1 year ago

c18e17b9bc58d4dcf41a6f910d65caea6132ba71 does the following:

NOTE: I might regret doing this different from Taminations, e.g. in the use case where we are switching from SD to Music tab and back again. Perhaps it should retain the selection? Gotta try it for a while and see how it feels, and notice if anything is surprising....

mpogue2 commented 1 year ago

TODO NEXT: We now have single click selection of items in the Current Sequence pane, which causes them to be rendered correctly. Next we need to flow through the UP/DOWN arrows from the event handler to the Current Sequence pane, IFF the SD tab is active. (DONE)

Implemented by 69accdd5d0ae1f72cb4f79dccc1715111814b2d8 .

mpogue2 commented 1 year ago

TODO (maybe): should the selection in the Current Sequence pane persist when changing tabs from SD to Music and back again? It probably should...

The selection is currently retained when moving from Music to SD/Dance Arranger mode. The selection is NOT retained when moving from Music to SD/Sequence Designer mode.

mpogue2 commented 1 year ago

TODO: As the user moves up and down in the Current Sequence one using UP/DOWN arrows, the Resolution field probably should be blank, except when the selection is on the last call in the Current Sequence. We're not currently remembering the resolution at every step of the sequence (which I suppose could be a different way of doing this).

mpogue2 commented 1 year ago

Bug: Context menu in Current Sequence pane has keyboard shortcuts (I added them), but they don't all actually work. Cmd-C works, but Cmd-Shift-C and Cmd-V do not.

mpogue2 commented 1 year ago

TODO: After Paste Sequence from Clipboard or Load Sequence from File, set selection to:

The difficulty here is that we can submit stuff to SD, but it's asynchronous, so we don't really know for sure when the paste/load operation is complete.

mpogue2 commented 1 year ago

As of c23cc4f3999f66581f279f76b8e65c1ea2f3c3ec:

mpogue2 commented 1 year ago

Commit: 54b5ee5225131cc3485fce089173aa78aad2c226 When Load Sequence is done, it now squares the set first, and then send the calls through the translator before they go to SD.

Paste Sequence, too: fa0a06607aa55aa01a55e0f839b56ca571510773

mpogue2 commented 1 year ago

BUG: I am seeing occasional crashes in rendering. Could be related to this? I'm not sure what causes this. 2023-01-12 18:04:45.552 SquareDesk[61438:9366295] +[CATransaction synchronize] called within transaction

Crash also spit this out on the Application Output pane: QPainter::begin: Paint device returned engine == 0, type: 3

Related: https://stackoverflow.com/questions/16192142/qtpainter-error-paint-device-returned-engine-0-type-3-painter-not-active

I think the [CATransaction...] happens when I do Load Sequence OR Save Sequence As. Basically, as soon as the dialog box is visible. The crash seems to happen when I switch from SquareDesk to Safari. Yep, verified that.

Here's the dump:

Process:               SquareDesk [61909]
Path:                  /Users/USER/*/SquareDesk.app/Contents/MacOS/SquareDesk
Identifier:            com.zenstarstudio.SquareDesk
Version:               0.9.6 (0.9.6.1)
Code Type:             ARM-64 (Native)
Parent Process:        qtcreator_processlauncher [31946]
User ID:               501

Date/Time:             2023-01-12 18:15:22.0452 -0800
OS Version:            macOS 13.1 (22C65)
Report Version:        12
Anonymous UUID:        4921A9E7-C3B3-A1E0-1FFD-EFBC5516BA2E

Sleep/Wake UUID:       94CD22CE-6E6D-4A71-8B12-12570D3DE0D3

Time Awake Since Boot: 640000 seconds
Time Since Wake:       6849 seconds

System Integrity Protection: enabled

Crashed Thread:        0  CrBrowserMain  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000018
Exception Codes:       0x0000000000000001, 0x0000000000000018

Termination Reason:    Namespace SIGNAL, Code 11 Segmentation fault: 11
Terminating Process:   exc handler [61909]

VM Region Info: 0x18 is not in any region.  Bytes before following region: 105553518919656
      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      UNUSED SPACE AT START
--->  
      MALLOC_NANO (reserved)   600018000000-600020000000 [128.0M] rw-/rwx SM=NUL  ...(unallocated)

Kernel Triage:
VM - pmap_enter retried due to resource shortage
VM - pmap_enter retried due to resource shortage
VM - pmap_enter retried due to resource shortage
VM - pmap_enter retried due to resource shortage
VM - pmap_enter retried due to resource shortage

Thread 0 Crashed:: CrBrowserMain Dispatch queue: com.apple.main-thread
0   QtGui                                  0x1039a1ef0 QScopedPointer<QPaintEnginePrivate, QScopedPointerDeleter<QPaintEnginePrivate> >::get() const + 0 (qscopedpointer.h:111) [inlined]
1   QtGui                                  0x1039a1ef0 decltype(fp.get()) qGetPtrHelper<QScopedPointer<QPaintEnginePrivate, QScopedPointerDeleter<QPaintEnginePrivate> > >(QScopedPointer<QPaintEnginePrivate, QScopedPointerDeleter<QPaintEnginePrivate> >&) + 0 (qglobal.h:1245) [inlined]
2   QtGui                                  0x1039a1ef0 QPaintEngine::d_func() + 0 (qpaintengine.h:52) [inlined]
3   QtGui                                  0x1039a1ef0 QPaintEnginePrivate::get(QPaintEngine*) + 0 (qpaintengine_p.h:103) [inlined]
4   QtGui                                  0x1039a1ef0 QMacCGContext::QMacCGContext(QPainter*) + 44 (qcoregraphics.mm:412)
5   QtGui                                  0x1039a1eec QMacCGContext::QMacCGContext(QPainter*) + 40 (qcoregraphics.mm:409)
6   libqmacstyle.dylib                     0x10916b0f4 QMacStylePrivate::drawNSViewInRect(NSView*, QRectF const&, QPainter*, void (CGContext*, CGRect const&) block_pointer) const + 56 (qmacstyle_mac.mm:2003)
7   libqmacstyle.dylib                     0x109172a90 QMacStyle::drawControl(QStyle::ControlElement, QStyleOption const*, QPainter*, QWidget const*) const + 12960 (qmacstyle_mac.mm:4012)
8   QtWidgets                              0x104062e9c QCommonStyle::drawControl(QStyle::ControlElement, QStyleOption const*, QPainter*, QWidget const*) const + 2136 (qcommonstyle.cpp:1777)
9   libqmacstyle.dylib                     0x109170128 QMacStyle::drawControl(QStyle::ControlElement, QStyleOption const*, QPainter*, QWidget const*) const + 2360 (qmacstyle_mac.mm:4621)
10  QtWidgets                              0x1041c8098 QStylePainter::drawControl(QStyle::ControlElement, QStyleOption const&) + 28 (qstylepainter.h:51) [inlined]
11  QtWidgets                              0x1041c8098 QTabBar::paintEvent(QPaintEvent*) + 1564 (qtabbar.cpp:1883)
12  QtWidgets                              0x10404563c QWidget::event(QEvent*) + 132
13  QtWidgets                              0x1041c790c QTabBar::event(QEvent*) + 736 (qtabbar.cpp:1771)
14  QtWidgets                              0x103ffbce4 QApplicationPrivate::notify_helper(QObject*, QEvent*) + 272 (qapplication.cpp:3315)
15  QtWidgets                              0x103ffd890 QApplication::notify(QObject*, QEvent*) + 3396
16  QtCore                                 0x104b02f64 QCoreApplication::notifyInternal2(QObject*, QEvent*) + 208 (qcoreapplication.cpp:1026)
17  QtWidgets                              0x1040387ac QWidgetPrivate::sendPaintEvent(QRegion const&) + 28 (qwidget.cpp:5637) [inlined]
18  QtWidgets                              0x1040387ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3336 (qwidget.cpp:5587)
19  QtWidgets                              0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
20  QtWidgets                              0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
21  QtWidgets                              0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
22  QtWidgets                              0x10403fe00 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 592 (qwidget.cpp:5752)
23  QtWidgets                              0x10403fe00 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 592 (qwidget.cpp:5752)
24  QtWidgets                              0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
25  QtWidgets                              0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
26  QtWidgets                              0x10403fe00 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 592 (qwidget.cpp:5752)
27  QtWidgets                              0x10403fe00 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 592 (qwidget.cpp:5752)
28  QtWidgets                              0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
29  QtWidgets                              0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
30  QtWidgets                              0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
31  QtWidgets                              0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
32  QtWidgets                              0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
33  QtWidgets                              0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
34  QtWidgets                              0x10403fe00 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 592 (qwidget.cpp:5752)
35  QtWidgets                              0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
36  QtWidgets                              0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
37  QtWidgets                              0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
38  QtWidgets                              0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
39  QtWidgets                              0x10403fe00 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 592 (qwidget.cpp:5752)
40  QtWidgets                              0x10403fe00 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 592 (qwidget.cpp:5752)
41  QtWidgets                              0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
42  QtWidgets                              0x104056450 QWidgetRepaintManager::paintAndFlush() + 3636 (qwidgetrepaintmanager.cpp:895)
43  QtWidgets                              0x1040567f4 QWidgetRepaintManager::sync() + 252 (qwidgetrepaintmanager.cpp:655)
44  QtWidgets                              0x104045ad8 QWidget::event(QEvent*) + 1312 (qwidget.cpp:9150)
45  QtWidgets                              0x104160494 QMainWindow::event(QEvent*) + 248 (qmainwindow.cpp:1303)
46  QtWidgets                              0x103ffbce4 QApplicationPrivate::notify_helper(QObject*, QEvent*) + 272 (qapplication.cpp:3315)
47  QtWidgets                              0x103ffd890 QApplication::notify(QObject*, QEvent*) + 3396
48  QtCore                                 0x104b02f64 QCoreApplication::notifyInternal2(QObject*, QEvent*) + 208 (qcoreapplication.cpp:1026)
49  QtCore                                 0x104b04034 QCoreApplication::sendEvent(QObject*, QEvent*) + 16 (qcoreapplication.cpp:1442) [inlined]
50  QtCore                                 0x104b04034 QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) + 816 (qcoreapplication.cpp:1804)
51  libqcocoa.dylib                        0x1074ef5a0 QCocoaEventDispatcherPrivate::processPostedEvents() + 312 (qcocoaeventdispatcher.mm:866)
52  libqcocoa.dylib                        0x1074efc30 QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void*) + 48 (qcocoaeventdispatcher.mm:889)
53  CoreFoundation                         0x1ab44ca18 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
54  CoreFoundation                         0x1ab44c9ac __CFRunLoopDoSource0 + 176
55  CoreFoundation                         0x1ab44c71c __CFRunLoopDoSources0 + 244
56  CoreFoundation                         0x1ab44b320 __CFRunLoopRun + 836
57  CoreFoundation                         0x1ab44a888 CFRunLoopRunSpecific + 612
58  HIToolbox                              0x1b4b1ffa0 RunCurrentEventLoopInMode + 292
59  HIToolbox                              0x1b4b1fc30 ReceiveNextEventCommon + 236
60  HIToolbox                              0x1b4b1fb2c _BlockUntilNextEventMatchingListInModeWithFilter + 72
61  AppKit                                 0x1ae6cc424 _DPSNextEvent + 632
62  AppKit                                 0x1ae6cb5b4 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 728
63  AppKit                                 0x1ae6bf9e4 -[NSApplication run] + 464
64  libqcocoa.dylib                        0x1074eeb18 QCocoaEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 1800 (qcocoaeventdispatcher.mm:394)
65  QtCore                                 0x104b0bfcc QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 36 (qeventloop.cpp:100) [inlined]
66  QtCore                                 0x104b0bfcc QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 536 (qeventloop.cpp:182)
67  QtCore                                 0x104b03618 QCoreApplication::exec() + 128 (qcoreapplication.cpp:1347)
68  SquareDesk                             0x102d8b404 main + 1176
69  dyld                                   0x1ab043e50 start + 2544
mpogue2 commented 1 year ago

Commit: 673a85a912b693773943411d4bf26226529496ac

This allows the Chromium browser that we use for Reference pages to access non-local pages, like Taminations and CSDS Online websites.

To Include CSDS Online and Taminations Online into Reference pages, do this:

OR for CSDS Online, do this:

NOTE: The CSDS "Text to Clipboard" works fine inside a Reference page, and the resulting calls can be pasted into SquareDesk's internal SD. HOWEVER, the late version of Taminations "Copy" button, which SAYS that it copied calls to the clipboard, actually doesn't do anything to the Clipboard. Very old versions of Taminations Standalone use Cmd-C to do the copy, and that copy DOES work. My guess is that Taminations changed the way it sticks stuff into the Clipboard, and the old way worked, and the new way does not.

mpogue2 commented 1 year ago

Accordion widgets for the Frames at the left:

This is super interesting too, and the Auto-Hide is kinda what I'm thinking about for Frames:

mpogue2 commented 1 year ago

Commit: 23d3f7d65ee1140a4c65018a5f75d75e514a6343

A few more UX changes, to add in frames. I went with the simplest approach of just adding a vertical box layout for the Frames, and hiding it when not in use. I also took the SD output (which is used mostly for debugging) out of the tab view, and promoted the Current Sequence pane up one level.

Current Sequence designer look (intentionally very much like the current look):

image

Switching over to the Dance Arranger view, there are now three prototype frames present (they can be hidden via menu option). The main "Current Sequence" window becomes the "Current Frame" when in Dance Arranger mode. (This look is intentionally more like CSDS and SquareDesk had a baby.)

image

The content of the frames is static right now, but the look and feel is kinda working now. The flow is left-to-right from Frame List on the left to Current Frame in the middle to picture on the right (when in Arranger mode). Hitting a F-key will swap in that frame to the Current Frame position, at the current call. F11/F12 will change sequences within a frame.

mpogue2 commented 1 year ago

Commit: 0438c613d9ac79df570db3ee3c4856d8510faaa8

Trying out zebra striping for the Current Sequence pane. Not sure if I like it or not. I've seen articles that recommend highlighting every 3 (instead of 2).

With zebra striping:

image

mpogue2 commented 1 year ago

Commit: 3715798c464359b5f208ae7d14776a891b5cccc9 This makes it possible to read the SDOutput info without horizontally scrolling all the time.

Also allows us to look at the SDOutput and Current Sequence panes at the same time, and to disappear the SDOutput pane when we don't want to see it anymore.

Example UX when SDOutput is enabled (it defaults to off now):

image

mpogue2 commented 1 year ago

Static Square to Resolve (SS) Ceder format example (from the Basic list):

@
#PROOFREAD#
#EASY#
#REC=10511#
#SEQTYPE=5#
#AUTHOR=Vic Ceder#
Heads 1/2 Square Thru,
Touch 1/4,
Split Circulate,
Boys Run,
Reverse Flutter Wheel,
Square Thru 4,
Trade By,
L.A
@
#PROOFREAD#
#EASY#

Record types in files ({level}.choreodb_to_csds.in) are just these:

Calls (except the last one) end in commas. There can be commas mid-line. Extra spaces can happen. Comments are (in parentheses), which can appear mid-line.

Vic's SQL schema (from https://www.ceder.net/faqdb/?section=10):

My sequence database is currently defined as:

CREATE TABLE ChoreoDb
  (CheckedByVdc     int, 
   LevelValidated   int,  // 0 = false, 1 = true
   SeqTypeInd       int, 
   Text             blob,
   SubmittedBy      int,  // Index into 'callerdb' where 0 = anonymous
   LevelInd         int, 
   Comments         blob,
   HandleList       varchar(255),  // stored with a comma on both ends (e.g., ",9,122,2124,")
   DifficultyInd    int,
   ModDateTime      datetime, 
   CreateDateTime   datetime,
   RecordId         int AUTO_INCREMENT PRIMARY KEY)
Where
CheckedByVdc indicates that the record has been proofread. (i.e., I have verified that the sequence works).
LevelValidated indicates that I have verified the level of the sequence.
SeqTypeInd indicates the type of the sequence. (e.g., Zero-Line to Resolve, etc.)
Text is the sequence text.
SubmittedBy indicates who submitted the sequence to the database.
LevelInd is the level of the sequence.
Comments is additional text associated with the sequence.
HandleList is a list of parse handles used by CSDS, so I can do database searches for calls and concepts without using text.
DifficultyInd indicates the difficulty of the sequence.
ModDateTime indicates the date and time that the sequence was last modified.
CreateDateTime indicates the date and time that the sequence was added to the database.
RecordId is a number that uniquely identifes the sequence within the database.
Our database runs under MySQL, a freeware database product. The SQL statements given above should work (perhaps with minor tweaking) in almost any database.
mpogue2 commented 1 year ago

My initial cut at a minimal on-disk format will be to use the Ceder format for files, each of which can contain many sequences. The file structure is this:

musicDir/sd:

I haven't yet decided whether to slurp this into a table in sqlite. It would be more convenient for searches, but then I have to have some import strategy (SD > import from CSDS, perhaps?), rather than having the import happen automatically at startup (there are only 4484 sequences total right now, in those 3 categories). And, I'll have to write a lot more code just to get something minimal up and running....I'm feeling the pressure now to get something completely up and running for August 2023. There's still much to do before I can write sequences in SD, save them on disk to a frame, and read them back for playback.

I'm tempted to just read in all the files at app startup, into an in-memory structure (I have plenty of memory, and the total of all of these files is only about 2.3Mb). I can just as easily do simple text searches by scanning thru the in-memory structure. Might take a little longer to fetch, but then again searching is not a P1 feature.

mpogue2 commented 1 year ago

TODO:

mpogue2 commented 1 year ago

Editorial comment: I think there's a general heuristic that I'm following here, that I like more and more as I do more of it: Rather than having strict modes like many apps do (e.g. in our case, "designer vs playback mode"), allow many individual panes to be hide/unhideable, so that custom views of many types can be made, BUT also have a small number of custom "sets of views" (in this case, exactly 2).

This might be even better with the Advanced Docking System referenced above, but for a simple minimal app without a whole embedded docking system, this heuristic seems to work surprisingly well (at least it nicely matches my mental model :-)....

mpogue2 commented 1 year ago

Commit: f3a3645d3f64ca42055bb6c42655fb36abeacd1c

Initial load code. If files do not exist (which is the case for everybody except me), there will be placeholder calls used, as per level. Filenames that we look for are hard-code right now, in /sd//SStoSS/, where the code specifies ".". These are "Static Square to Resolve" sequences (SS to SS, essentially).

So, if no files are found, you'll get fake data. If you want to use real data, put it here:

musicDir
    sd
        ceder
                SStoSS
                        <level> = {basic, ms, plus, a1, a2, c1}
        local
                SStoSS
                        <level>, as above

Files used (and the sequences inside those files) are hard-coded right now.

File format:

This is temporary, but it's useful for testing for now. Eventually, all of the sequence files will be found automatically, and assigned to Function keys (F1 - F10). If these files are not present, very simple dummy data will be used, just to see how it looks. The Current Sequence window will be live, even with this dummy data, though.

mpogue2 commented 1 year ago

Oh yeah, the label_SD_Resolve is back when in Dance Arranger mode, because SD can't handle Allemande Left or RLG at all, so this label tells you what the final resolve call is, just like it does in Sequence Designer mode.

Current UX (Sequence Designer):

image

Current UX (Dance Arranger):

image

mpogue2 commented 1 year ago

Commit 3a06cf7f9b1b9849eea846f36ce9c2e424e0546e makes the function keys work.

Function keys F1-F10 will now load the corresponding frame into the central Current Sequence window, will load the last used sequence, and will highlight the first call (Dance Arranger mode).

Fake data (just 1 sequence) will be used, if a required file (see L1279 in mainwindow.cpp) is not found in the musicDir/sd directory. F11/F12 can be used to load sequences backwards/forwards within a frame.

Only F2/F3/F6/F7 are available right now (there will be another mechanism to select WHICH frames are viewed in the sidebar and central views.

NOTE: Due to a weird bug, the Options tab cannot be hidden, because if it is hidden when I switch from SDesk to another window, the whole SDesk app crashes deep in the bowels of Qt framework code.

TODO:

Example (before pressing F7):

image

Example (after pressing F7):

image

mpogue2 commented 1 year ago

BUG: In that last picture, I think that the first item in the Current Sequence pane should be highlighted.

FEATURE?: Should I allow double-clicking in the sidebar frames? Should I have a context menu there for something?