[{"data":1,"prerenderedAt":2166},["ShallowReactive",2],{"docs":3,"doc:\u002Fdocs\u002Fweb":88},[4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84],{"path":5,"title":6,"description":7},"\u002Fdocs\u002Fcodemods","Codemods","A codemod is a small program that changes Live Sets. livesaver runs it over folders of sets, shows\nwhat would change, and with --apply writes the changes the same way every livesaver command\ndoes: the result must be well-formed XML, Live's backup scheme is followed\n(Backup\u002F\u003Cset> [date time].als), the run is journaled, and livesaver undo \u003Crun> puts every set\nback.",{"path":9,"title":10,"description":11},"\u002Fdocs\u002Fformat","Ableton Live file formats — what livesaver relies on","Facts collected from Live's own files (verified against real sets) and public research\n(Steinberg VST3 SDK, JUCE, Ableton's maxdevtools). Each page names its sources.",{"path":13,"title":14,"description":15},"\u002Fdocs\u002Fformat\u002Fcontainers","Containers and id spaces","How Live's files are packed: which are gzip-compressed XML and which are binary, what lies beside them, and how the ids inside a document are numbered.",{"path":17,"title":18,"description":19},"\u002Fdocs\u002Fformat\u002Ffileref","FileRef","A \u003CFileRef> locates one file. It appears in many containers, but only some are real dependencies.",{"path":21,"title":22,"description":23},"\u002Fdocs\u002Fformat\u002Ffinder","Finder tags, comments and plug-in bundles (macOS)","What status, reorg and the plug-in inventory read and write outside Live's own files.",{"path":25,"title":26,"description":27},"\u002Fdocs\u002Fformat\u002Ffingerprints","Fingerprints","How Live recognises a file again: the size and the checksum it stores with every reference, where vendors and pack updates break that, and what livesaver compares instead.",{"path":29,"title":30,"description":31},"\u002Fdocs\u002Fformat\u002Flive-setup","Live installation and library locations","Where Live keeps its app resources, its library folders and its own databases, and how livesaver finds them without being told. Everything below was read on a Mac; Windows is at the end, from Ableton's documentation.",{"path":33,"title":34,"description":35},"\u002Fdocs\u002Fformat\u002Fplugins","Plug-ins in Live Sets","How a Live Set stores a plug-in in each format, how the same plug-in is recognised across formats, and what an upgrade from VST2 to VST3 has to carry over.",{"path":37,"title":38,"description":39},"\u002Fdocs\u002Fformat\u002Fversions","\u003CAbleton> root attributes per Live version","The root is \u003CAbleton MajorVersion MinorVersion SchemaChangeCount Creator Revision>. Creator is \"Ableton Live x.y.z\".",{"path":41,"title":42,"description":43},"\u002Fdocs\u002Fguide\u002Fbrowser","In the browser","The app also runs on its own, as a page in your browser. It reads the folders you give it and changes nothing: good for a first look, or on a computer where you cannot install anything. In Chrome and Edge it can also fix samples and upgrade plug-ins, if you switch that on: see Fixing in the page.",{"path":45,"title":46,"description":47},"\u002Fdocs\u002Fguide\u002Fcommand-line","The command line","Everything the app does, the livesaver command does too, and more: project status in Finder, a catalog of your sets to search, and codemods. Every command only plans unless you pass --apply.",{"path":49,"title":50,"description":51},"\u002Fdocs\u002Fguide\u002Fgetting-started","Getting started","livesaver finds the samples your Ableton Live sets have lost, collects them into their projects, and shows which plug-ins are missing. This page takes you from nothing to your first scan.",{"path":53,"title":54,"description":55},"\u002Fdocs\u002Fguide\u002Fhistory","History and undo","Everything livesaver changes is written down as a run: what it was asked, every step it took, and the original of every set it rewrote. That is what makes an undo possible, also weeks later.",{"path":57,"title":58,"description":59},"\u002Fdocs\u002Fguide\u002Fmissing","When samples stay missing","A fix can only find what is in the folders it searches. What stays missing is listed by where it came from, because what helps differs: a pack is installed again, an old drive is plugged in, a folder is added.",{"path":61,"title":62,"description":63},"\u002Fdocs\u002Fguide\u002Fplugins","Plug-ins","Live finds a plug-in by its format and its id, never by its name. livesaver reads which plug-ins your sets use and compares them with what is installed, the way Live does, so you know before you open a set what will be missing in it.",{"path":65,"title":66,"description":67},"\u002Fdocs\u002Fguide\u002Fquestions","Questions and answers","Short answers to what comes up first. If yours is not here, ask on GitHub.",{"path":69,"title":70,"description":71},"\u002Fdocs\u002Fguide\u002Fsafety","How your work is kept safe","livesaver edits the files your music lives in. These are the rules it keeps, so that nothing is lost.",{"path":73,"title":74,"description":75},"\u002Fdocs\u002Fguide\u002Fsamples","Fix missing samples","A set that has lost its samples opens in Live with “Media files are missing”. livesaver finds the files again by what they are, puts them into the project, and points the set at them, for every project at once.",{"path":77,"title":78,"description":79},"\u002Fdocs\u002Fguide\u002Fwindows","livesaver on Windows","livesaver is made and tested on a Mac. Windows is new: it is built from what Ableton documents about Live on Windows and from the way sets that were saved on Windows store their files. No one has tried it on a Windows computer with Live yet. This page says what is there, what differs from a Mac, and what is not known.",{"path":81,"title":82,"description":83},"\u002Fdocs\u002Fverification","Verification","What is checked, and how to repeat it. Checks on a real library are read-only; everything that\nwrites runs on temporary copies.",{"path":85,"title":86,"description":87},"\u002Fdocs\u002Fweb","The web app","apps\u002Fweb is one app (Vite, Vue, Nuxt UI) that runs in two situations:",{"id":89,"title":86,"body":90,"description":87,"extension":2160,"meta":2161,"navigation":2162,"path":85,"seo":2163,"stem":2164,"__hash__":2165},"docs\u002Fdocs\u002Fweb.md",{"type":91,"value":92,"toc":2140},"minimark",[93,97,105,166,169,176,181,348,420,423,431,622,710,714,721,800,803,813,856,860,870,953,976,979,1035,1039,1046,1104,1114,1120,1161,1167,1170,1257,1275,1279,1285,1341,1344,1354,1439,1442,1557,1563,1566,1575,1671,1675,1678,1733,1736,1739,1746,1788,1791,1795,1802,1899,1903,1920,1924,1945,1949],[94,95,86],"h1",{"id":96},"the-web-app",[98,99,100,104],"p",{},[101,102,103],"code",{},"apps\u002Fweb"," is one app (Vite, Vue, Nuxt UI) that runs in two situations:",[106,107,108,142],"ul",{},[109,110,111,115,116,119,120,123,124,127,128,131,132,135,136,141],"li",{},[112,113,114],"strong",{},"With livesaver on the same computer"," (",[101,117,118],{},"livesaver web",", or ",[101,121,122],{},"bun run web"," in the repository):\nthe computer reads the folders by their paths and scans them like ",[101,125,126],{},"livesaver doctor"," and\n",[101,129,130],{},"livesaver plugins audit",", and it can fix what it finds like ",[101,133,134],{},"livesaver collect --apply",": all\nprojects, a selection, or one, after a review, with an undo. See\n",[137,138,140],"a",{"href":139},"#on-this-computer","On this computer",".",[109,143,144,147,148,151,152,155,156,160,161,165],{},[112,145,146],{},"On its own in a browser"," (any static host): it is handed folders and scans them itself\nwith the same code (",[101,149,150],{},"@livesaver\u002Fops",") on a browser host (",[101,153,154],{},"@livesaver\u002Fweb","). It only reads,\nunless its user switches fixing on where a browser lets a page edit a folder (Chrome, Edge):\nthen it fixes samples and upgrades plug-ins itself, with a backup of every set and an undo.\nThe sections from ",[137,157,159],{"href":158},"#how-it-is-built","How it is built"," to\n",[137,162,164],{"href":163},"#on-its-own-what-differs-from-the-command-line","What differs from the command line"," are\nabout this.",[98,167,168],{},"The same files serve both: relative URLs and hash routes, so they run at any path. What the app\ncannot do where it runs is shown and explained, not hidden: on its own it says how it can fix\nfrom there, for the browser it is in.",[98,170,171,172,141],{},"Fixing in the page is an experiment behind a switch. Writing needs the File System Access API,\nwhich Safari and Firefox do not offer (Brave only behind a flag) and whose handles hide files;\nand a page cannot see that Live is running. See ",[137,173,175],{"href":174},"#fixing-in-a-browser","Fixing in a browser",[177,178,180],"h2",{"id":179},"the-screens","The screens",[182,183,184,200],"table",{},[185,186,187],"thead",{},[188,189,190,194,197],"tr",{},[191,192,193],"th",{},"Place",[191,195,196],{},"What it shows",[191,198,199],{},"What can be done",[201,202,203,218,231,244,257,270,283,296,309,322,335],"tbody",{},[188,204,205,212,215],{},[206,207,208,211],"td",{},[112,209,210],{},"Overview",", before a scan",[206,213,214],{},"what livesaver does in three steps, the project folders and sample folders, the options",[206,216,217],{},"add folders, scan",[188,219,220,225,228],{},[206,221,222,224],{},[112,223,210],{},", after a scan",[206,226,227],{},"the library in one line, which opens into its folders and options; how many sets are complete, can be fixed, or have samples that stay missing (one bar); what a fix would do; what is missing, by source, with what to do about the largest; every reference by state; where found samples lie; the last changes",[206,229,230],{},"add a folder and scan again without leaving the page; review and fix, download the reports, undo the last fix",[188,232,233,238,241],{},[206,234,235],{},[112,236,237],{},"Samples › Projects",[206,239,240],{},"every project: state, sets, what a fix changes, what stays missing, what is copied",[206,242,243],{},"fix one, a selection, or all; a project opens from the side with its sets, its changes (old place → new place) and its gaps; show it in Finder",[188,245,246,251,254],{},[206,247,248],{},[112,249,250],{},"Samples › Missing",[206,252,253],{},"missing samples grouped by where they came from, each group with advice",[206,255,256],{},"add the folder that has them, copy the list, open a sample",[188,258,259,264,267],{},[206,260,261],{},[112,262,263],{},"Samples › Changes",[206,265,266],{},"every planned change: how the file was found, and whether the fingerprint confirms it",[206,268,269],{},"search, filter (uncertain only), open a change",[188,271,272,277,280],{},[206,273,274],{},[112,275,276],{},"Samples › Sets",[206,278,279],{},"every set with what its samples are",[206,281,282],{},"search, filter, open a set",[188,284,285,290,293],{},[206,286,287],{},[112,288,289],{},"Plug-ins › In your sets",[206,291,292],{},"every plug-in the sets use: format, state (not installed, Rosetta only, installed), how often and where",[206,294,295],{},"search, filter; a plug-in opens from the side with what to do, the sets that use it, where it is installed, and the same plug-in in other formats",[188,297,298,303,306],{},[206,299,300],{},[112,301,302],{},"Plug-ins › Installed",[206,304,305],{},"what is installed: format, native or Rosetta only, version, known to Live, used by how many sets",[206,307,308],{},"filter (Rosetta only, used by no set, not scanned by Live); what breaks if a plug-in is uninstalled",[188,310,311,316,319],{},[206,312,313],{},[112,314,315],{},"Plug-ins › Upgrade to VST3",[206,317,318],{},"per plug-in what converts and what stands in the way (in a rack, automation, an old file format, no VST3 installed); every plug-in in every set",[206,320,321],{},"upgrade all or the ticked plug-ins after a review; undo",[188,323,324,329,332],{},[206,325,326],{},[112,327,328],{},"History",[206,330,331],{},"every run that changed something, by day: what it did, where, and what became of it; on request also the runs that only planned or reported",[206,333,334],{},"a run opens from the side with what it was asked, its numbers, its report files and every step; undo a run, after a question that says what the undo does",[188,336,337,342,345],{},[206,338,339],{},[112,340,341],{},"Settings",[206,343,344],{},"the folders and options of a scan, the appearance, the keyboard shortcuts, what livesaver found on this computer (Live, its libraries, the settings file, where runs and originals are kept)",[206,346,347],{},"change them; reset them to the command line's settings; show a folder in Finder; the app says when a scan is older than they are",[106,349,350,356,362,368,374,396,402,408,414],{},[109,351,352,355],{},[112,353,354],{},"The folders are where the result is read."," The first visit has them on the Overview, and\nso has every later one: the line \"Your library\" says what was read and opens into the folders\nand options, with a button that scans again. What points at the folders (a notice, the advice\nfor missing samples) leads there, and a scan that is started in the Settings is watched on\nthe Overview, where its result appears.",[109,357,358,361],{},[112,359,360],{},"Nothing is written without a review."," A fix goes through three steps: what will happen\n(sets, references, copies, per project; with a switch that leaves the uncertain matches out),\nwhether everything is ready (Live closed, enough free space, where the backups go), then the\nfix and what it did, with its undo.",[109,363,364,367],{},[112,365,366],{},"A fix does what was scanned."," If folders or options were changed after the scan, the app\nsays so, and a fix still uses those of the scan.",[109,369,370,373],{},[112,371,372],{},"An undo is always within reach."," In the result of a fix, in the notice of the last fix on\nthe Overview (also after a reload), in a toast when a fix was made from another page, and for\nevery run in the History. The fix just made is undone with one click; a run from the History\nmay be weeks old, so that undo says first what it will do.",[109,375,376,379,380,383,384,387,388,391,392,395],{},[112,377,378],{},"Everything works with the keyboard."," ",[101,381,382],{},"?"," lists the keys: ",[101,385,386],{},"G"," then a letter goes to a place,\n",[101,389,390],{},"⌘K"," opens the palette, ",[101,393,394],{},"\u002F"," searches the table, the arrow keys walk its rows, Enter opens one.",[109,397,398,401],{},[112,399,400],{},"What fails is said where one is."," A scan that failed and a livesaver that no longer answers\nare said on every page, with what to do; an error nobody expected is shown, not swallowed.\nEvery page is part of the first load, so the app goes on working, and saying so, when what\nserved it is gone.",[109,403,404,407],{},[112,405,406],{},"Motion is short and optional."," A page fades in, a bar fills from its start; with the\nsystem's setting for reduced motion there is none.",[109,409,410,413],{},[112,411,412],{},"The tables hold a library."," Only the rows in view are in the page: 9,305 planned changes of\na real library scroll without a slow frame, and a search over them takes 27 ms.",[109,415,416,419],{},[112,417,418],{},"States are never told by colour alone."," Fine, can be fixed, missing: each has an icon of its\nown shape and a label in the text colour; the three colours are checked for colour-vision\ndeficiencies against the light and the dark surfaces.",[177,421,140],{"id":422},"on-this-computer",[98,424,425,115,427,430],{},[101,426,118],{},[101,428,429],{},"packages\u002Fcli\u002Fsrc\u002Fweb\u002F",") serves the page and answers it:",[182,432,433,443],{},[185,434,435],{},[188,436,437,440],{},[191,438,439],{},"Request",[191,441,442],{},"What it does",[201,444,445,459,469,479,492,507,517,530,551,564,577,591,612],{},[188,446,447,452],{},[206,448,449],{},[101,450,451],{},"GET \u002Fapi\u002Finfo",[206,453,454,455,458],{},"what the page starts with: the folders of the last scan, else the settings of the command line (search folders, the projects folder of ",[101,456,457],{},"status","); and what was found on this computer (Live's folders, the settings file, livesaver's own folder)",[188,460,461,466],{},[206,462,463],{},[101,464,465],{},"POST \u002Fapi\u002Freset",[206,467,468],{},"forgets the folders and options of the last scan: the page starts with the command line's settings again (refused while something runs)",[188,470,471,476],{},[206,472,473],{},[101,474,475],{},"GET \u002Fapi\u002Ffolders?path=",[206,477,478],{},"the folders in a folder: the page shows them to choose one, since a browser's own folder dialog never tells a path",[188,480,481,486],{},[206,482,483],{},[101,484,485],{},"POST \u002Fapi\u002Fcheck",[206,487,488,491],{},[101,489,490],{},"doctor"," over the given folders; answers line by line (progress, then the result)",[188,493,494,499],{},[206,495,496],{},[101,497,498],{},"POST \u002Fapi\u002Fscan",[206,500,501,502,506],{},"the samples and the plug-ins of every set (see ",[137,503,505],{"href":504},"#a-scan","A scan","); line by line",[188,508,509,514],{},[206,510,511],{},[101,512,513],{},"GET \u002Fapi\u002Fscan",[206,515,516],{},"the last scan, with what was scanned: a page that is opened again shows it without scanning",[188,518,519,524],{},[206,520,521],{},[101,522,523],{},"POST \u002Fapi\u002Fupgrade\u002Fplan",[206,525,526,529],{},[101,527,528],{},"plugins upgrade"," as a dry run: what converts to VST3, and what blocks the rest",[188,531,532,537],{},[206,533,534],{},[101,535,536],{},"POST \u002Fapi\u002Ffix",[206,538,539,542,543,546,547,550],{},[101,540,541],{},"collect --apply"," over all projects, or over one (",[101,544,545],{},"only","); ",[101,548,549],{},"certainOnly"," leaves uncertain matches out",[188,552,553,558],{},[206,554,555],{},[101,556,557],{},"POST \u002Fapi\u002Fupgrade",[206,559,560,563],{},[101,561,562],{},"plugins upgrade --apply",", of all plug-ins or of chosen ones, in all projects or in one",[188,565,566,571],{},[206,567,568],{},[101,569,570],{},"POST \u002Fapi\u002Fundo",[206,572,573,576],{},[101,574,575],{},"undo"," of a run; an undo that is refused (Live runs, there is no such run) is an answer that says why, like a fix that fails",[188,578,579,584],{},[206,580,581],{},[101,582,583],{},"GET \u002Fapi\u002Fstatus",[206,585,586,587,590],{},"whether Live is running, what runs right now and how far it is, and (",[101,588,589],{},"?path=",") the free space where a folder lies",[188,592,593,605],{},[206,594,595,598,599,598,602],{},[101,596,597],{},"GET \u002Fapi\u002Fruns",", ",[101,600,601],{},"\u002Fapi\u002Fruns\u002F\u003Crun>",[101,603,604],{},"\u002Fapi\u002Fruns\u002F\u003Crun>\u002Freports\u002F\u003Cfile>",[206,606,607,608,611],{},"the history: every run with what it did (as ",[101,609,610],{},"livesaver runs","), its steps, its report files",[188,613,614,619],{},[206,615,616],{},[101,617,618],{},"POST \u002Fapi\u002Freveal",[206,620,621],{},"shows a file in Finder",[106,623,624,643,649,655,661,670,687,701],{},[109,625,626,115,629,632,633,636,637,115,640,642],{},[112,627,628],{},"The same pipeline as the command line",[101,630,631],{},"collectRun","): settings, cache of complete sets,\nbackups, journal, run folder and undo are those of ",[101,634,635],{},"livesaver collect",". The result is shaped\nfor the page by ",[101,638,639],{},"checkView",[101,641,150],{},"), which the browser engine uses too.",[109,644,645,648],{},[112,646,647],{},"One project alone gets the plan it has among all."," A fix of one project searches the same\nfolders, the other projects included. On a real library every one of 67 projects with changes\ngot, checked alone, exactly the changes and copies it has in the check of all 299.",[109,650,651,654],{},[112,652,653],{},"A fix does what was checked."," The page asks first and says what will happen; if folders or\noptions were changed after the check, the fix still uses those of the check, and says so.",[109,656,657,660],{},[112,658,659],{},"Live must not be running",", and only one run goes at a time, as on the command line.",[109,662,663,666,667,669],{},[112,664,665],{},"A run goes on when the page is closed."," A fix must not stop half-way, so the server finishes\nit; the page asks ",[101,668,457],{}," to see that something runs. A scan is kept until something is\nwritten (a fix, an upgrade, an undo): what it found is no longer true then.",[109,671,672,675,676,679,680,682,683,686],{},[112,673,674],{},"A fix can leave the uncertain matches out."," The check's result says for every project what\na fix does with them and without (",[101,677,678],{},"certain"," in ",[101,681,639],{},"), from one check, so a page can\nshow both before it asks. On a real library the numbers without them (140 sets, 9,291\nreferences, 1,968 copies) equal those of a check with ",[101,684,685],{},"--certain-only",", for each of 299 projects.",[109,688,689,692,693,696,697,700],{},[112,690,691],{},"Only its own page may ask."," The server listens on this computer only. Every request must\ncarry a token that is written into the page when it is served, come to this address\n(",[101,694,695],{},"127.0.0.1"," or ",[101,698,699],{},"localhost",": a name that merely points here is refused) and, if it names an\norigin, from this page. Another site open in the browser can therefore neither read nor fix.",[109,702,703,115,706,709],{},[112,704,705],{},"Restoring form controls is switched off",[101,707,708],{},"autocomplete=\"off\"","): after a back navigation a\nbrowser hands out remembered ticks by position, so an option could show the tick of another\nbox while the page itself had it off.",[177,711,713],{"id":712},"the-app-elsewhere-connected-to-this-computer","The app elsewhere, connected to this computer",[98,715,716,717,720],{},"The app on livesaver's site is the same files as the app livesaver serves. On its own it only\nreads (unless fixing in the page is switched on); ",[101,718,719],{},"livesaver web --pair"," connects it to the\nlivesaver of the same computer:",[106,722,723,737,750,768,785],{},[109,724,725,728,729,732,733,736],{},[112,726,727],{},"The pairing link"," opens the app with where livesaver is and its token behind the ",[101,730,731],{},"#"," of\nthe address (",[101,734,735],{},"#\u002Fconnect?at=http:\u002F\u002F127.0.0.1:5483&token=…","), a part a browser does not send to\nthe site. The app takes it before it reads the address as a place to go to, keeps it for the\ntab (so a reload stays connected), and clears the address. It accepts only an address of this\ncomputer: a link cannot make the page talk to another machine.",[109,738,739,742,743,746,747,749],{},[112,740,741],{},"The server lets exactly that site in."," Started with ",[101,744,745],{},"--pair",", it answers what a browser\nasks before a page of another origin may send the token (the origin, the header, and that a\npublic site reaches this computer), and lets the paired site read its answers. Every other\norigin is refused as before, and the token and the address checks stay as they are. Without\n",[101,748,745],{},", the site is a stranger like any other.",[109,751,752,755,756,759,760,763,764,767],{},[112,753,754],{},"A browser has the last word."," Chrome, Edge and Firefox ask the user whether the page may\nreach this computer. Brave refuses without asking, unless the site was allowed under\n",[101,757,758],{},"brave:\u002F\u002Fsettings\u002Fcontent\u002FlocalhostAccess",". Safari does not allow it: to WebKit, a request to\n",[101,761,762],{},"http:\u002F\u002F127.0.0.1"," from a page of an ",[101,765,766],{},"https"," site is mixed content. While a browser asks, the\npage says that it is connecting. A browser that refuses says nothing, and to the page that is\nthe same as a livesaver that is gone: it says that livesaver does not answer, what this\nbrowser needs, and links to livesaver's own address, which serves the same app and which any\nbrowser opens (going there is no request of a page). Either way it can go on on its own.\nChecked with the app as deployed on the site: Chromium connects and scans once that\npermission is given, and WebKit refuses.",[109,769,770,115,773,776,777,780,781,784],{},[112,771,772],{},"The page says it for the browser at hand",[101,774,775],{},"lib\u002Fways.ts","): for each of the two ways a page\ncan fix (connected, or editing the folder itself) whether it works, works after a step in the\nbrowser's own settings, or does not. Brave is known by ",[101,778,779],{},"navigator.brave"," (its user agent is\nChrome's), the others by their user agents. A page cannot link to a browser's settings\n(",[101,782,783],{},"brave:\u002F\u002F…","), so those addresses are shown to be copied. The dialog also takes a pairing\nlink that is pasted, and connects the tab that is open.",[109,786,787,115,790,679,793,598,796,799],{},[112,788,789],{},"Both sides name their protocol",[101,791,792],{},"api",[101,794,795],{},"\u002Fapi\u002Finfo",[101,797,798],{},"WEB_API","). A page that livesaver\nserves always fits; a connected page may be older or newer than its livesaver, and says so\ninstead of misreading its answers.",[177,801,505],{"id":802},"a-scan",[98,804,805,806,808,809,812],{},"A scan is what the screens are built on: the samples (as ",[101,807,490],{}," reports them) and the\nplug-ins of every set (as ",[101,810,811],{},"plugins audit"," reports them).",[106,814,815,828,834,843],{},[109,816,817,820,821,679,824,827],{},[112,818,819],{},"Every set is read once."," The parse workers return a set's plug-ins with its references\n(",[101,822,823],{},"pluginUses",[101,825,826],{},"@livesaver\u002Fcore"," finds the plug-in devices by byte search and scans only\nthose, instead of the whole document), so the plug-ins cost no second pass. On a real library\n(876 sets) a scan takes 12.5 s; the check alone takes 12 s, and the audit used to take\nanother 11 s.",[109,829,830,833],{},[112,831,832],{},"The upgrade plan is made when it is asked for."," It reads the sets with a VST2 plug-in an\nupgrade says something about again (about 380 of 876), about 5 s, which a scan repeated after\nevery fix should not wait for. It is kept with the scan.",[109,835,836,839,840,141],{},[112,837,838],{},"No cache of complete sets",": a set that is skipped tells nothing about its plug-ins. Its\nreport files equal those of ",[101,841,842],{},"doctor --full",[109,844,845,115,848,851,852,855],{},[112,846,847],{},"Sets of an older Live can be left out",[101,849,850],{},"minLive",", the command line's ",[101,853,854],{},"--min-live","): old\nsaves that are kept as they were beside newer ones of the same song. Such a set is read (the\nLive that saved it is in its first line), and then not checked, not listed and not fixed; the\nscan says how many were left out, since they are in no other number.",[177,857,859],{"id":858},"one-contract-two-engines","One contract, two engines",[98,861,862,863,115,866,869],{},"The app talks to an ",[101,864,865],{},"Engine",[101,867,868],{},"apps\u002Fweb\u002Fsrc\u002Fengine\u002Ftypes.ts","): start, reset, scan, plan an\nupgrade, fix, upgrade, undo, the history, status, reveal, list folders. Two engines implement\nit:",[182,871,872,888],{},[185,873,874],{},[188,875,876,878,883],{},[191,877],{},[191,879,880],{},[101,881,882],{},"ComputerEngine",[191,884,885],{},[101,886,887],{},"BrowserEngine",[201,889,890,910,921,934],{},[188,891,892,895,898],{},[206,893,894],{},"what it is",[206,896,897],{},"livesaver on this computer, over the requests above",[206,899,900,901,598,904,679,907,909],{},"the browser: a worker over the folders the page was handed (",[101,902,903],{},"scanInWorker",[101,905,906],{},"serveEngine",[101,908,154],{},")",[188,911,912,915,918],{},[206,913,914],{},"folders",[206,916,917],{},"by their paths",[206,919,920],{},"uploaded or dropped; where they lie is worked out",[188,922,923,926,929],{},[206,924,925],{},"can",[206,927,928],{},"everything",[206,930,931,932,909],{},"scan; and, switched on by its user in Chrome or Edge, fix samples, upgrade plug-ins, undo, and keep a history (see ",[137,933,175],{"href":174},[188,935,936,939,942],{},[206,937,938],{},"plug-ins",[206,940,941],{},"with what is installed",[206,943,944,945,949,950],{},"which are used, and where; installed or not if it was handed the folders that say so (see ",[137,946,948],{"href":947},"#what-is-installed-in-a-browser","What is installed, in a browser","), else ",[101,951,952],{},"unknown",[98,954,955,956,959,960,963,964,967,968,971,972,975],{},"What an engine cannot do is in its ",[101,957,958],{},"capabilities",", and asking for it fails as ",[101,961,962],{},"Unsupported",", so\na screen shows and explains it instead of hiding it. An engine that is gone (livesaver was\nstopped, or started again, which gives its page a new token) fails as ",[101,965,966],{},"Unreachable","; the app\nnotices that in one place, whichever screen asked. One suite of tests\n(",[101,969,970],{},"apps\u002Fweb\u002Ftest\u002Fengine.conformance.test.ts",") runs the same scenarios against both, and demands\nthat both show the same for the same library. The browser's engine runs in it twice: reading\nonly, and with fixing switched on over a project folder that can be edited. The engines that\nwrite (livesaver, and the browser with fixing switched on) share the scenarios of a fix and of\nan upgrade of plug-ins, each with its undo (",[101,973,974],{},"engine.writing.test.ts",").",[177,977,159],{"id":978},"how-it-is-built",[106,980,981,987,999,1005,1011,1017,1023],{},[109,982,983,986],{},[112,984,985],{},"The page"," (Vue, Pinia, Nuxt UI in Vue mode, Tailwind) holds the state in stores (engine,\nlibrary, scan, fix, plug-ins, history) that talk to the engine; the stores and everything they\ncompute are plain TypeScript, tested without a browser. The history store has the one list of\nruns: the last fix and the last upgrade that can be undone are read from it, and every undo\ngoes through it, one at a time.",[109,988,989,992,993,679,996,998],{},[112,990,991],{},"An engine worker"," runs the scan (",[101,994,995],{},"scanFolders",[101,997,154],{},"), so the page stays\nresponsive. The files of the folders stay with the page; the worker asks for each one it reads.",[109,1000,1001,1004],{},[112,1002,1003],{},"Parse workers"," (started by the engine worker) gunzip the sets and find their references\nand plug-ins.",[109,1006,1007,1010],{},[112,1008,1009],{},"Nothing is fetched from elsewhere."," Icons and the font are part of the build, and a test\nfails on any request that leaves the page's own address: the app promises that nothing leaves\nthe computer.",[109,1012,1013,1016],{},[112,1014,1015],{},"For everyone."," Every scrolling area can take the keyboard's focus, the whole flow from scan\nto undo works without a mouse, and axe finds no barrier on any screen, in light and dark. A\nmessage of failure is red in its icon and frame, and in the colour of text in its words:\nred words on a red ground cannot be read.",[109,1018,1019,1022],{},[112,1020,1021],{},"Two files of script",": what comes from libraries (which a new version of the app rarely\nchanges), and the app. Together about 320 kB compressed.",[109,1024,1025,1027,1028,1031,1032,1034],{},[101,1026,122],{}," is Vite's development server with livesaver's API behind it. ",[101,1029,1030],{},"bun run build","\nbuilds the app and copies it (without source maps) into the command line's package, which is\nwhat ",[101,1033,118],{}," serves.",[177,1036,1038],{"id":1037},"folders-in-a-browser","Folders in a browser",[98,1040,1041,1042,1045],{},"A page gets a folder in one of three ways (",[101,1043,1044],{},"packages\u002Fweb\u002Fsrc\u002Fsource.ts","):",[182,1047,1048,1061],{},[185,1049,1050],{},[188,1051,1052,1055,1058],{},[191,1053,1054],{},"How",[191,1056,1057],{},"Browsers",[191,1059,1060],{},"What the page gets",[201,1062,1063,1077,1087],{},[188,1064,1065,1071,1074],{},[206,1066,1067,1068,909],{},"folder upload (",[101,1069,1070],{},"\u003Cinput webkitdirectory>",[206,1072,1073],{},"all",[206,1075,1076],{},"every file of the folder at once; nothing is uploaded anywhere",[188,1078,1079,1082,1084],{},[206,1080,1081],{},"drag and drop (entries API)",[206,1083,1073],{},[206,1085,1086],{},"the folder's entries; the page lists them and fetches a file when it is read",[188,1088,1089,1095,1101],{},[206,1090,1091,1094],{},[101,1092,1093],{},"showDirectoryPicker"," (File System Access API)",[206,1096,1097,1098,909],{},"Chrome, Edge (in Brave behind ",[101,1099,1100],{},"brave:\u002F\u002Fflags\u002F#file-system-access-api",[206,1102,1103],{},"a handle; folders are listed and files opened on demand",[98,1105,1106,1109,1110,1113],{},[101,1107,1108],{},"WebFs"," mounts these folders at absolute paths and implements the read-only ",[101,1111,1112],{},"FsRead"," port.",[98,1115,1116,1119],{},[112,1117,1118],{},"The page takes uploads and drops, not handles",", with one exception: a project folder that is\nto be fixed in the page (below). A handle is convenient (no \"upload\" question, nothing listed\nup front) and the only way a page can write, but Chromium does not show everything through it:",[106,1121,1122,1136],{},[109,1123,1124,1125,1128,1129,1131,1132,1135],{},"Entries with names it considers unsafe are left out without a word: a name with a ",[101,1126,1127],{},":"," (which\nFinder shows as ",[101,1130,394],{},", as in a sample folder \"Claps\u002FSnares\"), a name that starts or ends with a\nspace (\" (Freeze).wav\" and the like occur in real projects), ",[101,1133,1134],{},"desktop.ini"," and a few more. In\na real music folder that hid 5,220 of 108,423 entries, among them three whole sample folders,\nand the check then called samples missing that are there.",[109,1137,1138,1139,1142,1143,1146,1147,1150,1151,598,1154,1156,1157,1160],{},"No handle is given for a folder in ",[101,1140,1141],{},"\u002FApplications"," (where Live's ",[101,1144,1145],{},"App-Resources"," lies), nor for\nthe home, Documents or Desktop folder itself. Asked for one all the same, Chromium puts a\ndialog of its own in front of the page (\"can't open this folder because it contains system\nfiles\"), although the folder is read through its entries. So a drop asks for no handle when\nthe folder is an app's by its name (",[101,1148,1149],{},"folderOfAnApp",": the app, ",[101,1152,1153],{},"Contents",[101,1155,1145],{},",\n",[101,1158,1159],{},"Core Library","): the Live app is added without that dialog.",[98,1162,1163,1166],{},[112,1164,1165],{},"The page says what handing over a folder means",", where the folders are added: that nothing\nis uploaded (a browser's word for letting a page read), how a drop, the dialog and a handle\ndiffer, and what the browser's questions mean. And it shows how the Live app is added, in\npictures that are drawn in the page (they follow the theme, and are no one's screen).",[98,1168,1169],{},"Uploads and drops show every file. In a real project folder (299 projects, 46,507 files) a\nhandle hides 118 files: 36 samples, their analysis files, and Finder's icon files; no set and\nno folder. Sample folders stay uploads and drops; a project folder that is to be fixed needs\nits handle, and the page makes up for what the handle hides:",[106,1171,1172,1219],{},[109,1173,1174,1177,1178,598,1181,1184,1185,598,1188,1045,1191,1215,1218],{},[112,1175,1176],{},"A sample the handle hides is not a missing sample."," The first real fix in a page showed\nwhat happens otherwise: 41 samples that lay where their sets expect them counted as missing,\nwere \"found\" elsewhere, and were to be copied to the names the browser refuses. The fix\nfailed for all 48 sets it touched, and said it had copied the 23 files it had planned to\n(it had copied none: a copy now counts once it is made). So the file system says\nwhere it sees nothing and where it can make nothing (",[101,1179,1180],{},"FsRead.hides",[101,1182,1183],{},"FsRead.refuses","), and\na set is planned by that (",[101,1186,1187],{},"processSet",[101,1189,1190],{},"Choice.blind",[106,1192,1193,1199,1209],{},[109,1194,1195,1198],{},[101,1196,1197],{},"unseen",": a place where Live would look for the file is hidden. The file may be there:\nnothing is looked for in its place, and the reference is left alone.",[109,1200,1201,1204,1205,1208],{},[101,1202,1203],{},"unmade",": the file was found, and would be copied to a name the browser does not make.\nAnother place in the project is taken if there is one (",[101,1206,1207],{},"Project.places","); otherwise the\nreference is left alone, with the file that was found as its candidate.",[109,1210,1211,1214],{},[101,1212,1213],{},"locked",": the set itself has such a name, or lies in a folder with one. It is read (through\na listing, see below) and checked, and nothing is done for it.",[1216,1217],"br",{},"Each of the three is listed with the missing samples under a source of its own, with what to\ndo, and no set is planned to change for it: a fix then writes the sets it can, and fails for\nnone.",[109,1220,1221,115,1224,1226,1227,1254,1256],{},[112,1222,1223],{},"A listing of the same folder shows what the handle hides",[101,1225,1108],{},": the handle is what is\nread and written, the listing what it leaves out). The page gets one in three ways:",[106,1228,1229,1244,1251],{},[109,1230,1231,1232,1235,1236,1239,1240,1243],{},"The project folder is ",[112,1233,1234],{},"dropped"," rather than chosen in the dialog: a drop lists every\nfile and comes with the handle (",[101,1237,1238],{},"editableFromDrop","; the source keeps the files the handle\nhides, ",[101,1241,1242],{},"hidden","). The folder is then read in full from the start.",[109,1245,1246,1247,1250],{},"The same folder is given once more, as an upload or a drop, among the sample folders\n(",[101,1248,1249],{},"locate"," takes it for the project folder: one place, read once).",[109,1252,1253],{},"A folder that holds the project folder is among the sample folders (a library folder).",[1216,1255],{},"A place that a listing shows is not hidden, and still refused: a file there is seen, and\nnone can be made.",[98,1258,1259,1262,1263,1266,1267,1270,1271,1274],{},[112,1260,1261],{},"Files are fetched lazily."," For an uploaded folder even reading a file's size costs a round\ntrip to the browser (about 60 µs), and sending a ",[101,1264,1265],{},"File"," object to a worker about 30 µs: touching\nall 290,000 files of a library up front froze the page for 17 s. So the engine gets only the\npaths; it asks the page for a file when it needs its size or content (about 1,700 files in a run\nover 876 sets). ",[101,1268,1269],{},"FsRead.kind"," answers \"file or directory?\" from the listing alone, which is all\nthat the existence checks of the 104,000 references need. A dropped folder is only listed, too\n(about 2 s for 100,000 files): fetching each of its files (",[101,1272,1273],{},"FileSystemFileEntry.file()",") costs\nabout 180 µs, most of a minute for a library.",[177,1276,1278],{"id":1277},"folders-across-a-reload","Folders across a reload",[98,1280,1281,1282,1045],{},"A browser hands a page the files of a folder for one visit. What a page can keep\n(",[101,1283,1284],{},"apps\u002Fweb\u002Fsrc\u002Fengine\u002Fmemory.ts",[106,1286,1287,1301,1307,1325,1335],{},[109,1288,1289,1292,1293,1296,1297,1300],{},[112,1290,1291],{},"The lists",", with what was typed and ticked and how a scan matches: as text in the\nbrowser's storage for the site, written at once, so that a reload right after a change does\nnot lose it. A folder that comes back as a row only waits to be added again; added again, it\ntakes its place with its settings. Until then a scan does not read it, and a sample that\nlies in it counts as not found. The same holds for a folder the browser kept and wants to\nbe asked for. So the page says which folders are not there before a scan is made, and after\na scan that was made without them it says so on every page, and beside the samples that\nwere not found (",[101,1294,1295],{},"absent"," and ",[101,1298,1299],{},"waiting"," in the library store). (It was not said at first,\nand a library scanned after a reload looked as if its sample folders held nothing.)",[109,1302,1303,1306],{},[112,1304,1305],{},"The lists open when the page knows what it starts with."," Reading the folders of the last\nvisit back takes a browser a moment (its database is asked for the handles). A folder that\nwas added in that moment was put in place, then replaced by the folders that came back, and\nthe list that was noted for the next visit held it alone: the others were gone for good. It\nshowed on a slow machine in Firefox, whose database was asked although it can hold no\nhandle. So nothing is added, and nothing noted, before the engine has said what the page\nstarts with (the lists say \"one moment…\"), and a browser that hands a page no handle is not\nasked for any.",[109,1308,1309,1312,1313,1316,1317,1320,1321,1324],{},[112,1310,1311],{},"A folder's handle",", in the browser's database, where the browser handed one out: for a\nfolder chosen for editing, and for a dropped folder, whose drop offers a handle beside its\nentries in Chromium (",[101,1314,1315],{},"kept"," on a listing). A handle is read again on the next visit once the\nbrowser allows it (",[101,1318,1319],{},"queryPermission",", and ",[101,1322,1323],{},"requestPermission"," in answer to a click); one\nnotice asks for all the folders that wait.",[109,1326,1327,1330,1331,1334],{},[112,1328,1329],{},"A dropped folder is read again through its handle only if that loses nothing."," A handle\nhides entries with some names; the listing of the drop shows them all, so the page knows how\nmany files the handle would cost (",[101,1332,1333],{},"lostBehindHandle","). If any, the folder is not read through\nit: its row says how many files it is about, and asks for the drop again. On a real library\nthat is one folder of five: 3,719 of its 83,993 samples have such a name, or lie below a\nfolder with one.",[109,1336,1337,1340],{},[112,1338,1339],{},"No handle is kept in a private window."," A private window of Chromium (seen in 153) takes\na handle into its database, never answers when the handle is asked back, and from then on\nanswers nothing a page asks about folders (not even about its own file system) until the\nwindow is closed. A page is not told whether its window is private; it sees the room it is\ngiven, which is a share of the computer's memory there and 10 GiB or more elsewhere. Brave\ntells every page the same number and hands handles back in its private windows too (checked\nwith Brave 1.96 itself). Should a browser not answer after all, the page gives its database\none and a half seconds, goes on without, and does not ask again in that tab; and a drop does\nnot wait for a handle that does not come.",[177,1342,175],{"id":1343},"fixing-in-a-browser",[98,1345,1346,1347,1350,1351,1353],{},"Off unless the user switches it on in the Settings (kept in the browser's ",[101,1348,1349],{},"localStorage","), after\na dialog that lists the limits below and wants a tick. Only where the browser has\n",[101,1352,1093],{}," and a private file system for the page (Chrome, Edge).",[106,1355,1356,1384,1394,1408,1421,1427,1433],{},[109,1357,1358,379,1363,115,1366,1369,1370,1372,1373,1376,1377,598,1380,1383],{},[112,1359,1360,1361,141],{},"The same pipeline as ",[101,1362,541],{},[101,1364,1365],{},"fixFolders",[101,1367,1368],{},"packages\u002Fweb\u002Fsrc\u002Fengine\u002Ffix.ts",")\nruns ",[101,1371,490],{}," with the command line's ",[101,1374,1375],{},"applyWriter",", over a host whose write port\n(",[101,1378,1379],{},"WebFsWrite",[101,1381,1382],{},"packages\u002Fweb\u002Fsrc\u002Fwrite.ts",") writes through the handles of the project folders.\nSample folders are never written to. A file appears when its stream is closed (the browser\nwrites a swap file and moves it into place), so there is no half-written set or copy.",[109,1385,1386,1389,1390,1393],{},[112,1387,1388],{},"A project folder is chosen for editing",": the folder dialog with ",[101,1391,1392],{},"readwrite",", or a drop,\nwhose handle can only be read until the user allows more (the browser asks in answer to a\nclick). The page says for every project folder what it may do in it.",[109,1395,1396,1399,1400,1403,1404,1407],{},[112,1397,1398],{},"The run is kept in the page's own storage"," (the origin's private file system, in a folder\n",[101,1401,1402],{},"livesaver","): the journal, written ahead and flushed line by line, the original of every\nrewritten set, the reports, and what was asked (",[101,1405,1406],{},"run.json","), named and laid out as the command\nline's run folders. The History reads it from there, also after a reload. The browser is asked\nto keep the storage when the disk gets full.",[109,1409,1410,1416,1417,1420],{},[112,1411,1412,1413],{},"Undo is the command line's ",[101,1414,1415],{},"undoRun"," over the same ports. It needs the folder the run\nchanged among the folders the page has, at the same path, and refuses before it touches\nanything if a path of the journal lies elsewhere. A page has no Trash: copies that an undo\ntakes out are moved to ",[101,1418,1419],{},".livesaver-trash\u002F\u003Ctime>\u002F…"," in the project folder, which a scan skips\nlike every hidden folder.",[109,1422,1423,1426],{},[112,1424,1425],{},"One run that writes at a time",", across the tabs of the page (Web Locks); a scan does not\nstart while one runs.",[109,1428,1429,1432],{},[112,1430,1431],{},"Places must be known."," A fix writes absolute paths into the sets: of the project, and of a\npack that keeps its large files and Max devices. A project folder, or a folder with the\nFactory Packs or Live's content, that was placed at a stand-in path refuses the fix; the\nreview says so before, and shows where it takes these folders to lie.",[109,1434,1435,1438],{},[112,1436,1437],{},"A set that changed since it was read is not written."," A file behind a handle is fetched\nanew when its state is asked, so a set that Live saved between the reading and the writing is\nnoticed (size and time), as on the command line.",[98,1440,1441],{},"What a page cannot do, and says before the switch goes on:",[182,1443,1444,1455],{},[185,1445,1446],{},[188,1447,1448,1450,1452],{},[191,1449],{},[191,1451,140],{},[191,1453,1454],{},"In a browser",[201,1456,1457,1468,1479,1490,1501,1512,1522,1536,1547],{},[188,1458,1459,1462,1465],{},[206,1460,1461],{},"Live is running",[206,1463,1464],{},"checked, and a fix refuses",[206,1466,1467],{},"cannot be seen: the user confirms it in every review",[188,1469,1470,1473,1476],{},[206,1471,1472],{},"Finder tags and comment of a rewritten set",[206,1474,1475],{},"kept (the file is replaced through a clone)",[206,1477,1478],{},"lost: the browser's write makes a new file",[188,1480,1481,1484,1487],{},[206,1482,1483],{},"time of a copied sample",[206,1485,1486],{},"that of its source",[206,1488,1489],{},"that of the copying (the set says the same)",[188,1491,1492,1495,1498],{},[206,1493,1494],{},"date of a rewritten set",[206,1496,1497],{},"that of the fix; an undo puts the old one back",[206,1499,1500],{},"that of the fix; an undo cannot put the old one back",[188,1502,1503,1506,1509],{},[206,1504,1505],{},"what an undo takes out",[206,1507,1508],{},"the Trash",[206,1510,1511],{},"a hidden folder in the project folder",[188,1513,1514,1517,1520],{},[206,1515,1516],{},"free space",[206,1518,1519],{},"checked",[206,1521,952],{},[188,1523,1524,1530,1533],{},[206,1525,1526,1527,1529],{},"names with ",[101,1528,1127],{},", or a space at an end",[206,1531,1532],{},"seen and written",[206,1534,1535],{},"seen if the folder was dropped (or is listed by a folder around it), otherwise left alone as \"not shown by the browser\"; never made: a copy goes elsewhere in the project, or the reference is left with the reason",[188,1537,1538,1541,1544],{},[206,1539,1540],{},"what an undo needs",[206,1542,1543],{},"livesaver's state folder",[206,1545,1546],{},"the browser's storage for the site: cleared with the site's data",[188,1548,1549,1551,1554],{},[206,1550,938],{},[206,1552,1553],{},"what is installed is looked up; upgrade, with undo",[206,1555,1556],{},"what is installed is what the page was shown; upgrade, with undo, once that includes Live's plug-in database",[98,1558,1559,1562],{},[112,1560,1561],{},"What goes to a worker is made anew."," A fix and an upgrade run in a worker, and are told which\nprojects or plug-ins were chosen. An app keeps such choices in a state that wraps them (Vue's\ndoes), and a browser refuses to send a wrapped object to a worker: the engine sends copies. (A\nfix of one project failed on that until a test went through the app's state instead of calling\nthe engine directly.)",[177,1564,948],{"id":1565},"what-is-installed-in-a-browser",[98,1567,1568,1569,679,1572,975],{},"A page cannot look for plug-ins, but it can be shown them: the Settings take folders that say\nwhat is installed (",[101,1570,1571],{},"installedIn",[101,1573,1574],{},"packages\u002Fweb\u002Fsrc\u002Fengine\u002Finstalled.ts",[106,1576,1577,1600,1617,1637,1643,1649,1659,1665],{},[109,1578,1579,115,1582,1585,1586,598,1589,127,1592,1595,1596,1599],{},[112,1580,1581],{},"A plug-in folder",[101,1583,1584],{},"\u002FLibrary\u002FAudio\u002FPlug-Ins",", or a folder above it): its ",[101,1587,1588],{},"VST3",[101,1590,1591],{},"VST",[101,1593,1594],{},"Components"," folders are read as the command line reads them (",[101,1597,1598],{},"loadInventory","), with the\nprocessors each bundle is built for.",[109,1601,1602,115,1605,1608,1609,1612,1613,1616],{},[112,1603,1604],{},"The folder of Live's plug-in database",[101,1606,1607],{},"Live Database","): ",[101,1610,1611],{},"Live-plugins-*.db"," says which\nplug-ins Live scanned, by their ids and per processor. Without it a plug-in is known only if\nits bundle says which one it is (an Audio Unit; a VST3 with a ",[101,1614,1615],{},"moduleinfo.json","), and the\npage says that the database is missing.",[109,1618,1619,1622,1623,1626,1627,1629,1630,679,1633,1636],{},[112,1620,1621],{},"The database is read as a file."," A page has no SQLite. ",[101,1624,1625],{},"readSqliteTable"," in\n",[101,1628,826],{}," reads a table from the file format itself (table b-trees, overflow pages,\nthe row id that stands in for an integer key), and takes the write-ahead log beside the\ndatabase into account: while Live runs, what it scanned last is only in there.\n",[101,1631,1632],{},"parsePluginDatabase",[101,1634,1635],{},"@livesaver\u002Fplugins"," is the query the command line runs in SQL. On\na real database both give the same rows (269 plug-ins, 288 modules).",[109,1638,1639,1642],{},[112,1640,1641],{},"Where the plug-in folder lies"," a browser does not say, and the database names bundles by\ntheir paths: the folder is placed where most of those paths lead into it.",[109,1644,1645,1648],{},[112,1646,1647],{},"The Audio Units of macOS itself"," lie in a system folder a page is not given: one that a\nset uses is taken to be there.",[109,1650,1651,1654,1655,1658],{},[112,1652,1653],{},"The upgrade to VST3"," is the command line's ",[101,1656,1657],{},"upgradePlugins"," over the write port of a fix\nin the page, with the VST3 plug-ins Live knows taken from the database folder: without that\nfolder there is no upgrade, and the page says what it needs. The run is kept and undone like\na fix. An upgrade writes no path into a set, so it does not ask where the folders lie.",[109,1660,1661,1664],{},[112,1662,1663],{},"A plan that could not be made is made again after the next scan",": what stood in its way\n(no database folder) may have been added since.",[109,1666,1667,1670],{},[112,1668,1669],{},"On a real Mac",", read-only: shown its two plug-in folders (13,700 files) and Live's database\nfolder, this code finds what the command line finds of the same folders: 354 plug-ins in\nthree formats, each with the same id, place and processors, and the same 70 VST3 plug-ins\nLive knows. It takes a quarter of a second, once the browser has listed the folders.",[177,1672,1674],{"id":1673},"where-a-folder-lies-on-disk","Where a folder lies on disk",[98,1676,1677],{},"A browser never tells a page a folder's path, but sets store absolute paths, and those are\ncompared with the folders' paths.",[106,1679,1680,1686,1692,1712,1726],{},[109,1681,1682,1685],{},[112,1683,1684],{},"Project folders"," are located from the sets: a reference stored relative to its project also\nnames the file by an absolute path, which says where the project was when the set was saved.\nThe folder is the one with its name in that path. Projects moved inside the folder since then\ndo not matter; if the folder itself was renamed, its location is unknown.",[109,1687,1688,1691],{},[112,1689,1690],{},"Sample folders"," that hold a project folder, or lie directly in one, are placed by it.",[109,1693,1694,1697,1698,679,1701,1704,1705,1707,1708,1711],{},[112,1695,1696],{},"Ableton's own folders"," (the Live app or one of its folders down to the Core Library, the\nUser Library, the Factory Packs, or the folder that holds those two) are placed by the paths\nthe sets store for files in them (",[101,1699,1700],{},"leadsTo",[101,1702,1703],{},"packages\u002Fweb\u002Fsrc\u002Flocate.ts","): a stored path\ncounts if it names the folder by its name and the file it names is in the folder. Live finds\nwhat lies in these folders by its own rules whatever the stored path says, so a stale path\ndoes no harm here, and a fix that names such a folder in a set should name it as Live would.\nSets of older Lives name the app of their time: the sets of the newest Live decide, and more\nsets are read (up to 48) while only older ones gave a lead. On a real library the app's\n",[101,1706,1153],{}," folder and ",[101,1709,1710],{},"Music\u002FAbleton"," are placed this way, in two seconds.",[109,1713,1714,1717,1718,598,1720,1722,1723,975],{},[112,1715,1716],{},"A path that is typed for a folder of the Live app"," may be any path into the app (the app,\nits ",[101,1719,1153],{},[101,1721,1145],{}," or the Core Library): asked where \"Contents\" lies, one pastes\nthe path of the app. The folder is placed at its own path in that app (",[101,1724,1725],{},"liveFolderPath",[109,1727,1728,1729,1732],{},"Every other folder gets a stand-in path (",[101,1730,1731],{},"\u002F\u003Cname>","), unless the user types its path. For a\nfolder of the user's, other stored paths are no evidence: a path that no longer exists would\nmove a folder to a place where it is not, and the missing file would then seem to exist,\nunchecked.",[98,1734,1735],{},"With a stand-in path, a file that a set references by an absolute path into that folder is not\n\"outside the project\" but \"missing\", and is found again by name and fingerprint: the result is\nthe same repair, counted in another row.",[177,1737,1696],{"id":1738},"abletons-own-folders",[98,1740,1741,1742,1745],{},"Recognised by name among the given folders (",[101,1743,1744],{},"packages\u002Fweb\u002Fsrc\u002Fengine\u002Fableton.ts","), and named on\ntheir rows as soon as a folder is added; what is still missing is listed under the sample\nfolders.",[106,1747,1748,1760],{},[109,1749,1750,1296,1753,1756,1757,1759],{},[112,1751,1752],{},"User Library",[112,1754,1755],{},"Factory Packs",": a folder of that name, or the folder that holds it\n(",[101,1758,1710],{}," in the home folder).",[109,1761,1762,1765,1766,1769,1770,1773,1774,679,1776,1778,1779,1781,1782,1784,1785,1787],{},[112,1763,1764],{},"Live's own content"," lies inside the Live app, in ",[101,1767,1768],{},"Contents\u002FApp-Resources",": the Core Library,\nand Live's table of content it moved between versions (",[101,1771,1772],{},"Database\u002Ffilerefmap.db",", a SQLite file\nread by ",[101,1775,1625],{},[101,1777,826],{},"). The Live app itself can be dropped on the\npage: to a drop an app is a folder, while a folder dialog does not open one (there the path of\n",[101,1780,1145],{}," has to be pasted). ",[101,1783,1145],{},", the app's ",[101,1786,1153],{}," folder or the Core\nLibrary alone are recognised too. Of the app only the Core Library is searched.",[98,1789,1790],{},"Without Live's own content, samples of the Core Library cannot be found and moved content is not\nrecognised; the result says so. On a real library that made 55 of 460 complete sets look\nincomplete.",[177,1792,1794],{"id":1793},"windows","Windows",[98,1796,1797,1798,975],{},"Built from what Ableton documents and from sets saved on Windows; not tried on a Windows\ncomputer (see ",[137,1799,1801],{"href":1800},"guide\u002Fwindows","the guide",[106,1803,1804,1820,1844,1876,1886],{},[109,1805,1806,379,1809,115,1812,1815,1816,1819],{},[112,1807,1808],{},"Which system it is.",[101,1810,1811],{},"onWindows()",[101,1813,1814],{},"packages\u002Fweb\u002Fsrc\u002Fplatform.ts",") reads the browser's user\nagent. The page asks it once and sends the answer with every request (",[101,1817,1818],{},"ScanRequest.windows","),\nso the engine's worker need not be asked. With livesaver behind it, the page runs on the\ncomputer livesaver runs on, so the same answer says how that computer names its folders.",[109,1821,1822,1825,1826,1828,1829,1832,1833,1836,1837,1156,1840,679,1842,975],{},[112,1823,1824],{},"Paths."," Every path is handled with ",[101,1827,394],{},", a drive is a root of its own (",[101,1830,1831],{},"C:\u002FUsers\u002F…","), and a\ntyped path may be written with ",[101,1834,1835],{},"\\",". A folder is placed by the paths the sets store that fit\nthe system: paths with a drive on Windows, paths without one elsewhere (",[101,1838,1839],{},"locateFolder",[101,1841,1700],{},[101,1843,1703],{},[109,1845,1846,1849,1850,1853,1854,1857,1858,598,1860,1863,1864,696,1866,1869,1870,1873,1874,975],{},[112,1847,1848],{},"Ableton's folders."," Live's own content is the folder ",[101,1851,1852],{},"Resources"," of\n",[101,1855,1856],{},"C:\u002FProgramData\u002FAbleton\u002FLive \u003Cn> \u003CEdition>","; given that folder, the one above it, or the Core\nLibrary alone, the page places it as there (",[101,1859,1725],{},[101,1861,1862],{},"liveLandmark","). No handle is\nasked for a dropped folder called ",[101,1865,1852],{},[101,1867,1868],{},"Live \u003Cn> …"," on Windows: Chromium keeps the\nfolders of ",[101,1871,1872],{},"ProgramData"," from a page as it keeps an app's on a Mac (",[101,1875,1149],{},[109,1877,1878,1881,1882,1885],{},[112,1879,1880],{},"Plug-ins."," Only Live's plug-in database is read (",[101,1883,1884],{},"installedIn(folders, true)","): its rows\ncount without a look at a file, since a plug-in on Windows lies where a page is not given a\nfolder and its file says nothing livesaver reads; no row is \"Rosetta only\"; no Audio Unit is\ntaken to be there.",[109,1887,1888,379,1891,1894,1895,1898],{},[112,1889,1890],{},"Words.",[101,1892,1893],{},"apps\u002Fweb\u002Fsrc\u002Flib\u002Fplatform.ts"," holds what the page says differently: the folders'\nplaces, File Explorer for Finder, the steps to add Live's content (",[101,1896,1897],{},"LiveGuideWindows.vue","),\nand a note that Windows is only tested on macOS.",[177,1900,1902],{"id":1901},"installed-libraries","Installed libraries",[98,1904,1905,1906,1909,1910,1156,1913,598,1916,1919],{},"Two rules only apply to files of installed libraries: a file that its vendor re-saved slightly\nlarger is accepted when the audio is the same, and the opt-in rule that accepts a library file\nby its name and place in the library. The command line knows ",[101,1907,1908],{},"\u002FUsers\u002FShared"," (Native\nInstruments) as such a place. The page cannot see that path, so each sample folder has a box,\n\"Contains installed libraries\", ticked when the folder is called like one (",[101,1911,1912],{},"Shared",[101,1914,1915],{},"Native Instruments",[101,1917,1918],{},"… Library","). Ableton's packs and the Core Library always count. If the\nopt-in rule is switched on while no folder is marked, the page says that it will find nothing\nthere.",[177,1921,1923],{"id":1922},"on-its-own-what-differs-from-the-command-line","On its own: what differs from the command line",[106,1925,1926,1933,1936,1939,1942],{},[109,1927,1928,1929,1932],{},"A scan is read-only: nothing is collected or rewritten, and patched sets are only counted,\nnot scanned strictly (",[101,1930,1931],{},"quickPlan","). (A fix in the browser scans every set it writes strictly,\nlike the command line.)",[109,1934,1935],{},"Plug-ins: which are used and where. Whether they are installed only once the page was shown\nthe folders that say so.",[109,1937,1938],{},"Only the given folders are seen. The command line sees the whole disk.",[109,1940,1941],{},"Symbolic links are not seen: a browser leaves them out of a dropped folder. The command line\nindexes links to files.",[109,1943,1944],{},"No preferred folders for ties between identical copies, no cache of complete sets.",[177,1946,1948],{"id":1947},"how-it-is-tested","How it is tested",[106,1950,1951,1966,1975,1981,1987,2092,2101],{},[109,1952,1953,1956,1957,1959,1960,1962,1963,1965],{},[101,1954,1955],{},"packages\u002Fweb\u002Ftest",": ",[101,1958,1108],{}," over fake handles, uploads and listings; a ",[101,1961,490],{}," run over the\nbrowser host equals a run over the Node host on the fixtures; the scan (locating, Ableton's\nfolders and where they lie by what the sets store, the Live app given as a folder, the remap\ntable, the plug-ins, the shaped result);\nand the conversation between the page and the engine's worker. Writing through handles\n(",[101,1964,1379],{},") over folders in memory that behave like a browser's; a fix through them\nagainst the command line's pipeline on the same fixtures (the same references in the set,\nthe same files with the same content), its run in the page's storage, its undo byte for\nbyte, and what it refuses. What is installed, from folders handed to a page, against the\ninventory the command line makes of the same folders; an upgrade of plug-ins through handles\nagainst the command line's pipeline (the same set, byte for byte), and its undo.",[109,1967,1968,598,1971,1974],{},[101,1969,1970],{},"packages\u002Fcore\u002Ftest",[101,1972,1973],{},"packages\u002Fplugins\u002Ftest",": Live's plug-in database read from its file,\nagainst SQLite on the same file: with rows that overflow a page, tables of several levels,\nand a write-ahead log that holds what the database does not have yet (also with a log from\nan earlier state, and one that ends in the middle of a change).",[109,1976,1977,1980],{},[101,1978,1979],{},"packages\u002Fcli\u002Ftest",": what the page asks of this computer, on temporary copies of the fixtures:\na check, a scan, a fix of all, of some and of one project, with and without the uncertain\nmatches, an upgrade of plug-ins, undo, the history and its reports, and that the server\nanswers only its own page.",[109,1982,1983,1986],{},[101,1984,1985],{},"apps\u002Fweb\u002Ftest",": the two engines against one suite (see above); the stores (library, scan,\nreview, fix, undo, the history, a page that is opened again) against both engines; the app's\nown sums and words (states, plans, advice, what a run was and what its undo does). The\nfolders across a reload, over a memory that is a list: what is kept, what waits for the\nbrowser's OK, what is to be added again and takes its settings back. In a\nbrowser that lets a page edit folders: one project fixed alone through the app's state, the\nfolders that say what is installed, and an upgrade that is planned, written and taken back.",[109,1988,1989,1992,1993],{},[101,1990,1991],{},"bun run test:web",": the built app in Playwright's Chromium, WebKit and Firefox, 270 tests.\n",[106,1994,1995,1998,2001,2004,2007,2010,2017,2024,2033,2036,2042,2056,2059,2062,2069,2076,2079,2089],{},[109,1996,1997],{},"On its own: folders through the folder upload and by drops (with names a handle would hide,\nand an app as a folder; drops only in Chromium, which lets a test drop a folder), the\noverview, the tabs with search and filters, the side panels, a downloaded report, the hints.",[109,1999,2000],{},"With livesaver: a folder chosen in the page, a fix of one project after its review, undo, a\nselection fixed in one run, all fixed, the scan and the last fix still there after a reload,\nthe uncertain matches left out; the files on disk are compared each time.",[109,2002,2003],{},"Plug-ins: the set Live saved with VST2 and VST3 devices is upgraded after a review and\nundone, byte for byte; what the sets use against a made-up set of installed plug-ins, and\nwhat breaks if one is uninstalled; on its own, the app says what it cannot know there.",[109,2005,2006],{},"The history: runs from before (a plan of the command line, a run of an older version), a\nfix made on another page with the undo in its toast, every run with its details, a report\ndownloaded, a step shown in Finder, an undo that asks first and is then seen everywhere.",[109,2008,2009],{},"The settings: what livesaver found, a folder shown in Finder, the reset to the command\nline's settings; what every page says when livesaver is gone, or was started again.",[109,2011,2012,2013,2016],{},"The first steps, in the three engines (",[101,2014,2015],{},"onboarding.e2e.ts","): what the page says about\nhanding it a folder, with what only a browser with handles is told; the steps to add the\nLive app, in pictures, in light and dark; after a scan the folders on the overview, where\none is added and the library scanned again without leaving the page; a scan started in the\nSettings, which goes to the overview; an old save of a project that is left out by the\noption, from the hint in the project's panel to the scan that says how many sets it left\nout. With livesaver behind the app, the same option leaves the same set out.",[109,2018,2019,2020,2023],{},"The folders across a reload, with the browser's own database: in the three engines the\nlists with what was typed and ticked, a folder that is added again, one that is removed.\nIn Chromium with a profile that is kept (a context of Playwright is a private window): a\nproject folder chosen for editing is back and scanned; a dropped folder of the disk is\nback, and the test browser refuses when asked for it; one with names a kept folder would\nhide waits to be dropped again. In a private window no handle is kept, the page comes up\nat once, and its folder access keeps answering. ",[112,2021,2022],{},"That a person's browser asks, and reads\nthe folder once allowed, is not covered by a test","; it was seen in Brave itself, run with\na profile of its own.",[109,2025,2026,2027,2029,2030,2032],{},"Where Ableton's own folders lie, in the three engines: the Live app's ",[101,2028,1153],{}," folder and\n",[101,2031,1710],{}," are placed by what the sets store, and a path typed for the app's folder\nmay be any path into the app. In Chromium, the review of a fix in the page shows those\nplaces and is ready without a path being typed.",[109,2034,2035],{},"What is installed, shown to a page, in the three engines: what the page says without the\nfolders, with the plug-in folder alone, and with Live's database, where it says what\nlivesaver says of the same plug-ins. In Chromium, an upgrade to VST3 that the page makes\nitself: what it needs first, its plan, the review, and the set it writes against the set\nlivesaver writes for the same project on disk; the history, and the undo.",[109,2037,2038,2039,2041],{},"Fixing in the page (Chromium): the switch and its dialog, a folder that can only be read,\na folder of the disk that is dropped (read through its handle at once, and refused for\nediting by the test browser, which the page says), a fix after the review, compared with\nwhat ",[101,2040,134],{}," writes on the same projects on disk (the same references,\nthe same copies, the same backup), the history, the undo, one project fixed from the list\nof projects and taken back, a reload. WebKit and Firefox say\nthat they cannot. No test browser lets a page write to a folder of the disk without a\nperson saying yes (the headless one refuses, the full one waits for its prompt), and the\nfolder dialog cannot be driven: the project folder that is fixed in this test lies in the\nbrowser's private file system, behind the same handles.",[109,2043,2044,2045,2048,2049,2052,2053],{},"Fixing in a folder of the disk (",[101,2046,2047],{},"disk.e2e.ts",", Chromium as it is installed for people):\n\"allow on every visit\" is a setting of the browser for a site, so a profile is given that\nsetting before the browser starts with it (the guards of the File System Access API in\nits ",[101,2050,2051],{},"Preferences","), and the page is let in as it is for such a user. The folder is a\ntemporary one, with the browser's real rules for names: dropped to be edited, it is read\nin full, the fix writes the set, its copy and its backup to the disk, and the undo puts\nthem back; chosen \"in the dialog\" (the test answers the dialog with the handle of a drop),\nthe sample the handle hides is left alone and said to be, the fix fails for no set, and\nthe folder dropped as well shows the sample. ",[112,2054,2055],{},"The prompt itself, and the folder dialog,\nare not covered by a test.",[109,2057,2058],{},"A library of real size (299 projects, 876 sets, 9,305 planned changes, 2,243 missing\nsamples, 199 plug-ins; made up from a small real scan): a table builds fewer than 80 rows,\nscrolls to its end without a frame of half a second, and is sorted and searched at once.",[109,2060,2061],{},"The whole flow from scan to undo with the keyboard alone, the keys of the tables, and an\nundo from the history; no barrier that axe can find on any screen, in light and dark; no\nerror in the page; no request to another address; no motion for who asked for less.",[109,2063,2064,2065,2068],{},"The tests load the production build: a test runner's ",[101,2066,2067],{},"NODE_ENV"," would otherwise make Vite\nbuild Vue's development version.",[109,2070,2071,2072,2075],{},"Whether Live runs is told to the server by each test (",[101,2073,2074],{},"liveRunning","), so the tests do not\ndepend on the machine they run on; told that it runs, the review does not let a fix start,\nand an undo is refused.",[109,2077,2078],{},"A page from one address connected to livesaver at another: the pairing link, a fix and\nits undo across the two, a reload that stays connected, disconnecting; a livesaver that was\nnot started for pairing, and one of another version.",[109,2080,2081,2082,2084,2085,2088],{},"How a page can fix: what each engine is told about itself (the two ways, and a pairing\nlink that is pasted into a tab that is open), and what Brave is told. Brave cannot be driven\nby a test: it is made up in Chromium by what tells it apart (",[101,2083,779],{},", and no\nfolder to edit). Its two steps with the addresses to copy, a connection it keeps back, and\nthe app at livesaver's own address one link away. ",[112,2086,2087],{},"Whether Brave's own settings then let\nthe page through is not covered by a test","; it is tried by hand.",[109,2090,2091],{},"What a test waits for gets three times as long on a CI, whose machines are slower in\nspurts.",[109,2093,2094,2097,2098,2100],{},[101,2095,2096],{},"bun run test:node",": the built ",[101,2099,118],{}," under Node.js serves the app it ships with.",[109,2102,2103,2104],{},"On a real library (876 sets, 138,662 indexed files), read-only:\n",[106,2105,2106,2116,2131,2137],{},[109,2107,2108,2109,2111,2112,2115],{},"A scan in the app takes 13 s and shows the numbers of the command line: what ",[101,2110,490],{},"\ncounts, and for a fix without the uncertain matches what ",[101,2113,2114],{},"doctor --certain-only"," counts.",[109,2117,2118,2119,2121,2122,2124,2125,2127,2128,141],{},"A scan equals the three commands it stands for: its report files those of ",[101,2120,842],{},",\nits 199 plug-ins (order, state, instances, sets) those of ",[101,2123,811],{},", and its upgrade\nplan (386 rows) that of ",[101,2126,528],{},". The plug-in screens show these numbers, and the\n257 installed plug-ins of ",[101,2129,2130],{},"plugins list",[109,2132,2133,2134,2136],{},"On its own, given the project folder and the folders the command line searches with their\npaths typed, the report files are byte-identical to those of ",[101,2135,126],{},", apart from\nthe time stamp; with the Live app dropped and no path typed, the numbers equal the command\nline's. (Measured with the page this app replaced; the engine is the same code.)",[109,2138,2139],{},"Fixing is never tried there: it is tested on temporary copies.",{"title":2141,"searchDepth":2142,"depth":2142,"links":2143},"",2,[2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159],{"id":179,"depth":2142,"text":180},{"id":422,"depth":2142,"text":140},{"id":712,"depth":2142,"text":713},{"id":802,"depth":2142,"text":505},{"id":858,"depth":2142,"text":859},{"id":978,"depth":2142,"text":159},{"id":1037,"depth":2142,"text":1038},{"id":1277,"depth":2142,"text":1278},{"id":1343,"depth":2142,"text":175},{"id":1565,"depth":2142,"text":948},{"id":1673,"depth":2142,"text":1674},{"id":1738,"depth":2142,"text":1696},{"id":1793,"depth":2142,"text":1794},{"id":1901,"depth":2142,"text":1902},{"id":1922,"depth":2142,"text":1923},{"id":1947,"depth":2142,"text":1948},"md",{},true,{"title":86,"description":87},"docs\u002Fweb","prh2VzjcrtgTYVslmjBA1Hj9ulVqIlLhTcf3rZMFbjc",1791245843399]