Files
Barış Keser 1d3ef6a0b7 v1.0.2: htdemucs studio karaoke (CPU) + responsive fix + ozel select CSS + tek tikla indirme
- Studyo karaoke (yeni justmusic/separation.py): Demucs htdemucs ile gercek
  vokal/enstruman ayirma, YALNIZCA CPU. Enstrumantal (karaoke) / Akapella
  (sadece vokal) / hizli mid-side / kapali secenekleri mikrofon dugmesindeki
  menude. Stem'ler ~/Music/JustMusic/stems/<hash>/ altinda onbellege alinir, yani
  ayni sarki bir daha ayrilmaz. Ilk ayirma ~4-5 dk/sarki (olculdu: 258s), ilerleme
  gosterilir. engine.swap_source() ile gecis CALDIGI SANIYEYI KORUR ve DSP
  efektleri stem'e de uygulanir.
- Kucuk ekran: player kontrolleri artik cakismiyor. Kademeli responsive
  (1140/1010/900px) ile nis kontroller gizlenir; olcum: 980px ve 900px'te sifir
  cakisma, yatay tasma yok. Pencere alt siniri 1120 -> 900.
- Native select'ler tamamen ozel: appearance:none + kendi SVG chevron'u,
  hover/focus halkasi, ozel option renkleri (tarayici oku kalmadi).
- YouTube aramasi: satira tiklayinca ANINDA iner (her satirda ayrica indir
  dugmesi). Checkbox + toplu indirme butonu secim akisi olarak korundu.
- Fix: karaoke menusu acilir acilmaz kapaniyordu. Global disari-tikla-kapat
  dinleyicisi butonun kendi tiklamasini yakaliyordu (stopPropagation ile cozuldu).
- Paketleme: torch + demucs exe'ye gomuldu (kullanici tercihi). Donmus derlemede
  dogrulandi: demucs=True, UI yuklendi, toplam 1391 MB.
2026-07-18 09:00:50 +03:00

107 lines
3.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Just Music Premium — QtWebEngine giriş noktası."""
from __future__ import annotations
import sys
from PyQt6.QtCore import QEvent, QObject, QUrl
from PyQt6.QtWebEngineCore import QWebEngineUrlScheme
from justmusic import config
def _register_scheme() -> None:
"""app:// şemasını QApplication'DAN ÖNCE kaydeder."""
scheme = QWebEngineUrlScheme(config.SCHEME)
scheme.setSyntax(QWebEngineUrlScheme.Syntax.Host)
# LocalScheme YOK: sayfa "secure" origin olur -> uzaktan (ytimg) kapaklar yüklenir
scheme.setFlags(
QWebEngineUrlScheme.Flag.SecureScheme
| QWebEngineUrlScheme.Flag.LocalAccessAllowed
| QWebEngineUrlScheme.Flag.CorsEnabled
)
QWebEngineUrlScheme.registerScheme(scheme)
_register_scheme()
class DragDropFilter(QObject):
"""Pencereye bırakılan ses dosyalarını yakalar (web view'e gitmeden)."""
def __init__(self, bridge) -> None:
super().__init__()
self.bridge = bridge
def eventFilter(self, obj, event) -> bool: # noqa: N802
et = event.type()
if et in (QEvent.Type.DragEnter, QEvent.Type.DragMove):
md = event.mimeData()
if md and md.hasUrls():
event.acceptProposedAction()
return True
elif et == QEvent.Type.Drop:
md = event.mimeData()
if md and md.hasUrls():
paths = [u.toLocalFile() for u in md.urls() if u.toLocalFile()]
if paths:
self.bridge.import_paths(paths)
event.acceptProposedAction()
return True
return False
def main() -> int:
from PyQt6.QtGui import QIcon
from PyQt6.QtWebChannel import QWebChannel
from PyQt6.QtWebEngineWidgets import QWebEngineView
from PyQt6.QtWidgets import QApplication, QMainWindow
from justmusic.bridge import Bridge
from justmusic.scheme import AppSchemeHandler, configure_page
config.ensure_dirs()
app = QApplication(sys.argv)
app.setApplicationName(config.APP_NAME)
if config.LOGO_PNG.exists():
app.setWindowIcon(QIcon(str(config.LOGO_PNG)))
class MainWindow(QMainWindow):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle(config.APP_NAME)
self.resize(1460, 920)
self.setMinimumSize(900, 600) # küçük ekran: responsive CSS devreye girsin
self._bridge = None
def closeEvent(self, event): # noqa: N802
if self._bridge:
self._bridge.shutdown()
super().closeEvent(event)
win = MainWindow()
view = QWebEngineView(win)
handler = AppSchemeHandler(view)
view.page().profile().installUrlSchemeHandler(config.SCHEME, handler)
configure_page(view.page())
bridge = Bridge(win, win)
win._bridge = bridge
channel = QWebChannel(view.page())
channel.registerObject("bridge", bridge)
view.page().setWebChannel(channel)
drop_filter = DragDropFilter(bridge)
app.installEventFilter(drop_filter)
win.setCentralWidget(view)
view.load(QUrl("app://app/index.html"))
win.show()
exit_code = app.exec()
return exit_code
if __name__ == "__main__":
sys.exit(main())