Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package upplay for openSUSE:Factory checked in at 2026-02-24 15:39:58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/upplay (Old) and /work/SRC/openSUSE:Factory/.upplay.new.1977 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "upplay" Tue Feb 24 15:39:58 2026 rev:18 rq:1334710 version:1.9.10 Changes: -------- --- /work/SRC/openSUSE:Factory/upplay/upplay.changes 2026-01-27 16:12:47.115230308 +0100 +++ /work/SRC/openSUSE:Factory/.upplay.new.1977/upplay.changes 2026-02-24 15:40:47.299861370 +0100 @@ -1,0 +2,10 @@ +Tue Feb 24 11:16:14 UTC 2026 - Michael Pujos <[email protected]> + +- updated upplay.keyring +- Update to 1.9.10: + * Use regular dialog to show metadata from the player area instead of the + "tooltip-like" window which did not wrap lines + * Browser: fix popup popping up again if left-clicked in the same second. + * Browser: popup entry for searching artist + +------------------------------------------------------------------- Old: ---- upplay-1.9.9.tar.gz upplay-1.9.9.tar.gz.asc New: ---- upplay-1.9.10.tar.gz upplay-1.9.10.tar.gz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ upplay.spec ++++++ --- /var/tmp/diff_new_pack.2jfp7I/_old 2026-02-24 15:40:47.919887110 +0100 +++ /var/tmp/diff_new_pack.2jfp7I/_new 2026-02-24 15:40:47.919887110 +0100 @@ -17,14 +17,14 @@ Name: upplay -Version: 1.9.9 +Version: 1.9.10 Release: 0 Summary: UPnP and OpenHome audio Control Point License: GPL-2.0-or-later URL: https://www.lesbonscomptes.com/upplay/ Source0: https://www.lesbonscomptes.com/upplay/downloads/upplay-%{version}.tar.gz Source1: https://www.lesbonscomptes.com/upplay/downloads/upplay-%{version}.tar.gz.asc -Source2: https://www.lesbonscomptes.com/pages/jf-at-dockes.org.pub#/%{name}.keyring +Source2: https://www.lesbonscomptes.com/pages/lesbonscomptes.gpg#/%{name}.keyring BuildRequires: fdupes BuildRequires: gcc-c++ BuildRequires: hicolor-icon-theme ++++++ upplay-1.9.9.tar.gz -> upplay-1.9.10.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upplay-1.9.9/GUI/mdatawidget/mdatawidget.cpp new/upplay-1.9.10/GUI/mdatawidget/mdatawidget.cpp --- old/upplay-1.9.9/GUI/mdatawidget/mdatawidget.cpp 2025-12-17 19:41:14.000000000 +0100 +++ new/upplay-1.9.10/GUI/mdatawidget/mdatawidget.cpp 2026-01-28 14:30:09.000000000 +0100 @@ -48,6 +48,7 @@ #include "HelperStructs/Style.h" #include "upadapt/upputils.h" #include "GUI/widgets/tooltiplike.h" +#include "GUI/widgets/browserdialog.h" #include "GUI/widgets/cdwebpage.h" #include "utils/smallut.h" @@ -271,6 +272,16 @@ switch (what) { case PUP_SHOWDETAILS: { +#if 1 + auto html = metaDataToHtml(&m_data); + auto d = new BrowserDialog(); + auto browser = d->browser; + browser->setText(html); + browser->setReadOnly(true); + browser->setOpenExternalLinks(true); + d->show(); +#else + // Can't seem to get this to adjust size and break lines, it just becomes very wide. QString head("<html><head></head><body>\n"); if (Style::use_dark_colors()) { // The tooltip background stays light (because of the Qt::tooltip flag probably). But @@ -284,7 +295,9 @@ auto html = head + metaDataToHtml(&m_data) + tail; auto tooltipWindow = new TooltipWindow(html, this); tooltipWindow->move(QCursor::pos() + QPoint(-50, -50)); + tooltipWindow->resize(200,200); tooltipWindow->show(); +#endif } break; default: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upplay-1.9.9/dirbrowser/cdbrowser.cpp new/upplay-1.9.10/dirbrowser/cdbrowser.cpp --- old/upplay-1.9.9/dirbrowser/cdbrowser.cpp 2026-01-25 10:25:52.000000000 +0100 +++ new/upplay-1.9.10/dirbrowser/cdbrowser.cpp 2026-02-24 09:50:55.000000000 +0100 @@ -341,6 +341,14 @@ #endif // WEBKIT +static std::vector<struct CharFlags> butnames { + CHARFLAGENTRY(Qt::LeftButton), + CHARFLAGENTRY(Qt::RightButton), + CHARFLAGENTRY(Qt::MiddleButton), + CHARFLAGENTRY(Qt::BackButton), +}; + + bool CDBrowser::event(QEvent *event) { if (event->type() == QEvent::Gesture) { @@ -349,10 +357,12 @@ return QWidget::event(event); } +// For some reason we get a taphold event for a right-click followed by a left-click in the same +// second (e.g. popup+select send to playlist quickly). Happens with both webkit and +// webengine. Hence the lastpuptime thing, but this is a workaround, there is probably a proper fix. bool CDBrowser::gestureEvent(QGestureEvent *event) { - if (QTapAndHoldGesture *taphold = - dynamic_cast<QTapAndHoldGesture *>(event->gesture(Qt::TapAndHoldGesture))) { + if (auto taphold = dynamic_cast<QTapAndHoldGesture *>(event->gesture(Qt::TapAndHoldGesture))) { LOGDEB("CDBRowser: got taphold, state: " << taphold->state() << " has hotspot " << taphold->hasHotSpot() << "\n"); if (taphold->state() == Qt::GestureFinished) { @@ -363,23 +373,14 @@ // Avoid gestures in possible scrollbar areas. if ((relpos.x() > width() - 30) || (relpos.y() > height() - 20)) return false; - createPopupMenu(relpos); + if (time(0) - m_lastpuptime > 1) { + createPopupMenu(relpos); + } } } return true; } -#if 0 - std::string butname; - switch (m_lastbutton) { - case Qt::LeftButton: butname = "left";break; - case Qt::RightButton: butname = "right";break; - case Qt::MiddleButton: butname = "middle";break; - case Qt::BackButton: butname = "back";break; - default: butname = std::to_string(m_lastbutton);break; - } -#endif - bool CDBrowser::eventFilter(QObject *object, QEvent *event) { LOGDEB1("CDBrowser::eventFilter: event type " << event->type() << '\n'); @@ -389,7 +390,7 @@ switch (event->type()) { case QEvent::MouseButtonRelease: { - const QMouseEvent *mouseEvent(static_cast<QMouseEvent*>(event)); + auto mouseEvent = dynamic_cast<QMouseEvent*>(event); if (mouseEvent) { m_lastbutton = mouseEvent->button(); if (m_lastbutton == Qt::BackButton) { @@ -599,8 +600,8 @@ { m_timer.stop(); std::string scurl = qs2utf8s(url.toString()); - LOGDEB("CDBrowser::processOnLinkClicked: " << scurl << - " button " << m_lastbutton << " mid " << Qt::MiddleButton << "\n"); + LOGDEB("CDBrowser::processOnLinkClicked: "<< scurl << " button " << + valToString(butnames, m_lastbutton) << "\n"); // Get rid of http:// if (scurl.find("http://h/") != 0) { LOGERR("CDBrowser::onLinkClicked: bad link ! : " << qs2utf8s(url.toString())); @@ -1411,6 +1412,7 @@ PUP_TOGGLE_MODE, PUP_SEARCH_ARTIST_TRACKS, PUP_SEARCH_ARTIST_ALBUMS, + PUP_SEARCH_ARTIST_ARTIST, }; #ifdef USING_WEBENGINE @@ -1522,7 +1524,7 @@ LOGDEB0("CDBrowser::doCreatePopupMenu:" << " type [" << m_popupotype << "] IDX [" << m_popupidx << "] ISPL [" << m_popupispl << "] ISPATH [" << m_popupispath << "] title [" << m_popupobjtitle << "] objid [" << m_popupobjid << "]\n"); - + time(&m_lastpuptime); if (m_browsers->insertActive() || m_reader || m_reaper) { LOGINF("CDBrowser::createPopupMenu: no popup: active read\n"); return; @@ -1568,6 +1570,7 @@ if (entryhasartist) { popupaddaction(popup, tr("Search Albums by Artist"), PUP_SEARCH_ARTIST_ALBUMS); popupaddaction(popup, tr("Search Tracks by Artist"), PUP_SEARCH_ARTIST_TRACKS); + popupaddaction(popup, tr("Search for Artist"), PUP_SEARCH_ARTIST_ARTIST); } popup->connect(popup, SIGNAL(triggered(QAction *)), this, SLOT(itemActions(QAction *))); } else if (m_popupotype == "container") { @@ -1575,6 +1578,7 @@ if (!m_popupispath && entryhasartist) { popupaddaction(popup, tr("Search Albums by Artist"), PUP_SEARCH_ARTIST_ALBUMS); popupaddaction(popup, tr("Search Tracks by Artist"), PUP_SEARCH_ARTIST_TRACKS); + popupaddaction(popup, tr("Search for Artist"), PUP_SEARCH_ARTIST_ARTIST); } popupaddaction(popup, tr("Show Metadata"), PUP_SHOW_META); popupaddaction(popup, tr("Random play by tracks"), PUP_RAND_PLAY_TRACKS); @@ -1655,6 +1659,9 @@ if (m_popupmode == PUP_SEARCH_ARTIST_ALBUMS) { ss.push_back(std::string("upnp:class = \"object.container.album.musicAlbum\"" " and upnp:artist contains ") + quoted); + } else if (m_popupmode == PUP_SEARCH_ARTIST_ARTIST) { + ss.push_back(std::string("upnp:class = \"object.container.person.musicArtist\"" + " and dc:title contains ") + quoted); } else /*PUP_SEARCH_ARTIST_TRACKS*/ { ss.push_back(std::string("upnp:class derivedfrom \"object.item.audioItem\"" " and (dc:creator contains ") + quoted + @@ -1703,6 +1710,8 @@ case PUP_SEARCH_ARTIST_TRACKS: /* FALLTHROUGH */ case PUP_SEARCH_ARTIST_ALBUMS: + /* FALLTHROUGH */ + case PUP_SEARCH_ARTIST_ARTIST: popupSearch(); return; case PUP_ADD_FROMHERE: @@ -1803,7 +1812,9 @@ npath.push_back(CtPathElt(m_popupobjid, m_popupobjtitle, m_popupispl)); emit sig_browse_in_new_tab(u8s2qs(m_cds->srv()->getDeviceId()), npath); return; - } else if (m_popupmode == PUP_SEARCH_ARTIST_TRACKS || m_popupmode == PUP_SEARCH_ARTIST_ALBUMS) { + } else if (m_popupmode == PUP_SEARCH_ARTIST_TRACKS || + m_popupmode == PUP_SEARCH_ARTIST_ALBUMS || + m_popupmode == PUP_SEARCH_ARTIST_ARTIST) { popupSearch(); return; } else if (m_popupmode == PUP_SHOW_META) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upplay-1.9.9/dirbrowser/cdbrowser.h new/upplay-1.9.10/dirbrowser/cdbrowser.h --- old/upplay-1.9.9/dirbrowser/cdbrowser.h 2026-01-24 19:24:17.000000000 +0100 +++ new/upplay-1.9.10/dirbrowser/cdbrowser.h 2026-02-24 09:41:51.000000000 +0100 @@ -237,6 +237,7 @@ // Busy dialog for lengthy ops QProgressDialog *m_progressD{0}; time_t m_progstart; + time_t m_lastpuptime{0}; // Content of the currently visited container or search std::vector<UPnPClient::UPnPDirObject> m_entries; // Scroll position to be restored when we're done reading. This is diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upplay-1.9.9/upplay.pro new/upplay-1.9.10/upplay.pro --- old/upplay-1.9.9/upplay.pro 2026-01-25 10:27:19.000000000 +0100 +++ new/upplay-1.9.10/upplay.pro 2026-02-24 10:01:40.000000000 +0100 @@ -2,7 +2,7 @@ TARGET = upplay # VERSION is ^egrepped and must stay in the first column -VERSION = 1.9.9 +VERSION = 1.9.10 COPYRDATES = 2011-2025 # Possibly override WEBPLATFORM from the command line, or environment diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upplay-1.9.9/upqo/avtransport_qo.h new/upplay-1.9.10/upqo/avtransport_qo.h --- old/upplay-1.9.9/upqo/avtransport_qo.h 2025-04-23 10:43:22.000000000 +0200 +++ new/upplay-1.9.10/upqo/avtransport_qo.h 2026-01-25 15:20:58.000000000 +0100 @@ -338,7 +338,7 @@ // playlist. Scheduling a state update is not useful // either because the data will have the same // problem. Kodi only emits useful metadata when - // explicitely told to switch tracks (not even at regular + // explicitly told to switch tracks (not even at regular // track changes). if (!meta.m_resources.empty() && (force || m_tpstate == UPnPClient::AVTransport::Playing || diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upplay-1.9.9/utils/confgui.cpp new/upplay-1.9.10/utils/confgui.cpp --- old/upplay-1.9.9/utils/confgui.cpp 2025-04-11 18:03:47.000000000 +0200 +++ new/upplay-1.9.10/utils/confgui.cpp 2026-01-29 10:10:01.000000000 +0100 @@ -60,7 +60,7 @@ // left,top,right, bottom static QMargins margin(4,3,4,3); -// Margin around text to explicitely set pushbutton sizes lower than +// Margin around text to explicitly set pushbutton sizes lower than // the default min (80?). Different on Mac OS for some reason #ifdef __APPLE__ static const int pbTextMargin = 30; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upplay-1.9.9/utils/pathut.cpp new/upplay-1.9.10/utils/pathut.cpp --- old/upplay-1.9.9/utils/pathut.cpp 2025-05-12 18:49:03.000000000 +0200 +++ new/upplay-1.9.10/utils/pathut.cpp 2026-02-12 13:34:23.000000000 +0100 @@ -166,6 +166,52 @@ return static_cast<ssize_t>(::write(fd, buf, static_cast<int>(cnt))); } + +// Helper to convert FILETIME to time_t (seconds since Unix Epoch) +static time_t FileTimeToUnixTime(const FILETIME *ft) +{ + unsigned __int64 windowsTime = ((unsigned __int64)ft->dwHighDateTime << 32) | ft->dwLowDateTime; + // 2. Adjust for epoch difference (1601 to 1970 in 100-ns intervals) + windowsTime -= 116444736000000000ULL; + // 3. Convert 100-ns intervals to seconds + return (time_t)(windowsTime / 10000000ULL); +} + +// Populate our close-to-POSIX PathStat struct from Windows FIND_DATA, as returned from +// e.g. Find(First/Next)FileW() +void MapWinFindDataToStat(const WIN32_FIND_DATA *fd, struct PathStat *pstp) +{ + memset(pstp, 0, sizeof(struct PathStat)); + pstp->pst_size = ((unsigned __int64)fd->nFileSizeHigh << 32) | fd->nFileSizeLow; + // Note that we don't use pst_mode anywhere at the moment + pstp->pst_mode = 0; + enum PstType {PST_REGULAR, PST_SYMLINK, PST_DIR, PST_OTHER, PST_INVALID}; + pstp->pst_type = PathStat::PST_INVALID; + if (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + pstp->pst_type = PathStat::PST_DIR; + pstp->pst_mode |= S_IFDIR | 0755; + } else if (fd->dwFileAttributes & FILE_ATTRIBUTE_DEVICE) { + pstp->pst_type = PathStat::PST_OTHER; + } else if (fd->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + pstp->pst_type = PathStat::PST_SYMLINK; + pstp->pst_mode |= S_IFLNK | 0444; + } else { + pstp->pst_type = PathStat::PST_REGULAR; + pstp->pst_mode |= S_IFREG | 0644; + } + pstp->pst_mtime = FileTimeToUnixTime(&fd->ftLastWriteTime); + pstp->pst_btime = pstp->pst_ctime = FileTimeToUnixTime(&fd->ftCreationTime); + // Read-only check + if (fd->dwFileAttributes & FILE_ATTRIBUTE_READONLY) { + pstp->pst_mode &= ~0222; // Remove write permissions + } + // None of these are used by us on Windows + // uint64_t pst_ino; + // uint64_t pst_dev; + // uint64_t pst_blocks; + // uint64_t pst_blksize; +} + #else /* !_WIN32 -> */ #include <unistd.h> @@ -896,26 +942,37 @@ std::string path_tildexpand(const std::string& s) { + +#ifdef _WIN32 + if (s.empty() || !(startswith(s, "%USERPROFILE%") || s[0] == '~')) { + return s; + } +#else if (s.empty() || s[0] != '~') { return s; } +#endif + std::string o = s; #ifdef _WIN32 + if (startswith(o, "%USERPROFILE%")) { + o.replace(0, 13, "~"); + } path_slashize(o); #endif - if (s.length() == 1) { + if (o.length() == 1) { o.replace(0, 1, path_home()); - } else if (s[1] == '/') { + } else if (o[1] == '/') { o.replace(0, 2, path_home()); } else { - std::string::size_type pos = s.find('/'); - std::string::size_type l = (pos == std::string::npos) ? s.length() - 1 : pos - 1; + std::string::size_type pos = o.find('/'); + std::string::size_type l = (pos == std::string::npos) ? o.length() - 1 : pos - 1; #ifdef _WIN32 // Dont know what this means. Just replace with HOME o.replace(0, l + 1, path_home()); #else - struct passwd *entry = getpwnam(s.substr(1, l).c_str()); + struct passwd *entry = getpwnam(o.substr(1, l).c_str()); if (entry) { o.replace(0, l + 1, entry->pw_dir); } @@ -1242,7 +1299,11 @@ #endif } -#if defined(STATX_TYPE) +// The statx section was supplied by the developpers who needed to use file birth times for recoll. +// It causes problems with containers builds built with statx support but running on older kernels +// so it is now disabled by default. Set the ENABLE_STATX flag if needed (only recoll does it at the +// moment). +#if defined(STATX_TYPE) && defined(ENABLE_STATX) #include <sys/syscall.h> @@ -1467,19 +1528,51 @@ return nullptr; } #ifdef _WIN32 - std::string sdname; - if (!wchartoutf8(ent->d_name, sdname)) { + if (!wchartoutf8(ent->d_name, m->entry.d_name)) { LOGERR("wchartoutf8 failed for " << ent->d_name << "\n"); return nullptr; } - const char *dname = sdname.c_str(); #else - const char *dname = ent->d_name; + m->entry.d_name = ent->d_name; #endif - m->entry.d_name = dname; return &m->entry; } +// Run stat on the last read entry, using the dirfd and a relative path. On Linux, with everything +// in the cache (no real I/O), this yields fstreewalk around 20% sys cpu time improvement compared +// to a stat() on the absolute path. On Windows, it's free because the dir reading op also yields +// the attributes. +int PathDirContents::filepropsat(struct PathStat *stp, bool follow) +{ + if (nullptr == stp) { + return -1; + } + +#ifdef _WIN32 + int ret = -1; + if (nullptr != m->dirhdl) { + MapWinFindDataToStat(&m->dirhdl->data, stp); + ret = 0; + } +#else + std::string& dname = m->entry.d_name; + SYSPATH(dname, syspath); + struct STATXSTRUCT mst; +#if defined(STATX_TYPE) && defined(ENABLE_STATX) + int ret = statx(dirfd(m->dirhdl), syspath, follow ? 0 : AT_SYMLINK_NOFOLLOW, + STATX_BASIC_STATS | STATX_BTIME, &mst); + copystat(stp, mst); +#else // No statx -> + int ret = fstatat(dirfd(m->dirhdl), syspath, &mst, follow ? 0 : AT_SYMLINK_NOFOLLOW); + copystat(stp, mst); +#endif // !STATX +#endif // ! WIN + + if (ret < 0) { + *stp = PathStat{PathStat::PST_INVALID,0,0,0,0,0,0,0,0,0}; + } + return ret; +} bool listdir(const std::string& dir, std::string& reason, std::set<std::string>& entries) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upplay-1.9.9/utils/pathut.h new/upplay-1.9.10/utils/pathut.h --- old/upplay-1.9.9/utils/pathut.h 2025-05-12 18:49:03.000000000 +0200 +++ new/upplay-1.9.10/utils/pathut.h 2026-02-12 13:34:16.000000000 +0100 @@ -198,7 +198,7 @@ }; const struct Entry* readdir(); void rewinddir(); - + int filepropsat(struct PathStat *stp, bool follow); private: class Internal; Internal *m{nullptr}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upplay-1.9.9/utils/smallut.h new/upplay-1.9.10/utils/smallut.h --- old/upplay-1.9.9/utils/smallut.h 2025-10-30 09:05:47.000000000 +0100 +++ new/upplay-1.9.10/utils/smallut.h 2026-02-10 17:24:58.000000000 +0100 @@ -86,6 +86,9 @@ extern void stringtoupper(std::string& io); extern std::string stringtoupper(const std::string& io); extern bool beginswith(const std::string& b, const std::string& sml); +inline bool startswith(const std::string& b, const std::string& sml) { + return beginswith(b, sml); +} extern bool endswith(const std::string& bg, const std::string& sml); #ifdef _WIN32 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/upplay-1.9.9/windows/mkinstdir.sh new/upplay-1.9.10/windows/mkinstdir.sh --- old/upplay-1.9.9/windows/mkinstdir.sh 2025-12-14 08:42:39.000000000 +0100 +++ new/upplay-1.9.10/windows/mkinstdir.sh 2026-01-25 15:19:25.000000000 +0100 @@ -108,7 +108,7 @@ $QTBIN/windeployqt upplay.exe # Apparently because of the webkit graft (always on old mingw, conditionally with MSVC, - # we need to copy some DLLs explicitely? + # we need to copy some DLLs explicitly? if test "$MSVC" != "yes"; then addlibs="Qt5Core.dll Qt5Multimedia.dll Qt5MultimediaWidgets.dll Qt5OpenGL.dll \ Qt5Positioning.dll Qt5PrintSupport.dll Qt5Sensors.dll Qt5Sql.dll icudt57.dll icuin57.dll \ ++++++ upplay.keyring ++++++ Binary files /var/tmp/diff_new_pack.2jfp7I/_old and /var/tmp/diff_new_pack.2jfp7I/_new differ
