1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #include "MusicInfoTagLoaderCDDA.h"
10 
11 #include "MusicInfoTag.h"
12 #include "ServiceBroker.h"
13 #include "network/cddb.h"
14 #include "profiles/ProfileManager.h"
15 #include "settings/SettingsComponent.h"
16 #include "storage/MediaManager.h"
17 #include "utils/log.h"
18 
19 using namespace MUSIC_INFO;
20 
21 #ifdef HAS_DVD_DRIVE
22 using namespace MEDIA_DETECT;
23 using namespace CDDB;
24 #endif
25 
26 //! @todo - remove after Ubuntu 16.04 (Xenial) is EOL
27 #if !defined(LIBCDIO_VERSION_NUM) || (LIBCDIO_VERSION_NUM <= 83)
28 #define CDTEXT_FIELD_TITLE CDTEXT_TITLE
29 #define CDTEXT_FIELD_PERFORMER CDTEXT_PERFORMER
30 #define CDTEXT_FIELD_GENRE CDTEXT_GENRE
31 #endif
32 
33 CMusicInfoTagLoaderCDDA::CMusicInfoTagLoaderCDDA(void) = default;
34 
35 CMusicInfoTagLoaderCDDA::~CMusicInfoTagLoaderCDDA() = default;
36 
Load(const std::string & strFileName,CMusicInfoTag & tag,EmbeddedArt * art)37 bool CMusicInfoTagLoaderCDDA::Load(const std::string& strFileName, CMusicInfoTag& tag, EmbeddedArt *art)
38 {
39 #ifdef HAS_DVD_DRIVE
40   try
41   {
42     tag.SetURL(strFileName);
43     bool bResult = false;
44 
45     // Get information for the inserted disc
46     CCdInfo* pCdInfo = CServiceBroker::GetMediaManager().GetCdInfo();
47     if (pCdInfo == NULL)
48       return bResult;
49 
50     const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager();
51 
52     // Prepare cddb
53     Xcddb cddb;
54     cddb.setCacheDir(profileManager->GetCDDBFolder());
55 
56     int iTrack = atoi(strFileName.substr(13, strFileName.size() - 13 - 5).c_str());
57 
58     // duration is always available
59     tag.SetDuration( ( pCdInfo->GetTrackInformation(iTrack).nMins * 60 )
60                      + pCdInfo->GetTrackInformation(iTrack).nSecs );
61 
62     // Only load cached cddb info in this tag loader, the internet database query is made in CCDDADirectory
63     if (pCdInfo->HasCDDBInfo() && cddb.isCDCached(pCdInfo))
64     {
65       // get cddb information
66       if (cddb.queryCDinfo(pCdInfo))
67       {
68         // Fill the fileitems music tag with cddb information, if available
69         const std::string& strTitle = cddb.getTrackTitle(iTrack);
70         if (!strTitle.empty())
71         {
72           // Tracknumber
73           tag.SetTrackNumber(iTrack);
74 
75           // Title
76           tag.SetTitle(strTitle);
77 
78           // Artist: Use track artist or disc artist
79           std::string strArtist = cddb.getTrackArtist(iTrack);
80           if (strArtist.empty())
81             cddb.getDiskArtist(strArtist);
82           tag.SetArtist(strArtist);
83 
84           // Album
85           std::string strAlbum;
86           cddb.getDiskTitle( strAlbum );
87           tag.SetAlbum(strAlbum);
88 
89           // Album Artist
90           std::string strAlbumArtist;
91           cddb.getDiskArtist(strAlbumArtist);
92           tag.SetAlbumArtist(strAlbumArtist);
93 
94           // Year
95           tag.SetReleaseDate(cddb.getYear());
96 
97           // Genre
98           tag.SetGenre( cddb.getGenre() );
99 
100           tag.SetLoaded(true);
101           bResult = true;
102         }
103       }
104     }
105     else
106     {
107       // No cddb info, maybe we have CD-Text
108       trackinfo ti = pCdInfo->GetTrackInformation(iTrack);
109 
110       // Fill the fileitems music tag with CD-Text information, if available
111       std::string strTitle = ti.cdtext[CDTEXT_FIELD_TITLE];
112       if (!strTitle.empty())
113       {
114         // Tracknumber
115         tag.SetTrackNumber(iTrack);
116 
117         // Title
118         tag.SetTitle(strTitle);
119 
120         // Get info for track zero, as we may have and need CD-Text Album info
121         xbmc_cdtext_t discCDText = pCdInfo->GetDiscCDTextInformation();
122 
123         // Artist: Use track artist or disc artist
124         std::string strArtist = ti.cdtext[CDTEXT_FIELD_PERFORMER];
125         if (strArtist.empty())
126           strArtist = discCDText[CDTEXT_FIELD_PERFORMER];
127         tag.SetArtist(strArtist);
128 
129         // Album
130         std::string strAlbum;
131         strAlbum = discCDText[CDTEXT_FIELD_TITLE];
132         tag.SetAlbum(strAlbum);
133 
134         // Genre: use track or disc genre
135         std::string strGenre = ti.cdtext[CDTEXT_FIELD_GENRE];
136         if (strGenre.empty())
137           strGenre = discCDText[CDTEXT_FIELD_GENRE];
138         tag.SetGenre( strGenre );
139 
140         tag.SetLoaded(true);
141         bResult = true;
142       }
143     }
144     return bResult;
145   }
146   catch (...)
147   {
148     CLog::Log(LOGERROR, "Tag loader CDDB: exception in file %s", strFileName.c_str());
149   }
150 
151 #endif
152 
153   tag.SetLoaded(false);
154 
155   return false;
156 }
157