#!/bin/env python
# -*- coding: utf-8 -*-

""" #+begin_org
* ~[Summary]~ :: A =CmndSvc= for
#+end_org """

####+BEGIN: b:py3:cs:file/dblockControls :classification "cs-u"
""" #+begin_org
* [[elisp:(org-cycle)][| /Control Parameters Of This File/ |]] :: dblk ctrls classifications=cs-u
#+BEGIN_SRC emacs-lisp
(setq-local b:dblockControls t) ; (setq-local b:dblockControls nil)
(put 'b:dblockControls 'py3:cs:Classification "cs-u") ; one of cs-mu, cs-u, cs-lib, bpf-lib, pyLibPure
#+END_SRC
#+RESULTS:
: cs-u
#+end_org """
####+END:

####+BEGIN: b:prog:file/proclamations :outLevel 1
""" #+begin_org
* *[[elisp:(org-cycle)][| Proclamations |]]* :: Libre-Halaal Software --- Part Of BISOS ---  Poly-COMEEGA Format.
** This is Libre-Halaal Software. © Neda Communications, Inc. Subject to AGPL.
** It is part of BISOS (ByStar Internet Services OS)
** Best read and edited  with Blee in Poly-COMEEGA (Polymode Colaborative Org-Mode Enhance Emacs Generalized Authorship)
#+end_org """
####+END:

####+BEGIN: b:prog:file/particulars :authors ("./inserts/authors-mb.org")
""" #+begin_org
* *[[elisp:(org-cycle)][| Particulars |]]* :: Authors, version
** This File: /bisos/git/bxRepos/bisos-pip/lcnt/py3/bin/beamerExternalExtensions.py
** Authors: Mohsen BANAN, http://mohsen.banan.1.byname.net/contact
#+end_org """
####+END:

####+BEGIN: b:py3:file/particulars-csInfo :status "inUse"
""" #+begin_org
* *[[elisp:(org-cycle)][| Particulars-csInfo |]]*
#+end_org """
import typing
csInfo: typing.Dict[str, typing.Any] = { 'moduleName': ['beamerExternalExtensions'], }
csInfo['version'] = '202502114510'
csInfo['status']  = 'inUse'
csInfo['panel'] = 'beamerExternalExtensions-Panel.org'
csInfo['groupingType'] = 'IcmGroupingType-pkged'
csInfo['cmndParts'] = 'IcmCmndParts[common] IcmCmndParts[param]'
####+END:

""" #+begin_org
* [[elisp:(org-cycle)][| ~Description~ |]] :: [[file:/bisos/git/auth/bxRepos/blee-binders/bisos-core/COMEEGA/_nodeBase_/fullUsagePanel-en.org][BISOS COMEEGA Panel]]
*       [[elisp:(org-show-subtree)][|=]]  [[elisp:(org-cycle)][| *Module Description:* | ]]
**  [[elisp:(org-cycle)][| ]]  [Xref]          :: *[Related/Xrefs:]*  <<Xref-Here->>  -- External Documents  [[elisp:(org-cycle)][| ]]

**  [[elisp:(org-cycle)][| ]]   Model and Terminology                                      :Overview:
**      ====[[elisp:(org-cycle)][Fold]]==== Description:
Given the base directory of a beamer produced pdf file, process all disposition aspects.
This script provides full integration between Impressive and Beamer based on the following:

***      ==[[elisp:(org-cycle)][Fold]]== Model
****   =[[elisp:(org-cycle)][Fold]]= Content Structure Vs Content Dispositions
       A given document (content) has a specific structure and can have many resulting formats (Article, Presentaton, VoiceOver, ScreenCast (Video)).
       A given content can be presented/exposed in a variety of ways. Content disposition parameters play a role at that time.
****   =[[elisp:(org-cycle)][Fold]]= SlideNumber vs FrameName
       frameName is an attribute of  Content Structure. It is specified in the latex source and corresponding disposition parameters
       slideNumber (page of presentation format) maps to a frameName. [NOTYET, needs better description.]
***      ==[[elisp:(org-cycle)][Fold]]== Beamer Input Disposition Tagging
****   =[[elisp:(org-cycle)][Fold]]= Each frame that requires special disposition is tagged with [label=frameName]
***      ==[[elisp:(org-cycle)][Fold]]== ./disposition.gened   Directory Structure
****   =[[elisp:(org-cycle)][Fold]]= For each slide, there is a sequential slideNumber fileParam.
****   =[[elisp:(org-cycle)][Fold]]= Value of each slideNumber is *frameName*
****   =[[elisp:(org-cycle)][Fold]]= frameName is specified in BeamerInut with [label=frameName] or if not it becomes defaultDispParams
****   =[[elisp:(org-cycle)][Fold]]= There is a baseDir  with the name frameName in ./disposition.gened
****   =[[elisp:(org-cycle)][Fold]]= That baseDir includes disposition parameters for the slide such as:
       - transitionType -- These are all autogenerated from LaTeX source
***      ==[[elisp:(org-cycle)][Fold]]== ./audio         Directory Structure
****   =[[elisp:(org-cycle)][Fold]]= For each frameName that has voiceOver, there is a frameName.wav file.
****   =[[elisp:(org-cycle)][Fold]]= With audioProc.sh -- Based on frameName.wav, frameName.mp3 and frameName.length
***      ==[[elisp:(org-cycle)][Fold]]== ./impressive    Directory Structure
****   =[[elisp:(org-cycle)][Fold]]= For each of the well-known usages, an impressive input file with the name use.info will be created
****   =[[elisp:(org-cycle)][Fold]]= voiceOver.info  is gernerated by -i xxx of this script

**      ====[[elisp:(org-cycle)][Fold]]==== Background and Assumptions:
***      ==[[elisp:(org-cycle)][Fold]]== Components:  Debian/Ubuntu + Emacs + Beamer + Impressive
***      ==[[elisp:(org-cycle)][Fold]]== Background: Beamer + (Impressive + Pdfpc) gets us almost there. This is about getting all the way there.
***      ==[[elisp:(org-cycle)][Fold]]== Goals/Requirements:
****   =[[elisp:(org-cycle)][Fold]]=  BeamerInput should be the primary source for EVERYTHING.
****   =[[elisp:(org-cycle)][Fold]]=  Audio files should correlate to BeamerInput.
****   =[[elisp:(org-cycle)][Fold]]=  Presenter Console should be emacs based and provide for controlling Impressive.
****   =[[elisp:(org-cycle)][Fold]]=  Emacs should permit editing BeamerInput in the context of current slide.
***      ==[[elisp:(org-cycle)][Fold]]== Contours Of Languages And Tools
****   =[[elisp:(org-cycle)][Fold]]= Bash -- To glue things together
****   =[[elisp:(org-cycle)][Fold]]= Python -- To control Impressive and communicate with Emacs
****   =[[elisp:(org-cycle)][Fold]]= Elisp -- To control Emacs and Communicate with Impressive
****   =[[elisp:(org-cycle)][Fold]]= Tex/LaTeX -- To generate stuff out of BeamerInput.
****   =[[elisp:(org-cycle)][Fold]]= Choosing NOT to use: JavaScript, Perl
**      ====[[elisp:(org-cycle)][Fold]]==== Design:
***      ==[[elisp:(org-cycle)][Fold]]== Presenter-Console
         Two Options exist, Both are usable, neither of them is ultimate
****   =[[elisp:(org-cycle)][Fold]]= pdfpc Presenter Notes.
       Ubuntu's apt-get pdf-presenter-console will be used for now.
       With pdfpcnotes.sty \pnotes{} produces pres.pdfpc which can then be used by pdfpc
****   =[[elisp:(org-cycle)][Fold]]= Javascript based presenter-for-impressive -- http://flobosg.com/en/2013/02/impressive-presenter -- https://github.com/flobosg/impressive-presenter
       I have packaged this and it does work. It does not have a feature to get notes from BeamerInput.
       Its model is flexible and the same model can be adopted for Emacs-Impressive-Presenter-Console.

****   =[[elisp:(org-cycle)][Fold]]= Emacs-Impressive-Presenter-Console
       Mimic the javascript model of presenter-for-impressive with elisp.
       Extract notes from Beamer-input similar to pdfpc Presenter Notes.
       Send a particular slideNumber Selection to impressive -- May need updates to impressive to listen on a socket (similar to vlc's remote control).
       Emacs will display Current+Previous slides. Will have a running clock.
       Will permit BeamerInput notes editing of the current slide.

***      ==[[elisp:(org-cycle)][Fold]]== Correlation Of PDF File to BeamerInput
****   =[[elisp:(org-cycle)][Fold]]= Relevant Info is in pdfOut.nav and pdfOut.aux  and pdf.snm -- most convenient is .snm -- (for [label=frameName])
**** TODO =[[elisp:(org-cycle)][Fold]]= Start From Beamer-With-Impressive http://code.google.com/p/makebeamerinfo/  -- Takes latex.nav, generates impressive.info
       Convert perl to python and integrate with above.

***      ==[[elisp:(org-cycle)][Fold]]== Beamer Input Tagging
****   =[[elisp:(org-cycle)][Fold]]=  Impressive features are tagged with comments correlated to frameNames
****   =[[elisp:(org-cycle)][Fold]]=  The action parts are python callables in the context of this script.
****   =[[elisp:(org-cycle)][Fold]]=  Those functions, act within the ./disposition.gened directory, by creating/modifying
       file parameters.
****   =[[elisp:(org-cycle)][Fold]]=  The tags are identified in beamer source, and then acted upon with this script.

**      [End-Of-Description]
#+end_org """

####+BEGIN: b:prog:file/orgTopControls :outLevel 1
""" #+begin_org
* [[elisp:(org-cycle)][| Controls |]] :: [[elisp:(delete-other-windows)][(1)]] | [[elisp:(show-all)][Show-All]]  [[elisp:(org-shifttab)][Overview]]  [[elisp:(progn (org-shifttab) (org-content))][Content]] | [[file:Panel.org][Panel]] | [[elisp:(blee:ppmm:org-mode-toggle)][Nat]] | [[elisp:(bx:org:run-me)][Run]] | [[elisp:(bx:org:run-me-eml)][RunEml]] | [[elisp:(progn (save-buffer) (kill-buffer))][S&Q]]  [[elisp:(save-buffer)][Save]]  [[elisp:(kill-buffer)][Quit]] [[elisp:(org-cycle)][| ]]
** /Version Control/ ::  [[elisp:(call-interactively (quote cvs-update))][cvs-update]]  [[elisp:(vc-update)][vc-update]] | [[elisp:(bx:org:agenda:this-file-otherWin)][Agenda-List]]  [[elisp:(bx:org:todo:this-file-otherWin)][ToDo-List]]

#+end_org """
####+END:

####+BEGIN: b:py3:file/workbench :outLevel 1
""" #+begin_org
* [[elisp:(org-cycle)][| Workbench |]] :: [[elisp:(python-check (format "/bisos/venv/py3/bisos3/bin/python -m pyclbr %s" (bx:buf-fname))))][pyclbr]] || [[elisp:(python-check (format "/bisos/venv/py3/bisos3/bin/python -m pydoc ./%s" (bx:buf-fname))))][pydoc]] || [[elisp:(python-check (format "/bisos/pipx/bin/pyflakes %s" (bx:buf-fname)))][pyflakes]] | [[elisp:(python-check (format "/bisos/pipx/bin/pychecker %s" (bx:buf-fname))))][pychecker (executes)]] | [[elisp:(python-check (format "/bisos/pipx/bin/pycodestyle %s" (bx:buf-fname))))][pycodestyle]] | [[elisp:(python-check (format "/bisos/pipx/bin/flake8 %s" (bx:buf-fname))))][flake8]] | [[elisp:(python-check (format "/bisos/pipx/bin/pylint %s" (bx:buf-fname))))][pylint]]  [[elisp:(org-cycle)][| ]]
#+end_org """
####+END:

####+BEGIN: b:py3:cs:framework/imports :basedOn "classification"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CsFrmWrk   [[elisp:(outline-show-subtree+toggle)][||]] *Imports* =Based on Classification=cs-u=
#+end_org """
from bisos import b
from bisos.b import cs
from bisos.b import b_io
from bisos.common import csParam

import collections
####+END:

import sys
import os
import io

from PyPDF4.pdf import PdfFileReader
import re


""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CsFrmWrk   [[elisp:(outline-show-subtree+toggle)][||]] ~csuList emacs-list Specifications~  [[elisp:(blee:org:code-block/above-run)][ /Eval Below/ ]] [[elisp:(org-cycle)][| ]]
#+BEGIN_SRC emacs-lisp
(setq  b:py:cs:csuList
  (list
   "bisos.b.cs.ro"
   "bisos.csPlayer.bleep"
   "bisos.lcnt.latexSup"
 ))
#+END_SRC
#+RESULTS:
| bisos.b.cs.ro | bisos.csPlayer.bleep | bisos.lcnt.latexSup |
#+end_org """

####+BEGIN: b:py3:cs:framework/csuListProc :pyImports t :csuImports t :csuParams t
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CsFrmWrk   [[elisp:(outline-show-subtree+toggle)][||]] =Process CSU List= with /3/ in csuList pyImports=t csuImports=t csuParams=t
#+end_org """

from bisos.b.cs import ro
from bisos.csPlayer import bleep
from bisos.lcnt import latexSup


csuList = [ 'bisos.b.cs.ro', 'bisos.csPlayer.bleep', 'bisos.lcnt.latexSup', ]

g_importedCmndsModules = cs.csuList_importedModules(csuList)

def g_extraParams():
    csParams = cs.param.CmndParamDict()
    cs.csuList_commonParamsSpecify(csuList, csParams)
    cs.argsparseBasedOnCsParams(csParams)

####+END:

####+BEGIN: b:py3:cs:main/exposedSymbols :classes ()
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CsFrmWrk   [[elisp:(outline-show-subtree+toggle)][||]] ~CS Controls and Exposed Symbols List Specification~ with /0/ in Classes List
#+end_org """
####+END:

####+BEGIN: blee:bxPanel:foldingSection :outLevel 0 :sep nil :title "CmndSvcs" :anchor ""  :extraInfo "Command Services Section"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*     [[elisp:(outline-show-subtree+toggle)][| _CmndSvcs_: |]]  Command Services Section  [[elisp:(org-shifttab)][<)]] E|
#+end_org """
####+END:

####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "examples" :extent "verify" :ro "noCli" :comment "FrameWrk: CS-Main-Examples" :parsMand "" :parsOpt "" :argsMin "0" :argsMax "0" :asFunc "" :interactiveP ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<examples>>  *FrameWrk: CS-Main-Examples*  =verify= argsMin=0 argsMax=0 ro=noCli   [[elisp:(org-cycle)][| ]]
#+end_org """
class examples(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ ]
    cmndArgsLen = {'Min': 0, 'Max': 0,}
    rtInvConstraints = cs.rtInvoker.RtInvoker.new_noRo() # NO RO From CLI

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:
        """FrameWrk: CS-Main-Examples"""
        failed = b_io.eh.badOutcome
        callParamsDict = {}
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return failed(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
####+END:
        self.cmndDocStr(f""" #+begin_org
***** [[elisp:(org-cycle)][| *CmndDesc:* | ]]  Conventional top level example.
        #+end_org """)

        od = collections.OrderedDict
        cmnd = cs.examples.cmndEnter
        literal = cs.examples.execInsert

        cs.examples.myName(cs.G.icmMyName(), cs.G.icmMyFullName())

        cs.examples.commonBrief(roMenu=False,)
        bleep.examples_csBasic()

        mainPdfFile="""./presentationEnFa.pdf"""
        mainTtytexFile="""./presentationEnFa.ttytex"""
        mainSnmFile="""./presentationEnFa.snm"""

        selectedFramesRange = "1"

        cs.examples.menuChapter('*Disposition Setup/Set/Update  -- ./disposition.gened*')

        cmnd('dispositionBaseSetup', pars=od([('dispositionBase', '/tmp/t3/DISP'),]), args="", comment="# Just creates dispositionBaseDir.")

        cmnd('dispositionParamSet', pars=od([]), args="globalTimeout 2000", comment="")

        cmnd('frameParSet', pars=od([('dispositionBase', '/tmp/t3/DISP'),]), args="frameName transition up", comment="")

        cs.examples.menuChapter('*Extract Frames Parameters From Pdf/snm files -- into DispositionBase*')

        cmnd('latexSrcToDispositionUpdate', args=mainPdfFile, comment="# Sets up dispositionBase based on pdf and snm info.")
        cmnd('latexSrcToDispositionUpdate', pars=od([('dispositionBase', './disposition.gened'),]), args=mainPdfFile, comment="")

        cmnd('frameNamesList', pars=od([]), args=mainPdfFile, comment="# Gets frame names from pdf file.")

        cs.examples.menuSection('Extract Frames Parameters From TeX files -- into DispositionBase')

        cmnd('beamerExternalTagsUpdateAsFPs', pars=od([]), args=mainTtytexFile, comment="")

        cs.examples.menuSection('DispositionBase Full Update')

        cmnd('updateDispositionBase', pars=od([('dispositionBase', './disposition.gened'),]), args=mainPdfFile, comment="# Primary Preparations")
        cmnd('dispositionFrameNamesList', pars=od([]), args="", comment="# List FrameNames from dispositionBase")

        cs.examples.menuSection('Common Capabilities')

        cmnd('latexInputFilesList', args=mainTtytexFile, )
        cmnd('latexInputFilesList', args=f"{mainTtytexFile} ./articleEnFa.ttytex" , )

        cs.examples.menuChapter('*Construct Configuration Files From Disposition Base For Impressive -- stdout*')

        cmnd('frameParSet', pars=od([('dispositionBase', '/tmp/t3/DISP'),]), args="frameName transition up", comment="")
        cmnd('dispositionToImpressiveInfoPurposedStdout',  args="voiceOver presenter", comment="# Args specify purpose")
        cmnd('dispositionToImpressiveInfoPurposedStdout',  args="voiceOver", comment="")
        cmnd('dispositionToImpressiveInfoPurposedStdout', pars=od([('framesRange', selectedFramesRange),]), args="voiceOver recorderEach", comment="")

        cs.examples.menuChapter('*Construct Configuration Files And Run Impressive*')

        cmnd('updateDispositionBase', args=mainPdfFile, comment="# Primary Preparations")
        cmnd('frameNamesList', args=mainPdfFile, comment="# Gets frame names from pdf file")

        cmnd('dispositionToImpressivePurposed', pars=od([('inPdf', './presentationEnFa.pdf'),]), args="voiceOver", comment="# Applies To ALL -- Args specify purpose")
        cmnd('dispositionToImpressivePurposed', pars=od([('inPdf', './presentationEnFa.pdf'),]), args="voiceOver recorderEach", comment="# Applies To ALL -- Args specify purpose")

        cmnd('dispositionToImpressivePurposed', pars=od([('inPdf', './presentationEnFa.pdf'),]), args="voiceOver", comment="# Applies To framesRange -- Args specify purpose")
        cmnd('dispositionToImpressivePurposed', pars=od([('inPdf', './presentationEnFa.pdf'), ('framesRange', selectedFramesRange)]), args="voiceOver recorderEach", comment="# Applies To framesRange -- Args specify purpose")

        cmnd('dispositionToImpressivePurposed', args="voiceOver", comment="# Applies To Any -- Args specify purpose")
        cmnd('dispositionToImpressivePurposed', args="voiceOver recorderEach", comment="# Applies To Any -- Args specify purpose")


        b.ignore(ro.__doc__,  cmndArgsSpecDict)  # We are not using these modules, but they are auto imported.

        return(cmndOutcome)

####+BEGIN: bx:icm:py3:section :title "CS-Commands"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  /Section/    [[elisp:(outline-show-subtree+toggle)][||]] *CS-Commands*  [[elisp:(org-cycle)][| ]]
#+end_org """
####+END:


####+BEGIN: bx:cs:python:section :title "= =Framework::= Options, Arguments and Examples Specifications ="
"""
*  [[elisp:(beginning-of-buffer)][Top]] ############## [[elisp:(blee:ppmm:org-mode-toggle)][Nat]] [[elisp:(delete-other-windows)][(1)]]    *= =Framework::= Options, Arguments and Examples Specifications =*  [[elisp:(org-cycle)][| ]]  [[elisp:(org-show-subtree)][|=]]
"""
####+END:

####+BEGIN: b:py3:cs:func/typing :funcName "commonParamsSpecify" :comment "~CSU Specification~" :funcType "ParSpc" :deco ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  F-T-ParSpc [[elisp:(outline-show-subtree+toggle)][||]] /commonParamsSpecify/  ~CSU Specification~  [[elisp:(org-cycle)][| ]]
#+end_org """
def commonParamsSpecify(
####+END:
        csParams: cs.param.CmndParamDict,
) -> None:

    csParams.parDictAdd(
        parName='moduleVersion',
        parDescription="Module Version",
        parDataType=None,
        parDefault=None,
        parChoices=list(),
        parScope=cs.CmndParamScope.TargetParam,
        argparseShortOpt=None,
        argparseLongOpt='--version',
    )

    csParams.parDictAdd(
        parName='dispositionBase',
        parDescription="Disposition Base Directory",
        parDataType=None,
        parDefault=None,
        parChoices=list(),
        parScope=cs.CmndParamScope.TargetParam,
        argparseShortOpt=None,
        argparseLongOpt='--dispositionBase',
        )

    csParams.parDictAdd(
        parName='inPdf',
        parDescription="Input Pdf file with ttytex etc implied",
        parDataType=None,
        parDefault=None,
        parChoices=list(),
        parScope=cs.CmndParamScope.TargetParam,
        argparseShortOpt=None,
        argparseLongOpt='--inPdf',
    )

    csParams.parDictAdd(
        parName='framesRange',
        parDescription="Frames Range -- For Now Just Initial Number",
        parDataType=None,
        parDefault=None,
        parChoices=list(),
        parScope=cs.CmndParamScope.TargetParam,
        argparseShortOpt=None,
        argparseLongOpt='--framesRange',
    )

    return

####+BEGIN: bx:cs:python:func :funcName "dispositionBaseDefault" :funcType "defaultVerify" :retType "echo" :deco "" :argsList "dispositionBase"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  F-defaultVerify [[elisp:(outline-show-subtree+toggle)][||]] /dispositionBaseDefault/ retType=echo argsList=(dispositionBase)  [[elisp:(org-cycle)][| ]]
#+end_org """
def dispositionBaseDefault(
    dispositionBase,
):
####+END:
    if not dispositionBase:
        return './disposition.gened'
    else:
        return dispositionBase


####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "examplesOrig" :cmndType "ICM-Cmnd-FWrk" :comment "FrameWrk: ICM Examples" :parsMand "" :parsOpt "" :argsMin 0 :argsMax 0 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-ICM-Cmnd-FWrk [[elisp:(outline-show-subtree+toggle)][||]] <<examplesOrig>>  *FrameWrk: ICM Examples*  =verify= ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class examplesOrig(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ ]
    cmndArgsLen = {'Min': 0, 'Max': 0,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
    ) -> b.op.Outcome:
        """FrameWrk: ICM Examples"""
        failed = b_io.eh.badOutcome
        callParamsDict = {}
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, None).isProblematic():
            return failed(cmndOutcome)
####+END:
        comment='none'
        def cpsInit(): global comment; comment='none'; return collections.OrderedDict()
        def menuItem(): cs.examples.cmndInsert(cmndName, cps, cmndArgs, comment=comment, verbosity='little')
        def menuItemUnverbose(): cs.examples.cmndInsert(cmndName, cps, cmndArgs, comment=comment, verbosity='none')
        def execLineEx(cmndStr): cs.examples.execInsert(execLine=cmndStr)

        logControler = b_io.log.Control()
        logControler.loggerSetLevel(20)

        cs.examples.myName(cs.G.icmMyName(), cs.G.icmMyFullName())

        cs.examples.commonBrief()

        bleep.examples_csBasic()

        mainPdfFile="""./presentationEnFa.pdf"""
        mainTtytexFile="""./presentationEnFa.ttytex"""
        mainSnmFile="""./presentationEnFa.snm"""

        selectedFramesRange = "1"

####+BEGIN: bx:cs:python:cmnd:subSection :title "Dev And Testing"

####+END:

        cs.examples.menuChapter('*General Dev and Testing IIFs*')

        cmndName = "unitTest"
        cmndArgs = ""; cps = cpsInit(); # cps['icmsPkgName'] = icmsPkgName
        menuItem()
        cs.examples.cmndInsert(cmndName, cps, cmndArgs, verbosity='full')


####+BEGIN: bx:cs:python:cmnd:subSection :title "Disposition Setup/Set/Update -- ./disposition.gened"

####+END:
        cs.examples.menuChapter('*Disposition Setup/Set/Update  -- ./disposition.gened*')

        cmndName = "dispositionBaseSetup";  comment="""# Just creates dispositionBaseDir."""
        menuItem()
        cmndArgs = ""; cps = cpsInit(); cps['dispositionBase'] = '/tmp/t3/DISP'
        menuItem()

        cmndName = "dispositionParamSet"
        cmndArgs = "globalTimeout 2000"; cps = cpsInit(); # cps['dispositionBase'] = '/tmp/t3/DISP'
        menuItem()

        cmndName = "frameParSet"
        cmndArgs = "frameName transition up"; cps = cpsInit();   cps['dispositionBase'] = '/tmp/t3/DISP'
        menuItem()

####+BEGIN: bx:cs:python:cmnd:subSection :title "Extract Frames Parameters From Pdf/snm files -- into DispositionBase"

####+END:
        cs.examples.menuChapter('*Extract Frames Parameters From Pdf/snm files -- into DispositionBase*')

        cmndName = "latexSrcToDispositionUpdate" ; comment = """# Sets up dispositionBase based on pdf and snm info."""
        cmndArgs = mainPdfFile; cps = cpsInit();
        menuItem()
        cmndArgs = mainPdfFile; cps = cpsInit();  cps['dispositionBase'] = "./disposition.gened"
        menuItem()

        cmndName = "frameNamesList"; comment="""# Gets frame names from pdf file."""
        cmndArgs = mainPdfFile; cps = cpsInit(); # cps['icmsPkgName'] = icmsPkgName
        menuItemUnverbose()

        #cmndName = "frameNamesGet" ; comment="""# Gets from latex snm file."""
        #cmndArgs = mainSnmFile + " 25"; cps = cpsInit(); # cps['icmsPkgName'] = icmsPkgName
        #menuItem()


####+BEGIN: bx:cs:python:cmnd:subSection :title "Extract Frames Parameters From Pdf/snm files -- into DispositionBase"

####+END:
        cs.examples.menuSection('Extract Frames Parameters From TeX files -- into DispositionBase')

        cmndName = "beamerExternalTagsUpdateAsFPs"  ; comment = ""
        cmndArgs = mainTtytexFile;  cps = cpsInit(); #  cps['load'] = ''
        menuItem()


####+BEGIN: bx:cs:python:cmnd:subSection :title "DispositionBase Full Update"

####+END:
        cs.examples.menuSection('DispositionBase Full Update')

        cmndName = "updateDispositionBase"  ; comment = "# Primary Preparations"
        cmndArgs = mainPdfFile;  cps = cpsInit();  cps['dispositionBase'] = "./disposition.gened"
        menuItem()

        cps = cpsInit();  menuItemUnverbose()

        cmndName = "dispositionFrameNamesList"  ; comment = "# List FrameNames from dispositionBase"
        cmndArgs = "";
        cps = cpsInit();  menuItemUnverbose()



####+BEGIN: bx:cs:python:cmnd:subSection :title "Common Capabilities"

####+END:
        cs.examples.menuSection('Common Capabilities')

        cmndName = "latexInputFilesList"  ; comment = ""
        cmndArgs =  mainTtytexFile; cps = cpsInit(); #  cps['load'] = './presentationEnFa-itags.py'
        menuItem()

        cmndArgs =  mainTtytexFile + " ./articleEnFa.ttytex" ; menuItem()

####+BEGIN: bx:cs:python:cmnd:subSection :title "Construct Configuration Files From Disposition Base For Impressive -- stdout"

####+END:
        cs.examples.menuChapter('*Construct Configuration Files From Disposition Base For Impressive -- stdout*')

        cmndName = "frameParSet"  ; comment = ""
        cmndArgs = "frameName transition up"; cps = cpsInit();  cps['dispositionBase'] = '/tmp/t3/DISP'
        menuItem()

        cmndName = "dispositionToImpressiveInfoPurposedStdout" ; comment="""# Args specify purpose"""
        cmndArgs = "voiceOver presenter"; cps = cpsInit();
        menuItem()

        cmndArgs = "voiceOver";  menuItem()
        cmndArgs = "voiceOver recorderEach"; cps = cpsInit(); cps['framesRange'] = selectedFramesRange ;  menuItem()

####+BEGIN: bx:cs:python:cmnd:subSection :title "Update DispositionBase and Construct Configuration Files"

####+END:
        cs.examples.menuChapter('*Construct Configuration Files From Disposition Base*')

        cmndName = "updateThenImpressiveInfoStdout" ; comment="""# Args specify purpose"""
        cps = cpsInit(); cps['inPdf'] = "./presentationEnFa.pdf"

        cmndArgs = "voiceOver";  menuItem()
        cmndArgs = "voiceOver recorderEach";  cps['framesRange'] = selectedFramesRange ;  menuItem()


####+BEGIN: bx:cs:python:cmnd:subSection :title "Construct Configuration Files And Run Impressive"

####+END:
        cs.examples.menuChapter('*Construct Configuration Files And Run Impressive*')

        cmndName = "updateDispositionBase"  ; comment = "# Primary Preparations"
        cmndArgs = mainPdfFile; cps = cpsInit();  menuItemUnverbose()

        cmndName = "frameNamesList"; comment="""# Gets frame names from pdf file."""
        cmndArgs = mainPdfFile; cps = cpsInit();  menuItemUnverbose()


        cmndName = "dispositionToImpressivePurposed" ; comment="""# Applies To ALL -- Args specify purpose"""
        cps = cpsInit(); cps['inPdf'] = "./presentationEnFa.pdf"
        cmndArgs = "voiceOver";  menuItemUnverbose()
        cmndArgs = "voiceOver recorderEach" ; menuItemUnverbose()

        cmndName = "dispositionToImpressivePurposed" ; comment="""# Applies To framesRange -- Args specify purpose"""
        cps = cpsInit(); cps['inPdf'] = "./presentationEnFa.pdf"
        cmndArgs = "voiceOver";  menuItemUnverbose()
        cmndArgs = "voiceOver recorderEach"; cps['framesRange'] = selectedFramesRange ; menuItemUnverbose()

        cmndName = "dispositionToImpressivePurposed" ; comment="""# Applies To Any -- Args specify purpose"""
        cps = cpsInit(); cps['inPdf'] = "./presentationEnFa.pdf"
        cmndArgs = "voiceOver";  menuItemUnverbose()
        cmndArgs = "voiceOver recorderOnce" ; menuItemUnverbose()


        cs.examples.menuChapter('*Direct Invoke Commands*')

        execLineEx("""impressive""".format())

        return(cmndOutcome)

####+BEGIN: bx:cs:python:section :title "Disposition Base Setup"
"""
*  [[elisp:(beginning-of-buffer)][Top]] ############## [[elisp:(blee:ppmm:org-mode-toggle)][Nat]] [[elisp:(delete-other-windows)][(1)]]    *Disposition Base Setup*  [[elisp:(org-cycle)][| ]]  [[elisp:(org-show-subtree)][|=]]
"""
####+END:
    
####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "dispositionBaseSetup" :comment "Creates dispositionBase" :parsMand "" :parsOpt "dispositionBase" :argsMin 0 :argsMax 0 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<dispositionBaseSetup>>  *Creates dispositionBase*  =verify= parsOpt=dispositionBase ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class dispositionBaseSetup(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'dispositionBase', ]
    cmndArgsLen = {'Min': 0, 'Max': 0,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
    ) -> b.op.Outcome:
        """Creates dispositionBase"""
        failed = b_io.eh.badOutcome
        callParamsDict = {'dispositionBase': dispositionBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, None).isProblematic():
            return failed(cmndOutcome)
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
####+END:

        dispositionBase = dispositionBaseDefault(dispositionBase)

        dispositionParamBaseSetup().cmnd(
            interactive=False,
            dispositionBase=dispositionBase,
            dispositionParBase='.',
        )



        def cmndDesc(): """
** Sets up the base ./disposition.gened FILE_Param directory. Calls dispositionParamBaseSetup with dispositionParBase='.'
"""


####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "dispositionParamBaseSetup" :comment "Creates the given FP base" :parsMand "" :parsOpt "dispositionBase dispositionParBase" :argsMin 0 :argsMax 0 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<dispositionParamBaseSetup>>  *Creates the given FP base*  =verify= parsOpt=dispositionBase dispositionParBase ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class dispositionParamBaseSetup(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'dispositionBase', 'dispositionParBase', ]
    cmndArgsLen = {'Min': 0, 'Max': 0,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
             dispositionParBase: typing.Optional[str]=None,  # Cs Optional Param
    ) -> b.op.Outcome:
        """Creates the given FP base"""
        failed = b_io.eh.badOutcome
        callParamsDict = {'dispositionBase': dispositionBase, 'dispositionParBase': dispositionParBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, None).isProblematic():
            return failed(cmndOutcome)
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
        dispositionParBase = csParam.mappedValue('dispositionParBase', dispositionParBase)
####+END:
        self.cmndDocStr(f""" #+begin_org
** [[elisp:(org-cycle)][| *CmndDesc:* | ]]  Sets up ParBase -- For example for slideNumber and frameName.
        #+end_org """)

        dispositionBase = dispositionBaseDefault(dispositionBase)

        parRoot = os.path.join(dispositionBase, dispositionParBase)    

        thisParamBase = icm.FILE_ParamBase(fileSysPath=parRoot)

        thisParamBaseState = thisParamBase.baseValidityPredicate()
    
        if  thisParamBaseState == 'BadlyFormed':
            return b_io.eh.critical_usageError('')
        elif thisParamBaseState == 'NonExistent':
            thisParamBase.baseCreate()
        elif thisParamBaseState == 'InPlace':
            b_io.tm.here('InPlace')
        else:
            return b_io.eh.critical_oops('thisParamBaseState=' + thisParamBaseState)

        return



####+BEGIN: b:py3:cs:cmnd/classHead  :cmndName "dispositionParamSet" :comment "For Global disposition FPs" :parsMand "" :parsOpt "dispositionBase dispositionParBase" :argsMin 2 :argsMax 2 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<dispositionParamSet>>  *For Global disposition FPs*  =verify= parsOpt=dispositionBase dispositionParBase argsMin=2 argsMax=2 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class dispositionParamSet(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'dispositionBase', 'dispositionParBase', ]
    cmndArgsLen = {'Min': 2, 'Max': 2,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
             dispositionParBase: typing.Optional[str]=None,  # Cs Optional Param
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:
        """For Global disposition FPs"""
        failed = b_io.eh.badOutcome
        callParamsDict = {'dispositionBase': dispositionBase, 'dispositionParBase': dispositionParBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return failed(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
        dispositionParBase = csParam.mappedValue('dispositionParBase', dispositionParBase)
####+END:
        self.cmndDocStr(f""" #+begin_org
** [[elisp:(org-cycle)][| *CmndDesc:* | ]]  Thin layer on top of icm.FILE_Param()
        #+end_org """)

        dispositionBase = dispositionBaseDefault(dispositionBase)

        dispositionParName = effectiveArgsList[0]
        dispositionParValue = effectiveArgsList[1]

        dispositionBaseSetup().cmnd(interactive=False,
                                  dispositionBase=dispositionBase)

        parRoot = os.path.join(dispositionBase, dispositionParBase)

        thisFileParam = b.fp.FILE_Param()
        return  thisFileParam.writeTo(storeBase=parRoot,
                                      parName=dispositionParName,
                                      parValue=dispositionParValue)


####+BEGIN: bx:cs:python:func :funcName "impressiveFrameParSet" :comment "Func to set FPs based on ^%BxPy" :funcType "void" :retType "none" :deco "" :argsList "frameName parName parValue"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  F-void     [[elisp:(outline-show-subtree+toggle)][||]] /impressiveFrameParSet/ =Func to set FPs based on ^%BxPy= retType=none argsList=(frameName parName parValue)  [[elisp:(org-cycle)][| ]]
#+end_org """
def impressiveFrameParSet(
    frameName,
    parName,
    parValue,
):
####+END:
    """ Typically executed at load time.
        Specified in .tex file. Meant to be terse. 
    """

    frameParSet().cmnd(
        interactive=False,
        argsList=[frameName, parName, parValue,],
    )

    
####+BEGIN: b:py3:cs:cmnd/classHead  :cmndName "frameParSet" :comment "Sets FP in dispositionBase" :parsMand "" :parsOpt "dispositionBase" :argsMin 3 :argsMax 3 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<frameParSet>>  *Sets FP in dispositionBase*  =verify= parsOpt=dispositionBase argsMin=3 argsMax=3 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class frameParSet(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'dispositionBase', ]
    cmndArgsLen = {'Min': 3, 'Max': 3,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:
        """Sets FP in dispositionBase"""
        failed = b_io.eh.badOutcome
        callParamsDict = {'dispositionBase': dispositionBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return failed(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
####+END:

        dispositionBase = dispositionBaseDefault(dispositionBase)

        frameName = effectiveArgsList[0]
        parName = effectiveArgsList[1]
        parValue = effectiveArgsList[2]

        dispositionBaseSetup().cmnd(interactive=False,
                                  dispositionBase=dispositionBase)

        dispositionParBase = frameName
        parRoot = os.path.join(dispositionBase, dispositionParBase)
        
        thisFileParam = icm.FILE_Param()

        if parName == 'sound':
            dispositionParName = 'audio'     
        else:
            dispositionParName = parName
    
        dispositionParValue = parValue
    
        b_io.tm.here("frameName={frameName} parName={parName} parValue={parValue}"
                     .format(frameName=frameName, parName=dispositionParName, parValue=dispositionParValue))
    
        return  thisFileParam.writeTo(storeBase=parRoot,
                                      parName=dispositionParName,
                                      parValue=dispositionParValue)
    
        

####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "latexSrcToDispositionUpdate" :comment "$1=pdfFile" :parsMand "" :parsOpt "dispositionBase" :argsMin 1 :argsMax 1 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<latexSrcToDispositionUpdate>>  *$1=pdfFile*  =verify= parsOpt=dispositionBase argsMin=1 argsMax=1 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class latexSrcToDispositionUpdate(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'dispositionBase', ]
    cmndArgsLen = {'Min': 1, 'Max': 1,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:
        """$1=pdfFile"""
        failed = b_io.eh.badOutcome
        callParamsDict = {'dispositionBase': dispositionBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return failed(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
####+END:
        self.cmndDocStr(f""" #+begin_org
** [[elisp:(org-cycle)][| *CmndDesc:* | ]]  Given the pdfFileName,  determine total number of slides, then for each slide determine frameName.

    For each slideNumber associate frameName. For each frameName create baseParam directory.
    If ./audio create the 'sound': attribute.
    Makes sure basePdf.snm and basePdf.nav are available.
        #+end_org """)


        dispositionBase = dispositionBaseDefault(dispositionBase)

        pdfFileName = effectiveArgsList[0]
    
        # document = PdfFileReader(file(pdfFileName, "rb"))
        document = PdfFileReader(open(pdfFileName, "rb"))
        pages = document.getNumPages()    

        dispositionBaseSetup().cmnd(
            interactive=False,
            dispositionBase=dispositionBase,
        )

        fileName, fileExtension = os.path.splitext(pdfFileName)

        #navFileName = fileName + ".nav"
        snmFileName = fileName + ".snm"

        slideNumbersNames = frameNamesGet().cmnd(
            interactive=False,
            argsList=[snmFileName, pages,],
        )
    
        for i in range(len(slideNumbersNames)):
            # impressive's first slide, usually titlePage is slide Nu 1

            slideNu=i+1
            slideNumberName=format("slide" + str(slideNu))                
            frameName = slideNumbersNames[i]
        
            dispositionParamSet().cmnd(
                interactive=False,
                dispositionBase=dispositionBase,
                dispositionParBase='.',
                argsList=[slideNumberName, frameName,],
            )

            dispositionParamBaseSetup().cmnd(
                interactive=False,
                dispositionBase=dispositionBase,
                dispositionParBase=frameName,
            )


            if os.path.isdir("./audio"):
                if frameName ==  'defaultParams':
                    pass
                else:
                    audioAbsFilePath = os.path.abspath(format("./audio" + "/" + frameName + '.wav'))
                    dispositionParamSet().cmnd(
                        interactive=False,
                        dispositionBase=dispositionBase,
                        dispositionParBase=frameName,
                        argsList=['audio', audioAbsFilePath,],
                    )
                    # NOTYET, Compute duration and add that here.
            else:
                b_io.tm.here("Missing ./audio -- Skipped")

            # The first two slides (0 and 1)
            if i < 2:
                dispositionParamSet().cmnd(
                    interactive=False,
                    dispositionBase=dispositionBase,
                    dispositionParBase=frameName,
                    argsList=['transition', 'PagePeel'],
                )


####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "frameNamesList" :comment "$1 is pdfFile (interactiveOnly)" :parsMand "" :parsOpt "dispositionBase" :argsMin 1 :argsMax 1 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<frameNamesList>>  *$1 is pdfFile (interactiveOnly)*  =verify= parsOpt=dispositionBase argsMin=1 argsMax=1 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class frameNamesList(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'dispositionBase', ]
    cmndArgsLen = {'Min': 1, 'Max': 1,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:
        """$1 is pdfFile (interactiveOnly)"""
        failed = b_io.eh.badOutcome
        callParamsDict = {'dispositionBase': dispositionBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return failed(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
####+END:

        dispositionBase = dispositionBaseDefault(dispositionBase)

        pdfFileName = effectiveArgsList[0]

        thisFile=open(pdfFileName, "rb")

        document = PdfFileReader(thisFile)
        pages = document.getNumPages()    

        # dispositionBaseSetup(interactive=False, dispositionBase=dispositionBase)

        fileName, fileExtension = os.path.splitext(pdfFileName)

        #navFileName = fileName + ".nav"
        snmFileName = fileName + ".snm"

        slideNumbersNames = frameNamesGet().cmnd(
            interactive=False,
            argsList=[snmFileName, pages,],
        )

        for i in range(len(slideNumbersNames)):

            #slideNumberName=format("slide" + str(i))                
            frameName = slideNumbersNames[i]

            if rtInv.outs:
                b_io.ann.write("{slideNumber} {frameName}".format(
                    slideNumber=i+1, frameName=frameName,)
                )

        if not interactive:
            b_io.eh.critical_usageErro("Not expected to be used non-interactivly. Use frameNamesGet directly.")
            

####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "frameNameQuote" :comment "$1 is frameName" :parsMand "" :parsOpt "" :argsMin 1 :argsMax 1 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<frameNameQuote>>  *$1 is frameName*  =verify= argsMin=1 argsMax=1 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class frameNameQuote(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ ]
    cmndArgsLen = {'Min': 1, 'Max': 1,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:
        """$1 is frameName"""
        failed = b_io.eh.badOutcome
        callParamsDict = {}
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return failed(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
####+END:

        frameName = effectiveArgsList[0]
        frameNameQuoted=""

        thisOutcome = b.op.Outcome(invokerName=G.icmMyFullName())

        #
        thisOutcome = icm.subProc_bash(
            """uri@Encode.sh {frameName}"""
            .format(frameName=frameName),
            stdin=None, outcome=thisOutcome,
        )#.out()
        
        if thisOutcome.isProblematic():
            return(io.eh.badOutcome(thisOutcome))

        frameNameQuoted = thisOutcome.stdout.splitlines()[0]

        if rtInv.outs:
            icm.ANN_note(frameNameQuoted)

        return frameNameQuoted

    def cmndDesc(): """
** Given frameName return frameNameQuoted.
"""
    

####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "frameNamesGet" :comment "$1 is tex's snm file - $2=nuOfPages" :parsMand "" :parsOpt "" :argsMin 2 :argsMax 2 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<frameNamesGet>>  *$1 is tex's snm file - $2=nuOfPages*  =verify= argsMin=2 argsMax=2 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class frameNamesGet(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ ]
    cmndArgsLen = {'Min': 2, 'Max': 2,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:
        """$1 is tex's snm file - $2=nuOfPages"""
        failed = b_io.eh.badOutcome
        callParamsDict = {}
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return failed(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
####+END:

        snmFileName = effectiveArgsList[0]
        numberOfPages = int(effectiveArgsList[1])

        slideNumbersNames = []
        for i in range(0,numberOfPages):
            slideNumbersNames.append('defaultParams')
    

        # Open FileName and walkthrough it.
        with open(snmFileName, 'r') as fp:
            for line in fp:
                b_io.tm.here(line)
                #\beamer@slide {summary.problem<1>}{2}
                #matchObj = re.search( r'(.beamer.slide .) (.*) (}) ({) (.*) (})', line, re.M|re.I)
                matchObj = re.search( r'(\\beamer@slide {)(.*)(<.>)(}{)(.*)(})', line, re.M|re.I)            
                if matchObj:
                    # print "matchObj.group() : ", matchObj.group()
                    # print "matchObj.group(1) : ", matchObj.group(1)
                    # print "matchObj.group(2) : ", matchObj.group(2)
                    # print "matchObj.group(3) : ", matchObj.group(3)
                    # print "matchObj.group(4) : ", matchObj.group(4)
                    # print "matchObj.group(5) : ", matchObj.group(5)
                    # print "matchObj.group(6) : ", matchObj.group(6)

                    slideNumbersNames[int(matchObj.group(5))-1] = frameNameQuote().cmnd(
                        interactive=False,
                        argsList=[matchObj.group(2)]
                    )
                else:
                    b_io.tm.here("No match!!")

        if rtInv.outs:
            icm.ANN_note(slideNumbersNames)

        return slideNumbersNames

####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "beamerExternalTagsUpdateAsFPs" :comment "$1 is .ttytex -- extractes from tex and uses impressiveFrameParSet()" :parsMand "" :parsOpt "dispositionBase" :argsMin 1 :argsMax 1 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<beamerExternalTagsUpdateAsFPs>>  *$1 is .ttytex -- extractes from tex and uses impressiveFrameParSet()*  =verify= parsOpt=dispositionBase argsMin=1 argsMax=1 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class beamerExternalTagsUpdateAsFPs(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'dispositionBase', ]
    cmndArgsLen = {'Min': 1, 'Max': 1,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:
        """$1 is .ttytex -- extractes from tex and uses impressiveFrameParSet()"""
        failed = b_io.eh.badOutcome
        callParamsDict = {'dispositionBase': dispositionBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return failed(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
####+END:
        self.cmndDocStr(f""" #+begin_org
** [[elisp:(org-cycle)][| *CmndDesc:* | ]] Look in input files for ExternalTags as '^%BxPy:' and update them in the disposition.gened
        #+end_org """)

        dispositionBase = dispositionBaseDefault(dispositionBase)

        opOutcome = latexSup.latexInputFilesList().cmnd(
            interactive=False,
            argsList=effectiveArgsList,
        )

        if opOutcome.isProblematic():
            return(io.eh.badOutcome(opOutcome))

        filesList = opOutcome.results

        thisOutcome = b.op.Outcome(invokerName=G.icmMyFullName())

        #
        # Example Lines:
        # %BxPy: impressiveFrameParSet('JoiningByStar--IndividuallyAndEn-Mass', 'always', 'True')
        # %BxPy: impressiveFrameParSet('JoiningByStar--IndividuallyAndEn-Mass', 'transition', 'UnSpecified')
        #
        thisOutcome = icm.subProc_bash(
            """egrep '^%BxPy:' {filesList} | cut -d ':' -f 3 | sed -e 's/^[ ]*//'"""
            .format(filesList=" ".join(filesList)),
            stdin=None, outcome=thisOutcome,
        )#.out()
        
        if thisOutcome.isProblematic():
            return(io.eh.badOutcome(thisOutcome))

        for each in thisOutcome.stdout.splitlines():
            # Evals lines like this, resulting into ./disposition.gened/xx updates
            # impressiveFrameParSet('titlePage', 'always', 'True')
            #
            icm.evalStringInMain(each)

        return thisOutcome

    
####+BEGIN: bx:cs:python:section :title "Disposition Base Setup -- Main Usage Cmnds"
"""
*  [[elisp:(beginning-of-buffer)][Top]] ############## [[elisp:(blee:ppmm:org-mode-toggle)][Nat]] [[elisp:(delete-other-windows)][(1)]]    *Disposition Base Setup -- Main Usage Cmnds*  [[elisp:(org-cycle)][| ]]  [[elisp:(org-show-subtree)][|=]]
"""
####+END:
    

####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "updateDispositionBase" :comment "Full update dispositionBase" :parsMand "" :parsOpt "dispositionBase" :argsMin 1 :argsMax 1 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<updateDispositionBase>>  *Full update dispositionBase*  =verify= parsOpt=dispositionBase argsMin=1 argsMax=1 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class updateDispositionBase(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'dispositionBase', ]
    cmndArgsLen = {'Min': 1, 'Max': 1,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:
        """Full update dispositionBase"""
        failed = b_io.eh.badOutcome
        callParamsDict = {'dispositionBase': dispositionBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return failed(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
####+END:
        self.cmndDocStr(f""" #+begin_org
** [[elisp:(org-cycle)][| *CmndDesc:* | ]]  Given a purpose (voiceOver, presentation, etc) create an info file based on purposesList.
        #+end_org """)

        dispositionBase = dispositionBaseDefault(dispositionBase)

        inPdf = effectiveArgsList[0]

        latexSrcToDispositionUpdate().cmnd(
            interactive=False,
            dispositionBase=dispositionBase,
            argsList=[inPdf,],
        )

        fileName, fileExtension = os.path.splitext(inPdf)
        ttytexFileName = fileName + ".ttytex"

        beamerExternalTagsUpdateAsFPs().cmnd(
            interactive=False,
            dispositionBase=dispositionBase,
            argsList=[ttytexFileName,],
        )

        return


####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "dispositionFrameNamesList" :comment "" :parsMand "" :parsOpt "framesRange dispositionBase" :argsMin 0 :argsMax 0 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<dispositionFrameNamesList>>  =verify= parsOpt=framesRange dispositionBase ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class dispositionFrameNamesList(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'framesRange', 'dispositionBase', ]
    cmndArgsLen = {'Min': 0, 'Max': 0,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             framesRange: typing.Optional[str]=None,  # Cs Optional Param
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
    ) -> b.op.Outcome:

        failed = b_io.eh.badOutcome
        callParamsDict = {'framesRange': framesRange, 'dispositionBase': dispositionBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, None).isProblematic():
            return failed(cmndOutcome)
        framesRange = csParam.mappedValue('framesRange', framesRange)
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
####+END:
        self.cmndDocStr(f""" #+begin_org
** [[elisp:(org-cycle)][| *CmndDesc:* | ]]  Given a purpose (voiceOver, presentation, recorderEach) or a combination, create an info file based on purposesList.

For each slide impressiveInfoItemXX(purposesList), is called.
In each, based on puposesList and content of dispositionBase corresponing to that slide,
translate  dispositionBase info into impressive parameters and write them to stdout.
        #+end_org """)

        dispositionBase = dispositionBaseDefault(dispositionBase)

        thisParamBase = b.fp.FILE_ParamBase(fileSysPath=dispositionBase)

        thisParamBaseState = thisParamBase.baseValidityPredicate()

        if thisParamBaseState != 'InPlace':
            #return b_io.eh.critical_oops('thisParamBaseState=' + thisParamBaseState)
            return b_io.eh.critical_oops(f"thisParamBaseState={thisParamBaseState}")


        filesList = os.listdir(dispositionBase)  # This is instead of sorting

        #print(filesList)

        if framesRange:
            selectedFrameNu = int(framesRange)

        i = 0
        while True:
            i = i + 1
            this = format("slide" + str(i))       
            if this not in filesList:
                b_io.tm.here('Missing' + this)
                break           

            frameFileParam = icm.FILE_Param()
            frameFileParam = frameFileParam.readFrom(storeBase=dispositionBase, parName=this)

            if frameFileParam == None:
                return b_io.eh.critical_usageError('frameFileParam')

            thisLabeled = frameFileParam.parValueGet()
            # thisLabeledBase = os.path.join(dispositionBase, thisLabeled)
            
            if rtInv.outs:
                #b_io.ann.write("{slideNumber} {frameName}".format(
                #    slideNumber=i, frameName=thisLabeled,)
                #)
                b_io.ann.write("{frameName}".format(
                    frameName=thisLabeled,)
                )

            if not interactive:
                b_io.eh.critical_usageErro("Not expected to be used non-interactivly. Use frameNamesGet directly.")

        return

    
    
####+BEGIN: bx:cs:python:section :title "Impressive Configurations Based On DispositionBase"
"""
*  [[elisp:(beginning-of-buffer)][Top]] ############## [[elisp:(blee:ppmm:org-mode-toggle)][Nat]] [[elisp:(delete-other-windows)][(1)]]    *Impressive Configurations Based On DispositionBase*  [[elisp:(org-cycle)][| ]]  [[elisp:(org-show-subtree)][|=]]
"""
####+END:
    
    

####+BEGIN: bx:cs:python:func :funcName "impressiveTransitionValue" :comment "map disposition to impressive" :funcType "filter" :retType "str" :deco "" :argsList "transitionValue"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  F-filter   [[elisp:(outline-show-subtree+toggle)][||]] /impressiveTransitionValue/ =map disposition to impressive= retType=str argsList=(transitionValue)  [[elisp:(org-cycle)][| ]]
#+end_org """
def impressiveTransitionValue(
    transitionValue,
):
####+END:
    """Map dispositionBase transitionValue into impressiveTransitionValue.

You can get a listof impressiveTransitions from 'impressive -l'
"""
    if transitionValue == "default":
        return 'PagePeel'
    elif transitionValue == "UnSpecified":
        return 'SlideUp'
    else:
        return transitionValue

####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "dispositionToImpressiveInfoPurposedStdout" :comment "args are purposes (voiceOver, etc)" :parsMand "" :parsOpt "framesRange dispositionBase" :argsMin 1 :argsMax 1000 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<dispositionToImpressiveInfoPurposedStdout>>  *args are purposes (voiceOver, etc)*  =verify= parsOpt=framesRange dispositionBase argsMin=1 argsMax=1000 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class dispositionToImpressiveInfoPurposedStdout(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'framesRange', 'dispositionBase', ]
    cmndArgsLen = {'Min': 1, 'Max': 1000,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             framesRange: typing.Optional[str]=None,  # Cs Optional Param
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:
        """args are purposes (voiceOver, etc)"""
        failed = b_io.eh.badOutcome
        callParamsDict = {'framesRange': framesRange, 'dispositionBase': dispositionBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return failed(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
        framesRange = csParam.mappedValue('framesRange', framesRange)
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
####+END:

        dispositionBase = dispositionBaseDefault(dispositionBase)

        purposesList = []
        for thisArg in effectiveArgsList:
            purposesList.append(thisArg)

        thisParamBase = b.fp.FILE_ParamBase(fileSysPath=dispositionBase)

        thisParamBaseState = thisParamBase.baseValidityPredicate()

        if thisParamBaseState != 'InPlace':
            return b_io.eh.critical_oops('thisParamBaseState=' + thisParamBaseState)

        def impressiveInfoHeadStdout(purposesList):
            """ Considering  purposesList, output the head part of impressiveInfo """
            if 'presenter' in purposesList:
                path = os.path.dirname(dispositionBase)
                if path == None:
                    path = path + '/'

                sys.stdout.write(
                    dispositionToPresenterStdout().impressiveInfoHeadStr(path)
                )

            if 'voiceOver' in purposesList:
                pass

            if 'recorderEach' in purposesList:
                sys.stdout.write(
                    dispositionToImpressiveStdout_recorderEach().impressiveInfoHeadStr()
                )

            if 'recorderOnce' in purposesList:
                sys.stdout.write(
                    dispositionToImpressiveStdout_recorderEach().impressiveInfoHeadStr()
                )
                
        def impressivePagePropsBeginStdout():
            """ Just write out the beginning of PageProps."""

            sys.stdout.write("""

PageProps = {
            """)
            
        impressiveInfoHeadStdout(purposesList)

        impressivePagePropsBeginStdout()        

        filesList = os.listdir(dispositionBase)  # This is instead of sorting

        #print(filesList)

        if framesRange:
            selectedFrameNu = int(framesRange)

        i = 0
        while True:
            i = i + 1
            this = format("slide" + str(i))       
            if this not in filesList:
                b_io.tm.here('Missing' + this)
                break           

            frameFileParam = icm.FILE_Param()
            frameFileParam = frameFileParam.readFrom(storeBase=dispositionBase, parName=this)

            if frameFileParam == None:
                return b_io.eh.critical_usageError('frameFileParam')

            thisLabeled = frameFileParam.parValueGet()
            thisLabeledBase = os.path.join(dispositionBase, thisLabeled)

            def impressiveInfoItemAudio(purposesList):
                if not 'voiceOver' in purposesList:
                    return

                if framesRange:
                    if i == selectedFrameNu:
                        filePar = icm.FILE_Param()
                        filePar = filePar.readFrom(storeBase=thisLabeledBase, parName='audio')
                        if filePar == None:
                            return #io.eh.critical_usageError('')

                        else:
                            audioValue = filePar.parValueGet()
                            sys.stdout.write("""
              'sound': """+'"'+audioValue+'"'+""",""")

                        return
                    
                    elif i == (selectedFrameNu + 1):
                        sys.stdout.write("""
              'sound': """+'"/libre/ByStar/InitialTemplates/audio/common/silence1Sec.wav"'+""",""")
                        return

                    else:
                        return

                if thisLabeled == 'recorderStopResume':
                    sys.stdout.write("""
              'sound': """+'"/libre/ByStar/InitialTemplates/audio/common/silence1Sec.wav"'+""",""")
                    return

                if thisLabeled == 'recorderFinishStart':
                    sys.stdout.write("""
              'sound': """+'"/libre/ByStar/InitialTemplates/audio/common/silence1Sec.wav"'+""",""")
                    return

                filePar = icm.FILE_Param()
                filePar = filePar.readFrom(storeBase=thisLabeledBase, parName='audio')
                if filePar == None:
                    return #io.eh.critical_usageError('')

                else:
                    audioValue = filePar.parValueGet()
                    sys.stdout.write("""
              'sound': """+'"'+audioValue+'"'+""",""")

            def impressiveInfoItemTimeout(purposesList):
                if not 'voiceOver' in purposesList:
                    return

                if framesRange:
                    if i == selectedFrameNu:
                        pass
                    
                    elif i == (selectedFrameNu + 1):
                        sys.stdout.write("""
              'timeout': """+'1000'+""",""")
                        return

                    else:
                        return
                    

                if thisLabeled == 'recorderStopResume':
                    sys.stdout.write("""
              'timeout': """+'99999000'+""",""")
                    return

                if thisLabeled == 'recorderFinishStart':
                    sys.stdout.write("""
              'timeout': """+'99999000'+""",""")
                    return


                filePar = icm.FILE_Param()
                filePar = filePar.readFrom(storeBase=thisLabeledBase, parName='audio')
                if filePar == None:
                    return #io.eh.critical_usageError('')
                audioValue = filePar.parValueGet()

                audioSansSuffix = os.path.splitext(audioValue)[0]

                audioLengthFP=audioSansSuffix+".length"

                try:
                    fileParam = icm.FILE_ParamReadFromPath(parRoot=audioLengthFP)
                except IOError:
                    b_io.tm.here("Missing:  " + audioLengthFP)
                    return(None)

                audioLen=fileParam.parValueGet()
                sys.stdout.write("""
              'timeout': """ + audioLen + """,""")

            def impressiveInfoItemAlways(purposesList):

                filePar = icm.FILE_Param()
                filePar = filePar.readFrom(storeBase=thisLabeledBase, parName='always')
                if filePar == None:
                    return #io.eh.critical_usageError('')
                thisValue = filePar.parValueGet()
                sys.stdout.write("""
              'always': """ + thisValue + """,""")

            def impressiveInfoItemTransition(purposesList):
                filePar = icm.FILE_Param()
                filePar = filePar.readFrom(storeBase=thisLabeledBase, parName='transition')
                if filePar == None:
                    return #io.eh.critical_usageError('')
                transitionValue = filePar.parValueGet()
                transitionValue = impressiveTransitionValue(transitionValue)
                sys.stdout.write("""
              'transition': """+transitionValue+""",""")

            def impressiveInfoItemOverview(purposesList):
                filePar = icm.FILE_Param()
                filePar = filePar.readFrom(storeBase=thisLabeledBase, parName='overview')
                if filePar == None:
                    return b_io.eh.critical_usageError('')
                overviewValue = filePar.parValueGet()
                sys.stdout.write("""
              'overview': """+overviewValue+""",""")

            def impressiveInfoItemNotes(purposesList):
                filePar = icm.FILE_Param()
                filePar = filePar.readFrom(storeBase=thisLabeledBase, parName='notes')
                if filePar == None:
                    return b_io.eh.critical_usageError('')
                notesValue = filePar.parValueGet()
                sys.stdout.write("""
              'notes': """+notesValue+""",""")

            def impressiveInfoItemExtra(purposesList):
                if 'presenter' in purposesList:
                    sys.stdout.write("""
              'OnEnter': UpdateInfo,""")

            def impressiveInfoItemOnEnter(purposesList):

                if framesRange:
                    if i == selectedFrameNu:
                        if 'recorderEach' in purposesList:
                            sys.stdout.write("""
              'OnEnter': bxVideoRecorderStart,""")
                            return
                        
                    elif i == (selectedFrameNu + 1):
                        if 'recorderEach' in purposesList:
                            sys.stdout.write("""
              'OnEnter': bxVideoRecorderStop,""")
                            return
                    else:
                        return

                if 'recorderEach' in purposesList:
                            sys.stdout.write("""
              'OnEnter': bxVideoRecorderStart,""")
                            return

                if 'recorderOnce' in purposesList:
                            sys.stdout.write("""
              'OnEnter': bxVideoRecorderOnceStart,""")
                            return
                    
                if 'recorderStopResume' == thisLabeled:
                    sys.stdout.write("""
              'OnEnter': vlcRecordStop,""")
                    return
                if 'recorderFinishStart' == thisLabeled:
                    sys.stdout.write("""
              'OnEnter': vlcRecordFinish,""")
                    return

            def impressiveInfoItemOnLeave(purposesList):

                if framesRange:
                    return
                    
                if 'recorderEach' in purposesList:
                    sys.stdout.write("""
              'OnLeave': bxVideoRecorderStop,""")
                    return

                if 'recorderOnce' in purposesList:
                    sys.stdout.write("""
              'OnLeave': bxVideoRecorderOnceStop,""")
                    return
                
                if 'recorderStopResume' == thisLabeled:
                    sys.stdout.write("""
              'OnLeave': vlcRecordResume,""")
                    return
                if 'recorderFinishStart' == thisLabeled:
                    sys.stdout.write("""
              'OnLeave': vlcRecordStart,""")
                    return
                filePar = icm.FILE_Param()
                filePar = filePar.readFrom(storeBase=thisLabeledBase, parName='OnLeave')
                if filePar == None:
                    return #io.eh.critical_usageError('')
                thisValue = filePar.parValueGet()
                sys.stdout.write("""
              'OnLeave': """ + thisValue + """,""")

            def impressiveInfoItemHead(purposesList):            
                #if 'presenter' in purposesList:
        #         sys.stdout.write("""
        # """+str(i)+""": {""")

                  sys.stdout.write("""
        # frameName={frameName}
        {frameNumber}: {{""".format(frameName=thisLabeled, frameNumber=i))

            def impressiveInfoItemTail(purposesList):            
                #if 'presenter' in purposesList:
                sys.stdout.write("""
        },""")

            impressiveInfoItemHead(purposesList)
            impressiveInfoItemAudio(purposesList)
            impressiveInfoItemTimeout(purposesList)
            impressiveInfoItemAlways(purposesList)                
            impressiveInfoItemTransition(purposesList)
            #impressiveInfoItemOverview(purposesList)
            #impressiveInfoItemNotes(purposesList)                                
            impressiveInfoItemExtra(purposesList)
            impressiveInfoItemOnEnter(purposesList)
            impressiveInfoItemOnLeave(purposesList)               
            impressiveInfoItemTail(purposesList)


        # End Of The While True Statement
        # Output the Tail now.

        def impressiveInfoTailStdout(purposesList):
            #if 'presenter' in purposesList:
            sys.stdout.write("""
}\n\n"""
            )
        impressiveInfoTailStdout(purposesList)

        return


####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "dispositionToPresenterStdout" :comment "No longer used" :parsMand "" :parsOpt "dispositionBase" :argsMin 1 :argsMax 1 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<dispositionToPresenterStdout>>  *No longer used*  =verify= parsOpt=dispositionBase argsMin=1 argsMax=1 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class dispositionToPresenterStdout(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'dispositionBase', ]
    cmndArgsLen = {'Min': 1, 'Max': 1,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:
        """No longer used"""
        failed = b_io.eh.badOutcome
        callParamsDict = {'dispositionBase': dispositionBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return failed(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
####+END:

        dispositionBase = dispositionBaseDefault(dispositionBase)

        filename = effectiveArgsList[0]

        document = PdfFileReader(open(filename, "rb"))
        pages = document.getNumPages()
        b_io.tm.here()

        with open(filename+".info", 'w') as out:
            path = os.path.dirname(filename)
            b_io.tm.here(str(path))

            if path == None:
                return b_io.eh.critical_usageError('')

            b_io.tm.here()
            path = path + '/'

            out.write(
                self.impressiveInfoHeadStr(path)
            )
            
            out.write("""
                PageProps = {
                """)

            for i in range(1,pages + 1):
                if i < pages:
                    out.write("    "+str(i)+": {\n        'transition': None,\n        'overview': True,\n        'notes': '',\n        'OnEnter': UpdateInfo\n    },\n")
                else:
                    out.write("    "+str(i)+": {\n        'transition': None,\n        'overview': True,\n        'notes': '',\n        'OnEnter': UpdateInfo\n    }\n}")

    def impressiveInfoHeadStr(self,
                             path,
    ):
        return """\
import json


    def UpdateInfo():
        global FileName, FileList, PageCount
        global DocumentTitle
        global Pcurrent, Pnext, Tcurrent, Tnext, InitialPage
        global RTrunning, RTrestart, StartTime, PageEnterTime, CurrentTime

        with open('"""+path+"""json.txt', 'w') as io:
            json.dump(({"page_count": PageCount, "current_page": Pcurrent, "previous_page": Pnext, "start_time": StartTime, "pageenter_time": PageEnterTime, "current_time": CurrentTime, "notes": PageProps[Pcurrent]['notes']}), io)

"""
                    
    def cmndDesc(): """
** No longer used -- Creates  meta info for Presenter -- To be tested or deleted.
"""

####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "dispositionToImpressiveStdout_voiceOver_Obsoleted" :comment "" :parsMand "" :parsOpt "dispositionBase" :argsMin 0 :argsMax 0 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<dispositionToImpressiveStdout_voiceOver_Obsoleted>>  =verify= parsOpt=dispositionBase ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class dispositionToImpressiveStdout_voiceOver_Obsoleted(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'dispositionBase', ]
    cmndArgsLen = {'Min': 0, 'Max': 0,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
    ) -> b.op.Outcome:

        failed = b_io.eh.badOutcome
        callParamsDict = {'dispositionBase': dispositionBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, None).isProblematic():
            return failed(cmndOutcome)
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
####+END:

        if not dispositionBase:
           dispositionBase = './disposition.gened'

        thisParamBase = icm.FILE_ParamBase(fileSysPath=dispositionBase)

        thisParamBaseState = thisParamBase.baseValidityPredicate()

        if thisParamBaseState != 'InPlace':
            return b_io.eh.critical_oops('thisParamBaseState=' + thisParamBaseState)

        sys.stdout.write(
            self.impressiveInfoHeadStr()
        )

                    
    def cmndDesc(): """
** Map dispositionBase into ImpressiveInfo for voiceOver purposes.
"""

    def impressiveInfoHeadStr(self,
    ):
        """
** Returns a string for impressive.info header for recording purposes.
"""
        return """\

    import shlex
    import subprocess

    def vlcRecordStop():
        commandLine="/opt/public/osmt/bin/bx-vlcRecScreen -i rcRecordStop"
        commandArgs=shlex.split(commandLine)

        print("executing {commandLine}".format(commandLine=commandLine))

        p = subprocess.Popen(commandArgs,
                    stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE)

        out, err = p.communicate()

        if out: print("Stdout:" +  out)
        if err: print("Stderr:" +  err)

    def vlcRecordResume():
        commandLine="/opt/public/osmt/bin/bx-vlcRecScreen -i rcRecordResume"
        commandArgs=shlex.split(commandLine)

        print("executing {commandLine}".format(commandLine=commandLine))

        p = subprocess.Popen(commandArgs,
                    stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE)

        out, err = p.communicate()

        if out: print("Stdout:" +  out)
        if err: print("Stderr:" +  err)


    def vlcRecordFinish():
        commandLine="/opt/public/osmt/bin/bx-vlcRecScreen -i rcRecordShutdown"
        commandArgs=shlex.split(commandLine)

        print("executing {commandLine}".format(commandLine=commandLine))

        p = subprocess.Popen(commandArgs,
                    stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE)

        out, err = p.communicate()

        if out: print("Stdout:" +  out)
        if err: print("Stderr:" +  err)

    def vlcRecordStart():
        commandLine="/opt/public/osmt/bin/bx-vlcRecScreen -h -v -n showRun -p locSize=topLeft720 -i  recordStart"
        commandArgs=shlex.split(commandLine)

        print("executing {commandLine}".format(commandLine=commandLine))

        p = subprocess.Popen(commandArgs,
                    stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE)

        #out, err = p.communicate()

        #if out: print("Stdout:" +  out)
        #if err: print("Stderr:" +  err)
"""


####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "dispositionToImpressiveStdout_recorderEach" :comment "" :parsMand "" :parsOpt "dispositionBase" :argsMin 0 :argsMax 0 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<dispositionToImpressiveStdout_recorderEach>>  =verify= parsOpt=dispositionBase ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class dispositionToImpressiveStdout_recorderEach(cs.Cmnd):
    cmndParamsMandatory = [ ]
    cmndParamsOptional = [ 'dispositionBase', ]
    cmndArgsLen = {'Min': 0, 'Max': 0,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
    ) -> b.op.Outcome:

        failed = b_io.eh.badOutcome
        callParamsDict = {'dispositionBase': dispositionBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, None).isProblematic():
            return failed(cmndOutcome)
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
####+END:

        if not dispositionBase:
           dispositionBase = './disposition.gened'

        thisParamBase = icm.FILE_ParamBase(fileSysPath=dispositionBase)

        thisParamBaseState = thisParamBase.baseValidityPredicate()

        if thisParamBaseState != 'InPlace':
            return b_io.eh.critical_oops('thisParamBaseState=' + thisParamBaseState)

        sys.stdout.write(
            self.impressiveInfoHeadStr()
        )
                    
    def cmndDesc(): """
** Map dispositionBase into ImpressiveInfo for voiceOver purposes.
"""
        

    def impressiveInfoHeadStr(self,
    ):
        """
** Returns a string for impressive.info header for recording purposes.
"""
        return """\

from bisos import icm
from bisos.lcnt import impressiveSup

icm.libUserInit("-v 20")

def bxVideoRecorderStart():
    global FileName, FileList, PageCount
    global DocumentTitle
    global Pcurrent, Pnext, Tcurrent, Tnext, InitialPage
    global RTrunning, RTrestart, StartTime, PageEnterTime, CurrentTime

    impressiveSup.bxVideoRecorderStart(
        curPage=Pcurrent,
    )

def bxVideoRecorderStop():
    global FileName, FileList, PageCount
    global DocumentTitle
    global Pcurrent, Pnext, Tcurrent, Tnext, InitialPage
    global RTrunning, RTrestart, StartTime, PageEnterTime, CurrentTime

    impressiveSup.bxVideoRecorderStop(
        curPage=Pcurrent,
    )

def bxVideoRecorderOnceStart():
    global Pcurrent

    impressiveSup.bxVideoRecorderOnceStart(
        curPage=Pcurrent,
    )

def bxVideoRecorderOnceStop():
    global Pcurrent

    impressiveSup.bxVideoRecorderOnceStop(
        curPage=Pcurrent,
    )

"""
    

####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "updateThenImpressiveInfoStdout" :comment "Full update then ImpressiveInfoStdout" :parsMand "inPdf" :parsOpt "framesRange dispositionBase" :argsMin 1 :argsMax 1000 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<updateThenImpressiveInfoStdout>>  *Full update then ImpressiveInfoStdout*  =verify= parsMand=inPdf parsOpt=framesRange dispositionBase argsMin=1 argsMax=1000 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class updateThenImpressiveInfoStdout(cs.Cmnd):
    cmndParamsMandatory = [ 'inPdf', ]
    cmndParamsOptional = [ 'framesRange', 'dispositionBase', ]
    cmndArgsLen = {'Min': 1, 'Max': 1000,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             inPdf: typing.Optional[str]=None,  # Cs Mandatory Param
             framesRange: typing.Optional[str]=None,  # Cs Optional Param
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:
        """Full update then ImpressiveInfoStdout"""
        failed = b_io.eh.badOutcome
        callParamsDict = {'inPdf': inPdf, 'framesRange': framesRange, 'dispositionBase': dispositionBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return failed(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
        inPdf = csParam.mappedValue('inPdf', inPdf)
        framesRange = csParam.mappedValue('framesRange', framesRange)
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
####+END:

        dispositionBase = dispositionBaseDefault(dispositionBase)

        updateDispositionBase().cmnd(
            interactive=False,
            dispositionBase=dispositionBase,
            argsList=[inPdf,],
        )

        dispositionToImpressiveInfoPurposedStdout().cmnd(
            interactive=False,
            dispositionBase=dispositionBase,
            framesRange=framesRange,
            argsList=effectiveArgsList,
        )

        return

    def cmndDesc(): """
** Given a purpose (voiceOver, presentation, etc) create an info file based on purposesList.
"""

    
####+BEGIN: bx:cs:python:section :title "Impressive Purposed Preparations And Executions -- Main Usage Cmnds"
"""
*  [[elisp:(beginning-of-buffer)][Top]] ############## [[elisp:(blee:ppmm:org-mode-toggle)][Nat]] [[elisp:(delete-other-windows)][(1)]]    *Impressive Purposed Preparations And Executions -- Main Usage Cmnds*  [[elisp:(org-cycle)][| ]]  [[elisp:(org-show-subtree)][|=]]
"""
####+END:


####+BEGIN: b:py3:cs:cmnd/classHead :cmndName "dispositionToImpressivePurposed" :comment "Create Info and run impressive for each" :parsMand "inPdf" :parsOpt "framesRange dispositionBase" :argsMin 1 :argsMax 1000 :pyInv ""
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CmndSvc-   [[elisp:(outline-show-subtree+toggle)][||]] <<dispositionToImpressivePurposed>>  *Create Info and run impressive for each*  =verify= parsMand=inPdf parsOpt=framesRange dispositionBase argsMin=1 argsMax=1000 ro=cli   [[elisp:(org-cycle)][| ]]
#+end_org """
class dispositionToImpressivePurposed(cs.Cmnd):
    cmndParamsMandatory = [ 'inPdf', ]
    cmndParamsOptional = [ 'framesRange', 'dispositionBase', ]
    cmndArgsLen = {'Min': 1, 'Max': 1000,}

    @cs.track(fnLoc=True, fnEntry=True, fnExit=True)
    def cmnd(self,
             rtInv: cs.RtInvoker,
             cmndOutcome: b.op.Outcome,
             inPdf: typing.Optional[str]=None,  # Cs Mandatory Param
             framesRange: typing.Optional[str]=None,  # Cs Optional Param
             dispositionBase: typing.Optional[str]=None,  # Cs Optional Param
             argsList: typing.Optional[list[str]]=None,  # CsArgs
    ) -> b.op.Outcome:
        """Create Info and run impressive for each"""
        failed = b_io.eh.badOutcome
        callParamsDict = {'inPdf': inPdf, 'framesRange': framesRange, 'dispositionBase': dispositionBase, }
        if self.invocationValidate(rtInv, cmndOutcome, callParamsDict, argsList).isProblematic():
            return failed(cmndOutcome)
        cmndArgsSpecDict = self.cmndArgsSpec()
        inPdf = csParam.mappedValue('inPdf', inPdf)
        framesRange = csParam.mappedValue('framesRange', framesRange)
        dispositionBase = csParam.mappedValue('dispositionBase', dispositionBase)
####+END:
        dispositionBase = dispositionBaseDefault(dispositionBase)

        purposesStr="-".join(argsList)
        impressiveInfoPath=os.path.abspath("./tmp/impressive.{}".format(purposesStr))

        ucf.DIR_ensure(impressiveInfoPath)

        purposesList = effectiveArgsList
        
        with open(impressiveInfoPath, 'w') as f:
            with ucf.stdout_redirector(f):
                dispositionToImpressiveInfoPurposedStdout().cmnd(
                    interactive=False,
                    framesRange=framesRange,
                    dispositionBase=dispositionBase,
                    argsList=purposesList,
                )

        if framesRange:
            b_io.ann.write("impressive -i {framesRange} --nologo -Q -k -I {impressiveInfoPath} {inPdf}".
                          format(framesRange=framesRange, impressiveInfoPath=impressiveInfoPath, inPdf=inPdf))
        else:
            if 'recorderOnce' in purposesList:
                b_io.ann.write("impressive -i 1 --nologo -Q -k -I {impressiveInfoPath} {inPdf}".
                          format(impressiveInfoPath=impressiveInfoPath, inPdf=inPdf))
            else:
                b_io.ann.write("impressive --nologo -Q -k -I {impressiveInfoPath} {inPdf}".
                          format(impressiveInfoPath=impressiveInfoPath, inPdf=inPdf))
                
            

    def cmndDesc(): """
** Given a purpose (voiceOver, presentation, etc) create an info file based on purposesList.
"""


####+BEGIN: blee:bxPanel:foldingSection :outLevel 0 :title " ~End Of Editable Text~ "
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*     [[elisp:(outline-show-subtree+toggle)][| _ ~End Of Editable Text~ _: |]]    [[elisp:(org-shifttab)][<)]] E|
#+end_org """
####+END:

####+BEGIN: blee:bxPanel:foldingSection :outLevel 0 :sep nil :title "Main" :anchor ""  :extraInfo "Framework Dblock"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*     [[elisp:(outline-show-subtree+toggle)][| _Main_: |]]  Framework Dblock  [[elisp:(org-shifttab)][<)]] E|
#+end_org """
####+END:

####+BEGIN: b:py3:cs:framework/main :csInfo "csInfo" :noCmndEntry "examples" :extraParamsHook "g_extraParams" :importedCmndsModules "g_importedCmndsModules"
""" #+begin_org
*  _[[elisp:(blee:menu-sel:outline:popupMenu)][±]]_ _[[elisp:(blee:menu-sel:navigation:popupMenu)][Ξ]]_ [[elisp:(outline-show-branches+toggle)][|=]] [[elisp:(bx:orgm:indirectBufOther)][|>]] *[[elisp:(blee:ppmm:org-mode-toggle)][|N]]*  CsFrmWrk   [[elisp:(outline-show-subtree+toggle)][||]] =g_csMain= (csInfo, _examples_, g_extraParams, g_importedCmndsModules)
#+end_org """

if __name__ == '__main__':
    cs.main.g_csMain(
        csInfo=csInfo,
        noCmndEntry=examples,  # specify a Cmnd name
        extraParamsHook=g_extraParams,
        importedCmndsModules=g_importedCmndsModules,
    )

####+END:

####+BEGIN: b:py3:cs:framework/endOfFile :basedOn "classification"
""" #+begin_org
* [[elisp:(org-cycle)][| *End-Of-Editable-Text* |]] :: emacs and org variables and control parameters
#+end_org """

#+STARTUP: showall

### local variables:
### no-byte-compile: t
### end:
####+END:
