[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / cdrip / CDDARipJob.cpp
blob3063a91e655d95f5ac73117c15db5e1a94b15f41
1 /*
2 * Copyright (C) 2012-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "CDDARipJob.h"
11 #include "Encoder.h"
12 #include "EncoderAddon.h"
13 #include "EncoderFFmpeg.h"
14 #include "FileItem.h"
15 #include "ServiceBroker.h"
16 #include "Util.h"
17 #include "addons/AddonManager.h"
18 #include "addons/addoninfo/AddonType.h"
19 #include "dialogs/GUIDialogExtendedProgressBar.h"
20 #include "filesystem/File.h"
21 #include "filesystem/SpecialProtocol.h"
22 #include "guilib/GUIComponent.h"
23 #include "guilib/GUIWindowManager.h"
24 #include "guilib/LocalizeStrings.h"
25 #include "network/NetworkFileItemClassify.h"
26 #include "settings/AdvancedSettings.h"
27 #include "settings/Settings.h"
28 #include "settings/SettingsComponent.h"
29 #include "storage/MediaManager.h"
30 #include "utils/StringUtils.h"
31 #include "utils/SystemInfo.h"
32 #include "utils/log.h"
34 #if defined(TARGET_WINDOWS)
35 #include "platform/win32/CharsetConverter.h"
36 #endif
38 using namespace ADDON;
39 using namespace MUSIC_INFO;
40 using namespace XFILE;
41 using namespace KODI;
42 using namespace KODI::CDRIP;
44 CCDDARipJob::CCDDARipJob(const std::string& input,
45 const std::string& output,
46 const CMusicInfoTag& tag,
47 int encoder,
48 bool eject,
49 unsigned int rate,
50 unsigned int channels,
51 unsigned int bps)
52 : m_rate(rate),
53 m_channels(channels),
54 m_bps(bps),
55 m_tag(tag),
56 m_input(input),
57 m_output(CUtil::MakeLegalPath(output)),
58 m_eject(eject),
59 m_encoder(encoder)
63 CCDDARipJob::~CCDDARipJob() = default;
65 bool CCDDARipJob::DoWork()
67 CLog::Log(LOGINFO, "CCDDARipJob::{} - Start ripping track {} to {}", __func__, m_input, m_output);
69 // if we are ripping to a samba share, rip it to hd first and then copy it to the share
70 CFileItem file(m_output, false);
71 if (NETWORK::IsRemote(file))
72 m_output = SetupTempFile();
74 if (m_output.empty())
76 CLog::Log(LOGERROR, "CCDDARipJob::{} - Error opening file", __func__);
77 return false;
80 // init ripper
81 CFile reader;
82 std::unique_ptr<CEncoder> encoder{};
83 if (!reader.Open(m_input, READ_CACHED) || !(encoder = SetupEncoder(reader)))
85 CLog::Log(LOGERROR, "CCDDARipJob::{} - Opening failed", __func__);
86 return false;
89 // setup the progress dialog
90 CGUIDialogExtendedProgressBar* pDlgProgress =
91 CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogExtendedProgressBar>(
92 WINDOW_DIALOG_EXT_PROGRESS);
93 CGUIDialogProgressBarHandle* handle = pDlgProgress->GetHandle(g_localizeStrings.Get(605));
95 int iTrack = atoi(m_input.substr(13, m_input.size() - 13 - 5).c_str());
96 std::string strLine0 =
97 StringUtils::Format("{:02}. {} - {}", iTrack, m_tag.GetArtistString(), m_tag.GetTitle());
98 handle->SetText(strLine0);
100 // start ripping
101 int percent = 0;
102 int oldpercent = 0;
103 bool cancelled{false};
104 int result{-1};
105 while (!cancelled && (result = RipChunk(reader, encoder, percent)) == 0)
107 cancelled = ShouldCancel(percent, 100);
108 if (percent > oldpercent)
110 oldpercent = percent;
111 handle->SetPercentage(static_cast<float>(percent));
115 // close encoder ripper
116 encoder->EncoderClose();
117 encoder.reset();
118 reader.Close();
120 if (NETWORK::IsRemote(file) && !cancelled && result == 2)
122 // copy the ripped track to the share
123 if (!CFile::Copy(m_output, file.GetPath()))
125 CLog::Log(LOGERROR, "CCDDARipJob::{} - Error copying file from {} to {}", __func__, m_output,
126 file.GetPath());
127 CFile::Delete(m_output);
128 return false;
130 // delete cached file
131 CFile::Delete(m_output);
134 if (cancelled)
136 CLog::Log(LOGWARNING, "CCDDARipJob::{} - User Cancelled CDDA Rip", __func__);
137 CFile::Delete(m_output);
139 else if (result == 1)
140 CLog::Log(LOGERROR, "CCDDARipJob::{} - Error ripping {}", __func__, m_input);
141 else if (result < 0)
142 CLog::Log(LOGERROR, "CCDDARipJob::{} - Error encoding {}", __func__, m_input);
143 else
145 CLog::Log(LOGINFO, "CCDDARipJob::{} - Finished ripping {}", __func__, m_input);
146 if (m_eject)
148 CLog::Log(LOGINFO, "CCDDARipJob::{} - Ejecting CD", __func__);
149 CServiceBroker::GetMediaManager().EjectTray();
153 handle->MarkFinished();
155 return !cancelled && result == 2;
158 int CCDDARipJob::RipChunk(CFile& reader, const std::unique_ptr<CEncoder>& encoder, int& percent)
160 percent = 0;
162 uint8_t stream[1024];
164 // get data
165 ssize_t result = reader.Read(stream, 1024);
167 // return if rip is done or on some kind of error
168 if (result <= 0)
169 return 1;
171 // encode data
172 ssize_t encres = encoder->EncoderEncode(stream, result);
174 // Get progress indication
175 percent = static_cast<int>(reader.GetPosition() * 100 / reader.GetLength());
177 if (reader.GetPosition() == reader.GetLength())
178 return 2;
180 return -(1 - encres);
183 std::unique_ptr<CEncoder> CCDDARipJob::SetupEncoder(CFile& reader)
185 std::unique_ptr<CEncoder> encoder;
186 const std::string audioEncoder = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(
187 CSettings::SETTING_AUDIOCDS_ENCODER);
188 if (audioEncoder == "audioencoder.kodi.builtin.aac" ||
189 audioEncoder == "audioencoder.kodi.builtin.wma")
191 encoder = std::make_unique<CEncoderFFmpeg>();
193 else
195 const AddonInfoPtr addonInfo =
196 CServiceBroker::GetAddonMgr().GetAddonInfo(audioEncoder, AddonType::AUDIOENCODER);
197 if (addonInfo)
199 encoder = std::make_unique<CEncoderAddon>(addonInfo);
202 if (!encoder)
203 return std::unique_ptr<CEncoder>{};
205 // we have to set the tags before we init the Encoder
206 const std::string strTrack = StringUtils::Format(
207 "{}", std::stol(m_input.substr(13, m_input.size() - 13 - 5), nullptr, 10));
209 const std::string itemSeparator =
210 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator;
212 encoder->SetComment(std::string("Ripped with ") + CSysInfo::GetAppName());
213 encoder->SetArtist(StringUtils::Join(m_tag.GetArtist(), itemSeparator));
214 encoder->SetTitle(m_tag.GetTitle());
215 encoder->SetAlbum(m_tag.GetAlbum());
216 encoder->SetAlbumArtist(StringUtils::Join(m_tag.GetAlbumArtist(), itemSeparator));
217 encoder->SetGenre(StringUtils::Join(m_tag.GetGenre(), itemSeparator));
218 encoder->SetTrack(strTrack);
219 encoder->SetTrackLength(static_cast<int>(reader.GetLength()));
220 encoder->SetYear(m_tag.GetYearString());
222 // init encoder
223 if (!encoder->EncoderInit(m_output, m_channels, m_rate, m_bps))
224 encoder.reset();
226 return encoder;
229 std::string CCDDARipJob::SetupTempFile()
231 char tmp[MAX_PATH + 1];
232 #if defined(TARGET_WINDOWS)
233 using namespace KODI::PLATFORM::WINDOWS;
234 wchar_t tmpW[MAX_PATH];
235 GetTempFileName(ToW(CSpecialProtocol::TranslatePath("special://temp/")).c_str(), L"riptrack", 0,
236 tmpW);
237 auto tmpString = FromW(tmpW);
238 strncpy_s(tmp, tmpString.length(), tmpString.c_str(), MAX_PATH);
239 #else
240 int fd;
241 strncpy(tmp, CSpecialProtocol::TranslatePath("special://temp/riptrackXXXXXX").c_str(), MAX_PATH);
242 if ((fd = mkstemp(tmp)) == -1)
243 tmp[0] = '\0';
244 if (fd != -1)
245 close(fd);
246 #endif
247 return tmp;
250 bool CCDDARipJob::operator==(const CJob* job) const
252 if (strcmp(job->GetType(), GetType()) == 0)
254 const CCDDARipJob* rjob = dynamic_cast<const CCDDARipJob*>(job);
255 if (rjob)
257 return m_input == rjob->m_input && m_output == rjob->m_output;
260 return false;