mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2026-01-12 07:35:55 +01:00
2017-01-31 Fred Gleason <fredg@paravelsystems.com>
* Added an RLM for the TagStation NextRadio framework in 'rlm/rlm_tagstation.c'.
This commit is contained in:
95
conf/rlm_tagstation.conf
Normal file
95
conf/rlm_tagstation.conf
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
; rlm_tagstation.conf
|
||||||
|
;
|
||||||
|
; This is the sample configuration file for the 'rlm_tagstation' module for
|
||||||
|
; Rivendell, which can be used to update Now & Next data on a TagStation
|
||||||
|
; instance.
|
||||||
|
;
|
||||||
|
; To enable this module, add it to the 'Loadable Modules' list in
|
||||||
|
; RDAdmin->ManageHosts->RDAirPlay->ConfigureNow&Next. The 'Argument'
|
||||||
|
; field should point to the location of this file.
|
||||||
|
;
|
||||||
|
; This module requires the curl(1) network transfer tool, included with most
|
||||||
|
; Linux distros. It is also available at http://curl.haxx.se/.
|
||||||
|
|
||||||
|
|
||||||
|
; Section Header
|
||||||
|
;
|
||||||
|
; One section per Icecast2 mountpoint is configured, starting with
|
||||||
|
; 'TagStation1' and working up consecutively
|
||||||
|
[TagStation1]
|
||||||
|
|
||||||
|
; Customer ID
|
||||||
|
;
|
||||||
|
; The Customer ID of the TagStation account to which to send updates.
|
||||||
|
CustomerId=some_customer
|
||||||
|
|
||||||
|
; Password
|
||||||
|
;
|
||||||
|
; The password of the TagStation account to which to send updates.
|
||||||
|
Password=hackme
|
||||||
|
|
||||||
|
; TitleString. The metadata to be sent as the 'Title' field each time
|
||||||
|
; RDAirPlay changes play state, including any wildcards as placeholders for
|
||||||
|
; metadata values.
|
||||||
|
;
|
||||||
|
; The list of available wildcards can be found in the 'metadata_wildcards.txt'
|
||||||
|
; file in the Rivendell documentation directory.
|
||||||
|
;
|
||||||
|
TitleString=%t
|
||||||
|
|
||||||
|
; ArtistString. The metadata to be sent as the 'Artist' field each time
|
||||||
|
; RDAirPlay changes play state, including any wildcards as placeholders for
|
||||||
|
; metadata values.
|
||||||
|
;
|
||||||
|
ArtistString=%a
|
||||||
|
|
||||||
|
; AlbumString. The metadata to be sent as the 'Artist' field each time
|
||||||
|
; RDAirPlay changes play state, including any wildcards as placeholders for
|
||||||
|
; metadata values.
|
||||||
|
;
|
||||||
|
AlbumString=%l
|
||||||
|
|
||||||
|
; TagStation Categories. Each update to TagStation must be labeled as being
|
||||||
|
; one of four possible categories. Each Rivendell Group can be assigned
|
||||||
|
; one of the four categories here. The four categories are:
|
||||||
|
;
|
||||||
|
; Advertisements
|
||||||
|
; Gap Lookup
|
||||||
|
; Music
|
||||||
|
; Promotions
|
||||||
|
;
|
||||||
|
; If a group does not appear on one of the following lists, it will be
|
||||||
|
; automatically labeled as being in the 'Promotions' category.
|
||||||
|
;
|
||||||
|
; Multiple groups may be assigned to each category, separated by commas.
|
||||||
|
; No whitespace!
|
||||||
|
;
|
||||||
|
CategoryAdvertisement=TRAFFIC,PROMOS
|
||||||
|
CategoryGapLookup=
|
||||||
|
CategoryMusic=MUSIC
|
||||||
|
|
||||||
|
|
||||||
|
; Log Selection
|
||||||
|
;
|
||||||
|
; Set the status for each log to 'Yes', 'No' or 'Onair' to indicate whether
|
||||||
|
; state changes on that log should be output to this instance. If set
|
||||||
|
; to 'Onair', then output will be generated only if RDAirPlays OnAir flag
|
||||||
|
; is active.
|
||||||
|
MasterLog=Yes
|
||||||
|
Aux1Log=Yes
|
||||||
|
Aux2Log=Yes
|
||||||
|
|
||||||
|
|
||||||
|
; Additional TagStation instances can be configured by adding new sections...
|
||||||
|
;[TagStation2]
|
||||||
|
;CustomerId=another_customer
|
||||||
|
;Password=letmein
|
||||||
|
;TitleString=%t
|
||||||
|
;ArtistString=%a
|
||||||
|
;AlbumString=%l
|
||||||
|
;CategoryAdvertisement=TRAFFIC,PROMOS
|
||||||
|
;CategoryGapLookup=
|
||||||
|
;CategoryMusic=MUSIC
|
||||||
|
;MasterLog=Yes
|
||||||
|
;Aux1Log=No
|
||||||
|
;Aux2Log=Onair
|
||||||
@@ -29,6 +29,7 @@ OBJS = rlm_ando.rlm\
|
|||||||
rlm_shoutcast1.rlm\
|
rlm_shoutcast1.rlm\
|
||||||
rlm_spinitron_plus.rlm\
|
rlm_spinitron_plus.rlm\
|
||||||
rlm_spottrap.rlm\
|
rlm_spottrap.rlm\
|
||||||
|
rlm_tagstation.rlm\
|
||||||
rlm_test.rlm\
|
rlm_test.rlm\
|
||||||
rlm_twitter.rlm\
|
rlm_twitter.rlm\
|
||||||
rlm_udp.rlm \
|
rlm_udp.rlm \
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ RLM_MODULES=rlm_ando.rlm\
|
|||||||
rlm_shoutcast1.rlm\
|
rlm_shoutcast1.rlm\
|
||||||
rlm_spinitron_plus.rlm\
|
rlm_spinitron_plus.rlm\
|
||||||
rlm_spottrap.rlm\
|
rlm_spottrap.rlm\
|
||||||
|
rlm_tagstation.rlm\
|
||||||
rlm_test.rlm\
|
rlm_test.rlm\
|
||||||
rlm_twitter.rlm\
|
rlm_twitter.rlm\
|
||||||
rlm_udp.rlm\
|
rlm_udp.rlm\
|
||||||
|
|||||||
265
rlm/rlm_tagstation.c
Normal file
265
rlm/rlm_tagstation.c
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
/* rlm_tagstation.c
|
||||||
|
*
|
||||||
|
* (C) Copyright 2017 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.
|
||||||
|
*
|
||||||
|
* This is a sample Rivendell Loadable Module. All it does is print
|
||||||
|
* Now & Next data to standard output for each event transition.
|
||||||
|
*
|
||||||
|
* To compile this module, just do:
|
||||||
|
*
|
||||||
|
* gcc -shared -o rlm_tagstation.rlm rlm_tagstation.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <rlm/rlm.h>
|
||||||
|
|
||||||
|
int rlm_tagstation_devs;
|
||||||
|
char *rlm_tagstation_customerids;
|
||||||
|
char *rlm_tagstation_passwords;
|
||||||
|
char *rlm_tagstation_titles;
|
||||||
|
char *rlm_tagstation_artists;
|
||||||
|
char *rlm_tagstation_albums;
|
||||||
|
char *rlm_tagstation_adps;
|
||||||
|
char *rlm_tagstation_etos;
|
||||||
|
char *rlm_tagstation_muss;
|
||||||
|
int *rlm_tagstation_masters;
|
||||||
|
int *rlm_tagstation_aux1s;
|
||||||
|
int *rlm_tagstation_aux2s;
|
||||||
|
|
||||||
|
int rlm_tagstation_ContainsString(const char *str,const char *substr)
|
||||||
|
{
|
||||||
|
int ptr=0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(strspn(str+ptr,substr)==strlen(substr)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
while((str[ptr]!=',')&&(ptr<strlen(str))) {
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
} while(++ptr<strlen(str));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *rlm_tagstation_GetCategory(const char *grp_name,int num)
|
||||||
|
{
|
||||||
|
static char ret[3];
|
||||||
|
|
||||||
|
strncpy(ret,"PRO",3);
|
||||||
|
if(strlen(grp_name)!=0) {
|
||||||
|
if(rlm_tagstation_ContainsString(rlm_tagstation_adps+256*num,grp_name)>0) {
|
||||||
|
strncpy(ret,"ADP",3);
|
||||||
|
}
|
||||||
|
if(rlm_tagstation_ContainsString(rlm_tagstation_etos+256*num,grp_name)>0) {
|
||||||
|
strncpy(ret,"ETO",3);
|
||||||
|
}
|
||||||
|
if(rlm_tagstation_ContainsString(rlm_tagstation_muss+256*num,grp_name)>0) {
|
||||||
|
strncpy(ret,"MUS",3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int rlm_tagstation_GetLogStatus(void *ptr,const char *arg,const char *section,
|
||||||
|
const char *logname)
|
||||||
|
{
|
||||||
|
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
|
||||||
|
if(strcasecmp(tag,"yes")==0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(strcasecmp(tag,"on")==0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(strcasecmp(tag,"true")==0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(strcasecmp(tag,"no")==0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(strcasecmp(tag,"off")==0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(strcasecmp(tag,"false")==0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(strcasecmp(tag,"onair")==0) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void rlm_tagstation_RLMStart(void *ptr,const char *arg)
|
||||||
|
{
|
||||||
|
char username[256];
|
||||||
|
char section[256];
|
||||||
|
char errtext[256];
|
||||||
|
int i=1;
|
||||||
|
|
||||||
|
rlm_tagstation_devs=0;
|
||||||
|
rlm_tagstation_customerids=NULL;
|
||||||
|
rlm_tagstation_passwords=NULL;
|
||||||
|
rlm_tagstation_titles=NULL;
|
||||||
|
rlm_tagstation_artists=NULL;
|
||||||
|
rlm_tagstation_albums=NULL;
|
||||||
|
rlm_tagstation_adps=NULL;
|
||||||
|
rlm_tagstation_etos=NULL;
|
||||||
|
rlm_tagstation_muss=NULL;
|
||||||
|
rlm_tagstation_masters=NULL;
|
||||||
|
rlm_tagstation_aux1s=NULL;
|
||||||
|
rlm_tagstation_aux2s=NULL;
|
||||||
|
|
||||||
|
sprintf(section,"TagStation%d",i++);
|
||||||
|
strncpy(username,RLMGetStringValue(ptr,arg,section,"CustomerId",""),255);
|
||||||
|
username[255]=0;
|
||||||
|
if(strlen(username)==0) {
|
||||||
|
RLMLog(ptr,LOG_WARNING,"rlm_tagstation: no tagstation instances specified");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while(strlen(username)>0) {
|
||||||
|
rlm_tagstation_customerids=realloc(rlm_tagstation_customerids,
|
||||||
|
(rlm_tagstation_devs+1)*(rlm_tagstation_devs+1)*256);
|
||||||
|
strcpy(rlm_tagstation_customerids+256*rlm_tagstation_devs,username);
|
||||||
|
|
||||||
|
rlm_tagstation_passwords=realloc(rlm_tagstation_passwords,
|
||||||
|
(rlm_tagstation_devs+1)*(rlm_tagstation_devs+1)*256);
|
||||||
|
strcpy(rlm_tagstation_passwords+256*rlm_tagstation_devs,
|
||||||
|
RLMGetStringValue(ptr,arg,section,"Password",""));
|
||||||
|
|
||||||
|
rlm_tagstation_titles=realloc(rlm_tagstation_titles,(rlm_tagstation_devs+1)*256);
|
||||||
|
strncpy(rlm_tagstation_titles+256*rlm_tagstation_devs,
|
||||||
|
RLMGetStringValue(ptr,arg,section,"TitleString",""),256);
|
||||||
|
|
||||||
|
rlm_tagstation_artists=realloc(rlm_tagstation_artists,(rlm_tagstation_devs+1)*256);
|
||||||
|
strncpy(rlm_tagstation_artists+256*rlm_tagstation_devs,
|
||||||
|
RLMGetStringValue(ptr,arg,section,"ArtistString",""),256);
|
||||||
|
|
||||||
|
rlm_tagstation_albums=realloc(rlm_tagstation_albums,(rlm_tagstation_devs+1)*256);
|
||||||
|
strncpy(rlm_tagstation_albums+256*rlm_tagstation_devs,
|
||||||
|
RLMGetStringValue(ptr,arg,section,"AlbumString",""),256);
|
||||||
|
|
||||||
|
rlm_tagstation_adps=realloc(rlm_tagstation_adps,(rlm_tagstation_devs+1)*256);
|
||||||
|
strncpy(rlm_tagstation_adps+256*rlm_tagstation_devs,
|
||||||
|
RLMGetStringValue(ptr,arg,section,"CategoryAdvertisement",""),256);
|
||||||
|
|
||||||
|
rlm_tagstation_etos=realloc(rlm_tagstation_etos,(rlm_tagstation_devs+1)*256);
|
||||||
|
strncpy(rlm_tagstation_etos+256*rlm_tagstation_devs,
|
||||||
|
RLMGetStringValue(ptr,arg,section,"CategoryGapLookup",""),256);
|
||||||
|
|
||||||
|
rlm_tagstation_muss=realloc(rlm_tagstation_muss,(rlm_tagstation_devs+1)*256);
|
||||||
|
strncpy(rlm_tagstation_muss+256*rlm_tagstation_devs,
|
||||||
|
RLMGetStringValue(ptr,arg,section,"CategoryMusic",""),256);
|
||||||
|
|
||||||
|
rlm_tagstation_masters=realloc(rlm_tagstation_masters,
|
||||||
|
(rlm_tagstation_devs+1)*sizeof(int));
|
||||||
|
rlm_tagstation_masters[rlm_tagstation_devs]=
|
||||||
|
rlm_tagstation_GetLogStatus(ptr,arg,section,"MasterLog");
|
||||||
|
rlm_tagstation_aux1s=realloc(rlm_tagstation_aux1s,
|
||||||
|
(rlm_tagstation_devs+1)*sizeof(int));
|
||||||
|
rlm_tagstation_aux1s[rlm_tagstation_devs]=
|
||||||
|
rlm_tagstation_GetLogStatus(ptr,arg,section,"Aux1Log");
|
||||||
|
rlm_tagstation_aux2s=realloc(rlm_tagstation_aux2s,
|
||||||
|
(rlm_tagstation_devs+1)*sizeof(int));
|
||||||
|
rlm_tagstation_aux2s[rlm_tagstation_devs]=
|
||||||
|
rlm_tagstation_GetLogStatus(ptr,arg,section,"Aux2Log");
|
||||||
|
sprintf(errtext,
|
||||||
|
"rlm_tagstation: configured TagStation instance for Customer ID \"%s\"",
|
||||||
|
rlm_tagstation_customerids+256*rlm_tagstation_devs);
|
||||||
|
rlm_tagstation_devs++;
|
||||||
|
RLMLog(ptr,LOG_INFO,errtext);
|
||||||
|
sprintf(section,"TagStation%d",i++);
|
||||||
|
strncpy(username,RLMGetStringValue(ptr,arg,section,"Username",""),255);
|
||||||
|
username[255]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void rlm_tagstation_RLMFree(void *ptr)
|
||||||
|
{
|
||||||
|
free(rlm_tagstation_customerids);
|
||||||
|
free(rlm_tagstation_passwords);
|
||||||
|
free(rlm_tagstation_titles);
|
||||||
|
free(rlm_tagstation_artists);
|
||||||
|
free(rlm_tagstation_albums);
|
||||||
|
free(rlm_tagstation_adps);
|
||||||
|
free(rlm_tagstation_etos);
|
||||||
|
free(rlm_tagstation_muss);
|
||||||
|
free(rlm_tagstation_masters);
|
||||||
|
free(rlm_tagstation_aux1s);
|
||||||
|
free(rlm_tagstation_aux2s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void rlm_tagstation_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
|
||||||
|
const struct rlm_log *log,
|
||||||
|
const struct rlm_pad *now,
|
||||||
|
const struct rlm_pad *next)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int flag=0;
|
||||||
|
char account[1024];
|
||||||
|
char fmt[1024];
|
||||||
|
char url[4096];
|
||||||
|
char msg[1500];
|
||||||
|
|
||||||
|
for(i=0;i<rlm_tagstation_devs;i++) {
|
||||||
|
switch(log->log_mach) {
|
||||||
|
case 0:
|
||||||
|
flag=rlm_tagstation_masters[i];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
flag=rlm_tagstation_aux1s[i];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
flag=rlm_tagstation_aux2s[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
|
||||||
|
snprintf(fmt,1024,"https://tsl.tagstation.com/tsl.ashx?CID=%s&Title=%s&Artist=%s&Album=%s&EventCategory=%s&EventID=%%n&Duration=%%h&LookAhead=False",
|
||||||
|
rlm_tagstation_customerids+256*i,
|
||||||
|
rlm_tagstation_titles+256*i,
|
||||||
|
rlm_tagstation_artists+256*i,
|
||||||
|
rlm_tagstation_albums+256*i,
|
||||||
|
rlm_tagstation_GetCategory(now->rlm_group,i));
|
||||||
|
|
||||||
|
strncpy(url,RLMResolveNowNextEncoded(ptr,now,next,fmt,RLM_ENCODE_URL),
|
||||||
|
4096);
|
||||||
|
snprintf(account,1024,"%s:%s",rlm_tagstation_customerids+256*i,
|
||||||
|
rlm_tagstation_passwords+256*i);
|
||||||
|
if(strlen(now->rlm_title)!=0) {
|
||||||
|
if(fork()==0) {
|
||||||
|
execlp("curl","curl","-u",account,"-o","/dev/null","-s",
|
||||||
|
url,(char *)NULL);
|
||||||
|
RLMLog(ptr,LOG_WARNING,"rlm_tagstation: unable to execute curl(1)");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snprintf(msg,1500,"rlm_tagstation: sending pad update: \"%s\"",
|
||||||
|
(const char *)url);
|
||||||
|
RLMLog(ptr,LOG_INFO,msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user