mirror of
				https://github.com/ElvishArtisan/rivendell.git
				synced 2025-11-04 08:04:12 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			524 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			524 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// rdmonitor.cpp
 | 
						|
//
 | 
						|
// System Monitor for Rivendell
 | 
						|
//
 | 
						|
//   (C) Copyright 2012-2018 Fred Gleason <fredg@paravelsystems.com>
 | 
						|
//
 | 
						|
//   This program is free software; you can redistribute it and/or modify
 | 
						|
//   it under the terms of the GNU General Public License version 2 as
 | 
						|
//   published by the Free Software Foundation.
 | 
						|
//
 | 
						|
//   This program is distributed in the hope that it will be useful,
 | 
						|
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
//   GNU General Public License for more details.
 | 
						|
//
 | 
						|
//   You should have received a copy of the GNU General Public
 | 
						|
//   License along with this program; if not, write to the Free Software
 | 
						|
//   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						|
//
 | 
						|
 | 
						|
#include <signal.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <unistd.h>
 | 
						|
 | 
						|
#include <qapplication.h>
 | 
						|
#include <qdir.h>
 | 
						|
#include <qfontmetrics.h>
 | 
						|
#include <qlabel.h>
 | 
						|
#include <qmessagebox.h>
 | 
						|
#include <qpainter.h>
 | 
						|
#include <qprocess.h>
 | 
						|
#include <qsqldatabase.h>
 | 
						|
#include <qstringlist.h>
 | 
						|
#include <qtranslator.h>
 | 
						|
 | 
						|
#include <dbversion.h>
 | 
						|
#include <rd.h>
 | 
						|
#include <rdaudioinfo.h>
 | 
						|
#include <rdcmd_switch.h>
 | 
						|
#include <rdmonitor_config.h>
 | 
						|
#include <rdstation.h>
 | 
						|
#include <rdstatus.h>
 | 
						|
 | 
						|
#include "rdmonitor.h"
 | 
						|
 | 
						|
//
 | 
						|
// Icons
 | 
						|
//
 | 
						|
#include "../icons/rivendell-22x22.xpm"
 | 
						|
#include "../icons/greenball.xpm"
 | 
						|
#include "../icons/redball.xpm"
 | 
						|
 | 
						|
void SigHandler(int signo)
 | 
						|
{
 | 
						|
  switch(signo) {
 | 
						|
  case SIGTERM:
 | 
						|
  case SIGINT:
 | 
						|
    exit(0);
 | 
						|
    break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
MainWidget::MainWidget(QWidget *parent)
 | 
						|
  : QWidget(parent,(Qt::WindowFlags)(Qt::WStyle_Customize|Qt::WStyle_NoBorder|Qt::WStyle_StaysOnTop))
 | 
						|
    //  : QWidget(parent,"",(Qt::WindowFlags)(Qt::WStyle_Customize|Qt::WStyle_NoBorder|Qt::WStyle_StaysOnTop|Qt::WX11BypassWM|Qt::WA_AlwaysShowToolTips))
 | 
						|
{
 | 
						|
  QString str;
 | 
						|
  mon_dialog_x=0;
 | 
						|
  mon_dialog_y=0;
 | 
						|
  mon_rdselect_x=0;
 | 
						|
  mon_rdselect_y=0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Read Command Options
 | 
						|
  //
 | 
						|
  RDCmdSwitch *cmd=new RDCmdSwitch(qApp->argc(),qApp->argv(),"rdmonitor","\n");
 | 
						|
  delete cmd;
 | 
						|
 | 
						|
  //
 | 
						|
  // Hide at startup
 | 
						|
  //
 | 
						|
  setGeometry(0,0,0,0);
 | 
						|
 | 
						|
  //
 | 
						|
  // Generate Fonts
 | 
						|
  //
 | 
						|
  QFont font=QFont("Helvetica",12,QFont::Bold);
 | 
						|
  font.setPixelSize(12);
 | 
						|
  mon_metrics=new QFontMetrics(font);
 | 
						|
 | 
						|
  //
 | 
						|
  // Create And Set Icon
 | 
						|
  //
 | 
						|
  setIcon(QPixmap(rivendell_22x22_xpm));
 | 
						|
 | 
						|
  //
 | 
						|
  // Dialogs
 | 
						|
  //
 | 
						|
  mon_rdconfig=new RDConfig();
 | 
						|
  mon_rdconfig->load();
 | 
						|
  mon_rdconfig->setModuleName("RDMonitor");
 | 
						|
 | 
						|
  mon_desktop_widget=new QDesktopWidget();
 | 
						|
  mon_config=new RDMonitorConfig();
 | 
						|
  mon_config->load();
 | 
						|
  mon_position_dialog=new PositionDialog(mon_desktop_widget,mon_config,this);
 | 
						|
  mon_position_dialog->setGeometry(0,0,mon_position_dialog->sizeHint().width(),
 | 
						|
				   mon_position_dialog->sizeHint().height());
 | 
						|
 | 
						|
  //
 | 
						|
  // Name Label
 | 
						|
  //
 | 
						|
  mon_name_label=new QLabel(this);
 | 
						|
  mon_name_label->setFont(font);
 | 
						|
 | 
						|
  //
 | 
						|
  // Status Icons
 | 
						|
  //
 | 
						|
  mon_green_label=new QLabel(this);
 | 
						|
  mon_green_label->setPixmap(QPixmap(greenball_xpm));
 | 
						|
  mon_green_label->hide();
 | 
						|
 | 
						|
  mon_red_label=new QLabel(this);
 | 
						|
  mon_red_label->setPixmap(QPixmap(redball_xpm));
 | 
						|
  mon_red_label->hide();
 | 
						|
 | 
						|
  //
 | 
						|
  // Status Label
 | 
						|
  //
 | 
						|
  mon_status_label=new QLabel(tr("Status: unknown"),NULL,
 | 
						|
			      (Qt::WindowFlags)(Qt::WStyle_Customize|
 | 
						|
						Qt::WStyle_NoBorder|
 | 
						|
						Qt::WStyle_StaysOnTop));
 | 
						|
  mon_status_label->setAlignment(Qt::AlignCenter|Qt::AlignVCenter);
 | 
						|
  mon_status_label->
 | 
						|
    setStyleSheet(QString("background-color:")+RD_STATUS_BACKGROUND_COLOR);
 | 
						|
  mon_status_label->hide();
 | 
						|
 | 
						|
  //
 | 
						|
  // Validation Timer
 | 
						|
  //
 | 
						|
  mon_validate_timer=new QTimer(this);
 | 
						|
  connect(mon_validate_timer,SIGNAL(timeout()),this,SLOT(validate()));
 | 
						|
  mon_validate_timer->start(5000);
 | 
						|
 | 
						|
  //  mon_tooltip=new StatusTip(this);
 | 
						|
 | 
						|
  mon_name_label->setText(mon_rdconfig->label());
 | 
						|
  SetPosition();
 | 
						|
 | 
						|
  ::signal(SIGTERM,SigHandler);
 | 
						|
  ::signal(SIGINT,SigHandler);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
QSizePolicy MainWidget::sizePolicy() const
 | 
						|
{
 | 
						|
  return QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void MainWidget::validate()
 | 
						|
{
 | 
						|
  bool db_ok=false;
 | 
						|
  bool snd_ok=false;
 | 
						|
  int schema=0;
 | 
						|
  std::vector<QString> bad_cuts;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get Configurations
 | 
						|
  //
 | 
						|
  mon_rdconfig->load();
 | 
						|
  mon_name_label->setText(mon_rdconfig->label());
 | 
						|
 | 
						|
  //
 | 
						|
  // Check Audio Store
 | 
						|
  //
 | 
						|
  snd_ok=RDAudioStoreValid(mon_rdconfig);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check Database
 | 
						|
  //
 | 
						|
  db_ok=RDDbValid(mon_rdconfig,&schema);
 | 
						|
 | 
						|
  //
 | 
						|
  // Record Results
 | 
						|
  //
 | 
						|
  SetToolTip(db_ok,schema,snd_ok);
 | 
						|
  //  mon_tooltip->
 | 
						|
  //    setStatus(QRect(0,0,size().width(),size().height()),db_ok,schema,snd_ok);
 | 
						|
  SetSummaryState(db_ok&&(schema==RD_VERSION_DATABASE)&&snd_ok);
 | 
						|
  SetPosition();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void MainWidget::quitMainWidget()
 | 
						|
{
 | 
						|
  exit(0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void MainWidget::enterEvent(QEvent *e)
 | 
						|
{
 | 
						|
  mon_status_label->show();
 | 
						|
  QWidget::enterEvent(e);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void MainWidget::leaveEvent(QEvent *e)
 | 
						|
{
 | 
						|
  mon_status_label->hide();
 | 
						|
  QWidget::leaveEvent(e);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void MainWidget::mousePressEvent(QMouseEvent *e)
 | 
						|
{
 | 
						|
  if(e->button()!=Qt::RightButton) {
 | 
						|
    e->ignore();
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  e->accept();
 | 
						|
  mon_position_dialog->setGeometry(mon_dialog_x,mon_dialog_y,
 | 
						|
				   mon_position_dialog->sizeHint().width(),
 | 
						|
				   mon_position_dialog->sizeHint().height());
 | 
						|
  if(mon_position_dialog->exec()==0) {
 | 
						|
    mon_config->save();
 | 
						|
    SetPosition();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void MainWidget::mouseDoubleClickEvent(QMouseEvent *e)
 | 
						|
{
 | 
						|
  if(e->button()!=Qt::LeftButton) {
 | 
						|
    e->ignore();
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  e->accept();
 | 
						|
  QDir dir(RD_DEFAULT_RDSELECT_DIR);
 | 
						|
  dir.setFilter(QDir::Files|QDir::Readable);
 | 
						|
  dir.setNameFilter("*.conf");
 | 
						|
  if(dir.entryList().size()>1) {
 | 
						|
    QProcess *proc=new QProcess(this);
 | 
						|
    QStringList args;
 | 
						|
    args.push_back("-geometry");
 | 
						|
    args.push_back(QString().sprintf("+%d+%d",mon_rdselect_x,mon_rdselect_y));
 | 
						|
    proc->start("rdselect",args);
 | 
						|
    proc->waitForFinished(-1);
 | 
						|
    if(proc->exitStatus()!=QProcess::NormalExit) {
 | 
						|
      QMessageBox::critical(this,"RDMonitor - "+tr("Error"),
 | 
						|
			    tr("RDSelect crashed!"));
 | 
						|
      delete proc;
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    if(proc->exitCode()!=0) {
 | 
						|
      QMessageBox::critical(this,"RDMonitor - "+tr("Error"),
 | 
						|
			    tr("RDSelect returned non-zero exit code")+
 | 
						|
			    QString().sprintf(" %d.",proc->exitCode())+
 | 
						|
			    "\n\nERROR MESSAGE:\n"+
 | 
						|
			    proc->readAllStandardError());
 | 
						|
      delete proc;
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    delete proc;
 | 
						|
    validate();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void MainWidget::paintEvent(QPaintEvent *e)
 | 
						|
{
 | 
						|
  QPainter *p=new QPainter(this);
 | 
						|
  p->setPen(QPen(Qt::black,2));
 | 
						|
  p->drawRect(1,1,size().width(),size().height());
 | 
						|
 | 
						|
  delete p;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void MainWidget::resizeEvent(QResizeEvent *e)
 | 
						|
{
 | 
						|
  mon_name_label->setGeometry(10,5,size().width()-30,size().height()-10);
 | 
						|
  mon_green_label->setGeometry(size().width()-20,5,15,20);
 | 
						|
  mon_red_label->setGeometry(size().width()-20,5,15,20);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void MainWidget::SetSummaryState(bool state)
 | 
						|
{
 | 
						|
  if(state) {
 | 
						|
    mon_red_label->hide();
 | 
						|
    mon_green_label->show();
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    mon_green_label->hide();
 | 
						|
    mon_red_label->show();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void MainWidget::SetPosition()
 | 
						|
{
 | 
						|
  int width=mon_metrics->width(mon_name_label->text())+40;
 | 
						|
  QRect geo=mon_desktop_widget->screenGeometry(mon_config->screenNumber());
 | 
						|
  QRect main_geo=mon_desktop_widget->geometry();
 | 
						|
  int x=0;
 | 
						|
  int dx=mon_config->xOffset();
 | 
						|
  int y=0;
 | 
						|
  int dy=mon_config->yOffset();
 | 
						|
  int dw=mon_position_dialog->size().width()+30;
 | 
						|
  int dh=mon_position_dialog->size().height()+30;
 | 
						|
 | 
						|
  switch(mon_config->position()) {
 | 
						|
  case RDMonitorConfig::UpperLeft:
 | 
						|
    x=geo.x()+dx;
 | 
						|
    y=geo.y()+dy;
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::UpperCenter:
 | 
						|
    x=geo.x()+(geo.width()-width)/2;
 | 
						|
    y=geo.y()+dy;
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::UpperRight:
 | 
						|
    x=geo.x()-dx+geo.width()-width;
 | 
						|
    y=geo.y()+dy;
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::LowerLeft:
 | 
						|
    x=geo.x()+dx;
 | 
						|
    y=geo.y()-dy+geo.height()-RDMONITOR_HEIGHT;
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::LowerCenter:
 | 
						|
    x=geo.x()+(geo.width()-width)/2;
 | 
						|
    y=geo.y()-dy+geo.height()-RDMONITOR_HEIGHT;
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::LowerRight:
 | 
						|
    x=geo.x()-dx+geo.width()-width;
 | 
						|
    y=geo.y()-dy+geo.height()-RDMONITOR_HEIGHT;
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::LastPosition:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Ensure sane values
 | 
						|
  //
 | 
						|
  if(x<0) {
 | 
						|
    x=0;
 | 
						|
  }
 | 
						|
  if(x>(main_geo.width()-width)) {
 | 
						|
    x=main_geo.width()-width;
 | 
						|
  }
 | 
						|
  if(y<0) {
 | 
						|
    y=0;
 | 
						|
  }
 | 
						|
  if(y>(main_geo.height()-RDMONITOR_HEIGHT)) {
 | 
						|
    y=main_geo.height()-RDMONITOR_HEIGHT;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Set the dialog position
 | 
						|
  //
 | 
						|
  switch(mon_config->position()) {
 | 
						|
  case RDMonitorConfig::UpperLeft:
 | 
						|
    mon_dialog_x=x;
 | 
						|
    mon_rdselect_x=x;
 | 
						|
    mon_dialog_y=y+RDMONITOR_HEIGHT;
 | 
						|
    mon_rdselect_y=y+RDMONITOR_HEIGHT;
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::UpperCenter:
 | 
						|
    mon_dialog_x=x+(width-dw)/2;
 | 
						|
    mon_dialog_y=y+RDMONITOR_HEIGHT;
 | 
						|
    mon_rdselect_x=x+(width-RDSELECT_WIDTH)/2;
 | 
						|
    mon_rdselect_y=y+RDMONITOR_HEIGHT;
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::UpperRight:
 | 
						|
    mon_dialog_x=x+width-dw;
 | 
						|
    mon_dialog_y=y+RDMONITOR_HEIGHT;
 | 
						|
    mon_rdselect_x=x+width-RDSELECT_WIDTH;
 | 
						|
    mon_rdselect_y=y+RDMONITOR_HEIGHT;
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::LowerLeft:
 | 
						|
    mon_dialog_x=x;
 | 
						|
    mon_rdselect_x=x;
 | 
						|
    mon_dialog_y=y-dh;
 | 
						|
    mon_rdselect_y=y-RDSELECT_HEIGHT-30;
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::LowerCenter:
 | 
						|
    mon_dialog_x=x+(width-dw)/2;
 | 
						|
    mon_dialog_y=y-dh;
 | 
						|
    mon_rdselect_x=x+(width-RDSELECT_WIDTH)/2;
 | 
						|
    mon_rdselect_y=y-RDSELECT_HEIGHT-30;
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::LowerRight:
 | 
						|
    mon_dialog_x=x+width-dw;
 | 
						|
    mon_rdselect_x=x+width-RDSELECT_WIDTH;
 | 
						|
    mon_dialog_y=y-dh;
 | 
						|
    mon_rdselect_y=y-RDSELECT_HEIGHT-30;
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::LastPosition:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  setGeometry(x,y,width,RDMONITOR_HEIGHT);
 | 
						|
  SetStatusPosition();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void MainWidget::SetToolTip(bool db_status,int schema,bool snd_status)
 | 
						|
{
 | 
						|
  mon_status_label->clear();
 | 
						|
  if(db_status&&(schema==RD_VERSION_DATABASE)&&snd_status) {
 | 
						|
    mon_status_label->setText(tr("Status: OK"));
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    if(!db_status) {
 | 
						|
      mon_status_label->setText(tr("Database: CONNECTION FAILED"));
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      if(schema!=RD_VERSION_DATABASE) {
 | 
						|
	mon_status_label->setText(tr("Database: SCHEMA SKEWED"));
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if(!snd_status) {
 | 
						|
      if(!mon_status_label->text().isEmpty()) {
 | 
						|
	mon_status_label->setText(mon_status_label->text()+"\n");
 | 
						|
      }
 | 
						|
      mon_status_label->
 | 
						|
	setText(mon_status_label->text()+tr("Audio Store: FAILED"));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  SetStatusPosition();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void MainWidget::SetStatusPosition()
 | 
						|
{
 | 
						|
  QFontMetrics *fm=new QFontMetrics(mon_status_label->font());
 | 
						|
  int h=10+fm->height();
 | 
						|
  int w=10+fm->width(mon_status_label->text());
 | 
						|
  QRect g=geometry();
 | 
						|
 | 
						|
  switch(mon_config->position()) {
 | 
						|
  case RDMonitorConfig::UpperLeft:
 | 
						|
    mon_status_label->setGeometry(20+g.x(),g.y()+(2+g.height()),w,h);
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::UpperCenter:
 | 
						|
    mon_status_label->
 | 
						|
      setGeometry(g.x()+(g.width()-w)/2,g.y()+(2+g.height()),w,h);
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::UpperRight:
 | 
						|
    mon_status_label->
 | 
						|
      setGeometry(g.x()+g.width()-w-20,g.y()+(2+g.height()),w,h);
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::LowerLeft:
 | 
						|
    mon_status_label->setGeometry(20+g.x(),g.y()-(2+h),w,h);
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::LowerCenter:
 | 
						|
    mon_status_label->setGeometry(g.x()+(g.width()-w)/2,g.y()-(2+h),w,h);
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::LowerRight:
 | 
						|
    mon_status_label->setGeometry(g.x()+g.width()-w-20,g.y()-(2+h),w,h);
 | 
						|
    break;
 | 
						|
 | 
						|
  case RDMonitorConfig::LastPosition:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  delete fm;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int main(int argc,char *argv[])
 | 
						|
{
 | 
						|
  QApplication::setStyle(RD_GUI_STYLE);
 | 
						|
  QApplication a(argc,argv);
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Load Translations
 | 
						|
  //
 | 
						|
  QTranslator qt(0);
 | 
						|
  qt.load(QString("/usr/share/qt4/translations/qt_")+QTextCodec::locale(),
 | 
						|
	  ".");
 | 
						|
  a.installTranslator(&qt);
 | 
						|
 | 
						|
  QTranslator rd(0);
 | 
						|
  rd.load(QString(PREFIX)+QString("/share/rivendell/librd_")+
 | 
						|
	     QTextCodec::locale(),".");
 | 
						|
  a.installTranslator(&rd);
 | 
						|
 | 
						|
  QTranslator rdhpi(0);
 | 
						|
  rdhpi.load(QString(PREFIX)+QString("/share/rivendell/librdhpi_")+
 | 
						|
	     QTextCodec::locale(),".");
 | 
						|
  a.installTranslator(&rdhpi);
 | 
						|
 | 
						|
  QTranslator tr(0);
 | 
						|
  tr.load(QString(PREFIX)+QString("/share/rivendell/rdmonitor_")+
 | 
						|
	     QTextCodec::locale(),".");
 | 
						|
  a.installTranslator(&tr);
 | 
						|
 | 
						|
  //
 | 
						|
  // Start Event Loop
 | 
						|
  //
 | 
						|
  MainWidget *w=new MainWidget();
 | 
						|
  a.setMainWidget(w);
 | 
						|
  w->show();
 | 
						|
  return a.exec();
 | 
						|
}
 |