ronantakizawa/codereview-bench huggingface dataset:
Repository: xbmc/xbmc
File: xbmc/InfoScanner.h (C/C++)

Code before:
/*
 *  Copyright (C) 2016-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include <set>
#include <string>
#include <vector>

class CGUIDialogProgressBarHandle;

class CInfoScanner
{
public:
  /*!
    \brief Return values from the information lookup functions.
   */
  enum class InfoRet
  {
    CANCELLED,
    ERROR,
    NOT_NEEDED,
    HAVE_ALREADY,
    NOT_FOUND,
    ADDED
  };

  /*
   \brief Type of information returned from tag readers.
  */

  enum INFO_TYPE
  {
    NO_NFO       = 0, //!< No info found
    FULL_NFO     = 1, //!< Full info specified
    URL_NFO      = 2, //!< A URL to grab info from was found
    OVERRIDE_NFO = 3, //!< Override info was found
    COMBINED_NFO = 4, //!< A URL to grab info from + override info was found
    ERROR_NFO    = 5, //!< Error processing info
    TITLE_NFO    = 6  //!< At least Title was read (and optionally the Year)
  };

  //! \brief Empty destructor.
  virtual ~CInfoScanner() = default;

  virtual bool DoScan(const std::string& strDirectory) = 0;

Review comment (suggestion):
This will not compile on Windows, because it comes with a macro named `ERROR`.

Code after:
/*
 *  Copyright (C) 2016-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include <set>
#include <string>

class CGUIDialogProgressBarHandle;

class CInfoScanner
{
public:
  /*!
    \brief Return values from the information lookup functions.
   */
  enum class InfoRet
  {
    CANCELLED,
    INFO_ERROR, // ERROR clashes with windows macro
    NOT_NEEDED,
    HAVE_ALREADY,
    NOT_FOUND,
    ADDED
  };

  /*
   \brief Type of information returned from tag readers.
  */

  enum INFO_TYPE
  {
    NO_NFO       = 0, //!< No info found
    FULL_NFO     = 1, //!< Full info specified
    URL_NFO      = 2, //!< A URL to grab info from was found
    OVERRIDE_NFO = 3, //!< Override info was found
    COMBINED_NFO = 4, //!< A URL to grab info from + override info was found
    ERROR_NFO    = 5, //!< Error processing info
    TITLE_NFO    = 6  //!< At least Title was read (and optionally the Year)
  };

  //! \brief Empty destructor.
  virtual ~CInfoScanner() = default;

  virtual bool DoScan(const std::string& strDirectory) = 0;
Repository: xbmc/xbmc
File: xbmc/favourites/FavouritesUtils.cpp (C++)

Code before:
bool RemoveItem(CFileItemList& items, const std::shared_ptr<CFileItem>& item)
{
  int iBefore = items.Size();
  items.Remove(item.get());
  return items.Size() == iBefore - 1;
}

bool ShouldEnableMoveItems()
{
  if (CServiceBroker::GetFavouritesService().Size() <= 1)
    return false;

  auto& mgr = CServiceBroker::GetGUI()->GetWindowManager();
  CGUIWindowFavourites* window = mgr.GetWindow<CGUIWindowFavourites>(WINDOW_FAVOURITES);
  if (window && window->IsActive())
  {
    const CGUIViewState* state = window->GetViewState();
    if (state && state->GetSortMethod().sortBy != SortByUserPreference)
      return false; // in favs window, allow move only if current sort method is by user preference
  }
  return true;
}

namespace
{
bool ExecuteAction(const std::string& execString)
{
  if (!execString.empty())
  {
    CGUIMessage message(GUI_MSG_EXECUTE, 0, 0);
    message.SetStringParam(execString);
    CServiceBroker::GetGUI()->GetWindowManager().SendMessage(message);
    return true;
  }
  return false;
}
} // unnamed namespace

bool ExecuteAction(const CExecString& execString)
{
  return ExecuteAction(execString.GetExecString());
}

bool ExecuteAction(const CFavouritesURL& favURL)
{
  if (favURL.IsValid())
    return ExecuteAction(favURL.GetExecString());

  return false;
}


Review comment (bug):
In the past I fixed a bug due to passing a std::shared_ptr<CFileItem> reference around, and the caller dropped the refcount to zero and rugpulled the pointer. Is it possible to pass by value, forcing a copy, and then do the best to elide a copy later with std::move()?

Code after:
bool RemoveItem(CFileItemList& items, const std::shared_ptr<CFileItem>& item)
{
  int iBefore = items.Size();
  items.Remove(item.get());
  return items.Size() == iBefore - 1;
}

bool ShouldEnableMoveItems()
{
  if (CServiceBroker::GetFavouritesService().Size() <= 1)
    return false;

  auto& mgr = CServiceBroker::GetGUI()->GetWindowManager();
  CGUIWindowFavourites* window = mgr.GetWindow<CGUIWindowFavourites>(WINDOW_FAVOURITES);
  if (window && window->IsActive())
  {
    const CGUIViewState* state = window->GetViewState();
    if (state && state->GetSortMethod().sortBy != SortByUserPreference)
      return false; // in favs window, allow move only if current sort method is by user preference
  }
  return true;
}

namespace
{
bool ExecuteAction(const std::string& execString, const std::shared_ptr<CFileItem>& item)
{
  if (!execString.empty())
  {
    CGUIMessage message(GUI_MSG_EXECUTE, 0, 0, 0, 0, item);
    message.SetStringParam(execString);
    CServiceBroker::GetGUI()->GetWindowManager().SendMessage(message);
    return true;
  }
  return false;
}
} // unnamed namespace

bool ExecuteAction(const CExecString& execString, const std::shared_ptr<CFileItem>& item)
{
  return ExecuteAction(execString.GetExecString(), item);
}

bool ExecuteAction(const CFavouritesURL& favURL, const std::shared_ptr<CFileItem>& item)
{
  if (favURL.IsValid())
    return ExecuteAction(favURL.GetExecString(), item);

  return false;
}
Repository: xbmc/xbmc
File: xbmc/utils/URIUtils.cpp (C++)

Code before:
std::string URIUtils::GetBasePath(const std::string& strPath)
{
  std::string strCheck(strPath);
  if (IsStack(strPath))
    strCheck = CStackDirectory::GetFirstStackedFile(strPath);

  std::string strDirectory = GetDirectory(strCheck);
  if (IsInRAR(strCheck))
  {
    std::string strPath=strDirectory;
    GetParentPath(strPath, strDirectory);
  }
  if (IsStack(strPath))
  {
    strCheck = strDirectory;
    RemoveSlashAtEnd(strCheck);
    if (GetFileName(strCheck).size() == 3 && StringUtils::StartsWithNoCase(GetFileName(strCheck), "cd"))
      strDirectory = GetDirectory(strCheck);
  }
  return strDirectory;
}

std::string URIUtils::GetDiscBase(std::string file)
{
  if (IsBlurayPath(file))
    file = GetBlurayFile(file);

  std::string parent{GetParentPath(file)};
  std::string parentFolder{parent};
  RemoveSlashAtEnd(parentFolder);
  parentFolder = GetFileName(parentFolder);
  if (StringUtils::EqualsNoCase(parentFolder, "VIDEO_TS") ||
      StringUtils::EqualsNoCase(parentFolder, "BDMV"))
    return GetParentPath(parent); // go back up another one
  return parent;
}

std::string URIUtils::GetDiscBasePath(const std::string& file)
{
  std::string base{GetDiscBase(file)};
  if (IsDiscImage(base))
    return GetDirectory(base);
  return base;
}

std::string URIUtils::GetBlurayFile(const std::string& path)
{
  if (IsBlurayPath(path))
  {
    CURL url(path);
    CURL url2(url.GetHostName()); // strip bluray://

Review comment (suggestion):
I would go with a `const std::string& file`, not a copy (by-val vs. by-ref param). The implementation detail that you need to modify the parameter's value should not be exposed to the interface of the function.

Code after:
std::string URIUtils::GetBasePath(const std::string& strPath)
{
  std::string strCheck(strPath);
  if (IsStack(strPath))
    strCheck = CStackDirectory::GetFirstStackedFile(strPath);

  std::string strDirectory = GetDirectory(strCheck);
  if (IsInRAR(strCheck))
  {
    std::string strPath=strDirectory;
    GetParentPath(strPath, strDirectory);
  }
  if (IsStack(strPath))
  {
    strCheck = strDirectory;
    RemoveSlashAtEnd(strCheck);
    if (GetFileName(strCheck).size() == 3 && StringUtils::StartsWithNoCase(GetFileName(strCheck), "cd"))
      strDirectory = GetDirectory(strCheck);
  }
  return strDirectory;
}

std::string URIUtils::GetDiscBase(const std::string& file)
{
  std::string discFile;
  if (IsBlurayPath(file))
    discFile = GetBlurayFile(file);
  else
    discFile = file;

  std::string parent{GetParentPath(discFile)};
  std::string parentFolder{parent};
  RemoveSlashAtEnd(parentFolder);
  parentFolder = GetFileName(parentFolder);
  if (StringUtils::EqualsNoCase(parentFolder, "VIDEO_TS") ||
      StringUtils::EqualsNoCase(parentFolder, "BDMV"))
    return GetParentPath(parent); // go back up another one
  return parent;
}

std::string URIUtils::GetDiscBasePath(const std::string& file)
{
  std::string base{GetDiscBase(file)};
  if (IsDiscImage(base))
    return GetDirectory(base);
  return base;
}

std::string URIUtils::GetBlurayFile(const std::string& path)
{
  if (IsBlurayPath(path))
Repository: xbmc/xbmc
File: xbmc/video/VideoDatabase.cpp (C++)

Code before:
  if (GetEpisodeInfo(strFilenameAndPath, details))
    return true;
  if (GetMusicVideoInfo(strFilenameAndPath, details))
    return true;
  if (GetFileInfo(strFilenameAndPath, details))
    return true;

  return false;
}

bool CVideoDatabase::HasMovieInfo(const std::string& strFilenameAndPath)
{
  try
  {
    if (nullptr == m_pDB)
      return false;
    if (nullptr == m_pDS)
      return false;

    int idMovie = GetMovieId(strFilenameAndPath);
    if (idMovie > 0) // index of zero is also invalid
      return true;

    // Check to see if filename has been updated with bluray:// or dvd://
    const int idFile = GetFileId(strFilenameAndPath);
    idMovie = GetMovieId(idFile);
    return (idMovie > 0);
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "{} ({}) failed", __FUNCTION__, strFilenameAndPath);
  }
  return false;
}

bool CVideoDatabase::HasTvShowInfo(const std::string& strPath)
{
  try
  {
    if (nullptr == m_pDB)
      return false;
    if (nullptr == m_pDS)
      return false;
    int idTvShow = GetTvShowId(strPath);
    return (idTvShow > 0); // index of zero is also invalid
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "{} ({}) failed", __FUNCTION__, strPath);
  }
  return false;

Review comment (suggestion):
There is already a method `CVideoDatabase::GetMovieId(const std::string& strFilenameAndPath)`. Why can't you just use it?

In this case you would not even need the new metod `CVideoDatabase::GetMovieId(int fileId)` you have introduced with this PR.

Code after:
  }
  return false;
}

bool CVideoDatabase::HasTvShowInfo(const std::string& strPath)
{
  try
  {
    if (nullptr == m_pDB)
      return false;
    if (nullptr == m_pDS)
      return false;
    int idTvShow = GetTvShowId(strPath);
    return (idTvShow > 0); // index of zero is also invalid
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "{} ({}) failed", __FUNCTION__, strPath);
  }
  return false;
}

bool CVideoDatabase::HasEpisodeInfo(const std::string& strFilenameAndPath)
{
  try
  {
    if (nullptr == m_pDB)
      return false;
    if (nullptr == m_pDS)
      return false;
    int idEpisode = GetEpisodeId(strFilenameAndPath);
    return (idEpisode > 0); // index of zero is also invalid
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "{} ({}) failed", __FUNCTION__, strFilenameAndPath);
  }
  return false;
}

bool CVideoDatabase::HasMusicVideoInfo(const std::string& strFilenameAndPath)
{
  try
  {
    if (nullptr == m_pDB)
      return false;
    if (nullptr == m_pDS)
      return false;
    int idMVideo = GetMusicVideoId(strFilenameAndPath);
    return (idMVideo > 0); // index of zero is also invalid
  }
Repository: xbmc/xbmc
File: xbmc/video/VideoDatabase.cpp (C++)

Code before:

  try
  {
    m_pDS->query(PrepareSQL(
        "SELECT strPath FROM path JOIN files ON path.idPath = files.idPath WHERE idFile = %i",
        idFile));

    if (!m_pDS->eof())
    {
      return m_pDS->fv("strPath").get_asString();
    }
    m_pDS->close();
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "{} failed for file {}", __FUNCTION__, idFile);
  }

  return "";
}

int CVideoDatabase::GetFileIdByMovie(int idMovie)
{
  const std::string query{PrepareSQL("SELECT idFile FROM movie WHERE idMovie = %i", idMovie)};
  const int idFile{GetSingleValueInt(query, m_pDS)};
  return idFile > 0 ? idFile : -1;
  }

  int CVideoDatabase::GetFileIdByEpisode(int idEpisode)
  {
    const std::string query{
        PrepareSQL("SELECT idFile FROM episode WHERE idEpisode = %i", idEpisode)};
    const int idFile{GetSingleValueInt(query, m_pDS)};
    return idFile > 0 ? idFile : -1;
  }

void CVideoDatabase::GetSameVideoItems(const CFileItem& item, CFileItemList& items)
{
  if (!m_pDB || !m_pDS)
    return;

  std::vector<int> itemIds;

  int dbId = item.GetVideoInfoTag()->m_iDbId;
  MediaType mediaType = item.GetVideoInfoTag()->m_type;

  try
  {
    // get items with same unique ids (imdb, tmdb, etc.) as the specified item, these are
    // the different versions of the item
    // note: old records may have the type 'unknown'

Review comment (refactor):
It's OK to rely more on helper functions but this cosmetic change is not related to the fix and doesn't belong to this commit (or PR).

Code after:
        "SELECT strPath FROM path JOIN files ON path.idPath = files.idPath WHERE idFile = %i",
        idFile));

    if (!m_pDS->eof())
    {
      return m_pDS->fv("strPath").get_asString();
    }
    m_pDS->close();
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "{} failed for file {}", __FUNCTION__, idFile);
  }

  return "";
}

int CVideoDatabase::GetFileIdByMovie(int idMovie)
{
  if (!m_pDB || !m_pDS)
    return -1;

  int idFile = -1;

  try
  {
    m_pDS->query(PrepareSQL("SELECT idFile FROM movie WHERE idMovie = %i", idMovie));

    if (!m_pDS->eof())
    {
      idFile = m_pDS->fv("idFile").get_asInt();
    }

    m_pDS->close();
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "{} failed for movie {}", __FUNCTION__, idMovie);
  }

  return idFile;
}

void CVideoDatabase::GetSameVideoItems(const CFileItem& item, CFileItemList& items)
{
  if (!m_pDB || !m_pDS)
    return;

  std::vector<int> itemIds;

  int dbId = item.GetVideoInfoTag()->m_iDbId;
Repository: xbmc/xbmc
File: xbmc/video/VideoDatabase.cpp (C++)

Code before:
bool CVideoDatabase::LoadVideoInfo(const std::string& strFilenameAndPath, CVideoInfoTag& details, int getDetails /* = VideoDbDetailsAll */)
{
  if (GetMovieInfo(strFilenameAndPath, details))
    return true;
  if (GetEpisodeInfo(strFilenameAndPath, details))
    return true;
  if (GetMusicVideoInfo(strFilenameAndPath, details))
    return true;
  if (GetFileInfo(strFilenameAndPath, details))
    return true;

  return false;
}

bool CVideoDatabase::HasMovieInfo(const std::string& strFilenameAndPath)
{
  try
  {
    if (nullptr == m_pDB)
      return false;
    if (nullptr == m_pDS)
      return false;

    int idMovie = GetMovieId(strFilenameAndPath);
    if (idMovie > 0) // index of zero is also invalid
      return true;
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "{} ({}) failed", __FUNCTION__, strFilenameAndPath);
  }
  return false;
}

bool CVideoDatabase::HasTvShowInfo(const std::string& strPath)
{
  try
  {
    if (nullptr == m_pDB)
      return false;
    if (nullptr == m_pDS)
      return false;
    int idTvShow = GetTvShowId(strPath);
    return (idTvShow > 0); // index of zero is also invalid
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "{} ({}) failed", __FUNCTION__, strPath);
  }
  return false;
}

Review comment (suggestion):
can you please revert those changes.
as a general rule I'd say it's ok to touch up code in immediate proximity to something changed by the commit, but not unrelated areas of the code. It creates unnecessary noise for the review.

Code after:
bool CVideoDatabase::LoadVideoInfo(const std::string& strFilenameAndPath, CVideoInfoTag& details, int getDetails /* = VideoDbDetailsAll */)
{
  if (GetMovieInfo(strFilenameAndPath, details))
    return true;
  if (GetEpisodeInfo(strFilenameAndPath, details))
    return true;
  if (GetMusicVideoInfo(strFilenameAndPath, details))
    return true;
  if (GetFileInfo(strFilenameAndPath, details))
    return true;

  return false;
}

bool CVideoDatabase::HasMovieInfo(const std::string& strFilenameAndPath)
{
  try
  {
    if (nullptr == m_pDB)
      return false;
    if (nullptr == m_pDS)
      return false;

    int idMovie = GetMovieId(strFilenameAndPath);
    return (idMovie > 0); // index of zero is also invalid
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "{} ({}) failed", __FUNCTION__, strFilenameAndPath);
  }
  return false;
}

bool CVideoDatabase::HasTvShowInfo(const std::string& strPath)
{
  try
  {
    if (nullptr == m_pDB)
      return false;
    if (nullptr == m_pDS)
      return false;
    int idTvShow = GetTvShowId(strPath);
    return (idTvShow > 0); // index of zero is also invalid
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "{} ({}) failed", __FUNCTION__, strPath);
  }
  return false;
}
Repository: xbmc/xbmc
File: xbmc/video/test/TestVideoInfoScanner.cpp (C++)

Code before:
/*
 *  Copyright (C) 2005-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#include "FileItem.h"
#include "ServiceBroker.h"
#include "settings/AdvancedSettings.h"
#include "settings/SettingsComponent.h"
#include "video/VideoInfoScanner.h"

#include <gtest/gtest.h>

using namespace KODI;
using ::testing::Test;
using ::testing::WithParamInterface;
using ::testing::ValuesIn;

typedef struct
{
  const char* path;
  std::vector<VIDEO::EPISODE> ranges;
  std::vector<VIDEO::EPISODE> noranges;
} TestEntry;

static const TestEntry TestData[] = {
    //season+episode
    {"foo.S02E03.mkv", {{2, 3}}, {{2, 3}}},
    {"foo.203.mkv", {{2, 3}}, {{2, 3}}},
    //episode only
    {"foo.Ep03.mkv", {{1, 3}}, {{1, 3}}},
    {"foo.Ep_03.mkv", {{1, 3}}, {{1, 3}}},
    {"foo.Part.III.mkv", {{1, 3}}, {{1, 3}}},
    {"foo.Part.3.mkv", {{1, 3}}, {{1, 3}}},
    {"foo.E03.mkv", {{1, 3}}, {{1, 3}}},
    {"foo.2009.E03.mkv", {{1, 3}}, {{1, 3}}},
    // multi-episode
    {"The Legend of Korra - S01E01-02 - Welcome to Republic City & A Leaf in the Wind.mkv",
     {{1, 1}, {1, 2}},
     {{1, 1}, {1, 2}}},
    {"foo.S01E01E02.mkv", {{1, 1}, {1, 2}}, {{1, 1}, {1, 2}}},
    {"foo.S01E03E04E05.mkv", {{1, 3}, {1, 4}, {1, 5}}, {{1, 3}, {1, 4}, {1, 5}}},
    {"foo.S02E01-S02E02.mkv", {{2, 1}, {2, 2}}, {{2, 1}, {2, 2}}},
    {"foo S02E01-bar-S02E02-bar.mkv", {{2, 1}, {2, 2}}, {{2, 1}, {2, 2}}},

Review comment (suggestion):
please apply Copilots's nitpick 
```suggestion
struct TestEntry
```

Code after:
/*
 *  Copyright (C) 2005-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#include "FileItem.h"
#include "ServiceBroker.h"
#include "settings/AdvancedSettings.h"
#include "settings/SettingsComponent.h"
#include "video/VideoInfoScanner.h"

#include <gtest/gtest.h>

using namespace KODI;
using ::testing::Test;
using ::testing::WithParamInterface;
using ::testing::ValuesIn;

struct TestEntry
{
  const char* path;
  std::vector<VIDEO::EPISODE> ranges;
  std::vector<VIDEO::EPISODE> noranges;
};

static const TestEntry TestData[] = {
    //season+episode
    {"foo.S02E03.mkv", {{2, 3}}, {{2, 3}}},
    {"foo.203.mkv", {{2, 3}}, {{2, 3}}},
    //episode only
    {"foo.Ep03.mkv", {{1, 3}}, {{1, 3}}},
    {"foo.Ep_03.mkv", {{1, 3}}, {{1, 3}}},
    {"foo.Part.III.mkv", {{1, 3}}, {{1, 3}}},
    {"foo.Part.3.mkv", {{1, 3}}, {{1, 3}}},
    {"foo.E03.mkv", {{1, 3}}, {{1, 3}}},
    {"foo.2009.E03.mkv", {{1, 3}}, {{1, 3}}},
    // multi-episode
    {"The Legend of Korra - S01E01-02 - Welcome to Republic City & A Leaf in the Wind.mkv",
     {{1, 1}, {1, 2}},
     {{1, 1}, {1, 2}}},
    {"foo.S01E01E02.mkv", {{1, 1}, {1, 2}}, {{1, 1}, {1, 2}}},
    {"foo.S01E03E04E05.mkv", {{1, 3}, {1, 4}, {1, 5}}, {{1, 3}, {1, 4}, {1, 5}}},
    {"foo.S02E01-S02E02.mkv", {{2, 1}, {2, 2}}, {{2, 1}, {2, 2}}},
    {"foo S02E01-bar-S02E02-bar.mkv", {{2, 1}, {2, 2}}, {{2, 1}, {2, 2}}},
Repository: xbmc/xbmc
File: xbmc/filesystem/BlurayDirectory.cpp (C++)

Code before:
void CBlurayDirectory::FindMountPoint(std::string* file)
{
#ifdef HAVE_GETMNTENT_R
  const char* device = file->c_str();

  /* bd path may be a symlink (e.g. /dev/dvd -> /dev/sr0), so make sure
   * we look up the real device
   */
  char* bd_device = realpath(device, NULL);
  if (bd_device == NULL)
    return;

  struct stat st;
  if (lstat(bd_device, &st) == 0 && S_ISBLK(st.st_mode))
  {
    FILE* mtab = setmntent("/proc/self/mounts", "r");
    if (mtab)
    {
      struct mntent *m, mbuf;
      char buf[8192];

      while ((m = getmntent_r(mtab, &mbuf, buf, sizeof(buf))) != NULL)
      {
        if (!strcmp(m->mnt_fsname, bd_device))
        {
          CLog::Log(LOGERROR, "{}: found mount point = {}", __func__, m->mnt_dir);
          // TODO: maybe leak
          *file = std::string(strdup(m->mnt_dir));
          break;
        }
      }
      endmntent(mtab);
    }
  }
  free(bd_device);
#endif
}

bool CBlurayDirectory::GetDirectory(const CURL& url, CFileItemList &items)
{
  Dispose();
  m_url = url;
  std::string root = m_url.GetHostName();
  std::string file = m_url.GetFileName();
  URIUtils::RemoveSlashAtEnd(file);
  URIUtils::RemoveSlashAtEnd(root);

  if (!InitializeBluray(root))
    return false;

  if(file == "root")

Review comment (suggestion):
Better to use CLog:LogF, and then the ``__func__`` is unneccessary

Code after:
  Dispose();
  m_url = url;
  std::string root = m_url.GetHostName();
  std::string file = m_url.GetFileName();
  URIUtils::RemoveSlashAtEnd(file);
  URIUtils::RemoveSlashAtEnd(root);

  if (!InitializeBluray(root))
    return false;

  if(file == "root")
    GetRoot(items);
  else if(file == "root/titles")
    GetTitles(false, items);
  else
  {
    CURL url2 = GetUnderlyingCURL(url);
    CDirectory::CHints hints;
    hints.flags = m_flags;
    if (!CDirectory::GetDirectory(url2, items, hints))
      return false;

    // Found items will have underlying protocol (eg. udf:// or smb://)
    // in path so add back bluray://
    // (so properly recognised in cache as bluray:// files for CFile:Exists() etc..)
    CURL url3{url};
    for (const auto& item : items)
    {
      const CURL url4{item->GetPath()};
      url3.SetFileName(url4.GetFileName());
      item->SetPath(url3.Get());
    }

    url3.SetFileName("menu");
    const std::shared_ptr<CFileItem> item{std::make_shared<CFileItem>()};
    item->SetPath(url3.Get());
    items.Add(item);
  }

  items.AddSortMethod(SortByTrackNumber,  554, LABEL_MASKS("%L", "%D", "%L", ""));    // FileName, Duration | Foldername, empty
  items.AddSortMethod(SortBySize,         553, LABEL_MASKS("%L", "%I", "%L", "%I"));  // FileName, Size | Foldername, Size

  return true;
}

CURL CBlurayDirectory::GetUnderlyingCURL(const CURL& url)
{
  assert(url.IsProtocol("bluray"));
  std::string host = url.GetHostName();
  const std::string& filename = url.GetFileName();
  return CURL(host.append(filename));