Skip to content

Commit

Permalink
Merge branch 'master' into sanic-no-motd
Browse files Browse the repository at this point in the history
  • Loading branch information
cosven authored Jan 9, 2025
2 parents 0181381 + 9a917b6 commit 8aeb256
Show file tree
Hide file tree
Showing 9 changed files with 286 additions and 116 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
if: startsWith(matrix.os, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get -y install libmpv1
sudo apt-get -y install libmpv2
- name: Install macOS Dependencies
if: startsWith(matrix.os, 'macos')
Expand Down
3 changes: 3 additions & 0 deletions feeluown/entry_points/run_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ def before_start_app(args):
# Run.
#
if AppMode.gui in AppMode(config.MODE):
# Disable sandbox so that webpage can be loaded (in some cases)
# https://stackoverflow.com/a/74325318/4302892
os.environ.setdefault('QTWEBENGINE_DISABLE_SANDBOX', '1')
if sys.platform == 'win32':
# Enable auto scale by default so that it can work well with HiDPI display.
os.environ.setdefault('QT_AUTO_SCREEN_SCALE_FACTOR', '1')
Expand Down
15 changes: 13 additions & 2 deletions feeluown/gui/components/player_playlist.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from typing import TYPE_CHECKING

from PyQt5.QtCore import Qt, QModelIndex, QItemSelectionModel
from PyQt5.QtWidgets import QMenu, QAbstractItemView

from feeluown.player import PlaylistMode
from feeluown.gui.components import SongMenuInitializer
from feeluown.gui.helpers import fetch_cover_wrapper
from feeluown.gui.widgets.song_minicard_list import (
Expand All @@ -10,6 +13,10 @@
from feeluown.utils.reader import create_reader


if TYPE_CHECKING:
from feeluown.app.gui_app import GuiApp


class PlayerPlaylistModel(SongMiniCardListModel):
"""
this is a singleton class (ensured by PlayerPlaylistView)
Expand Down Expand Up @@ -51,7 +58,7 @@ class PlayerPlaylistView(SongMiniCardListView):

_model = None

def __init__(self, app, *args, **kwargs):
def __init__(self, app: 'GuiApp', *args, **kwargs):
super().__init__(*args, **kwargs)
self._app = app

Expand All @@ -70,7 +77,11 @@ def contextMenuEvent(self, e):

songs = [index.data(Qt.UserRole)[0] for index in indexes]
menu = QMenu()
action = menu.addAction('从播放队列中移除')
if self._app.playlist.mode is PlaylistMode.fm:
btn_text = '不想听'
else:
btn_text = '从播放队列中移除'
action = menu.addAction(btn_text)
action.triggered.connect(lambda: self._remove_songs(songs))
if len(songs) == 1:
menu.addSeparator()
Expand Down
28 changes: 24 additions & 4 deletions feeluown/gui/uimain/playlist_overlay.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
QColor, QLinearGradient, QPalette, QPainter,
)

from feeluown.player import PlaybackMode
from feeluown.player import PlaybackMode, SongsRadio
from feeluown.gui.helpers import fetch_cover_wrapper, esc_hide_widget
from feeluown.gui.components.player_playlist import PlayerPlaylistView
from feeluown.gui.widgets.textbtn import TextButton
Expand Down Expand Up @@ -45,10 +45,14 @@ def __init__(self, app, *args, **kwargs):
self._clear_playlist_btn = TextButton('清空播放队列')
self._playback_mode_switch = PlaybackModeSwitch(app)
self._goto_current_song_btn = TextButton('跳转到当前歌曲')
self._songs_radio_btn = TextButton('自动续歌')
# Please update the list when you add new buttons.
self._btns = [self._clear_playlist_btn,
self._playback_mode_switch,
self._goto_current_song_btn]
self._btns = [
self._clear_playlist_btn,
self._playback_mode_switch,
self._goto_current_song_btn,
self._songs_radio_btn,
]
self._stacked_layout = QStackedLayout()
self._shadow_width = 15
self._view_options = dict(row_height=60, no_scroll_v=False)
Expand All @@ -60,6 +64,7 @@ def __init__(self, app, *args, **kwargs):

self._clear_playlist_btn.clicked.connect(self._app.playlist.clear)
self._goto_current_song_btn.clicked.connect(self.goto_current_song)
self._songs_radio_btn.clicked.connect(self.enter_songs_radio)
esc_hide_widget(self)
q_app = QApplication.instance()
assert q_app is not None # make type checker happy.
Expand All @@ -72,22 +77,28 @@ def __init__(self, app, *args, **kwargs):
def setup_ui(self):
self._layout = QVBoxLayout(self)
self._btn_layout = QHBoxLayout()
self._btn_layout2 = QHBoxLayout()
self._layout.setContentsMargins(self._shadow_width, 0, 0, 0)
self._layout.setSpacing(0)
self._btn_layout.setContentsMargins(7, 7, 7, 7)
self._btn_layout.setSpacing(7)
self._btn_layout2.setContentsMargins(7, 0, 7, 7)
self._btn_layout2.setSpacing(7)

self._tabbar.setDocumentMode(True)
self._tabbar.addTab('播放列表')
self._tabbar.addTab('最近播放')
self._layout.addWidget(self._tabbar)
self._layout.addLayout(self._btn_layout)
self._layout.addLayout(self._btn_layout2)
self._layout.addLayout(self._stacked_layout)

self._btn_layout.addWidget(self._clear_playlist_btn)
self._btn_layout.addWidget(self._playback_mode_switch)
self._btn_layout.addWidget(self._goto_current_song_btn)
self._btn_layout2.addWidget(self._songs_radio_btn)
self._btn_layout.addStretch(0)
self._btn_layout2.addStretch(0)

def on_focus_changed(self, _, new):
"""
Expand All @@ -105,6 +116,15 @@ def goto_current_song(self):
assert isinstance(view, PlayerPlaylistView)
view.scroll_to_current_song()

def enter_songs_radio(self):
songs = self._app.playlist.list()
if not songs:
self._app.show_msg('播放队列为空,不能激活“自动续歌”功能')
else:
radio = SongsRadio(self._app, songs)
self._app.fm.activate(radio.fetch_songs_func, reset=False)
self._app.show_msg('“自动续歌”功能已激活')

def show_tab(self, index):
if not self.isVisible():
return
Expand Down
3 changes: 2 additions & 1 deletion feeluown/player/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from .playlist import PlaylistMode, Playlist
from .metadata_assembler import MetadataAssembler
from .fm import FM
from .radio import SongRadio
from .radio import SongRadio, SongsRadio
from .lyric import LiveLyric, parse_lyric_text, Line as LyricLine, Lyric
from .recently_played import RecentlyPlayed
from .delegate import PlayerPositionDelegate
Expand All @@ -22,6 +22,7 @@
'FM',
'PlaylistMode',
'SongRadio',
'SongsRadio',

'Player',
'Playlist',
Expand Down
25 changes: 10 additions & 15 deletions feeluown/player/fm.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
from typing import TYPE_CHECKING

import asyncio
import logging
from collections import deque

from feeluown.excs import ProviderIOError
from feeluown.player import PlaylistMode

if TYPE_CHECKING:
from feeluown.app import App

logger = logging.getLogger(__name__)


Expand All @@ -23,18 +27,16 @@ class FM:
maybe a bit confusing.
"""

def __init__(self, app):
def __init__(self, app: 'App'):
"""
:type app: feeluown.app.App
"""
self._app = app

# store songs that are going to be added to playlist
self._queue = deque()
self._activated = False
self._is_fetching_songs = False
self._fetch_songs_task_name = 'fm-fetch-songs'
self._fetch_songs_func = None
self._fetch_songs_func = None # fn(number_to_fetch)
self._minimum_per_fetch = 3

self._app.playlist.mode_changed.connect(self._on_playlist_mode_changed)
Expand Down Expand Up @@ -78,10 +80,6 @@ def is_active(self):
return self._app.playlist.mode is PlaylistMode.fm

def _on_playlist_eof_reached(self):
if self._queue:
self._feed_playlist()
return

if self._is_fetching_songs:
return

Expand All @@ -102,9 +100,8 @@ def _on_playlist_fm_mode_exited(self):
self._fetch_songs_func = None
logger.info('fm mode deactivated')

def _feed_playlist(self):
while self._queue:
song = self._queue.popleft()
def _feed_playlist(self, songs):
for song in songs:
self._app.playlist.fm_add(song)
self._app.playlist.next()

Expand All @@ -120,8 +117,6 @@ def _on_songs_fetched(self, future):
logger.info('No enough songs, exit fm mode now')
self.deactivate()
else:
for song in songs:
self._queue.append(song)
self._feed_playlist()
self._feed_playlist(songs)
finally:
self._is_fetching_songs = False
Loading

0 comments on commit 8aeb256

Please sign in to comment.