00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "ripping.h"
00022 #include "settings_general.h"
00023 #define AND &&
00024 #define OR ||
00025 #define NOT !
00026 #define EQUAL ==
00027
00028 #include <KGlobal>
00029 #include <KLocale>
00030 #include <QDir>
00031 #include <QFileInfo>
00032 #include "proxyinfo.h"
00033
00034 ripping::ripping(QObject *parent) : streamripper_base(parent)
00035 {
00036 internal_splitBehavior = QString::SkipEmptyParts;
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 resetStreamripperProperties();
00058
00059
00060
00061
00062 QObject::connect(&m_process,
00063 SIGNAL(stateChanged(QProcess::ProcessState)),
00064 this,
00065 SLOT(streamripperStateChange(QProcess::ProcessState)));
00066 QObject::connect(&m_process,
00067 SIGNAL(error(QProcess::ProcessError)),
00068 this,
00069 SLOT(errorOccured(QProcess::ProcessError)));
00070 QObject::connect(this,
00071 SIGNAL(bitrateChanged(qlonglong, PropertyValue)),
00072 this,
00073 SLOT(emit_metaInterval_milliSecondsChanged()));
00074 }
00075
00076 ripping::~ripping()
00077 {
00078 }
00079
00080 void ripping::emit_metaInterval_milliSecondsChanged()
00081 {
00082 emit metaInterval_milliSecondsChanged(index(), metaInterval_milliSeconds());
00083 }
00084
00085 void ripping::resetStreamripperProperties()
00086 {
00087 setBitrate(default_value_of_bitrate());
00088 setDataSize(default_value_of_dataSize());
00089 setError(default_value_of_error());
00090 setMetaInterval(default_value_of_metaInterval());
00091 setRelayPort(default_value_of_relayPort());
00092 setServerName(default_value_of_serverName());
00093 setSong(default_value_of_song());
00094 setStatus(default_value_of_status());
00095 setStreamName(default_value_of_streamName());
00096 }
00097
00098 void ripping::interpretate_console_output(QStringList & stringList)
00099 {
00100
00101 QString my_line;
00102
00103
00104 bool statusSet=false;
00105 bool relayPortSet=false;
00106 bool streamNameSet=false;
00107 bool serverNameSet=false;
00108 bool bitrateSet=false;
00109 bool metaIntervalSet=false;
00110 bool errorSet=false;
00111
00112 QString help_string;
00113 bool okay;
00114 qint64 helper_qint64;
00115
00116
00117
00118 while (!stringList.isEmpty()) {
00119 my_line = stringList.takeLast();
00120
00121
00122
00123
00124 if (my_line.toLower().startsWith(QString("[ripping... ] "))) {
00125 if (!statusSet) {
00126 setStatus(is_ripping);
00127
00128 my_line = my_line.remove(0, 17);
00129 helper_interpretate_metainfo_and_datasize(my_line);
00130 statusSet = true;
00131 };
00132 }
00133 else if (my_line.toLower().startsWith(QString("[buffering - | ] "))) {
00134 if (!statusSet) {
00135 setStatus(is_buffering);
00136
00137 my_line = my_line.remove(0, 17);
00138 setSong(my_line);
00139 setDataSize(0);
00140 statusSet = true;
00141 };
00142 }
00143 else if (my_line.toLower().startsWith(QString("[skipping... ] "))) {
00144 if (!statusSet) {
00145 setStatus(is_skipping);
00146
00147 my_line = my_line.remove(0, 17);
00148 helper_interpretate_metainfo_and_datasize(my_line);
00149 statusSet = true;
00150 };
00151 }
00152 else if (my_line.toLower().startsWith(QString("connecting")) ||
00153 my_line.toLower().startsWith(QString("[getting track name"))) {
00154 if (!statusSet) {
00155 setStatus(is_connecting);
00156 setSong(default_value_of_song());
00157 setDataSize(default_value_of_dataSize());
00158 statusSet = true;
00159 };
00160 }
00161 else if (my_line.toLower().startsWith(QString("shutting down")) ||
00162 my_line.toLower().startsWith(QString("bye.."))) {
00163 if (!statusSet) {
00164 setStatus(is_saving);
00165 setSong(default_value_of_song());
00166 setDataSize(default_value_of_dataSize());
00167 statusSet = true;
00168 };
00169 }
00170 else if (my_line.toLower().startsWith(QString("relay port: "))) {
00171 if (!relayPortSet) {
00172 helper_qint64 = my_line.right(my_line.size()-12).toLongLong(&okay);
00173 if (NOT okay) {
00174 setRelayPort(-1);
00175 } else {
00176 setRelayPort(helper_qint64);
00177 };
00178 relayPortSet = true;
00179 };
00180 }
00181 else if (my_line.toLower().startsWith(QString("stream: "))) {
00182 if (!streamNameSet) {
00183 setStreamName(my_line.right(my_line.size()-8));
00184 streamNameSet = true;
00185 };
00186 }
00187 else if (my_line.toLower().startsWith(QString("server name: "))) {
00188 if (!serverNameSet) {
00189 setServerName(my_line.right(my_line.size()-13));
00190 serverNameSet = true;
00191 };
00192 }
00193 else if (my_line.toLower().startsWith(QString("bitrate: "))) {
00194 if (!bitrateSet) {
00195 helper_qint64 = my_line.right(my_line.size()-9).toLongLong(&okay);
00196 if (NOT okay) {
00197 setBitrate(-1);
00198 } else {
00199 setBitrate(helper_qint64);
00200 };
00201 bitrateSet = true;
00202 };
00203 }
00204 else if (my_line.toLower().startsWith(QString("declared bitrate: "))) {
00205 if (!bitrateSet) {
00206 helper_qint64 = my_line.right(my_line.size()-18).toLongLong(&okay);
00207 if (NOT okay) {
00208 setBitrate(-1);
00209 } else {
00210 setBitrate(helper_qint64);
00211 };
00212 bitrateSet = true;
00213 };
00214 }
00215 else if (my_line.toLower().startsWith(QString("meta interval: "))) {
00216 if (!metaIntervalSet) {
00217 helper_qint64 = my_line.right(my_line.size()-15).toLongLong(&okay);
00218 if (NOT okay) {
00219 setMetaInterval(-1);
00220 } else {
00221 setMetaInterval(helper_qint64);
00222 };
00223 metaIntervalSet = true;
00224 }
00225 }
00226 else if (my_line.toLower().startsWith(QString("error -"))) {
00227 if (!errorSet) {
00228 setError(my_line);
00229 errorSet = true;
00230 };
00231 } else {
00232 kDebug()
00233 << "could not recognize the following string:"
00234 << my_line
00235 << "size:"
00236 << my_line.size();
00237 };
00238 };
00239 }
00240
00241 void ripping::helper_interpretate_metainfo_and_datasize(QString my_line)
00242 {
00243
00244 QString help_string;
00245 bool okay;
00246 qint64 dataSize;
00247
00248
00249 help_string = my_line.section('[', -1);
00250
00251 my_line.truncate(my_line.size() - help_string.size() - 2);
00252
00253
00254
00255
00256
00257 setSong(my_line);
00258
00259
00260
00261 help_string=help_string.remove(']').simplified().toUpper();
00262 if (help_string.endsWith(QString("KB")) OR help_string.endsWith('K')) {
00263 if (help_string.endsWith(QString("KB"))) {
00264 help_string.truncate(help_string.size() - 2);
00265 } else {
00266 help_string.truncate(help_string.size() - 1);
00267 };
00268 dataSize = help_string.toLongLong(&okay) * 1024;
00269 } else {
00270 if (help_string.endsWith(QString("MB")) OR help_string.endsWith('M')) {
00271 if (help_string.endsWith(QString("MB"))) {
00272 help_string.truncate(help_string.size() - 2);
00273 } else {
00274 help_string.truncate(help_string.size() - 1);
00275 };
00276 dataSize = help_string.toDouble(&okay) * 1024 * 1024;
00277 } else {
00278 if (help_string.endsWith('B')) {
00279
00280 help_string.truncate(help_string.size() - 1);
00281 dataSize = help_string.toLongLong(&okay);
00282 } else {
00283 okay = false;
00284 };
00285 };
00286 };
00287 if (NOT okay) {
00288 setDataSize(-1);
00289 } else {
00290 setDataSize(dataSize);
00291 };
00292 }
00293
00294 PropertyValue ripping::streamName() const
00295 {
00296 return internal_streamName;
00297 }
00298
00299 PropertyValue ripping::formatedStreamName(const QString & theStreamName)
00300 {
00301
00302 PropertyValue temp_streamName;
00303
00304 temp_streamName.internalValue = theStreamName;
00305 if (theStreamName == "Streamripper_rips") {
00306 temp_streamName.formatedValue = theStreamName;
00307 temp_streamName.type = PropertyValue::error;
00308 temp_streamName.toolTip = i18nc(
00309 "@info:tooltip Leave Streamripper_rips unchanged, it is a generic name of a directory",
00310 "Nameless stream. Using <emphasis>Streamripper_rips</emphasis> as replacement.");
00311 temp_streamName.whatsThis = i18nc(
00312 "@info:whatsthis Leave Streamripper_rips unchanged, it is a generic name of a directory",
00313 "This stream does not send a name in his meta data. "
00314 "<emphasis>Streamripper_rips</emphasis> is used as replacement, and "
00315 "you find the recorded files in the directory of the same name.");
00316 } else {
00317 if (theStreamName.isEmpty()) {
00318 temp_streamName.formatedValue = i18nc("@item", "not recognized");
00319 temp_streamName.type = PropertyValue::unset;
00320 temp_streamName.toolTip = i18nc(
00321 "@info:tooltip",
00322 "Could not connect to server.");
00323 temp_streamName.whatsThis = i18nc(
00324 "@info:whatsthis",
00325 "Could not connect to the specified server. So the stream name could not be recognized.");
00326 } else {
00327 temp_streamName.formatedValue = theStreamName;
00328 temp_streamName.type = PropertyValue::value;
00329 };
00330 };
00331
00332 return temp_streamName;
00333 }
00334
00335 void ripping::setStreamName(const QString & newStreamName)
00336 {
00337 if (internal_streamName.internalValue.toString() != newStreamName) {
00338 internal_streamName = formatedStreamName(newStreamName);
00339 emit streamNameChanged(index(), internal_streamName);
00340 };
00341 }
00342
00343 QString ripping::default_value_of_streamName()
00344 {
00345 return QString();
00346 }
00347
00348 PropertyValue ripping::formatedServerName(const QString & theServerName)
00349 {
00350
00351 PropertyValue temp_serverName;
00352
00353
00354 temp_serverName.internalValue = theServerName;
00355 temp_serverName.formatedValue = theServerName;
00356 if (theServerName.isEmpty()) {
00357 temp_serverName.type = PropertyValue::unset;
00358 } else {
00359 temp_serverName.type = PropertyValue::value;
00360 };
00361
00362
00363 return temp_serverName;
00364 }
00365
00366 PropertyValue ripping::serverName() const
00367 {
00368 return internal_serverName;
00369 }
00370
00371 void ripping::setServerName(const QString & newServerName)
00372 {
00373 if (internal_serverName.internalValue.toString() != newServerName) {
00374 internal_serverName = formatedServerName(newServerName);
00375 emit serverNameChanged(index(), internal_serverName);
00376 };
00377 }
00378
00379 QString ripping::default_value_of_serverName()
00380 {
00381 return QString();
00382 }
00383
00384 PropertyValue ripping::status() const
00385 {
00386 return internal_status;
00387 }
00388
00389 PropertyValue ripping::formatedStatus(const statusType theStatus)
00390 {
00391
00392 PropertyValue temp_status;
00393
00394
00395 temp_status.internalValue.setValue(theStatus);
00396 if (theStatus == idle) {
00397 temp_status.type = PropertyValue::unset;
00398 } else {
00399 temp_status.type = PropertyValue::value;
00400 };
00401 switch (theStatus) {
00402 case idle:
00403 temp_status.formatedValue.clear();
00404 temp_status.toolTip.clear();
00405 temp_status.whatsThis.clear();
00406 break;
00407 case is_starting:
00408 temp_status.formatedValue = i18nc("@item status of streamripper", "Starting...");
00409 temp_status.toolTip = i18nc("@info:tooltip", "Invocing Streamripper...");
00410 temp_status.whatsThis = i18nc(
00411 "@info:whatsthis",
00412 "KRadioRipper is invocing Streamripper, the program used to "
00413 "perform the recording process.");
00414 break;
00415 case is_connecting:
00416 temp_status.formatedValue = i18nc("@item status of Streamripper", "Connecting...");
00417 temp_status.toolTip = i18nc("@info:tooltip", "Connecting with the stream server...");
00418 temp_status.whatsThis = i18nc("@info:whatsthis",
00419 "Streamripper is connecting with the stream server.");
00420 break;
00421 case is_buffering:
00422 temp_status.formatedValue = i18nc("@item status of Streamripper", "Buffering...");
00423 temp_status.toolTip = i18nc("@info:tooltip", "Buffering stream data...");
00424 temp_status.whatsThis = i18nc(
00425 "@info:whatsthis",
00426 "Stream data is buffered before starting the recording process.");
00427 break;
00428 case is_skipping:
00429 temp_status.formatedValue = i18nc("@item status of Streamripper", "Skipping...");
00430 temp_status.toolTip = i18nc("@info:tooltip", "Skipping the actual track...");
00431 temp_status.whatsThis = i18nc(
00432 "@info:whatsthis",
00433 "<para>KRadioRipper skips by default the first track, because this track will lack "
00434 "the begin.</para><para>You can change this behavior by editing the settings of the "
00435 "stream.</para>");
00436 break;
00437 case is_ripping:
00438 temp_status.formatedValue = i18nc("@item status of Streamripper", "Recording...");
00439 temp_status.toolTip = i18nc("@info:tooltip", "Recording the stream...");
00440 temp_status.whatsThis = i18nc("@info:whatsthis", "KRadioRipper is recording the stream.");
00441 break;
00442 case is_saving:
00443 temp_status.formatedValue = i18nc("@item status of Streamripper", "Saving...");
00444 temp_status.toolTip = i18nc("@info:tooltip", "Saving files...");
00445 temp_status.whatsThis = i18nc(
00446 "@info:whatsthis",
00447 "The buffer is processed and the last files are saved.");
00448 break;
00449 };
00450
00451 return temp_status;
00452 }
00453
00454 void ripping::setStatus(const statusType newStatus)
00455 {
00456 if (internal_status.internalValue.value<statusType>() != newStatus) {
00457 internal_status = formatedStatus(newStatus);
00458 emit statusChanged(index(), internal_status);
00459 refreshRelayPort();
00460 };
00461
00462 bool newIsRunning = (newStatus != idle);
00463 if (internal_isRunning != newIsRunning) {
00464 internal_isRunning = newIsRunning;
00465 if (newIsRunning) {
00466 emit running();
00467 } else {
00468 emit not_running();
00469 };
00470 };
00471 }
00472
00473 ripping::statusType ripping::default_value_of_status()
00474 {
00475 return idle;
00476 }
00477
00478 PropertyValue ripping::error() const
00479 {
00480 return internal_error;
00481 }
00482
00483 PropertyValue ripping::formatedError(const QString & theError)
00484 {
00485
00486 PropertyValue temp_error;
00487 QString streamripper_error_number;
00488 QString temp_message_of_unknown_id;
00489
00490
00491 temp_error.internalValue = theError;
00492
00493 if (theError.isEmpty()) {
00494 temp_error.type = PropertyValue::unset;
00495 } else {
00496 temp_error.type = PropertyValue::value;
00497 };
00498
00499
00500 if (theError.startsWith(QString("error -"))) {
00501 streamripper_error_number = theError.right(theError.size() - 7);
00502 streamripper_error_number = streamripper_error_number.section(' ', 0, 0);
00503 switch (streamripper_error_number.toLongLong()) {
00504 case 3:
00505 case 6:
00506 temp_error.formatedValue = i18nc("@item error message", "connection failed");
00507 temp_error.toolTip = i18nc("@info:tooltip error message", "Could not connect to server");
00508 temp_error.whatsThis = i18nc(
00509 "@info:whatsthis error message",
00510 "Either the URL is invalid or the corresponding server does not exist.");
00511 break;
00512 case 7:
00513 temp_error.formatedValue = i18nc("@item error message", "incompatible stream");
00514 temp_error.toolTip = i18nc("@info:tooltip error message",
00515 "KRadioRipper can not record this type of stream.");
00516 temp_error.whatsThis = i18nc("@info:whatsthis error message",
00517 "Streamripper (and so also KRadioRipper) can only "
00518 "record shoutcast and icecast streams.");
00519 break;
00520 case 56:
00521 temp_error.formatedValue = i18nc("@item error message", "connection refused");
00522 temp_error.toolTip = i18nc("@info:tooltip error message",
00523 "Try changing the user agent string");
00524 temp_error.whatsThis = i18nc(
00525 "@info:whatsthis error message",
00526 "<para>The server has refused the connection.</para><para>You can try to use another "
00527 "user agent string - maybe the server will accept this.</para>");
00528 break;
00529 case 64:
00530 temp_error.formatedValue = i18nc("@item error message", "no stream");
00531 temp_error.toolTip = i18nc("@info:tooltip error message", "invalid playlist");
00532 temp_error.whatsThis = i18nc("@info:whatsthis error message",
00533 "The URL does not point directly to a stream, but to a "
00534 "playlist. And the playlist is invalid.");
00535 break;
00536 case 36:
00537 case 1001:
00538 temp_error.formatedValue = i18nc("@item error message", "bad download directory");
00539 temp_error.toolTip = i18nc(
00540 "@info:tooltip error message",
00541 "KRadioRipper could not write the file because the download directory is not writable.");
00542 temp_error.whatsThis = i18nc(
00543 "@info:whatsthis error message",
00544 "<para>The download directory is not accessible. Either "
00545 "it does not exist or you do not have sufficient access rights.</para><para>You "
00546 "can change the download directory at <emphasis>Settings</emphasis>, <emphasis>"
00547 "Configure KRadioRipper...</emphasis>, <emphasis>Saving</emphasis>"
00548 "</para>");
00549 break;
00550 default:
00551 temp_message_of_unknown_id = theError.right(theError.size() - 7);
00552 temp_message_of_unknown_id = temp_message_of_unknown_id.section(' ', 1, 1);
00553 temp_error.formatedValue = i18nc("@item error message for an error that was not recognized "
00554 "(item 1: ID number of the error; item 2: error "
00555 "description in english",
00556 "Error %1: %2",
00557 streamripper_error_number.toLongLong(),
00558 temp_message_of_unknown_id);
00559 break;
00560 };
00561 } else {
00562 temp_error.formatedValue = theError;
00563 };
00564
00565 return temp_error;
00566 }
00567
00568 void ripping::setError(const QString & newError)
00569 {
00570 if ((internal_error.internalValue.toString() != newError)) {
00571
00572
00573
00574 internal_error = formatedError(newError);
00575 emit errorChanged(index(), internal_error);
00576 refreshRelayPort();
00577 };
00578 }
00579
00580 QString ripping::default_value_of_error()
00581 {
00582 return QString();
00583 }
00584
00585 PropertyValue ripping::song() const
00586 {
00587 return internal_song;
00588 }
00589
00590 PropertyValue ripping::formatedSong(const QString & theSong)
00591 {
00592
00593 PropertyValue temp_song;
00594
00595
00596 temp_song.internalValue = theSong;
00597 if ((theSong.isEmpty()) OR (theSong EQUAL " - ")) {
00598 temp_song.type = PropertyValue::unset;
00599 temp_song.formatedValue.clear();
00600 } else {
00601 temp_song.type = PropertyValue::value;
00602 temp_song.formatedValue = theSong;
00603 };
00604
00605 return temp_song;
00606 }
00607
00608 void ripping::setSong(const QString & newSong)
00609 {
00610 if (internal_song.internalValue.toString() != newSong) {
00611 internal_song = formatedSong(newSong);
00612 emit songChanged(index(), internal_song);
00613 };
00614 }
00615
00616 QString ripping::default_value_of_song()
00617 {
00618 return QString();
00619 }
00620
00621 PropertyValue ripping::dataSize() const
00622 {
00623 return internal_dataSize;
00624 }
00625
00626 PropertyValue ripping::formatedDataSize(const qint64 theDataSize)
00627 {
00628
00629 PropertyValue temp_dataSize;
00630
00631
00632 temp_dataSize.internalValue = theDataSize;
00633 if (theDataSize == (-1)) {
00634 temp_dataSize.type = PropertyValue::error;
00635 temp_dataSize.formatedValue = i18nc("@item", "error");
00636 temp_dataSize.toolTip = i18nc ("@info:tooltip", "Error determinating track size");
00637 temp_dataSize.whatsThis = i18nc (
00638 "@info:whatsthis",
00639 "The track size could not be determinated. Please report this as a bug.");
00640 } else {
00641 if (theDataSize >= 0) {
00642 temp_dataSize.type = PropertyValue::value;
00643 temp_dataSize.formatedValue = ki18nc("@item The unit is MiB instead of MB. See "
00644 "http://en.wikipedia.org/wiki/Binary_prefix "
00645 "for details.",
00646 "%1 MiB")
00647 .subs(double(theDataSize) / (1024 * 1024), 0, 'f', 2).toString();
00648 temp_dataSize.whatsThis = i18nc("@info:whatsthis",
00649 "<para>The size of the track in MiB.</para><para>MiB "
00650 "has a binary prefix which means 1024 * 1024 B = "
00651 "1048576 B (different from MB which would mean "
00652 "1000000 B).</para>");
00653 } else {
00654 temp_dataSize.type = PropertyValue::unset;
00655 temp_dataSize.formatedValue.clear();
00656 temp_dataSize.whatsThis.clear();
00657 };
00658 temp_dataSize.toolTip.clear();
00659 };
00660 temp_dataSize.formatedValueAlignment = (Qt::AlignRight | Qt::AlignVCenter);
00661
00662 return temp_dataSize;
00663 }
00664
00665 void ripping::setDataSize(const qint64 newDataSize)
00666 {
00667 if (internal_dataSize.internalValue.toLongLong() != newDataSize) {
00668 internal_dataSize = formatedDataSize(newDataSize);
00669 emit dataSizeChanged(index(), internal_dataSize);
00670 };
00671 }
00672
00673 qint64 ripping::default_value_of_dataSize()
00674 {
00675 return (-2);
00676 }
00677
00678 bool ripping::default_value_of_isRunning()
00679 {
00680 return false;
00681 }
00682
00683 bool ripping::isRunning() const
00684 {
00685 return internal_isRunning;
00686 }
00687
00688 PropertyValue ripping::relayPort() const
00689 {
00690 return internal_relayPort;
00691 }
00692
00693 PropertyValue ripping::formatedRelayPort(const qint64 theRelayPort)
00694 {
00695
00696 PropertyValue temp_relayPort;
00697
00698
00699 temp_relayPort.internalValue = theRelayPort;
00700 if (theRelayPort == (-1)) {
00701 temp_relayPort.type = PropertyValue::error;
00702 temp_relayPort.formatedValue = i18nc(
00703 "@item",
00704 "error");
00705 temp_relayPort.toolTip = i18nc (
00706 "@info:tooltip",
00707 "Error determinating relay server port");
00708 temp_relayPort.whatsThis = i18nc (
00709 "@info:whatsthis",
00710 "The port of the relay server could not be determinated. Please report this as a bug.");
00711 } else {
00712 if (theRelayPort >= 0) {
00713 temp_relayPort.type = PropertyValue::value;
00714 temp_relayPort.formatedValue = KGlobal::locale()->formatLong(theRelayPort);
00715 } else {
00716 temp_relayPort.type = PropertyValue::unset;
00717 temp_relayPort.formatedValue.clear();
00718 };
00719 temp_relayPort.toolTip.clear();
00720 temp_relayPort.whatsThis.clear();
00721 };
00722 temp_relayPort.formatedValueAlignment = (Qt::AlignRight | Qt::AlignVCenter);
00723
00724 return temp_relayPort;
00725 }
00726
00727 void ripping::refreshRelayPort()
00728 {
00729 statusType actualStatus = status().internalValue.value<statusType>();
00730 if ((actualStatus == is_skipping || actualStatus == is_ripping) &&
00731 (error().type == PropertyValue::unset)) {
00732 internal_relayPort = formatedRelayPort(lastRecognizedRelayPort);
00733 } else {
00734 internal_relayPort = formatedRelayPort(-2);
00735 };
00736 emit relayPortChanged(index(), internal_relayPort);
00737 }
00738
00739 void ripping::setRelayPort(const qint64 newRelayPort)
00740 {
00741 if (lastRecognizedRelayPort != newRelayPort) {
00742 lastRecognizedRelayPort = newRelayPort;
00743 refreshRelayPort();
00744 };
00745 }
00746
00747 qint64 ripping::default_value_of_relayPort()
00748 {
00749 return (-2);
00750 }
00751
00752 PropertyValue ripping::bitrate() const
00753 {
00754 return internal_bitrate;
00755 }
00756
00757 PropertyValue ripping::formatedBitrate(const qint64 theBitrate)
00758 {
00759
00760 PropertyValue temp_bitrate;
00761
00762
00763 temp_bitrate.internalValue=theBitrate;
00764
00765 if (theBitrate >= 1) {
00766 temp_bitrate.formatedValue = i18ncp(
00767 "@item This makes a nicly formated string for the bitrate of a stream - %1 is an integer. "
00768 "WARNING: Unit has changed! It is now kbit instead of Kibit. "
00769 "This means 1000 bit (NOT 1024).",
00770 "%1 kbit/s",
00771 "%1 kbit/s",
00772 theBitrate);
00773 temp_bitrate.type = PropertyValue::value;
00774 temp_bitrate.toolTip = i18nc("@info:tooltip", "declared bit rate");
00775 temp_bitrate.whatsThis = i18nc(
00776 "@info:whatsthis WARNING Unit has changed from binary prefix to SI prefix",
00777 "<para>The declared bit rate of the stream in kbit/s.</para><para>kbit has an SI prefix "
00778 "which means 1000 bit (different from Kibit which would mean 1024 bit). So 1 kbit/s "
00779 "means 1000 bits per second.</para>");
00780 } else {
00781 if (theBitrate >= -1) {
00782 temp_bitrate.formatedValue = i18nc(
00783 "@item This makes a nicly formated string for the bitrate of a stream.",
00784 "Unable to recognize bitrate.");
00785 temp_bitrate.type = PropertyValue::error;
00786 temp_bitrate.toolTip = i18nc (
00787 "@info:tooltip",
00788 "Error determinating bit rate");
00789 temp_bitrate.whatsThis = i18nc (
00790 "@info:whatsthis",
00791 "The bit rate could not be determinated. Please report this as a bug.");
00792 } else {
00793 temp_bitrate.formatedValue.clear();
00794 temp_bitrate.type = PropertyValue::unset;
00795 temp_bitrate.toolTip.clear();
00796 temp_bitrate.whatsThis.clear();
00797 }
00798 };
00799
00800 temp_bitrate.formatedValueAlignment = (Qt::AlignRight | Qt::AlignVCenter);
00801
00802 return temp_bitrate;
00803 }
00804
00805 void ripping::setBitrate(const qint64 newBitrate)
00806 {
00807 if (internal_bitrate.internalValue.toLongLong() != newBitrate) {
00808 internal_bitrate = formatedBitrate(newBitrate);
00809 emit bitrateChanged(index(), internal_bitrate);
00810 };
00811 }
00812
00813 qint64 ripping::default_value_of_bitrate()
00814 {
00815 return (-2);
00816 }
00817
00818 PropertyValue ripping::metaInterval() const
00819 {
00820 return internal_metaInterval;
00821 }
00822
00823 PropertyValue ripping::formatedMetaInterval(const qint64 theMetaInterval)
00824 {
00825
00826 PropertyValue temp_metaInterval;
00827
00828
00829 temp_metaInterval.internalValue = theMetaInterval;
00830 if (theMetaInterval > 0) {
00831 temp_metaInterval.formatedValue =
00832 ki18nc("@item The unit is KiB instead of kB. See "
00833 "http://en.wikipedia.org/wiki/Binary_prefix for details.",
00834 "%1 KiB")
00835 .subs(qint64(theMetaInterval / 1024)).toString();
00836 temp_metaInterval.type = PropertyValue::value;
00837 } else {
00838 if (theMetaInterval >= -1) {
00839 temp_metaInterval.formatedValue = i18nc(
00840 "@item",
00841 "error");
00842 temp_metaInterval.type = PropertyValue::error;
00843 } else {
00844 temp_metaInterval.formatedValue.clear();
00845 temp_metaInterval.type = PropertyValue::unset;
00846 };
00847 };
00848 temp_metaInterval.formatedValueAlignment = (Qt::AlignRight | Qt::AlignVCenter);
00849
00850 return temp_metaInterval;
00851 }
00852
00853 void ripping::setMetaInterval(const qint64 newMetaInterval)
00854 {
00855 if (internal_metaInterval.internalValue != newMetaInterval) {
00856 internal_metaInterval = formatedMetaInterval(newMetaInterval);
00857 emit metaIntervalChanged(index(), internal_metaInterval);
00858 };
00859 }
00860
00861 qint64 ripping::default_value_of_metaInterval()
00862 {
00863 return (-2);
00864 }
00865
00866 PropertyValue ripping::metaInterval_milliSeconds() const
00867 {
00868
00869 qint64 temp;
00870
00871
00872 if (bitrate().type == PropertyValue::value &&
00873 metaInterval().type == PropertyValue::value &&
00874 bitrate().internalValue.toLongLong() > 0) {
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888 temp = (metaInterval().internalValue.toLongLong() * 8) / bitrate().internalValue.toLongLong();
00889 } else if (bitrate().type == PropertyValue::unset ||
00890 metaInterval().type == PropertyValue::unset) {
00891 temp = -2;
00892 } else {
00893 temp = -1;
00894 };
00895 return formatedMetaInterval_milliSeconds(temp);
00896 }
00897
00898 PropertyValue ripping::formatedMetaInterval_milliSeconds(const qint64 theMetaInterval)
00899 {
00900
00901 PropertyValue temp_metaInterval_milliSeconds;
00902
00903
00904 temp_metaInterval_milliSeconds.internalValue = theMetaInterval;
00905 if (theMetaInterval > 0) {
00906 temp_metaInterval_milliSeconds.formatedValue =
00907 ki18nc("@item milliseconds", "%1 ms").subs(theMetaInterval).toString();
00908 temp_metaInterval_milliSeconds.type = PropertyValue::value;
00909 } else {
00910 if (theMetaInterval >= -1) {
00911 temp_metaInterval_milliSeconds.formatedValue = i18nc(
00912 "@item",
00913 "error");
00914 temp_metaInterval_milliSeconds.type = PropertyValue::error;
00915 } else {
00916 temp_metaInterval_milliSeconds.formatedValue.clear();
00917 temp_metaInterval_milliSeconds.type = PropertyValue::unset;
00918 };
00919 };
00920 temp_metaInterval_milliSeconds.formatedValueAlignment = (Qt::AlignRight | Qt::AlignVCenter);
00921
00922 return temp_metaInterval_milliSeconds;
00923 }
00924
00925 void ripping::errorOccured(const QProcess::ProcessError error)
00926 {
00927
00928 QFileInfo m_file_info(settings_general::streamripperCommand());
00929
00930
00931 switch (error) {
00932 case QProcess::FailedToStart:
00933 if (m_file_info.exists()) {
00934 setError(i18nc(
00935 "@item streamripper error",
00936 "Insufficient permissions to invoke Streamripper."));
00937 } else {
00938 setError(i18nc("@item streamripper error", "Streamripper binary not found."));
00939 };
00940 break;
00941 case QProcess::Crashed:
00942 setError(i18nc("@item streamripper error", "Streamripper crashed."));
00943 break;
00944 case QProcess::Timedout:
00945 setError(i18nc("@item streamripper error", "Streamripper does not react."));
00946 break;
00947 default:
00948 setError(i18nc("@item streamripper error", "Error accessing Streamripper."));
00949 break;
00950 };
00951 }
00952
00953 void ripping::streamripperStateChange(const QProcess::ProcessState newState)
00954 {
00955 if (newState == QProcess::NotRunning) {
00956 setStatus(default_value_of_status());
00957 setSong(default_value_of_song());
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970 setDataSize(default_value_of_dataSize());
00971 setRelayPort(default_value_of_relayPort());
00972 };
00973 }
00974
00975 QStringList ripping::parameterList() const
00976 {
00977
00978 QStringList parameters;
00979 QString temp;
00980
00981
00982 parameters.append(serverUri());
00983
00984 parameters.append(QString("-t"));
00985
00986
00987
00988
00989 temp = proxyinfo::proxyserver(serverUri()).at(0);
00990 if (temp != "direct://") {
00991 parameters.append(QString("-p"));
00992 parameters.append(temp);
00993 };
00994
00995 if (settings_general::createRelayServer()) {
00996
00997 parameters.append(QString("-r"));
00998 parameters.append(QString::number(settings_general::preferedPortForRelayServer()));
00999
01000
01001 parameters.append(QString("-R"));
01002 if (settings_general::limitConnections()) {
01003 parameters.append(QString::number(settings_general::limitConnectionsToX()));
01004 } else {
01005 parameters.append(QString("0"));
01006 };
01007 };
01008
01009 parameters.append(QString("-c"));
01010
01011 return parameters;
01012 }
01013
01014 QString ripping::streamripperCommand() const
01015 {
01016 return settings_general::streamripperCommand();
01017 }
01018
01019 void ripping::startStreamripper()
01020 {
01021
01022 QFileInfo * dir;
01023 QDir *dirCreator;
01024 QString temp;
01025
01026
01027 if (m_process.state() == QProcess::NotRunning) {
01028
01029 setError(QString());
01030 setStatus(is_starting);
01031 temp = workingDirectory();
01032 if (temp.startsWith(QLatin1String("file://"))) {
01033 temp.remove(0, 7);
01034 };
01035 dir = new QFileInfo(temp);
01036
01037 if ((!dir->exists()) && dir->isAbsolute()) {
01038 dirCreator = new QDir();
01039 dirCreator->mkpath(dir->filePath());
01040 dir->refresh();
01041 };
01042 if (dir->exists() && dir->isAbsolute() && dir->isDir() &&
01043 dir->isReadable() && dir->isWritable()) {
01044 m_process.setWorkingDirectory(workingDirectory());
01045 streamripper_base::startStreamripper();
01046 } else {
01047
01048 setError("error -1001 [BAD_DOWNLOAD_DIRECTORY]");
01049 setStatus(idle);
01050 };
01051 };
01052 }
01053
01054 void ripping::shutDown()
01055 {
01056 m_process.terminate();
01057
01058
01059 }
01060
01061 bool ripping::doesTheUserWantsThatTheStreamIsRipping(ripping::statusType theStatus)
01062 {
01063 return (!((theStatus == ripping::idle) OR (theStatus == ripping::is_saving)));
01064 }
01065
01066 bool ripping::doesTheUserWantsThatTheStreamIsRipping()
01067 {
01068 return doesTheUserWantsThatTheStreamIsRipping(
01069 internal_status.internalValue.value<statusType>());
01070 }