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