Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 155be4a
Showing
7 changed files
with
1,171 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#------------------------------------------------- | ||
# | ||
# Project created by QtCreator 2011-10-14T18:13:25 | ||
# | ||
#------------------------------------------------- | ||
|
||
QT += core gui | ||
|
||
TARGET = ScryptMiner GUI | ||
TEMPLATE = app | ||
|
||
|
||
SOURCES += main.cpp\ | ||
mainwindow.cpp | ||
|
||
HEADERS += mainwindow.h | ||
|
||
FORMS += mainwindow.ui |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
ScryptMiner-GUI | ||
=== | ||
|
||
A simple GUI for the scrypt-based cpuminer written in C++ using Qt. | ||
|
||
To use, copy the minerd executable to the same directory as the GUI itself, alongside with any needed libraries. | ||
After that, just run the GUI executable. | ||
|
||
=== | ||
|
||
LICENSING INFORMATION | ||
|
||
=== | ||
|
||
Copyright (C) 2011 by Matoking | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#include <QtGui/QApplication> | ||
#include "mainwindow.h" | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
QApplication a(argc, argv); | ||
MainWindow w; | ||
w.show(); | ||
|
||
return a.exec(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,327 @@ | ||
#include "mainwindow.h" | ||
#include "ui_mainwindow.h" | ||
|
||
MainWindow::MainWindow(QWidget *parent) : | ||
QMainWindow(parent), | ||
ui(new Ui::MainWindow) | ||
{ | ||
ui->setupUi(this); | ||
|
||
setFixedSize(400, 420); | ||
|
||
checkSettings(); | ||
|
||
minerActive = false; | ||
|
||
minerProcess = new QProcess(this); | ||
minerProcess->setProcessChannelMode(QProcess::MergedChannels); | ||
|
||
readTimer = new QTimer(this); | ||
|
||
acceptedShares = 0; | ||
rejectedShares = 0; | ||
|
||
roundAcceptedShares = 0; | ||
roundRejectedShares = 0; | ||
|
||
initThreads = 0; | ||
|
||
connect(readTimer, SIGNAL(timeout()), this, SLOT(readProcessOutput())); | ||
|
||
connect(ui->startButton, SIGNAL(pressed()), this, SLOT(startPressed())); | ||
connect(minerProcess, SIGNAL(started()), this, SLOT(minerStarted())); | ||
connect(minerProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(minerError(QProcess::ProcessError))); | ||
connect(minerProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(minerFinished(int, QProcess::ExitStatus))); | ||
connect(minerProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readProcessOutput())); | ||
} | ||
|
||
MainWindow::~MainWindow() | ||
{ | ||
minerProcess->kill(); | ||
|
||
saveSettings(); | ||
|
||
delete ui; | ||
} | ||
|
||
void MainWindow::startPressed() | ||
{ | ||
if (minerActive == false) | ||
{ | ||
startMining(); | ||
ui->startButton->setText("Stop Mining"); | ||
minerActive = true; | ||
} | ||
else | ||
{ | ||
stopMining(); | ||
ui->startButton->setText("Start Mining"); | ||
minerActive = false; | ||
} | ||
|
||
} | ||
|
||
void MainWindow::startMining() | ||
{ | ||
QStringList args; | ||
QString url = ui->rpcServerLine->text(); | ||
if (!url.contains("http://")) | ||
url.prepend("http://"); | ||
qDebug(url.toAscii()); | ||
QString urlLine = QString("%1:%2").arg(url, ui->portLine->text()); | ||
QString userpassLine = QString("%1:%2").arg(ui->usernameLine->text(), ui->passwordLine->text()); | ||
args << "--algo" << "scrypt"; | ||
args << "--s" << ui->scantimeLine->text().toAscii(); | ||
args << "--url" << urlLine.toAscii(); | ||
args << "--userpass" << userpassLine.toAscii(); | ||
args << "--threads" << ui->threadsBox->currentText().toAscii(); | ||
args << "-P"; | ||
|
||
threadSpeed.clear(); | ||
|
||
acceptedShares = 0; | ||
rejectedShares = 0; | ||
|
||
roundAcceptedShares = 0; | ||
roundRejectedShares = 0; | ||
|
||
initThreads = ui->threadsBox->currentText().toInt(); | ||
|
||
QString program = "minerd"; | ||
|
||
minerProcess->start(program,args); | ||
minerProcess->waitForStarted(-1); | ||
|
||
readTimer->start(500); | ||
} | ||
|
||
void MainWindow::stopMining() | ||
{ | ||
reportToList("Miner stopped", 0, NULL); | ||
ui->mineSpeedLabel->setText("N/A"); | ||
ui->shareCount->setText("Accepted: 0 - Rejected: 0"); | ||
minerProcess->kill(); | ||
readTimer->stop(); | ||
} | ||
|
||
void MainWindow::saveSettings() | ||
{ | ||
QSettings settings("easyminer.conf", QSettings::IniFormat); | ||
|
||
settings.setValue("threads", ui->threadsBox->currentText()); | ||
settings.setValue("scantime", ui->scantimeLine->text()); | ||
settings.setValue("url", ui->rpcServerLine->text()); | ||
settings.setValue("username", ui->usernameLine->text()); | ||
settings.setValue("password", ui->passwordLine->text()); | ||
settings.setValue("port", ui->portLine->text()); | ||
|
||
settings.sync(); | ||
} | ||
|
||
void MainWindow::checkSettings() | ||
{ | ||
QSettings settings("easyminer.conf", QSettings::IniFormat); | ||
if (settings.value("threads").isValid()) | ||
{ | ||
int threads = settings.value("threads").toInt(); | ||
threads--; | ||
ui->threadsBox->setCurrentIndex(threads); | ||
} | ||
|
||
if (settings.value("scantime").isValid()) | ||
ui->scantimeLine->setText(settings.value("scantime").toString()); | ||
if (settings.value("url").isValid()) | ||
ui->rpcServerLine->setText(settings.value("url").toString()); | ||
if (settings.value("username").isValid()) | ||
ui->usernameLine->setText(settings.value("username").toString()); | ||
if (settings.value("password").isValid()) | ||
ui->passwordLine->setText(settings.value("password").toString()); | ||
if (settings.value("port").isValid()) | ||
ui->portLine->setText(settings.value("port").toString()); | ||
} | ||
|
||
void MainWindow::readProcessOutput() | ||
{ | ||
QByteArray output; | ||
|
||
minerProcess->reset(); | ||
|
||
output = minerProcess->readAll(); | ||
|
||
QString outputString(output); | ||
|
||
if (!outputString.isEmpty()) | ||
{ | ||
QStringList list = outputString.split("\n"); | ||
int i; | ||
for (i=0; i<list.size(); i++) | ||
{ | ||
QString line = list.at(i); | ||
if (line.contains("PROOF OF WORK RESULT: true")) | ||
reportToList("Share accepted", SHARE_SUCCESS, getTime(line)); | ||
|
||
else if (line.contains("PROOF OF WORK RESULT: false")) | ||
reportToList("Share rejected", SHARE_FAIL, getTime(line)); | ||
|
||
else if (line.contains("LONGPOLL detected new block")) | ||
reportToList("LONGPOLL detected a new block", LONGPOLL, getTime(line)); | ||
|
||
else if (line.contains("Supported options:")) | ||
reportToList("Miner didn't start properly. Try checking your settings.", FATAL_ERROR, NULL); | ||
|
||
else if (line.contains("The requested URL returned error: 403")) | ||
reportToList("Couldn't connect. Try checking your username and password.", ERROR, NULL); | ||
else if (line.contains("thread ") && line.contains("khash/sec")) | ||
{ | ||
QString threadIDstr = line.at(line.indexOf("thread ")+7); | ||
int threadID = threadIDstr.toInt(); | ||
|
||
int threadSpeedindx = line.indexOf(","); | ||
QString threadSpeedstr = line.mid(threadSpeedindx); | ||
threadSpeedstr.chop(10); | ||
threadSpeedstr.remove(", "); | ||
threadSpeedstr.remove(" "); | ||
threadSpeedstr.remove('\n'); | ||
double speed=0; | ||
speed = threadSpeedstr.toDouble(); | ||
qDebug(threadSpeedstr.toAscii()); | ||
|
||
threadSpeed[threadID] = speed; | ||
|
||
updateSpeed(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
void MainWindow::minerError(QProcess::ProcessError error) | ||
{ | ||
QString errorMessage; | ||
switch(error) | ||
{ | ||
case QProcess::Crashed: | ||
errorMessage = "Miner killed"; | ||
break; | ||
|
||
case QProcess::FailedToStart: | ||
errorMessage = "Miner failed to start"; | ||
break; | ||
|
||
default: | ||
errorMessage = "Unknown error"; | ||
break; | ||
} | ||
|
||
reportToList(errorMessage, ERROR, NULL); | ||
|
||
} | ||
|
||
void MainWindow::minerFinished(int exitCode, QProcess::ExitStatus exitStatus) | ||
{ | ||
QString exitMessage; | ||
switch(exitStatus) | ||
{ | ||
case QProcess::NormalExit: | ||
exitMessage = "Miner exited normally"; | ||
|
||
case QProcess::CrashExit: | ||
exitMessage = "Miner exited."; | ||
|
||
default: | ||
exitMessage = "Miner exited abnormally."; | ||
} | ||
} | ||
|
||
void MainWindow::minerStarted() | ||
{ | ||
reportToList("Miner started. It usually takes a minute until the program starts reporting information.", STARTED, NULL); | ||
} | ||
|
||
void MainWindow::updateSpeed() | ||
{ | ||
double totalSpeed=0; | ||
int totalThreads=0; | ||
QMapIterator<int, double> iter(threadSpeed); | ||
while(iter.hasNext()) | ||
{ | ||
iter.next(); | ||
totalSpeed += iter.value(); | ||
totalThreads++; | ||
} | ||
|
||
if (totalThreads != initThreads) | ||
{ | ||
totalSpeed = (totalSpeed/totalThreads)*initThreads; | ||
} | ||
|
||
QString speedString = QString("%1").arg(totalSpeed); | ||
QString threadsString = QString("%1").arg(initThreads); | ||
|
||
QString acceptedString = QString("%1").arg(acceptedShares); | ||
QString rejectedString = QString("%1").arg(rejectedShares); | ||
|
||
QString roundAcceptedString = QString("%1").arg(roundAcceptedShares); | ||
QString roundRejectedString = QString("%1").arg(roundRejectedShares); | ||
|
||
if (totalThreads == initThreads) | ||
ui->mineSpeedLabel->setText(QString("%1 khash/sec - %2 thread(s)").arg(speedString, threadsString)); | ||
else | ||
ui->mineSpeedLabel->setText(QString("~%1 khash/sec - %2 thread(s)").arg(speedString, threadsString)); | ||
|
||
ui->shareCount->setText(QString("Accepted: %1 (%3) - Rejected: %2 (%4)").arg(acceptedString, rejectedString, roundAcceptedString, roundRejectedString)); | ||
} | ||
|
||
void MainWindow::reportToList(QString msg, int type, QString time) | ||
{ | ||
QString message; | ||
if (time == NULL) | ||
message = QString("[%1] - %2").arg(QTime::currentTime().toString(), msg); | ||
else | ||
message = QString("[%1] - %2").arg(time, msg); | ||
|
||
switch(type) | ||
{ | ||
case SHARE_SUCCESS: | ||
acceptedShares++; | ||
roundAcceptedShares++; | ||
updateSpeed(); | ||
break; | ||
|
||
case SHARE_FAIL: | ||
rejectedShares++; | ||
roundRejectedShares++; | ||
updateSpeed(); | ||
break; | ||
|
||
case FATAL_ERROR: | ||
startPressed(); | ||
break; | ||
|
||
case LONGPOLL: | ||
roundAcceptedShares = 0; | ||
roundRejectedShares = 0; | ||
break; | ||
|
||
default: | ||
break; | ||
} | ||
|
||
ui->list->addItem(message); | ||
ui->list->scrollToBottom(); | ||
} | ||
|
||
QString MainWindow::getTime(QString time) | ||
{ | ||
if (time.contains("[")) | ||
{ | ||
time.resize(21); | ||
time.remove("["); | ||
time.remove("]"); | ||
time.remove(1,11); | ||
|
||
return time; | ||
} | ||
else | ||
return NULL; | ||
} |
Oops, something went wrong.