00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <shouter.h>
00023 #include <jutils.h>
00024 #include <generic.h>
00025 #include <config.h>
00026
00027 extern bool got_sigpipe;
00028
00029 Shouter::Shouter()
00030 : Entry() {
00031
00032
00033
00034
00035
00036
00037
00038 ice = shout_new();
00039
00040
00041
00042
00043 running = false;
00044 retry = 0;
00045 errors = 0;
00046
00047
00048 host("localhost");
00049 ip("127.0.0.1");
00050 port(8000);
00051 pass("hackme");
00052 mount("live");
00053 login(SHOUT_PROTOCOL_HTTP);
00054 name("Streaming with MuSE");
00055 url("http://muse.dyne.org");
00056 desc("Free Software Multiple Streaming Engine");
00057 bps("24000");
00058 freq("22050");
00059 channels("1");
00060
00061 profile_changed = true;
00062 }
00063
00064 Shouter::~Shouter() {
00065 func("Shouter::~Shouter");
00066 stop();
00067 shout_free(ice);
00068 }
00069
00070 bool Shouter::start() {
00071 int res;
00072 char srv[64];
00073 switch(login()) {
00074 case SHOUT_PROTOCOL_HTTP: sprintf(srv,"icecast2"); break;
00075 case SHOUT_PROTOCOL_ICY: sprintf(srv,"shoutcast"); break;
00076 default: sprintf(srv,"icecast 1"); break;
00077 }
00078
00079 if(shout_get_connected(ice)) {
00080
00081 func("icecast still connected: disconnecting");
00082 shout_close(ice);
00083 shout_sync(ice);
00084 }
00085
00086 notice("Contacting %s server %s on port %u",srv,host(),port());
00087
00088 res = shout_open(ice);
00089 func("Shouter::start() shout_open returns %i",res);
00090 shout_sync(ice);
00091
00092 if(res==SHOUTERR_SUCCESS) {
00093 notice("started streaming on %s",streamurl);
00094 running = true;
00095 } else {
00096 error("shout_open: %s",shout_get_error(ice));
00097 shout_close(ice);
00098 shout_sync(ice);
00099 running = false;
00100 }
00101
00102 return(running);
00103 }
00104
00105 bool Shouter::stop() {
00106 if(running) {
00107 notice("closed stream to %s",streamurl);
00108 shout_close(ice);
00109 running = false;
00110 }
00111 return true;
00112 }
00113
00114 bool Shouter::apply_profile() {
00115 char temp[256];
00116 func("Shouter::apply_profile() on shouter id %i",id);
00117
00118 bool was_running = running, res = true;
00119 if(was_running) stop();
00120
00121 if(shout_set_host(ice,host()))
00122 error("shout_set_host: %s",shout_get_error(ice));
00123
00124 if( shout_set_port(ice,port()) )
00125 error("shout_set_port: %s",shout_get_error(ice));
00126
00127 if( shout_set_password(ice,pass()) )
00128 error("shout_set_password: %s",shout_get_error(ice));
00129
00130
00131 if((mount())[0]!='/') {
00132 char tmp[MAX_VALUE_SIZE];
00133 sprintf(tmp,"/%s",mount());
00134 mount(tmp);
00135 }
00136
00137
00138
00139 if(format == SHOUT_FORMAT_VORBIS)
00140 if(!strstr(mount(),".ogg")) {
00141 char tmp[MAX_VALUE_SIZE];
00142 sprintf(tmp,"%s.ogg",mount());
00143 mount(tmp);
00144 }
00145
00146
00147 if( shout_set_mount(ice,mount()) )
00148 error("shout_set_mount: %s",shout_get_error(ice));
00149
00150 if( shout_set_name(ice,name()) )
00151 error("shout_set_name: %s",shout_get_error(ice));
00152
00153 if( shout_set_url(ice,url()) )
00154 error("shout_set_url: %s",shout_get_error(ice));
00155
00156 if( shout_set_description(ice,desc()) )
00157 error("shout_set_description: %s",shout_get_error(ice));
00158
00159
00160
00161
00162
00163 if( shout_set_audio_info(ice, SHOUT_AI_BITRATE, bps()) )
00164 error("shout_set_audio_info %s: %s",SHOUT_AI_BITRATE, bps());
00165
00166 if( shout_set_audio_info(ice, SHOUT_AI_SAMPLERATE, freq()) )
00167 error("shout_set_audio_info %s: %s",SHOUT_AI_SAMPLERATE, freq());
00168
00169 if( shout_set_audio_info(ice, SHOUT_AI_CHANNELS, channels()) )
00170 error("shout_set_audio_info %s: %s",SHOUT_AI_CHANNELS, channels());
00171
00172 func("Shouter audio info: %sKbp/s %sHz %s channels %sq",
00173 shout_get_audio_info(ice, SHOUT_AI_BITRATE),
00174 shout_get_audio_info(ice, SHOUT_AI_SAMPLERATE),
00175 shout_get_audio_info(ice, SHOUT_AI_CHANNELS));
00176
00177 if( shout_set_protocol(ice,login()) )
00178 error("shout_set_protocol %i: %s",login(),shout_get_error(ice));
00179
00180 if( shout_set_format(ice,format) )
00181 error("shout_set_format: %s",shout_get_error(ice));
00182
00183 if( shout_set_user(ice,"source") )
00184 error("shout_set_user: %s",shout_get_error(ice));
00185
00186 snprintf(temp,256,"%s ver. %s",PACKAGE,VERSION);
00187 if( shout_set_agent(ice,temp) )
00188 error("shout_set_agent: %s",shout_get_error(ice));
00189
00190 snprintf(streamurl,MAX_VALUE_SIZE,
00191 "http://%s:%i%s",host(),port(),mount());
00192
00193 if(was_running) { res = start(); }
00194 profile_changed = false;
00195 return res;
00196 }
00197
00198 int Shouter::send(short int *buf, unsigned int enc) {
00199 int res = 0;
00200 if(!running) return(0);
00201 if(enc<1) return res;
00202
00203 shout_sync(ice);
00204
00205 res = shout_send(ice,(unsigned char*) buf, enc);
00206 if(res) {
00207 error("shout_send: %s",shout_get_error(ice));
00208 if (got_sigpipe && (res==SHOUTERR_SOCKET)) {
00209 errors++;
00210 got_sigpipe = false;
00211 if(errors>10) {
00212 res = -2;
00213 errors = 0;
00214 }
00215 } else res = -1;
00216 } else errors = 0;
00217
00218 return(res);
00219 }