Spaces:
Running on Zero
Running on Zero
| """ABC notation utilities: MusicXML conversion and HTML visualization.""" | |
| import html as html_module | |
| import json | |
| import os | |
| import subprocess | |
| import tempfile | |
| from config import ABC2XML_PATH, APP_DIR | |
| def abc_to_musicxml_file(abc: str): | |
| """Convert ABC to MusicXML using abc2xml.py; return file path for download or None.""" | |
| if not (abc or "").strip(): | |
| return None | |
| try: | |
| result = subprocess.run( | |
| [os.environ.get("PYTHON", "python"), ABC2XML_PATH, "-"], | |
| input=(abc or "").strip().encode("utf-8"), | |
| capture_output=True, | |
| cwd=APP_DIR, | |
| timeout=30, | |
| ) | |
| if result.returncode != 0 or not result.stdout: | |
| return None | |
| xml_bytes = result.stdout | |
| if isinstance(xml_bytes, bytes): | |
| xml_str = xml_bytes.decode("utf-8", errors="replace") | |
| else: | |
| xml_str = xml_bytes | |
| tmpdir = tempfile.mkdtemp(prefix="musicxml_") | |
| score_path = os.path.join(tmpdir, "score.musicxml") | |
| try: | |
| with open(score_path, "w", encoding="utf-8") as f: | |
| f.write(xml_str) | |
| return score_path | |
| except Exception: | |
| try: | |
| os.unlink(score_path) | |
| except Exception: | |
| pass | |
| try: | |
| os.rmdir(tmpdir) | |
| except Exception: | |
| pass | |
| return None | |
| except Exception: | |
| return None | |
| def abc_viz_html(abc: str) -> str: | |
| """Generate HTML with ABCJS for rendering ABC notation in Gradio.""" | |
| viz_abc = abc or "" | |
| data_attr = html_module.escape(json.dumps(viz_abc), quote=True) | |
| # Gradio strips <script> in gr.HTML; use iframe srcdoc so ABCJS runs inside the frame. | |
| inner = ( | |
| '<!DOCTYPE html><html><head><meta charset="utf-8">' | |
| '<style>body{overflow:auto;margin:0;} #abc-viz{width:100%;}</style></head><body>' | |
| '<div id="abc-viz" data-abc="' + data_attr + '"></div>' | |
| '<script src="https://cdnjs.cloudflare.com/ajax/libs/abcjs/6.4.0/abcjs-basic-min.js"><\x2fscript>' | |
| '<script>' | |
| '(function(){ var el=document.getElementById("abc-viz"); if(!el) return; ' | |
| 'var run=function(){ try { var abc=JSON.parse(el.getAttribute("data-abc")); ' | |
| 'if(typeof ABCJS!=="undefined"&&abc) ABCJS.renderAbc("abc-viz",abc,{responsive:"resize"}); } catch(e){ el.innerHTML="<span>Invalid ABC</span>"; } }; ' | |
| 'if(typeof ABCJS!=="undefined") run(); else { var s=document.createElement("script"); ' | |
| 's.src="https://cdnjs.cloudflare.com/ajax/libs/abcjs/6.4.0/abcjs-basic-min.js"; s.onload=run; document.head.appendChild(s); } })();' | |
| '<\x2fscript></body></html>' | |
| ) | |
| srcdoc_escaped = inner.replace("&", "&").replace('"', """) | |
| return '<iframe sandbox="allow-scripts" title="ABC notation" style="width:100%;height:60vh;max-height:400px;display:block;" srcdoc="' + srcdoc_escaped + '"></iframe>' | |