Merged 'jackports'

This commit is contained in:
Fred Gleason 2018-06-12 19:02:54 +00:00
commit 354eadf55b
31 changed files with 454 additions and 209 deletions

View File

@ -17045,3 +17045,18 @@
implied schema. implied schema.
2018-06-11 Fred Gleason <fredg@paravelsystems.com> 2018-06-11 Fred Gleason <fredg@paravelsystems.com>
* Fixed a bug that broke the build when JACK support was disabled. * Fixed a bug that broke the build when JACK support was disabled.
* Added a 'STATIONS.JACK_PORTS' field to the database.
* Incremented the database version to 287.
* Added an 'Initial Audio Ports' control to the 'JACK Configuration'
dialog in rdadmin(1).
2018-06-12 Fred Gleason <fredg@paravelsystems.com>
* Changed the name of the 'Initial Audio Ports' control to
'Active Audio Ports' in the 'Configure JACK' dialog in rdadmin(1).
2018-06-12 Fred Gleason <fredg@paravelsystems.com>
* Added a 'card-num' parameter to the 'Meter Enable' ['ME'] command
in caed(8).
* Added an 'RDCae::enableMetering()' method.
* Modified rdairplay(1) to enable metering explicitly.
* Modified rdcartslots(1) to enable metering explicitly.
* Modified rdlibrary(1) to enable metering explicitly.
* Modified rdpanel(1) to enable metering explicitly.

View File

@ -171,6 +171,9 @@ MainObject::MainObject(QObject *parent,const char *name)
argnum[i]=0; argnum[i]=0;
argptr[i]=0; argptr[i]=0;
auth[i]=false; auth[i]=false;
for(int j=0;j<RD_MAX_CARDS;j++) {
update_meters[j][i]=false;
}
} }
for(int i=0;i<RD_MAX_CARDS;i++) { for(int i=0;i<RD_MAX_CARDS;i++) {
cae_driver[i]=RDStation::None; cae_driver[i]=RDStation::None;
@ -1808,6 +1811,15 @@ void MainObject::DispatchCommand(int ch)
return; return;
} }
meter_port[ch]=port; meter_port[ch]=port;
for(int i=2;i<argnum[ch];i++) {
sscanf(args[ch][i],"%d",&card);
if((card<0)||(card>=RD_MAX_CARDS)) {
EchoArgs(ch,'-');
return;
}
update_meters[card][ch]=true;
}
EchoArgs(ch,'+'); EchoArgs(ch,'+');
SendMeterOutputStatusUpdate(); SendMeterOutputStatusUpdate();
return; return;
@ -1885,6 +1897,7 @@ void MainObject::KillSocket(int ch)
auth[ch]=false; auth[ch]=false;
meter_port[ch]=0; meter_port[ch]=0;
for(int i=0;i<RD_MAX_CARDS;i++) { for(int i=0;i<RD_MAX_CARDS;i++) {
update_meters[i][ch]=false;
for(int j=0;j<RD_MAX_STREAMS;j++) { for(int j=0;j<RD_MAX_STREAMS;j++) {
if(record_owner[i][j]==ch) { if(record_owner[i][j]==ch) {
unsigned len=0; unsigned len=0;
@ -2307,30 +2320,35 @@ void MainObject::FreeMadDecoder(int card,int stream)
void MainObject::SendMeterLevelUpdate(const QString &type,int cardnum, void MainObject::SendMeterLevelUpdate(const QString &type,int cardnum,
int portnum,short levels[]) int portnum,short levels[])
{ {
char msg[1500]; for(int l=0;l<CAE_MAX_CONNECTIONS;l++) {
int n=snprintf(msg,1500,"ML %s %d %d %d %d", if((meter_port[l]>0)&&update_meters[cardnum][l]) {
(const char *)type,cardnum,portnum,levels[0],levels[1]); SendMeterUpdate(QString().sprintf("ML %s %d %d %d %d",
SendMeterUpdate(msg,n); (const char *)type,cardnum,portnum,levels[0],levels[1]),l);
}
}
} }
void MainObject::SendStreamMeterLevelUpdate(int cardnum,int streamnum, void MainObject::SendStreamMeterLevelUpdate(int cardnum,int streamnum,
short levels[]) short levels[])
{ {
char msg[1500]; for(int l=0;l<CAE_MAX_CONNECTIONS;l++) {
int n=snprintf(msg,1500,"MO %d %d %d %d", if((meter_port[l]>0)&&update_meters[cardnum][l]) {
cardnum,streamnum,levels[0],levels[1]); SendMeterUpdate(QString().sprintf("MO %d %d %d %d",
SendMeterUpdate(msg,n); cardnum,streamnum,levels[0],levels[1]),l);
}
}
} }
void MainObject::SendMeterPositionUpdate(int cardnum,unsigned pos[]) void MainObject::SendMeterPositionUpdate(int cardnum,unsigned pos[])
{ {
char msg[1500]; for(unsigned k=0;k<RD_MAX_STREAMS;k++) {
int n; for(int l=0;l<CAE_MAX_CONNECTIONS;l++) {
for(unsigned i=0;i<RD_MAX_STREAMS;i++) { if((meter_port[l]>0)&&update_meters[cardnum][l]) {
n=snprintf(msg,1500,"MP %d %d %d",cardnum,i,pos[i]); SendMeterUpdate(QString().sprintf("MP %d %d %d",cardnum,k,pos[k]),l);
SendMeterUpdate(msg,n); }
}
} }
} }
@ -2341,7 +2359,12 @@ void MainObject::SendMeterOutputStatusUpdate()
if(cae_driver[i]!=RDStation::None) { if(cae_driver[i]!=RDStation::None) {
for(unsigned j=0;j<RD_MAX_PORTS;j++) { for(unsigned j=0;j<RD_MAX_PORTS;j++) {
for(unsigned k=0;k<RD_MAX_STREAMS;k++) { for(unsigned k=0;k<RD_MAX_STREAMS;k++) {
SendMeterOutputStatusUpdate(i,j,k); for(unsigned l=0;l<CAE_MAX_CONNECTIONS;l++) {
if((meter_port[l]>0)&&update_meters[i][l]) {
SendMeterUpdate(QString().sprintf("MS %d %d %d %d",i,j,k,
output_status_flag[i][j][k]),l);
}
}
} }
} }
} }
@ -2351,23 +2374,20 @@ void MainObject::SendMeterOutputStatusUpdate()
void MainObject::SendMeterOutputStatusUpdate(int card,int port,int stream) void MainObject::SendMeterOutputStatusUpdate(int card,int port,int stream)
{ {
char msg[1500]; for(unsigned l=0;l<CAE_MAX_CONNECTIONS;l++) {
int n; if((meter_port[l]>0)&&update_meters[card][l]) {
n=snprintf(msg,1500,"MS %d %d %d %d",card,port,stream, SendMeterUpdate(QString().sprintf("MS %d %d %d %d",card,port,stream,
output_status_flag[card][port][stream]); output_status_flag[card][port][stream]),l);
SendMeterUpdate(msg,n);
}
void MainObject::SendMeterUpdate(const char *msg,unsigned len)
{
for(unsigned i=0;i<CAE_MAX_CONNECTIONS;i++) {
if(meter_port[i]>0) {
meter_socket->writeBlock(msg,len,socket[i]->peerAddress(),meter_port[i]);
} }
} }
} }
void MainObject::SendMeterUpdate(const QString &msg,int conn_id)
{
meter_socket->writeBlock(msg,msg.length(),socket[conn_id]->peerAddress(),
meter_port[conn_id]);
}
int main(int argc,char *argv[]) int main(int argc,char *argv[])
{ {

View File

@ -142,7 +142,7 @@ class MainObject : public QObject
void SendMeterPositionUpdate(int cardnum,unsigned pos[]); void SendMeterPositionUpdate(int cardnum,unsigned pos[]);
void SendMeterOutputStatusUpdate(); void SendMeterOutputStatusUpdate();
void SendMeterOutputStatusUpdate(int card,int port,int stream); void SendMeterOutputStatusUpdate(int card,int port,int stream);
void SendMeterUpdate(const char *msg,unsigned len); void SendMeterUpdate(const QString &msg,int conn_id);
bool debug; bool debug;
unsigned system_sample_rate; unsigned system_sample_rate;
Q_INT16 tcp_port; Q_INT16 tcp_port;
@ -165,6 +165,7 @@ class MainObject : public QObject
bool play_pitch[RD_MAX_CARDS][RD_MAX_STREAMS]; bool play_pitch[RD_MAX_CARDS][RD_MAX_STREAMS];
bool port_status[RD_MAX_CARDS][RD_MAX_PORTS]; bool port_status[RD_MAX_CARDS][RD_MAX_PORTS];
bool output_status_flag[RD_MAX_CARDS][RD_MAX_PORTS][RD_MAX_STREAMS]; bool output_status_flag[RD_MAX_CARDS][RD_MAX_PORTS][RD_MAX_STREAMS];
bool update_meters[RD_MAX_CARDS][CAE_MAX_CONNECTIONS];
struct { struct {
int card; int card;
int stream; int stream;

View File

@ -41,8 +41,6 @@ jack_client_t *jack_client;
RDMeterAverage *jack_input_meter[RD_MAX_PORTS][2]; RDMeterAverage *jack_input_meter[RD_MAX_PORTS][2];
RDMeterAverage *jack_output_meter[RD_MAX_PORTS][2]; RDMeterAverage *jack_output_meter[RD_MAX_PORTS][2];
RDMeterAverage *jack_stream_output_meter[RD_MAX_STREAMS][2]; RDMeterAverage *jack_stream_output_meter[RD_MAX_STREAMS][2];
//volatile jack_default_audio_sample_t jack_input_meter[RD_MAX_PORTS][2];
//volatile jack_default_audio_sample_t jack_output_meter[RD_MAX_PORTS][2];
volatile jack_default_audio_sample_t volatile jack_default_audio_sample_t
jack_input_volume[RD_MAX_PORTS]; jack_input_volume[RD_MAX_PORTS];
volatile jack_default_audio_sample_t volatile jack_default_audio_sample_t
@ -87,10 +85,14 @@ int JackProcess(jack_nframes_t nframes, void *arg)
// //
for(int i=0;i<RD_MAX_PORTS;i++) { for(int i=0;i<RD_MAX_PORTS;i++) {
for(int j=0;j<2;j++) { for(int j=0;j<2;j++) {
jack_input_buffer[i][j]=(jack_default_audio_sample_t *) if(jack_input_port[i][j]!=NULL) {
jack_port_get_buffer(jack_input_port[i][j],nframes); jack_input_buffer[i][j]=(jack_default_audio_sample_t *)
jack_output_buffer[i][j]=(jack_default_audio_sample_t *) jack_port_get_buffer(jack_input_port[i][j],nframes);
jack_port_get_buffer(jack_output_port[i][j],nframes); }
if(jack_output_port[i][j]!=NULL) {
jack_output_buffer[i][j]=(jack_default_audio_sample_t *)
jack_port_get_buffer(jack_output_port[i][j],nframes);
}
} }
} }
@ -99,8 +101,10 @@ int JackProcess(jack_nframes_t nframes, void *arg)
// //
for(int i=0;i<RD_MAX_PORTS;i++) { for(int i=0;i<RD_MAX_PORTS;i++) {
for(int j=0;j<2;j++) { for(int j=0;j<2;j++) {
for(unsigned k=0;k<nframes;k++) { if(jack_output_port[i][j]!=NULL) {
jack_output_buffer[i][j][k]=0.0; for(unsigned k=0;k<nframes;k++) {
jack_output_buffer[i][j][k]=0.0;
}
} }
} }
} }
@ -112,9 +116,11 @@ int JackProcess(jack_nframes_t nframes, void *arg)
for(int j=0;j<RD_MAX_PORTS;j++) { for(int j=0;j<RD_MAX_PORTS;j++) {
if(jack_passthrough_volume[i][j]>0.0) { if(jack_passthrough_volume[i][j]>0.0) {
for(int k=0;k<2;k++) { for(int k=0;k<2;k++) {
for(unsigned l=0;l<nframes;l++) { if((jack_output_port[j][k]!=NULL)&&(jack_input_port[i][k]!=NULL)) {
jack_output_buffer[j][k][l]+= for(unsigned l=0;l<nframes;l++) {
jack_input_buffer[i][k][l]*jack_passthrough_volume[i][j]; jack_output_buffer[j][k][l]+=
jack_input_buffer[i][k][l]*jack_passthrough_volume[i][j];
}
} }
} }
} }
@ -125,68 +131,70 @@ int JackProcess(jack_nframes_t nframes, void *arg)
// Process Input Streams // Process Input Streams
// //
for(int i=0;i<RD_MAX_PORTS;i++) { for(int i=0;i<RD_MAX_PORTS;i++) {
if(jack_recording[i]) { if(jack_input_port[i][0]!=NULL) {
switch(jack_input_channels[i]) { if(jack_recording[i]) {
case 1: // mono switch(jack_input_channels[i]) {
for(unsigned j=0;j<nframes;j++) { case 1: // mono
switch(jack_input_mode[jack_card_process][i]) { for(unsigned j=0;j<nframes;j++) {
case 3: // R only switch(jack_input_mode[jack_card_process][i]) {
jack_callback_buffer[j]=jack_input_volume[i]* case 3: // R only
jack_input_buffer[i][1][j]; jack_callback_buffer[j]=jack_input_volume[i]*
break; jack_input_buffer[i][1][j];
case 2: // L only break;
jack_callback_buffer[j]=jack_input_volume[i]* case 2: // L only
jack_input_buffer[i][0][j]; jack_callback_buffer[j]=jack_input_volume[i]*
break; jack_input_buffer[i][0][j];
case 1: // swap, sum R+L break;
case 0: // normal, sum L+R case 1: // swap, sum R+L
default: case 0: // normal, sum L+R
jack_callback_buffer[j]=jack_input_volume[i]* default:
(jack_input_buffer[i][0][j]+jack_input_buffer[i][1][j]); jack_callback_buffer[j]=jack_input_volume[i]*
break; (jack_input_buffer[i][0][j]+jack_input_buffer[i][1][j]);
} break;
} // for nframes }
n=jack_record_ring[i]-> } // for nframes
write((char *)jack_callback_buffer, n=jack_record_ring[i]->
nframes*sizeof(jack_default_audio_sample_t))/ write((char *)jack_callback_buffer,
sizeof(jack_default_audio_sample_t); nframes*sizeof(jack_default_audio_sample_t))/
break; sizeof(jack_default_audio_sample_t);
break;
case 2: // stereo case 2: // stereo
for(unsigned j=0;j<nframes;j++) { for(unsigned j=0;j<nframes;j++) {
switch(jack_input_mode[jack_card_process][i]) { switch(jack_input_mode[jack_card_process][i]) {
case 3: // R only case 3: // R only
memset(&jack_callback_buffer[2*j],0, memset(&jack_callback_buffer[2*j],0,
sizeof(jack_input_buffer[i][0][j])); sizeof(jack_input_buffer[i][0][j]));
jack_callback_buffer[2*j+1]=jack_input_volume[i]* jack_callback_buffer[2*j+1]=jack_input_volume[i]*
jack_input_buffer[i][1][j]; jack_input_buffer[i][1][j];
break; break;
case 2: // L only case 2: // L only
jack_callback_buffer[2*j]=jack_input_volume[i]* jack_callback_buffer[2*j]=jack_input_volume[i]*
jack_input_buffer[i][0][j]; jack_input_buffer[i][0][j];
memset(&jack_callback_buffer[2*j+1],0, memset(&jack_callback_buffer[2*j+1],0,
sizeof(jack_input_buffer[i][1][j])); sizeof(jack_input_buffer[i][1][j]));
break; break;
case 1: // swap case 1: // swap
jack_callback_buffer[2*j]=jack_input_volume[i]* jack_callback_buffer[2*j]=jack_input_volume[i]*
jack_input_buffer[i][1][j]; jack_input_buffer[i][1][j];
jack_callback_buffer[2*j+1]=jack_input_volume[i]* jack_callback_buffer[2*j+1]=jack_input_volume[i]*
jack_input_buffer[i][0][j]; jack_input_buffer[i][0][j];
break; break;
case 0: // normal case 0: // normal
default: default:
jack_callback_buffer[2*j]=jack_input_volume[i]* jack_callback_buffer[2*j]=jack_input_volume[i]*
jack_input_buffer[i][0][j]; jack_input_buffer[i][0][j];
jack_callback_buffer[2*j+1]=jack_input_volume[i]* jack_callback_buffer[2*j+1]=jack_input_volume[i]*
jack_input_buffer[i][1][j]; jack_input_buffer[i][1][j];
break; break;
} }
} // for nframes } // for nframes
n=jack_record_ring[i]-> n=jack_record_ring[i]->
write((char *)jack_callback_buffer, write((char *)jack_callback_buffer,
2*nframes*sizeof(jack_default_audio_sample_t))/ 2*nframes*sizeof(jack_default_audio_sample_t))/
(2*sizeof(jack_default_audio_sample_t)); (2*sizeof(jack_default_audio_sample_t));
break; break;
}
} }
} }
} }
@ -229,37 +237,39 @@ int JackProcess(jack_nframes_t nframes, void *arg)
break; break;
} }
for(int j=0;j<RD_MAX_PORTS;j++) { for(int j=0;j<RD_MAX_PORTS;j++) {
if(jack_output_volume[j][i]>0.0) { if(jack_output_port[j][0]!=NULL) {
switch(jack_output_channels[i]) { if(jack_output_volume[j][i]>0.0) {
case 1: switch(jack_output_channels[i]) {
for(unsigned k=0;k<n;k++) { case 1:
jack_output_buffer[j][0][k]= for(unsigned k=0;k<n;k++) {
jack_output_buffer[j][0][k]+jack_output_volume[j][i]* jack_output_buffer[j][0][k]=
jack_callback_buffer[k]; jack_output_buffer[j][0][k]+jack_output_volume[j][i]*
jack_output_buffer[j][1][k]= jack_callback_buffer[k];
jack_output_buffer[j][1][k]+jack_output_volume[j][i]* jack_output_buffer[j][1][k]=
jack_callback_buffer[k]; jack_output_buffer[j][1][k]+jack_output_volume[j][i]*
} jack_callback_buffer[k];
if(n!=nframes && jack_eof[i]) { }
jack_stopping[i]=true; if(n!=nframes && jack_eof[i]) {
jack_playing[i]=false; jack_stopping[i]=true;
} jack_playing[i]=false;
break; }
break;
case 2: case 2:
for(unsigned k=0;k<n;k++) { for(unsigned k=0;k<n;k++) {
jack_output_buffer[j][0][k]= jack_output_buffer[j][0][k]=
jack_output_buffer[j][0][k]+jack_output_volume[j][i]* jack_output_buffer[j][0][k]+jack_output_volume[j][i]*
jack_callback_buffer[k*2]; jack_callback_buffer[k*2];
jack_output_buffer[j][1][k]= jack_output_buffer[j][1][k]=
jack_output_buffer[j][1][k]+jack_output_volume[j][i]* jack_output_buffer[j][1][k]+jack_output_volume[j][i]*
jack_callback_buffer[k*2+1]; jack_callback_buffer[k*2+1];
}
if(n!=nframes && jack_eof[i]) {
jack_stopping[i]=true;
jack_playing[i]=false;
}
break;
} }
if(n!=nframes && jack_eof[i]) {
jack_stopping[i]=true;
jack_playing[i]=false;
}
break;
} }
} }
} }
@ -272,47 +282,49 @@ int JackProcess(jack_nframes_t nframes, void *arg)
// Process Meters // Process Meters
// //
for(int i=0;i<RD_MAX_PORTS;i++) { for(int i=0;i<RD_MAX_PORTS;i++) {
// input meters (taking input mode into account) if(jack_input_port[i][0]!=NULL) {
in_meter[0]=0.0; // input meters (taking input mode into account)
in_meter[1]=0.0; in_meter[0]=0.0;
for(unsigned k=0;k<nframes;k++) { in_meter[1]=0.0;
switch(jack_input_mode[jack_card_process][i]) {
case 3: // R only
if(jack_input_buffer[i][1][k]>in_meter[1])
in_meter[1]=jack_input_buffer[i][1][k];
break;
case 2: // L only
if(jack_input_buffer[i][0][k]>in_meter[0])
in_meter[0]=jack_input_buffer[i][0][k];
break;
case 1: // swap
if(jack_input_buffer[i][0][k]>in_meter[1])
in_meter[1]=jack_input_buffer[i][0][k];
if(jack_input_buffer[i][1][k]>in_meter[0])
in_meter[0]=jack_input_buffer[i][1][k];
break;
case 0: // normal
default:
if(jack_input_buffer[i][0][k]>in_meter[0])
in_meter[0]=jack_input_buffer[i][0][k];
if(jack_input_buffer[i][1][k]>in_meter[1])
in_meter[1]=jack_input_buffer[i][1][k];
break;
}
} // for nframes
jack_input_meter[i][0]->addValue(in_meter[0]);
jack_input_meter[i][1]->addValue(in_meter[1]);
// output meters
for(int j=0;j<2;j++) {
out_meter[j]=0.0;
for(unsigned k=0;k<nframes;k++) { for(unsigned k=0;k<nframes;k++) {
if(jack_output_buffer[i][j][k]>out_meter[j]) switch(jack_input_mode[jack_card_process][i]) {
out_meter[j]=jack_output_buffer[i][j][k]; case 3: // R only
} if(jack_input_buffer[i][1][k]>in_meter[1])
jack_output_meter[i][j]->addValue(out_meter[j]); in_meter[1]=jack_input_buffer[i][1][k];
break;
case 2: // L only
if(jack_input_buffer[i][0][k]>in_meter[0])
in_meter[0]=jack_input_buffer[i][0][k];
break;
case 1: // swap
if(jack_input_buffer[i][0][k]>in_meter[1])
in_meter[1]=jack_input_buffer[i][0][k];
if(jack_input_buffer[i][1][k]>in_meter[0])
in_meter[0]=jack_input_buffer[i][1][k];
break;
case 0: // normal
default:
if(jack_input_buffer[i][0][k]>in_meter[0])
in_meter[0]=jack_input_buffer[i][0][k];
if(jack_input_buffer[i][1][k]>in_meter[1])
in_meter[1]=jack_input_buffer[i][1][k];
break;
}
} // for nframes
jack_input_meter[i][0]->addValue(in_meter[0]);
jack_input_meter[i][1]->addValue(in_meter[1]);
}
if(jack_output_port[i][0]!=NULL) {
// output meters
for(int j=0;j<2;j++) {
out_meter[j]=0.0;
for(unsigned k=0;k<nframes;k++) {
if(jack_output_buffer[i][j][k]>out_meter[j])
out_meter[j]=jack_output_buffer[i][j][k];
}
jack_output_meter[i][j]->addValue(out_meter[j]);
}
} }
} // for RD_MAX_PORTS } // for RD_MAX_PORTS
return 0; return 0;
} }
@ -631,6 +643,12 @@ void MainObject::jackInit(RDStation *station)
// Register Ports // Register Ports
// //
for(int i=0;i<RD_MAX_PORTS;i++) { for(int i=0;i<RD_MAX_PORTS;i++) {
for(int j=0;j<2;j++) {
jack_output_port[i][j]=NULL;
jack_input_port[i][j]=NULL;
}
}
for(int i=0;i<station->jackPorts();i++) {
name=QString().sprintf("playout_%dL",i); name=QString().sprintf("playout_%dL",i);
jack_output_port[i][0]= jack_output_port[i][0]=
jack_port_register(jack_client,(const char *)name, jack_port_register(jack_client,(const char *)name,

View File

@ -1459,11 +1459,14 @@
<sect2> <sect2>
<title><command>Meter Enable</command></title> <title><command>Meter Enable</command></title>
<para> <para>
Set UDP port to whcih to send meter update messages. Set UDP port to which to send meter update messages for the specified
card(s).
</para> </para>
<para> <para>
<userinput>ME <userinput>ME
<replaceable>udp-port</replaceable>!</userinput> <replaceable>udp-port</replaceable>
<replaceable>card0</replaceable>
<replaceable>..</replaceable>!</userinput>
</para> </para>
<variablelist> <variablelist>
<varlistentry> <varlistentry>
@ -1476,6 +1479,16 @@
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>
<replaceable>card0</replaceable>
</term>
<listitem>
<para>
Audio card number for which to send updates.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</sect2> </sect2>
</sect1> </sect1>

View File

@ -25,6 +25,7 @@ FILTER_MODE int(11) 0=Synchronous, 1=Asynchronous
START_JACK enum('Y','N') START_JACK enum('Y','N')
JACK_SERVER_NAME char(64) JACK_SERVER_NAME char(64)
JACK_COMMAND_LINE char(255) JACK_COMMAND_LINE char(255)
JACK_PORTS int(11) signed
CUE_CARD int(11) signed CUE_CARD int(11) signed
CUE_PORT int(11) signed CUE_PORT int(11) signed
CUE_START_CART int(10) unsigned CUE_START_CART int(10) unsigned

View File

@ -24,7 +24,7 @@
/* /*
* Current Database Version * Current Database Version
*/ */
#define RD_VERSION_DATABASE 286 #define RD_VERSION_DATABASE 287
#endif // DBVERSION_H #endif // DBVERSION_H

View File

@ -118,10 +118,30 @@ void RDCae::connectHost()
SendCommand(QString().sprintf("IS %d %d!",i,j)); SendCommand(QString().sprintf("IS %d %d!",i,j));
} }
} }
SendCommand(QString().sprintf("ME %u!",cae_meter_socket->port()));
} }
} }
void RDCae::enableMetering(std::vector<int> *cards)
{
QString cmd=QString().sprintf("ME %u",cae_meter_socket->port());
for(unsigned i=0;i<cards->size();i++) {
if(cards->at(i)>=0) {
bool found=false;
for(unsigned j=0;j<i;j++) {
if(cards->at(i)==cards->at(j)) {
found=true;
}
}
if(!found) {
cmd+=QString().sprintf(" %d",cards->at(i));
}
}
}
SendCommand(cmd+"!");
}
bool RDCae::loadPlay(int card,QString name,int *stream,int *handle) bool RDCae::loadPlay(int card,QString name,int *stream,int *handle)
{ {
int count=0; int count=0;

View File

@ -45,6 +45,7 @@ class RDCae : public QObject
RDCae(RDStation *station,RDConfig *config,QObject *parent=0); RDCae(RDStation *station,RDConfig *config,QObject *parent=0);
~RDCae(); ~RDCae();
void connectHost(); void connectHost();
void enableMetering(std::vector<int> *cards);
bool loadPlay(int card,QString name,int *stream,int *handle); bool loadPlay(int card,QString name,int *stream,int *handle);
void unloadPlay(int handle); void unloadPlay(int handle);
void positionPlay(int handle,int pos); void positionPlay(int handle,int pos);
@ -127,4 +128,4 @@ class RDCae : public QObject
}; };
#endif #endif // RDCAE_H

View File

@ -336,6 +336,18 @@ void RDStation::setJackCommandLine(const QString &str) const
} }
int RDStation::jackPorts() const
{
return RDGetSqlValue("STATIONS","NAME",station_name,"JACK_PORTS").toInt();
}
void RDStation::setJackPorts(int ports) const
{
SetRow("JACK_PORTS",ports);
}
int RDStation::cueCard() const int RDStation::cueCard() const
{ {
return RDGetSqlValue("STATIONS","NAME",station_name,"CUE_CARD").toInt(); return RDGetSqlValue("STATIONS","NAME",station_name,"CUE_CARD").toInt();
@ -867,14 +879,15 @@ bool RDStation::create(const QString &name,QString *err_msg,
"START_JACK,"+ // 13 "START_JACK,"+ // 13
"JACK_SERVER_NAME,"+ // 14 "JACK_SERVER_NAME,"+ // 14
"JACK_COMMAND_LINE,"+ // 15 "JACK_COMMAND_LINE,"+ // 15
"CUE_CARD,"+ // 16 "JACK_PORTS,"+ // 16
"CUE_PORT,"+ // 17 "CUE_CARD,"+ // 17
"CUE_START_CART,"+ // 18 "CUE_PORT,"+ // 18
"CUE_STOP_CART,"+ // 19 "CUE_START_CART,"+ // 19
"CARTSLOT_COLUMNS,"+ // 20 "CUE_STOP_CART,"+ // 20
"CARTSLOT_ROWS,"+ // 21 "CARTSLOT_COLUMNS,"+ // 21
"ENABLE_DRAGDROP,"+ // 22 "CARTSLOT_ROWS,"+ // 22
"ENFORCE_PANEL_SETUP "+ // 23 "ENABLE_DRAGDROP,"+ // 23
"ENFORCE_PANEL_SETUP "+ // 24
"from STATIONS where "+ "from STATIONS where "+
"NAME=\""+RDEscapeString(exemplar)+"\""; "NAME=\""+RDEscapeString(exemplar)+"\"";
q=new RDSqlQuery(sql); q=new RDSqlQuery(sql);
@ -901,14 +914,15 @@ bool RDStation::create(const QString &name,QString *err_msg,
"START_JACK=\""+RDEscapeString(q->value(13).toString())+"\","+ "START_JACK=\""+RDEscapeString(q->value(13).toString())+"\","+
"JACK_SERVER_NAME=\""+RDEscapeString(q->value(14).toString())+"\","+ "JACK_SERVER_NAME=\""+RDEscapeString(q->value(14).toString())+"\","+
"JACK_COMMAND_LINE=\""+RDEscapeString(q->value(15).toString())+"\","+ "JACK_COMMAND_LINE=\""+RDEscapeString(q->value(15).toString())+"\","+
QString().sprintf("CUE_CARD=%d,",q->value(16).toInt())+ QString().sprintf("JACK_PORTS=%d,",q->value(16).toInt())+
QString().sprintf("CUE_PORT=%d,",q->value(17).toInt())+ QString().sprintf("CUE_CARD=%d,",q->value(17).toInt())+
QString().sprintf("CUE_START_CART=%u,",q->value(18).toInt())+ QString().sprintf("CUE_PORT=%d,",q->value(18).toInt())+
QString().sprintf("CUE_STOP_CART=%u,",q->value(19).toInt())+ QString().sprintf("CUE_START_CART=%u,",q->value(19).toInt())+
QString().sprintf("CARTSLOT_COLUMNS=%d,",q->value(20).toInt())+ QString().sprintf("CUE_STOP_CART=%u,",q->value(20).toInt())+
QString().sprintf("CARTSLOT_ROWS=%d,",q->value(21).toInt())+ QString().sprintf("CARTSLOT_COLUMNS=%d,",q->value(21).toInt())+
"ENABLE_DRAGDROP=\""+RDEscapeString(q->value(22).toString())+"\","+ QString().sprintf("CARTSLOT_ROWS=%d,",q->value(22).toInt())+
"ENFORCE_PANEL_SETUP=\""+RDEscapeString(q->value(23).toString())+"\""; "ENABLE_DRAGDROP=\""+RDEscapeString(q->value(23).toString())+"\","+
"ENFORCE_PANEL_SETUP=\""+RDEscapeString(q->value(24).toString())+"\"";
q1=new RDSqlQuery(sql); q1=new RDSqlQuery(sql);
if(!q1->isActive()) { if(!q1->isActive()) {
*err_msg=QObject::tr("host already exists"); *err_msg=QObject::tr("host already exists");

View File

@ -76,6 +76,8 @@ class RDStation
void setJackServerName(const QString &str) const; void setJackServerName(const QString &str) const;
QString jackCommandLine() const; QString jackCommandLine() const;
void setJackCommandLine(const QString &str) const; void setJackCommandLine(const QString &str) const;
int jackPorts() const;
void setJackPorts(int ports) const;
int cueCard() const; int cueCard() const;
void setCueCard(int card); void setCueCard(int card);
int cuePort() const; int cuePort() const;

View File

@ -95,6 +95,16 @@ EditJack::EditJack(RDStation *station,QWidget *parent)
edit_jack_command_line_label-> edit_jack_command_line_label->
setAlignment(AlignRight|AlignVCenter|ShowPrefix); setAlignment(AlignRight|AlignVCenter|ShowPrefix);
//
// Active Audio Ports
//
edit_jack_audio_ports_spin=new QSpinBox(this);
edit_jack_audio_ports_spin->setRange(0,24);
edit_jack_audio_ports_label=
new QLabel(edit_jack_audio_ports_spin,tr("Active Audio Ports")+":",this);
edit_jack_audio_ports_label->setFont(font);
edit_jack_audio_ports_label->setAlignment(AlignRight|AlignVCenter|ShowPrefix);
// //
// JACK Client List // JACK Client List
// //
@ -159,6 +169,7 @@ EditJack::EditJack(RDStation *station,QWidget *parent)
edit_start_jack_box->setChecked(edit_station->startJack()); edit_start_jack_box->setChecked(edit_station->startJack());
edit_jack_server_name_edit->setText(edit_station->jackServerName()); edit_jack_server_name_edit->setText(edit_station->jackServerName());
edit_jack_command_line_edit->setText(edit_station->jackCommandLine()); edit_jack_command_line_edit->setText(edit_station->jackCommandLine());
edit_jack_audio_ports_spin->setValue(edit_station->jackPorts());
if(edit_jack_server_name_edit->text().isEmpty()) { if(edit_jack_server_name_edit->text().isEmpty()) {
edit_jack_server_name_edit->setText(EDITJACK_DEFAULT_SERVERNAME); edit_jack_server_name_edit->setText(EDITJACK_DEFAULT_SERVERNAME);
} }
@ -170,7 +181,7 @@ EditJack::EditJack(RDStation *station,QWidget *parent)
QSize EditJack::sizeHint() const QSize EditJack::sizeHint() const
{ {
return QSize(450,330); return QSize(450,352);
} }
@ -279,6 +290,7 @@ void EditJack::okData()
edit_station->setJackServerName(edit_jack_server_name_edit->text()); edit_station->setJackServerName(edit_jack_server_name_edit->text());
} }
edit_station->setJackCommandLine(edit_jack_command_line_edit->text()); edit_station->setJackCommandLine(edit_jack_command_line_edit->text());
edit_station->setJackPorts(edit_jack_audio_ports_spin->value());
item=(RDListViewItem *)edit_jack_client_view->firstChild(); item=(RDListViewItem *)edit_jack_client_view->firstChild();
while(item!=NULL) { while(item!=NULL) {
sql=QString("update JACK_CLIENTS set DESCRIPTION=\"")+ sql=QString("update JACK_CLIENTS set DESCRIPTION=\"")+
@ -311,9 +323,12 @@ void EditJack::resizeEvent(QResizeEvent *e)
edit_jack_command_line_label->setGeometry(10,54,130,20); edit_jack_command_line_label->setGeometry(10,54,130,20);
edit_jack_command_line_edit->setGeometry(145,54,size().width()-155,20); edit_jack_command_line_edit->setGeometry(145,54,size().width()-155,20);
edit_jack_client_label->setGeometry(15,80,sizeHint().width()-28,20); edit_jack_audio_ports_label->setGeometry(10,76,130,20);
edit_jack_audio_ports_spin->setGeometry(145,76,50,20);
edit_jack_client_label->setGeometry(15,103,sizeHint().width()-28,20);
edit_jack_client_view-> edit_jack_client_view->
setGeometry(10,102,size().width()-20,size().height()-170); setGeometry(10,124,size().width()-20,size().height()-192);
edit_add_button->setGeometry(15,size().height()-60,50,30); edit_add_button->setGeometry(15,size().height()-60,50,30);
edit_edit_button->setGeometry(75,size().height()-60,50,30); edit_edit_button->setGeometry(75,size().height()-60,50,30);

View File

@ -21,17 +21,18 @@
#ifndef EDIT_JACK_H #ifndef EDIT_JACK_H
#define EDIT_JACK_H #define EDIT_JACK_H
#include <qdialog.h>
#include <qlistview.h>
#include <qtextedit.h>
#include <qpixmap.h>
#include <qcheckbox.h> #include <qcheckbox.h>
#include <qlineedit.h> #include <qdialog.h>
#include <qpushbutton.h>
#include <qlabel.h> #include <qlabel.h>
#include <qlineedit.h>
#include <qlistview.h>
#include <qpixmap.h>
#include <qpushbutton.h>
#include <qspinbox.h>
#include <qtextedit.h>
#include <rdstation.h>
#include <rdlistview.h> #include <rdlistview.h>
#include <rdstation.h>
#define EDITJACK_DEFAULT_SERVERNAME QObject::tr("(default)") #define EDITJACK_DEFAULT_SERVERNAME QObject::tr("(default)")
@ -63,6 +64,8 @@ class EditJack : public QDialog
QLineEdit *edit_jack_server_name_edit; QLineEdit *edit_jack_server_name_edit;
QLabel *edit_jack_command_line_label; QLabel *edit_jack_command_line_label;
QLineEdit *edit_jack_command_line_edit; QLineEdit *edit_jack_command_line_edit;
QLabel *edit_jack_audio_ports_label;
QSpinBox *edit_jack_audio_ports_spin;
QLabel *edit_jack_client_label; QLabel *edit_jack_client_label;
RDListView *edit_jack_client_view; RDListView *edit_jack_client_view;
RDStation *edit_station; RDStation *edit_station;

View File

@ -1922,6 +1922,10 @@ Stále ještě chcete uložit?</translation>
<source>Are you sure you want to delete JACK Client</source> <source>Are you sure you want to delete JACK Client</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Active Audio Ports</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>EditJackClient</name> <name>EditJackClient</name>

View File

@ -1897,6 +1897,10 @@ Do you still want to save?</source>
<source>Are you sure you want to delete JACK Client</source> <source>Are you sure you want to delete JACK Client</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Active Audio Ports</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>EditJackClient</name> <name>EditJackClient</name>

View File

@ -1928,6 +1928,10 @@ Do you still want to save?</source>
<source>Are you sure you want to delete JACK Client</source> <source>Are you sure you want to delete JACK Client</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Active Audio Ports</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>EditJackClient</name> <name>EditJackClient</name>

View File

@ -1650,6 +1650,10 @@ Do you still want to save?</source>
<source>Are you sure you want to delete JACK Client</source> <source>Are you sure you want to delete JACK Client</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Active Audio Ports</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>EditJackClient</name> <name>EditJackClient</name>

View File

@ -1884,6 +1884,10 @@ Vil du framleis lagra?</translation>
<source>Are you sure you want to delete JACK Client</source> <source>Are you sure you want to delete JACK Client</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Active Audio Ports</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>EditJackClient</name> <name>EditJackClient</name>

View File

@ -1884,6 +1884,10 @@ Vil du framleis lagra?</translation>
<source>Are you sure you want to delete JACK Client</source> <source>Are you sure you want to delete JACK Client</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Active Audio Ports</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>EditJackClient</name> <name>EditJackClient</name>

View File

@ -1882,6 +1882,10 @@ Você ainda quer salvar?</translation>
<source>Are you sure you want to delete JACK Client</source> <source>Are you sure you want to delete JACK Client</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Active Audio Ports</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>EditJackClient</name> <name>EditJackClient</name>

View File

@ -304,6 +304,8 @@ MainWidget::MainWidget(QWidget *parent)
// //
// CAE Connection // CAE Connection
// //
connect(rda->cae(),SIGNAL(isConnected(bool)),
this,SLOT(caeConnectedData(bool)));
rda->cae()->connectHost(); rda->cae()->connectHost();
// //
@ -315,7 +317,7 @@ MainWidget::MainWidget(QWidget *parent)
// //
// RIPC Connection // RIPC Connection
// //
connect(rda->ripc(),SIGNAL(connected(bool)),this,SLOT(ripcConnected(bool))); connect(rda->ripc(),SIGNAL(connected(bool)),this,SLOT(ripcConnectedData(bool)));
connect(rda,SIGNAL(userChanged()),this,SLOT(userData())); connect(rda,SIGNAL(userChanged()),this,SLOT(userData()));
connect(rda->ripc(),SIGNAL(rmlReceived(RDMacro *)), connect(rda->ripc(),SIGNAL(rmlReceived(RDMacro *)),
this,SLOT(rmlReceivedData(RDMacro *))); this,SLOT(rmlReceivedData(RDMacro *)));
@ -914,7 +916,24 @@ QSizePolicy MainWidget::sizePolicy() const
} }
void MainWidget::ripcConnected(bool state) void MainWidget::caeConnectedData(bool state)
{
std::vector<int> cards;
cards.push_back(rda->airplayConf()->card(RDAirPlayConf::MainLog1Channel));
cards.push_back(rda->airplayConf()->card(RDAirPlayConf::MainLog2Channel));
cards.push_back(rda->airplayConf()->card(RDAirPlayConf::AuxLog1Channel));
cards.push_back(rda->airplayConf()->card(RDAirPlayConf::AuxLog2Channel));
cards.push_back(rda->airplayConf()->card(RDAirPlayConf::SoundPanel1Channel));
cards.push_back(rda->airplayConf()->card(RDAirPlayConf::SoundPanel2Channel));
cards.push_back(rda->airplayConf()->card(RDAirPlayConf::SoundPanel3Channel));
cards.push_back(rda->airplayConf()->card(RDAirPlayConf::SoundPanel4Channel));
cards.push_back(rda->airplayConf()->card(RDAirPlayConf::SoundPanel5Channel));
rda->cae()->enableMetering(&cards);
}
void MainWidget::ripcConnectedData(bool state)
{ {
QString logname; QString logname;
QHostAddress addr; QHostAddress addr;

View File

@ -98,7 +98,8 @@ class MainWidget : public QWidget
private slots: private slots:
void logLine(RDConfig::LogPriority prio,const QString &msg); void logLine(RDConfig::LogPriority prio,const QString &msg);
void ripcConnected(bool state); void caeConnectedData(bool state);
void ripcConnectedData(bool state);
void rmlReceivedData(RDMacro *rml); void rmlReceivedData(RDMacro *rml);
void gpiStateChangedData(int matrix,int line,bool state); void gpiStateChangedData(int matrix,int line,bool state);
void logChannelStartedData(int id,int mport,int card,int port); void logChannelStartedData(int id,int mport,int card,int port);

View File

@ -37,6 +37,7 @@
#include <rdapplication.h> #include <rdapplication.h>
#include <rdcheck_daemons.h> #include <rdcheck_daemons.h>
#include <rddbheartbeat.h> #include <rddbheartbeat.h>
#include <rdescape_string.h>
#include "rdcartslots.h" #include "rdcartslots.h"
@ -92,6 +93,8 @@ MainWidget::MainWidget(QWidget *parent)
// //
// CAE Connection // CAE Connection
// //
connect(rda->cae(),SIGNAL(isConnected(bool)),
this,SLOT(caeConnectedData(bool)));
rda->cae()->connectHost(); rda->cae()->connectHost();
// //
@ -166,6 +169,22 @@ QSize MainWidget::sizeHint() const
} }
void MainWidget::caeConnectedData(bool state)
{
std::vector<int> cards;
QString sql=QString("select CARD from CARTSLOTS where ")+
"STATION_NAME=\""+RDEscapeString(rda->config()->stationName())+"\"";
RDSqlQuery *q=new RDSqlQuery(sql);
while(q->next()) {
cards.push_back(q->value(0).toInt());
}
delete q;
rda->cae()->enableMetering(&cards);
}
void MainWidget::rmlReceivedData(RDMacro *rml) void MainWidget::rmlReceivedData(RDMacro *rml)
{ {
RunLocalMacros(rml); RunLocalMacros(rml);

View File

@ -56,6 +56,7 @@ class MainWidget : public QWidget
QSizePolicy sizePolicy() const; QSizePolicy sizePolicy() const;
private slots: private slots:
void caeConnectedData(bool state);
void userData(); void userData();
void rmlReceivedData(RDMacro *rml); void rmlReceivedData(RDMacro *rml);
@ -66,12 +67,6 @@ class MainWidget : public QWidget
private: private:
void RunLocalMacros(RDMacro *rml); void RunLocalMacros(RDMacro *rml);
void SetCaption(); void SetCaption();
// RDConfig *panel_config;
// RDCae *panel_cae;
// RDRipc *panel_ripc;
// RDUser *panel_user;
// RDStation *panel_station;
// RDSystem *panel_system;
RDEventPlayer *panel_player; RDEventPlayer *panel_player;
QPixmap *lib_rivendell_map; QPixmap *lib_rivendell_map;
QString panel_filter; QString panel_filter;

View File

@ -190,6 +190,8 @@ MainWidget::MainWidget(QWidget *parent)
// //
// CAE Connection // CAE Connection
// //
connect(rda->cae(),SIGNAL(isConnected(bool)),
this,SLOT(caeConnectedData(bool)));
rda->cae()->connectHost(); rda->cae()->connectHost();
// //
@ -483,6 +485,17 @@ QSizePolicy MainWidget::sizePolicy() const
} }
void MainWidget::caeConnectedData(bool state)
{
if(state) {
std::vector<int> cards;
cards.push_back(rda->libraryConf()->inputCard());
cards.push_back(rda->libraryConf()->outputCard());
rda->cae()->enableMetering(&cards);
}
}
void MainWidget::userData() void MainWidget::userData()
{ {
QString sql; QString sql;

View File

@ -70,6 +70,7 @@ class MainWidget : public QWidget
QSizePolicy sizePolicy() const; QSizePolicy sizePolicy() const;
private slots: private slots:
void caeConnectedData(bool state);
void userData(); void userData();
void filterChangedData(const QString &str); void filterChangedData(const QString &str);
void searchClickedData(); void searchClickedData();

View File

@ -145,6 +145,8 @@ MainWidget::MainWidget(QWidget *parent)
// //
// CAE Connection // CAE Connection
// //
connect(rda->cae(),SIGNAL(isConnected(bool)),
this,SLOT(caeConnectedData(bool)));
rda->cae()->connectHost(); rda->cae()->connectHost();
// //
@ -342,6 +344,19 @@ QSizePolicy MainWidget::sizePolicy() const
} }
void MainWidget::caeConnectedData(bool state)
{
std::vector<int> cards;
cards.push_back(rda->airplayConf()->card(RDAirPlayConf::SoundPanel1Channel));
cards.push_back(rda->airplayConf()->card(RDAirPlayConf::SoundPanel2Channel));
cards.push_back(rda->airplayConf()->card(RDAirPlayConf::SoundPanel3Channel));
cards.push_back(rda->airplayConf()->card(RDAirPlayConf::SoundPanel4Channel));
cards.push_back(rda->airplayConf()->card(RDAirPlayConf::SoundPanel5Channel));
rda->cae()->enableMetering(&cards);
}
void MainWidget::userData() void MainWidget::userData()
{ {
SetCaption(); SetCaption();

View File

@ -49,6 +49,7 @@ class MainWidget : public QWidget
QSizePolicy sizePolicy() const; QSizePolicy sizePolicy() const;
private slots: private slots:
void caeConnectedData(bool state);
void userData(); void userData();
void masterTimerData(); void masterTimerData();
void meterData(); void meterData();

View File

@ -29,6 +29,25 @@ bool MainObject::RevertSchema(int cur_schema,int set_schema,QString *err_msg) co
RDSqlQuery *q; RDSqlQuery *q;
QString tablename; QString tablename;
//
// Maintainer's Note:
//
// When adding a schema reversion here, be sure also to implement the
// corresponding update in updateschema.cpp!
//
//
// Revert 287
//
if((cur_schema==287)&&(set_schema<cur_schema)) {
sql=QString("alter table STATIONS drop column JACK_PORTS");
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
cur_schema--;
}
// //
// Revert 286 // Revert 286
// //

View File

@ -56,7 +56,7 @@ void MainObject::InitializeSchemaMap() {
global_version_map["2.17"]=268; global_version_map["2.17"]=268;
global_version_map["2.18"]=272; global_version_map["2.18"]=272;
global_version_map["2.19"]=275; global_version_map["2.19"]=275;
global_version_map["2.20"]=286; global_version_map["2.20"]=287;
} }

View File

@ -7157,6 +7157,17 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) co
cur_schema++; cur_schema++;
} }
if((cur_schema<287)&&(set_schema>cur_schema)) {
sql=QString("alter table STATIONS add column ")+
"JACK_PORTS int not null default 8 after JACK_COMMAND_LINE";
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
cur_schema++;
}
// //
// Maintainer's Note: // Maintainer's Note: