From 7ba5399c632fdbd65c2514cdecdf0d9f2454a24e Mon Sep 17 00:00:00 2001 From: brown fox Date: Thu, 1 Jun 2017 18:39:28 +0200 Subject: [PATCH 01/67] added optional commandline options -x proxy defines proxy to use, (see CURLOPT_PROXY) -f hotmusic defines the base name of the mp3 file(s) created -d duration defines the recording length in seconds (see CURLOPT_TIMEOUT) fixed header parsing added visual studio 2010 project files (for debugging using curl-master) --- README.mkd | 14 +- include/parsing.h | 1 + include/shoutcast.h | 4 +- include/types.h | 3 + shoutcastRecorder/shoutcastRecorder.sln | 20 +++ .../shoutcastRecorder/ReadMe.txt | 40 ++++++ shoutcastRecorder/shoutcastRecorder/getopt.c | 117 +++++++++++++++++ shoutcastRecorder/shoutcastRecorder/getopt.h | 7 + .../shoutcastRecorder/shoutcastRecorder.cpp | 7 + .../shoutcastRecorder.vcxproj | 123 ++++++++++++++++++ .../shoutcastRecorder.vcxproj.filters | 117 +++++++++++++++++ .../shoutcastRecorder/stdafx.cpp | 8 ++ shoutcastRecorder/shoutcastRecorder/stdafx.h | 15 +++ .../shoutcastRecorder/targetver.h | 8 ++ src/curl.c | 4 + src/header.c | 3 +- src/icy-string.c | 15 ++- src/log.c | 3 +- src/main.c | 59 ++++++++- src/metadata.c | 4 +- src/mp3data.c | 3 +- src/shoutcast.c | 4 +- src/stream.c | 20 ++- 23 files changed, 567 insertions(+), 32 deletions(-) create mode 100755 shoutcastRecorder/shoutcastRecorder.sln create mode 100755 shoutcastRecorder/shoutcastRecorder/ReadMe.txt create mode 100755 shoutcastRecorder/shoutcastRecorder/getopt.c create mode 100755 shoutcastRecorder/shoutcastRecorder/getopt.h create mode 100755 shoutcastRecorder/shoutcastRecorder/shoutcastRecorder.cpp create mode 100755 shoutcastRecorder/shoutcastRecorder/shoutcastRecorder.vcxproj create mode 100755 shoutcastRecorder/shoutcastRecorder/shoutcastRecorder.vcxproj.filters create mode 100755 shoutcastRecorder/shoutcastRecorder/stdafx.cpp create mode 100755 shoutcastRecorder/shoutcastRecorder/stdafx.h create mode 100755 shoutcastRecorder/shoutcastRecorder/targetver.h diff --git a/README.mkd b/README.mkd index 40d4bba..819d53a 100644 --- a/README.mkd +++ b/README.mkd @@ -28,12 +28,23 @@ How to run it Here are two examples : - ./shoutr -u http://88.190.24.47:80 + ./shoutr -u http://88.190.24.47:80 or ./shoutr -p frequence3.pls +Additional commandline options + -x proxy defines proxy to use, (see CURLOPT_PROXY) + -f hotmusic defines the base name of the mp3 file(s) created + -d duration defines the recording length in seconds (see CURLOPT_TIMEOUT) + +without these additional commandline options specified + no proxy is used (note: libcurl respects the proxy environment variables + named http_proxy, ftp_proxy, sftp_proxy etc., see CURLOPT_PROXY) + basename will be radio###.mp3 (where ### is incrementing number) + duration will be infinite (see CURLOPT_TIMEOUT) + TODO ---- @@ -44,6 +55,7 @@ Some interesting features to add : - add a big shoucast radio list with lots of radios - add shoutr_start and shoutr_stop functions. - add id3tags +- add option to name downloaded music using metadata LICENSE ------- diff --git a/include/parsing.h b/include/parsing.h index 850ce72..f9cb979 100644 --- a/include/parsing.h +++ b/include/parsing.h @@ -1,2 +1,3 @@ size_t parse_data(void *ptr, size_t size, size_t nmemb, void *userdata); +size_t parse_header(void *ptr, size_t size, size_t nmemb, void *userdata); \ No newline at end of file diff --git a/include/shoutcast.h b/include/shoutcast.h index 48cbbff..5090d9c 100644 --- a/include/shoutcast.h +++ b/include/shoutcast.h @@ -3,8 +3,8 @@ #include "types.h" -int load_stream(Stream *stream, const char *url); +int load_stream(Stream *stream, const char *url, const char *proxy, const char *basefilename, const char* duration); void global_listener(Stream *stream, char *buffer); -int write_data(Stream *stream, size_t *size); +int write_data(Stream *stream); #endif // __SHOUTCAST_H_ diff --git a/include/types.h b/include/types.h index 80d27fa..bc533ef 100644 --- a/include/types.h +++ b/include/types.h @@ -48,6 +48,9 @@ typedef struct typedef struct { char url[255]; // Stream url + char proxy[255]; // Network proxy + char basefilename[255]; // basefilename of output mp3 file + unsigned int duration; // max recording duration FILE *output_stream; // Output MP3 file char stream_title[500]; // Current title diff --git a/shoutcastRecorder/shoutcastRecorder.sln b/shoutcastRecorder/shoutcastRecorder.sln new file mode 100755 index 0000000..050de9a --- /dev/null +++ b/shoutcastRecorder/shoutcastRecorder.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shoutcastRecorder", "shoutcastRecorder\shoutcastRecorder.vcxproj", "{7EFF25AC-DF8A-44AF-83EE-B20CB7056DB7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7EFF25AC-DF8A-44AF-83EE-B20CB7056DB7}.Debug|Win32.ActiveCfg = Debug|Win32 + {7EFF25AC-DF8A-44AF-83EE-B20CB7056DB7}.Debug|Win32.Build.0 = Debug|Win32 + {7EFF25AC-DF8A-44AF-83EE-B20CB7056DB7}.Release|Win32.ActiveCfg = Release|Win32 + {7EFF25AC-DF8A-44AF-83EE-B20CB7056DB7}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/shoutcastRecorder/shoutcastRecorder/ReadMe.txt b/shoutcastRecorder/shoutcastRecorder/ReadMe.txt new file mode 100755 index 0000000..3935621 --- /dev/null +++ b/shoutcastRecorder/shoutcastRecorder/ReadMe.txt @@ -0,0 +1,40 @@ +======================================================================== + CONSOLE APPLICATION : shoutcastRecorder Project Overview +======================================================================== + +AppWizard has created this shoutcastRecorder application for you. + +This file contains a summary of what you will find in each of the files that +make up your shoutcastRecorder application. + + +shoutcastRecorder.vcxproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +shoutcastRecorder.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +shoutcastRecorder.cpp + This is the main application source file. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named shoutcastRecorder.pch and a precompiled types file named StdAfx.obj. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/shoutcastRecorder/shoutcastRecorder/getopt.c b/shoutcastRecorder/shoutcastRecorder/getopt.c new file mode 100755 index 0000000..1ea6e95 --- /dev/null +++ b/shoutcastRecorder/shoutcastRecorder/getopt.c @@ -0,0 +1,117 @@ +// from https://gist.github.com/superwills/5815344 + +// Put this in a separate .h file (called "getopt.h"). +// The prototype for the header file is: +/* +#ifndef GETOPT_H +#define GETOPT_H +int getopt(int nargc, char * const nargv[], const char *ostr) ; +#endif +*/ + +#include "getopt.h" // make sure you construct the header file as dictated above + +/* +* Copyright (c) 1987, 1993, 1994 +* The Regents of the University of California. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* 3. All advertising materials mentioning features or use of this software +* must display the following acknowledgement: +* This product includes software developed by the University of +* California, Berkeley and its contributors. +* 4. Neither the name of the University nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ + +#include +#include + +int opterr = 1, /* if error message should be printed */ + optind = 1, /* index into parent argv vector */ + optopt, /* character checked for validity */ + optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ + +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + +/* + * getopt -- + * Parse argc/argv argument vector. + */ +int getopt(int nargc, char * const nargv[], const char *ostr) +{ + static char *place = EMSG; /* option letter processing */ + const char *oli; /* option letter list index */ + + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc || *(place = nargv[optind]) != '-') { + place = EMSG; + return (-1); + } + if (place[1] && *++place == '-') { /* found "--" */ + ++optind; + place = EMSG; + return (-1); + } + } /* option letter okay? */ + if ((optopt = (int)*place++) == (int)':' || + !(oli = strchr(ostr, optopt))) { + /* + * if the user didn't specify '-' as an option, + * assume it means -1. + */ + if (optopt == (int)'-') + return (-1); + if (!*place) + ++optind; + if (opterr && *ostr != ':') + (void)printf("illegal option -- %c\n", optopt); + return (BADCH); + } + if (*++oli != ':') { /* don't need argument */ + optarg = NULL; + if (!*place) + ++optind; + } + else { /* need an argument */ + if (*place) /* no white space */ + optarg = place; + else if (nargc <= ++optind) { /* no arg */ + place = EMSG; + if (*ostr == ':') + return (BADARG); + if (opterr) + (void)printf("option requires an argument -- %c\n", optopt); + return (BADCH); + } + else /* white space */ + optarg = nargv[optind]; + place = EMSG; + ++optind; + } + return (optopt); /* dump back option letter */ +} diff --git a/shoutcastRecorder/shoutcastRecorder/getopt.h b/shoutcastRecorder/shoutcastRecorder/getopt.h new file mode 100755 index 0000000..8924258 --- /dev/null +++ b/shoutcastRecorder/shoutcastRecorder/getopt.h @@ -0,0 +1,7 @@ +#ifndef GETOPT_H +#define GETOPT_H + +int getopt(int nargc, char * const nargv[], const char *ostr) ; + +extern char *optarg; /* argument associated with option */ +#endif diff --git a/shoutcastRecorder/shoutcastRecorder/shoutcastRecorder.cpp b/shoutcastRecorder/shoutcastRecorder/shoutcastRecorder.cpp new file mode 100755 index 0000000..7f028de --- /dev/null +++ b/shoutcastRecorder/shoutcastRecorder/shoutcastRecorder.cpp @@ -0,0 +1,7 @@ +// shoutcastRecorder.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" + + + diff --git a/shoutcastRecorder/shoutcastRecorder/shoutcastRecorder.vcxproj b/shoutcastRecorder/shoutcastRecorder/shoutcastRecorder.vcxproj new file mode 100755 index 0000000..454797a --- /dev/null +++ b/shoutcastRecorder/shoutcastRecorder/shoutcastRecorder.vcxproj @@ -0,0 +1,123 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {7EFF25AC-DF8A-44AF-83EE-B20CB7056DB7} + Win32Proj + shoutcastRecorder + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + true + ..\..\..\curl-master\include\curl;$(IncludePath) + + + false + ..\..\..\curl-master\include\curl;$(IncludePath) + + + + + + Level3 + Disabled + WIN32;CURL_STATICLIB;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\include;..\..\..\curl-master\include;%(AdditionalIncludeDirectories) + + + Console + true + ..\..\..\curl-master\build\Win32\VC10\LIB Debug - DLL Windows SSPI + libcurld.lib;Ws2_32.lib;Wldap32.lib;crypt32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;CURL_STATICLIB;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\include;..\..\..\curl-master\include;%(AdditionalIncludeDirectories) + + + Console + true + true + true + ..\..\..\curl-master\build\Win32\VC10\LIB Debug - DLL Windows SSPI + libcurld.lib;Ws2_32.lib;Wldap32.lib;crypt32.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/shoutcastRecorder/shoutcastRecorder/shoutcastRecorder.vcxproj.filters b/shoutcastRecorder/shoutcastRecorder/shoutcastRecorder.vcxproj.filters new file mode 100755 index 0000000..0b94490 --- /dev/null +++ b/shoutcastRecorder/shoutcastRecorder/shoutcastRecorder.vcxproj.filters @@ -0,0 +1,117 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {f6d41f57-d9af-48a6-b803-afbad02b9764} + + + {f9dce2be-2382-4226-b11b-cca6f61584ca} + + + + + + + + Header Files + + + Header Files + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + Header Files + + + + + Source Files + + + Source Files + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + Source Files + + + \ No newline at end of file diff --git a/shoutcastRecorder/shoutcastRecorder/stdafx.cpp b/shoutcastRecorder/shoutcastRecorder/stdafx.cpp new file mode 100755 index 0000000..32d2274 --- /dev/null +++ b/shoutcastRecorder/shoutcastRecorder/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// shoutcastRecorder.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/shoutcastRecorder/shoutcastRecorder/stdafx.h b/shoutcastRecorder/shoutcastRecorder/stdafx.h new file mode 100755 index 0000000..47a0d02 --- /dev/null +++ b/shoutcastRecorder/shoutcastRecorder/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/shoutcastRecorder/shoutcastRecorder/targetver.h b/shoutcastRecorder/shoutcastRecorder/targetver.h new file mode 100755 index 0000000..90e767b --- /dev/null +++ b/shoutcastRecorder/shoutcastRecorder/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/src/curl.c b/src/curl.c index d243e6e..6e79e8e 100644 --- a/src/curl.c +++ b/src/curl.c @@ -25,6 +25,10 @@ int read_stream(Stream *stream) curl_easy_setopt(curl, CURLOPT_URL, stream->url); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl, CURLOPT_PROXY, stream->proxy); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, stream->duration); + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, parse_header); + curl_easy_setopt(curl, CURLOPT_HEADERDATA, stream); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, parse_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, stream); diff --git a/src/header.c b/src/header.c index 0443b7e..3cb1b37 100644 --- a/src/header.c +++ b/src/header.c @@ -9,10 +9,11 @@ int header_listener(Stream *stream, char *buffer) { + ICYHeader *header; if (!is_header(stream)) return 1; - ICYHeader *header = &stream->header; + header = &stream->header; if (stream->bytes_count_total >= HEADER_MAX) { printf("Error : couldn't retrieve server information.\n"); diff --git a/src/icy-string.c b/src/icy-string.c index 579df22..fd2ad3b 100644 --- a/src/icy-string.c +++ b/src/icy-string.c @@ -27,13 +27,14 @@ int get_http_header_field(char *header, const char* field, char* value) occurrence = strstr(header, field); content_pos = strlen(field)+1; - // TODO : Test NULL value - for (i=content_pos; occurrence[i] != '\0';i++) { - if (is_cr_present(occurrence, i)) { - // ":" is deleted - strncpy(value, occurrence+content_pos, i-content_pos); - value[i-content_pos-1] = '\0'; - return 0; + if (occurrence != NULL) { + for (i=content_pos; occurrence[i] != '\0';i++) { + if (is_cr_present(occurrence, i)) { + // ":" is deleted + strncpy(value, occurrence+content_pos, i-content_pos); + value[i-content_pos-1] = '\0'; + return 0; + } } } // Value hasn't been found diff --git a/src/log.c b/src/log.c index da24803..7d8d288 100644 --- a/src/log.c +++ b/src/log.c @@ -5,6 +5,7 @@ static FILE *fp_log; static FILE *fp_prog; +static char current_time[20]; static int get_time(char *string) { @@ -61,8 +62,6 @@ int log_close_files(void) static int log_append(FILE *fp, char *line) { - char current_time[20]; - if (fp == NULL || line == NULL) return -1; diff --git a/src/main.c b/src/main.c index 4f04021..95f359f 100644 --- a/src/main.c +++ b/src/main.c @@ -3,10 +3,14 @@ #include #include +#ifdef _WIN32 +#include +#include "../shoutcastRecorder/shoutcastRecorder/getopt.h" +#else #include // linux #include - +#endif #include "types.h" #include "parsing.h" #include "shoutcast.h" @@ -20,6 +24,9 @@ void usage(void) printf("Usage: shoutr [OPTIONS]\n"); printf(" -p\t: playlist file\n"); printf(" -u\t: stream url\n"); + printf(" -x\t: proxy (default no proxy)\n"); + printf(" -f\t: basefilename (default radio)\n"); + printf(" -d\t: recording duration (in seconds, default 0 = unlimited)\n"); } int main(int argc, char *argv[]) @@ -29,8 +36,11 @@ int main(int argc, char *argv[]) int uflag = 0; int c; char *cvalue = NULL; + char *proxy = NULL; + char *basefilename = "radio"; + char *duration = "0"; - while ((c = getopt(argc, argv, "p:u:h")) != -1) { + while ((c = getopt(argc, argv, "p:u:h:x:f:d:")) != -1) { switch(c) { // playlist case 'p': @@ -42,6 +52,18 @@ int main(int argc, char *argv[]) uflag = 1; cvalue = optarg; break; + // proxy + case 'x': + proxy = optarg; + break; + // basefilename + case 'f': + basefilename = optarg; + break; + // duration + case 'd': + duration = optarg; + break; case 'h': default: usage(); @@ -70,7 +92,7 @@ int main(int argc, char *argv[]) if (uflag) { Stream stream; - load_stream(&stream, cvalue); + load_stream(&stream, cvalue, proxy, basefilename, duration); if ((ret = read_stream(&stream)) < 0) { printf("Error : Couldn't read Shoutcast stream\n"); @@ -85,26 +107,49 @@ int main(int argc, char *argv[]) return ret; } +size_t parse_header(void *ptr, size_t size, size_t nmemb, void *userdata) +{ + unsigned int i; + char buffer; + Stream *stream = (Stream *)userdata; + size_t numbytes = size * nmemb; + + //stream->header.buffer; + //copy *ptr to neader.buffer starting at header.ptr position + void* dest = stream->header.ptr; + memcpy(dest, ptr, numbytes); + + for (i=0;ibytes_count_total++; + } + + printf("%.*s", (int) numbytes, (char*)ptr); + return numbytes; +} + size_t parse_data(void *ptr, size_t size, size_t nmemb, void *userdata) { unsigned int i; char buffer; Stream *stream = (Stream *)userdata; + size_t numbytes = size * nmemb; - stream->mp3data.buffer = (char*) malloc(nmemb); + stream->mp3data.buffer = (char*) malloc(numbytes); stream->mp3data.ptr = stream->mp3data.buffer; - for (i=0;ibytes_count_total++; } - write_data(stream, &size); + write_data(stream); free(stream->mp3data.buffer); stream->mp3data.size = 0; stream->blocks_count++; - return nmemb; + return numbytes; } diff --git a/src/metadata.c b/src/metadata.c index d5b57be..ca5f7aa 100644 --- a/src/metadata.c +++ b/src/metadata.c @@ -57,8 +57,8 @@ int metadata_body_handler(Stream *stream, char *buffer) { char new_filename[255] = ""; fclose(stream->output_stream); - sprintf(new_filename, "radio%d.mp3", stream->metadata_count); - stream->output_stream = fopen(new_filename, "w"); + sprintf(new_filename, "%s%d.mp3", stream->basefilename, stream->metadata_count); + stream->output_stream = fopen(new_filename, "wb"); } diff --git a/src/mp3data.c b/src/mp3data.c index 8d94626..66ad639 100644 --- a/src/mp3data.c +++ b/src/mp3data.c @@ -8,10 +8,11 @@ int mp3data_listener(Stream *stream, char *buffer) { + Mp3Data *mp3data; if (!is_mp3data(stream)) return -1; - Mp3Data *mp3data = &stream->mp3data; + mp3data = &stream->mp3data; *mp3data->ptr = *buffer; mp3data->size++; diff --git a/src/shoutcast.c b/src/shoutcast.c index 0890f52..c295a65 100644 --- a/src/shoutcast.c +++ b/src/shoutcast.c @@ -21,9 +21,9 @@ void global_listener(Stream *stream, char *buffer) mp3data_listener(stream, buffer); } -int write_data(Stream *stream, size_t *size) +int write_data(Stream *stream) { - int written = fwrite(stream->mp3data.buffer, *size, + int written = fwrite(stream->mp3data.buffer, sizeof(char), stream->mp3data.size, (FILE *)stream->output_stream); return written; diff --git a/src/stream.c b/src/stream.c index 93fbdb3..f57c77c 100644 --- a/src/stream.c +++ b/src/stream.c @@ -8,8 +8,10 @@ #include "pls.h" #include "curl.h" -int load_stream(Stream *stream, const char *url) +int load_stream(Stream *stream, const char *url, const char *proxy, const char *basefilename, const char* duration) { + char filename[255] = ""; + ICYHeader *header = &stream->header; MetaData *metadata = &stream->metadata; Mp3Data *mp3data = &stream->mp3data; @@ -40,14 +42,18 @@ int load_stream(Stream *stream, const char *url) stream->status = E_STATUS_HEADER; - stream->output_stream = fopen("radio0.mp3","w"); - if (strcpy(stream->url, url) != NULL) + stream->duration = atoi(duration); + + if ((strcpy(stream->url, url) != NULL) && (strcpy(stream->proxy, proxy) != NULL)&& (strcpy(stream->basefilename, basefilename) != NULL)) + { + sprintf(filename, "%s%d.mp3", stream->basefilename, stream->metadata_count); + stream->output_stream = fopen(filename, "wb"); return 0; - else - return 1; + } + return -1; } -int load_stream_from_playlist(char *filename) +int load_stream_from_playlist(char *filename, const char *proxy, const char *basefilename, const char *duration) { Stream stream; PlsFile pls; @@ -68,7 +74,7 @@ int load_stream_from_playlist(char *filename) goto early_err; } - if ((ret = load_stream(&stream, pls.entries->file)) < 0) { + if ((ret = load_stream(&stream, pls.entries->file, proxy, basefilename, duration)) < 0) { printf("Error : Couldn't load Shoutcast stream\n"); goto err; } From 898725870fda059c92cd9251f7ec60f3174d7b33 Mon Sep 17 00:00:00 2001 From: brown fox Date: Fri, 2 Jun 2017 19:23:29 +0200 Subject: [PATCH 02/67] fix segmentation fault on raspberrypi --- src/main.c | 5 ++++- src/stream.c | 19 +++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/main.c b/src/main.c index 95f359f..db62a6e 100644 --- a/src/main.c +++ b/src/main.c @@ -37,7 +37,10 @@ int main(int argc, char *argv[]) int c; char *cvalue = NULL; char *proxy = NULL; - char *basefilename = "radio"; + + char* basefilename = malloc(255*sizeof(char)); + snprintf(basefilename, 255, "radio"); + char *duration = "0"; while ((c = getopt(argc, argv, "p:u:h:x:f:d:")) != -1) { diff --git a/src/stream.c b/src/stream.c index f57c77c..9385b2c 100644 --- a/src/stream.c +++ b/src/stream.c @@ -10,6 +10,7 @@ int load_stream(Stream *stream, const char *url, const char *proxy, const char *basefilename, const char* duration) { + int success = TRUE; char filename[255] = ""; ICYHeader *header = &stream->header; @@ -43,14 +44,24 @@ int load_stream(Stream *stream, const char *url, const char *proxy, const char * stream->status = E_STATUS_HEADER; stream->duration = atoi(duration); - - if ((strcpy(stream->url, url) != NULL) && (strcpy(stream->proxy, proxy) != NULL)&& (strcpy(stream->basefilename, basefilename) != NULL)) + + memset(stream->proxy, 0, 255); + memset(stream->url, 0, 255); + memset(stream->basefilename, 0, 255); + memset(filename, 0, 255); + + if (proxy != NULL) { + success = strncpy(stream->proxy, proxy, 254) != NULL; + } + + success = success && ((strncpy(stream->url, url, 254) != NULL) && (strncpy(stream->basefilename, basefilename, 254) != NULL)); + if (success) { - sprintf(filename, "%s%d.mp3", stream->basefilename, stream->metadata_count); + snprintf(filename, 254, "%s%d.mp3", stream->basefilename, stream->metadata_count); stream->output_stream = fopen(filename, "wb"); return 0; } - return -1; + return 1; } int load_stream_from_playlist(char *filename, const char *proxy, const char *basefilename, const char *duration) From 1bc1c984e007c916c992bb7593bc0b88c00fb26e Mon Sep 17 00:00:00 2001 From: brown fox Date: Fri, 2 Jun 2017 19:28:18 +0200 Subject: [PATCH 03/67] updated readme --- README.mkd | 1 + 1 file changed, 1 insertion(+) diff --git a/README.mkd b/README.mkd index 819d53a..c47e77d 100644 --- a/README.mkd +++ b/README.mkd @@ -35,6 +35,7 @@ or ./shoutr -p frequence3.pls Additional commandline options + -x proxy defines proxy to use, (see CURLOPT_PROXY) -f hotmusic defines the base name of the mp3 file(s) created -d duration defines the recording length in seconds (see CURLOPT_TIMEOUT) From 5820f1eb6989bd6214d18e5785b68d442d667a1b Mon Sep 17 00:00:00 2001 From: brown fox Date: Fri, 2 Jun 2017 19:29:47 +0200 Subject: [PATCH 04/67] updated README.mkd --- README.mkd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.mkd b/README.mkd index c47e77d..a6d6404 100644 --- a/README.mkd +++ b/README.mkd @@ -41,8 +41,8 @@ Additional commandline options -d duration defines the recording length in seconds (see CURLOPT_TIMEOUT) without these additional commandline options specified - no proxy is used (note: libcurl respects the proxy environment variables - named http_proxy, ftp_proxy, sftp_proxy etc., see CURLOPT_PROXY) + + no proxy is used (note: libcurl respects the proxy environment variables named http_proxy, ftp_proxy, sftp_proxy etc., see CURLOPT_PROXY) basename will be radio###.mp3 (where ### is incrementing number) duration will be infinite (see CURLOPT_TIMEOUT) From 501aad5fbdc2d71156d38216ebc905009f37005b Mon Sep 17 00:00:00 2001 From: brown fox Date: Tue, 12 Sep 2017 20:50:16 +0200 Subject: [PATCH 05/67] fixed pls parsing --- src/curl.c | 10 ++++++++-- src/main.c | 13 +++++++------ src/metadata.c | 2 +- src/pls.c | 48 +++++++++++++++++++++++------------------------- src/stream.c | 9 ++++++--- 5 files changed, 45 insertions(+), 37 deletions(-) mode change 100644 => 100755 src/pls.c diff --git a/src/curl.c b/src/curl.c index 6e79e8e..1b20f56 100644 --- a/src/curl.c +++ b/src/curl.c @@ -12,11 +12,16 @@ int read_stream(Stream *stream) int ret = 0; if (stream->url == NULL) { + printf("Error : stream->url null\n"); ret = -1; goto early_err; } + printf("stream->url [%s]\n", stream->url); + printf("stream->proxy [%s]\n", stream->proxy); + if ((curl = curl_easy_init()) == NULL) { + printf("Error : curl_easy_init\n"); ret = -1; goto early_err; } @@ -32,8 +37,9 @@ int read_stream(Stream *stream) curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, parse_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, stream); - if ((curl_res = curl_easy_perform(curl)) != 0) { - printf("ERROR : %s\n", curl_easy_strerror(curl_res)); + curl_res = curl_easy_perform(curl); + if (curl_res != CURLE_OK && curl_res != CURLE_OPERATION_TIMEDOUT) { + printf("ERROR %2d: %s\n", curl_res, curl_easy_strerror(curl_res)); ret = -1; goto err; } diff --git a/src/main.c b/src/main.c index db62a6e..3858929 100644 --- a/src/main.c +++ b/src/main.c @@ -17,7 +17,7 @@ #include "curl.h" #include "log.h" -int load_stream_from_playlist(char *filename); +int load_stream_from_playlist(char *filename, const char *proxy, const char *basefilename, const char *duration); void usage(void) { @@ -37,12 +37,11 @@ int main(int argc, char *argv[]) int c; char *cvalue = NULL; char *proxy = NULL; + char *duration = "0"; - char* basefilename = malloc(255*sizeof(char)); - snprintf(basefilename, 255, "radio"); + char* basefilename = (char*) malloc(255*sizeof(char)); + sprintf(basefilename, "radio"); - char *duration = "0"; - while ((c = getopt(argc, argv, "p:u:h:x:f:d:")) != -1) { switch(c) { // playlist @@ -87,7 +86,9 @@ int main(int argc, char *argv[]) } if (pflag) { - if ((ret = load_stream_from_playlist(cvalue)) < 0) { + //if ((ret = load_stream_from_playlist(cvalue)) < 0) + if ((ret = load_stream_from_playlist(cvalue, proxy, basefilename, duration)) < 0) + { printf("Couldn't load stream from playlist\n"); goto err; } diff --git a/src/metadata.c b/src/metadata.c index ca5f7aa..996ab1c 100644 --- a/src/metadata.c +++ b/src/metadata.c @@ -57,7 +57,7 @@ int metadata_body_handler(Stream *stream, char *buffer) { char new_filename[255] = ""; fclose(stream->output_stream); - sprintf(new_filename, "%s%d.mp3", stream->basefilename, stream->metadata_count); + sprintf(new_filename, "%s%03d.mp3", stream->basefilename, stream->metadata_count); stream->output_stream = fopen(new_filename, "wb"); } diff --git a/src/pls.c b/src/pls.c old mode 100644 new mode 100755 index 144970e..e8d39f7 --- a/src/pls.c +++ b/src/pls.c @@ -14,7 +14,7 @@ void print_pls(PlsFile *pls) unsigned int i; PlsEntry *entry = pls->entries; for (i=0;inumber_entries;i++) { - printf("[%2d] %s - %s\n", i, entry->file, entry->title); + printf("%2d %s\n", i, entry->file); entry++; } } @@ -28,10 +28,12 @@ int pls_load_file(char *filename, PlsFile *pls) fp = fopen(filename, "r"); if (fp == NULL) { + printf("fopen(%s) failed\n", filename); return -1; } if (!is_pls_file(fp)) { + printf("%s is not a pls file\n", filename); return -1; } @@ -53,13 +55,14 @@ int init_pls_struct(PlsFile *pls, unsigned int number_entries) pls->entries = malloc(number_entries*sizeof(PlsEntry)); pls->version = 0; if (pls->entries == NULL) { + printf("no entries\n"); return -1; } else { unsigned int i; PlsEntry *entry = pls->entries; for (i=0;inumber_entries;i++) { - strcpy(entry->file, "\0"); - strcpy(entry->title, "\0"); + memset(entry->file, 0, sizeof entry->file); + memset(entry->title, 0, sizeof entry->file); entry++; } return 0; @@ -72,7 +75,7 @@ static int pls_get_field(char *buffer, char *value) char *ptr_end; ptr_begin = strstr(buffer, "=")+1; - ptr_end = strstr(buffer, "\n"); + ptr_end = strstr(buffer, "\n")-1; strncpy(value, ptr_begin, (int)(ptr_end - ptr_begin)); return 0; @@ -86,20 +89,13 @@ static int pls_get_entries(FILE *fp, PlsFile *pls) fseek(fp, 0 ,SEEK_SET); fgets(buffer, MAX_LINE_LENGTH, fp); - fgets(buffer, MAX_LINE_LENGTH, fp); for (i=0;inumber_entries;i++) { fgets(buffer, MAX_LINE_LENGTH, fp); - // TODO : gérer le NULL - - pls_get_field(buffer, entry->file); - - fgets(buffer, MAX_LINE_LENGTH, fp); - pls_get_field(buffer, entry->title); - - fgets(buffer, MAX_LINE_LENGTH, fp); - // strcpy(entry->length, buffer); - entry++; + if (strstr(buffer, "File") != NULL) { + pls_get_field(buffer, entry->file); + entry++; + } } return 0; // TODO : use a better return value } @@ -107,10 +103,12 @@ static int pls_get_entries(FILE *fp, PlsFile *pls) int is_pls_file(FILE *fp) { char buffer[MAX_LINE_LENGTH]; - + fseek(fp, 0 ,SEEK_SET); fgets(buffer, MAX_LINE_LENGTH, fp); - if (strcmp(buffer, "[playlist]\n") != 0) { + + if (strncmp(buffer, "[playlist]", 10) != 0) { fseek(fp, 0 ,SEEK_SET); + printf("no [playlist] in %s\n", buffer); return FALSE; } @@ -124,7 +122,7 @@ int is_pls_file(FILE *fp) fseek(fp, 0, SEEK_SET); return TRUE; } - + printf("no [Version=]\n"); return FALSE; } @@ -135,12 +133,12 @@ static unsigned int pls_get_number_entries(FILE *fp) fseek(fp, 0, SEEK_SET); fgets(buffer, MAX_LINE_LENGTH, fp); - fgets(buffer, MAX_LINE_LENGTH, fp); - - if (strstr(buffer, "NumberOfEntries=") != NULL) { - sprintf(number_entries_str, "%c%c", buffer[16], buffer[17]); - return (unsigned int)atoi(number_entries_str); - } else { - return 0; + while (!feof (fp)) { + fgets(buffer, MAX_LINE_LENGTH, fp); + if (strstr(buffer, "NumberOfEntries=") != NULL) { + sprintf(number_entries_str, "%c%c", buffer[16], buffer[17]); + return (unsigned int)atoi(number_entries_str); + } } + return 0; } diff --git a/src/stream.c b/src/stream.c index 9385b2c..9fabcab 100644 --- a/src/stream.c +++ b/src/stream.c @@ -57,7 +57,7 @@ int load_stream(Stream *stream, const char *url, const char *proxy, const char * success = success && ((strncpy(stream->url, url, 254) != NULL) && (strncpy(stream->basefilename, basefilename, 254) != NULL)); if (success) { - snprintf(filename, 254, "%s%d.mp3", stream->basefilename, stream->metadata_count); + sprintf(filename, "%s%03d.mp3", stream->basefilename, stream->metadata_count); stream->output_stream = fopen(filename, "wb"); return 0; } @@ -68,14 +68,17 @@ int load_stream_from_playlist(char *filename, const char *proxy, const char *bas { Stream stream; PlsFile pls; + PlsEntry *entry; int ret = 0; if (filename == NULL) { + printf("Error : Couldn't load null file\n"); ret = -1; goto early_err; } if (!is_pls_extension(filename)) { + printf("Error : !is_pls_extension(%s)\n", filename); ret = -1; goto early_err; } @@ -84,8 +87,8 @@ int load_stream_from_playlist(char *filename, const char *proxy, const char *bas printf("Error : Couldn't load pls file\n"); goto early_err; } - - if ((ret = load_stream(&stream, pls.entries->file, proxy, basefilename, duration)) < 0) { + entry = pls.entries; + if ((ret = load_stream(&stream, entry->file, proxy, basefilename, duration)) < 0) { printf("Error : Couldn't load Shoutcast stream\n"); goto err; } From 488cba846e6ebeeb106472f7892118421ef65438 Mon Sep 17 00:00:00 2001 From: brown fox Date: Sun, 10 Mar 2019 12:51:54 +0100 Subject: [PATCH 06/67] update remote --- src/curl.c | 2 ++ src/main.c | 17 +++++++++++++---- src/metadata.c | 2 +- src/stream.c | 7 ++----- 4 files changed, 18 insertions(+), 10 deletions(-) mode change 100644 => 100755 src/curl.c mode change 100644 => 100755 src/main.c mode change 100644 => 100755 src/metadata.c mode change 100644 => 100755 src/stream.c diff --git a/src/curl.c b/src/curl.c old mode 100644 new mode 100755 index 1b20f56..a674587 --- a/src/curl.c +++ b/src/curl.c @@ -36,6 +36,8 @@ int read_stream(Stream *stream) curl_easy_setopt(curl, CURLOPT_HEADERDATA, stream); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, parse_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, stream); + curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); + curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 60L); curl_res = curl_easy_perform(curl); if (curl_res != CURLE_OK && curl_res != CURLE_OPERATION_TIMEDOUT) { diff --git a/src/main.c b/src/main.c old mode 100644 new mode 100755 index 3858929..f49bd91 --- a/src/main.c +++ b/src/main.c @@ -17,7 +17,7 @@ #include "curl.h" #include "log.h" -int load_stream_from_playlist(char *filename, const char *proxy, const char *basefilename, const char *duration); +int load_stream_from_playlist(char *filename); void usage(void) { @@ -86,9 +86,7 @@ int main(int argc, char *argv[]) } if (pflag) { - //if ((ret = load_stream_from_playlist(cvalue)) < 0) - if ((ret = load_stream_from_playlist(cvalue, proxy, basefilename, duration)) < 0) - { + if ((ret = load_stream_from_playlist(cvalue)) < 0) { printf("Couldn't load stream from playlist\n"); goto err; } @@ -157,3 +155,14 @@ size_t parse_data(void *ptr, size_t size, size_t nmemb, void *userdata) return numbytes; } +am->bytes_count_total++; + } + + write_data(stream); + free(stream->mp3data.buffer); + stream->mp3data.size = 0; + + stream->blocks_count++; + + return numbytes; +} diff --git a/src/metadata.c b/src/metadata.c old mode 100644 new mode 100755 index 996ab1c..c54009b --- a/src/metadata.c +++ b/src/metadata.c @@ -57,7 +57,7 @@ int metadata_body_handler(Stream *stream, char *buffer) { char new_filename[255] = ""; fclose(stream->output_stream); - sprintf(new_filename, "%s%03d.mp3", stream->basefilename, stream->metadata_count); + sprintf(new_filename, "%s%03d-%s.mp3", stream->basefilename, stream->metadata_count, stream->stream_title); stream->output_stream = fopen(new_filename, "wb"); } diff --git a/src/stream.c b/src/stream.c old mode 100644 new mode 100755 index 9fabcab..f26cfef --- a/src/stream.c +++ b/src/stream.c @@ -68,17 +68,14 @@ int load_stream_from_playlist(char *filename, const char *proxy, const char *bas { Stream stream; PlsFile pls; - PlsEntry *entry; int ret = 0; if (filename == NULL) { - printf("Error : Couldn't load null file\n"); ret = -1; goto early_err; } if (!is_pls_extension(filename)) { - printf("Error : !is_pls_extension(%s)\n", filename); ret = -1; goto early_err; } @@ -87,8 +84,8 @@ int load_stream_from_playlist(char *filename, const char *proxy, const char *bas printf("Error : Couldn't load pls file\n"); goto early_err; } - entry = pls.entries; - if ((ret = load_stream(&stream, entry->file, proxy, basefilename, duration)) < 0) { + + if ((ret = load_stream(&stream, pls.entries->file, proxy, basefilename, duration)) < 0) { printf("Error : Couldn't load Shoutcast stream\n"); goto err; } From c5a1cc66e17abdf2df3c10861f89d372d2fa4abc Mon Sep 17 00:00:00 2001 From: smitdol Date: Sun, 16 Aug 2020 10:03:31 +0200 Subject: [PATCH 07/67] new file only when stream_title changes --- src/log.c | 32 ++++++++++++++++++++++++++++---- src/main.c | 11 ----------- src/metadata.c | 31 +++++++++++++++++++++++-------- src/stream.c | 3 ++- 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/src/log.c b/src/log.c index 7d8d288..e9571d1 100644 --- a/src/log.c +++ b/src/log.c @@ -6,6 +6,8 @@ static FILE *fp_log; static FILE *fp_prog; static char current_time[20]; +static char current_date[20]; +static char tempfile[255]; static int get_time(char *string) { @@ -28,21 +30,42 @@ static int get_time(char *string) return 0; } +static int get_date(char *string) +{ + time_t rawtime; + struct tm *timeinfo; + + if (string == NULL) + return -1; + + time (&rawtime); + timeinfo = localtime(&rawtime); + + sprintf(string, "%d%02d%02d", 1900+timeinfo->tm_year, timeinfo->tm_mon+1, timeinfo->tm_mday); + + return 0; +} + int log_open_files(void) { if (fp_log != NULL) return -1; - fp_log = fopen("shoutr.log","a"); + if( get_date(current_date) <0) { + printf("Couldn't get date"); + return -1; + } + snprintf(tempfile,255,"shoutr.%s.log",current_date); + fp_log = fopen(tempfile,"a"); if (fp_log == NULL) { printf("Couldn't open shoutr.log file\n"); return -1; } - fp_prog = fopen("prog.log","a"); + snprintf(tempfile,255,"prog.%s.log",current_date); + fp_prog = fopen(tempfile,"a"); if (fp_prog == NULL) { printf("Couldn't open prog.log file\n"); - fclose(fp_log); return -1; } @@ -82,7 +105,8 @@ static int log_append(FILE *fp, char *line) void slog(char *line) { - log_append(fp_log, line); + if (log_append(fp_log, line) < 0) + printf("Coudln't write shoutr log\n"); } void slog_prog(char *line) diff --git a/src/main.c b/src/main.c index f49bd91..09f8a7e 100755 --- a/src/main.c +++ b/src/main.c @@ -155,14 +155,3 @@ size_t parse_data(void *ptr, size_t size, size_t nmemb, void *userdata) return numbytes; } -am->bytes_count_total++; - } - - write_data(stream); - free(stream->mp3data.buffer); - stream->mp3data.size = 0; - - stream->blocks_count++; - - return numbytes; -} diff --git a/src/metadata.c b/src/metadata.c index c54009b..87a8f2b 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -48,19 +48,34 @@ int metadata_body_handler(Stream *stream, char *buffer) char metadata_content[500]; char stream_title[500]; strncpy(metadata_content, metadata->buffer, metadata->size); - get_metadata_field(metadata_content, "StreamTitle", stream->stream_title); - sprintf(stream_title, "%s\n", stream->stream_title); - printf("%s", stream_title); - slog_prog(stream_title); - stream->metadata_count++; - + get_metadata_field(metadata_content, "StreamTitle", stream_title); + stream_title[499]='\0'; + // filter problematic characters from StreamTitle + for (int i =0; i < 499; i++) { + if (stream_title[i]=='*') { stream_title[i]='_'; continue; } + if (stream_title[i]=='?') { stream_title[i]='_'; continue; } + if (stream_title[i]=='>') { stream_title[i]='_'; continue; } + if (stream_title[i]=='<') { stream_title[i]='_'; continue; } + if (stream_title[i]=='\\') { stream_title[i]='_'; continue; } + if (stream_title[i]=='|') { stream_title[i]='_'; continue; } + if (stream_title[i]=='\"') { stream_title[i]='_'; continue; } + if (stream_title[i]==':') { stream_title[i]='_'; continue; } + if (stream_title[i]=='/') { stream_title[i]='_'; continue; } + if (stream_title[i]=='\0') { break;} //done + } + printf("%s\n", stream_title); + if (0 != strncmp(stream->stream_title, stream_title, 500)) { + strncpy(stream->stream_title,stream_title, 500); + stream->metadata_count++; char new_filename[255] = ""; + snprintf(new_filename,255,"%s%03d-%s.mp3", stream->basefilename, stream->metadata_count, stream->stream_title); + new_filename[254]='\0'; fclose(stream->output_stream); - sprintf(new_filename, "%s%03d-%s.mp3", stream->basefilename, stream->metadata_count, stream->stream_title); stream->output_stream = fopen(new_filename, "wb"); - } + snprintf(stream_title,500, "%s\n", stream->stream_title); + slog_prog(stream_title); stream->bytes_count = 0; stream->status = E_STATUS_MP3DATA; diff --git a/src/stream.c b/src/stream.c index f26cfef..16c4f08 100755 --- a/src/stream.c +++ b/src/stream.c @@ -39,7 +39,8 @@ int load_stream(Stream *stream, const char *url, const char *proxy, const char * stream->bytes_count_total = 0; stream->blocks_count = 0; stream->metadata_count = 0; - stream->stream_title[0] = '\0'; + stream->stream_title[0] = '*';//force create new file + stream->stream_title[1] = '\0'; stream->status = E_STATUS_HEADER; From 68bc8d85ae47b558aee3c398086ce87967f78b3a Mon Sep 17 00:00:00 2001 From: smitdol Date: Thu, 20 Aug 2020 18:36:51 +0200 Subject: [PATCH 08/67] extra logging and no-metainfo handling --- src/header.c | 3 ++- src/metadata.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/header.c b/src/header.c index 3cb1b37..be5b742 100644 --- a/src/header.c +++ b/src/header.c @@ -1,5 +1,6 @@ #include #include +#include #include "types.h" #include "header.h" @@ -28,7 +29,7 @@ int header_listener(Stream *stream, char *buffer) if (header->metaint == 0) { printf("Error : Couldn't find metaint information\n"); - exit(-1); + header->metaint = INT_MAX; } print_header(header); diff --git a/src/metadata.c b/src/metadata.c index 87a8f2b..5559cab 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -50,6 +50,7 @@ int metadata_body_handler(Stream *stream, char *buffer) strncpy(metadata_content, metadata->buffer, metadata->size); get_metadata_field(metadata_content, "StreamTitle", stream_title); stream_title[499]='\0'; + metadata_content[499]='\0'; // filter problematic characters from StreamTitle for (int i =0; i < 499; i++) { if (stream_title[i]=='*') { stream_title[i]='_'; continue; } @@ -77,6 +78,10 @@ int metadata_body_handler(Stream *stream, char *buffer) snprintf(stream_title,500, "%s\n", stream->stream_title); slog_prog(stream_title); + // slog metadata_content + snprintf(stream_title,500, "%s\n", metadata_content); + slog(stream_title); + stream->bytes_count = 0; stream->status = E_STATUS_MP3DATA; } else { From 0c6d46591daa8d246a758e20cd6de1a0eeeb191d Mon Sep 17 00:00:00 2001 From: smitdol Date: Thu, 27 Aug 2020 21:09:00 +0200 Subject: [PATCH 09/67] handling redirects and timestamping basefilenam --- src/curl.c | 1 + src/header.c | 1 - src/mp3data.c | 4 +++- src/stream.c | 9 +++++++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/curl.c b/src/curl.c index a674587..8381cd5 100755 --- a/src/curl.c +++ b/src/curl.c @@ -38,6 +38,7 @@ int read_stream(Stream *stream) curl_easy_setopt(curl, CURLOPT_WRITEDATA, stream); curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 60L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_res = curl_easy_perform(curl); if (curl_res != CURLE_OK && curl_res != CURLE_OPERATION_TIMEDOUT) { diff --git a/src/header.c b/src/header.c index be5b742..7e777c7 100644 --- a/src/header.c +++ b/src/header.c @@ -29,7 +29,6 @@ int header_listener(Stream *stream, char *buffer) if (header->metaint == 0) { printf("Error : Couldn't find metaint information\n"); - header->metaint = INT_MAX; } print_header(header); diff --git a/src/mp3data.c b/src/mp3data.c index 66ad639..d2fbdce 100644 --- a/src/mp3data.c +++ b/src/mp3data.c @@ -14,12 +14,14 @@ int mp3data_listener(Stream *stream, char *buffer) mp3data = &stream->mp3data; + if (mp3data->ptr == NULL) + return 0; *mp3data->ptr = *buffer; mp3data->size++; mp3data->ptr++; stream->bytes_count++; - if (stream->bytes_count == stream->header.metaint) + if (stream->header.metaint > 0 && stream->bytes_count == stream->header.metaint) stream->status = E_STATUS_METADATA_HEADER; return 0; diff --git a/src/stream.c b/src/stream.c index 16c4f08..8ec240a 100755 --- a/src/stream.c +++ b/src/stream.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "types.h" #include "stream.h" @@ -54,8 +55,12 @@ int load_stream(Stream *stream, const char *url, const char *proxy, const char * if (proxy != NULL) { success = strncpy(stream->proxy, proxy, 254) != NULL; } - - success = success && ((strncpy(stream->url, url, 254) != NULL) && (strncpy(stream->basefilename, basefilename, 254) != NULL)); + + time_t rawtime; + struct tm * timeinfo; + time (&rawtime); + timeinfo = localtime(&rawtime); + success = success && ((strncpy(stream->url, url, 254) != NULL) && (0 != strftime(stream->basefilename,254,basefilename,timeinfo))); if (success) { sprintf(filename, "%s%03d.mp3", stream->basefilename, stream->metadata_count); From 619de6e3f0d37d9d6b9ee5857bb05e7c5cd29970 Mon Sep 17 00:00:00 2001 From: smitdol Date: Fri, 28 Aug 2020 11:44:39 +0200 Subject: [PATCH 10/67] HTTP 1.0 --- src/curl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/curl.c b/src/curl.c index 8381cd5..d6dad68 100755 --- a/src/curl.c +++ b/src/curl.c @@ -39,6 +39,7 @@ int read_stream(Stream *stream) curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 60L); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); curl_res = curl_easy_perform(curl); if (curl_res != CURLE_OK && curl_res != CURLE_OPERATION_TIMEDOUT) { From 7a466e8bceb21ce22f0ebe57183ac13cb90def76 Mon Sep 17 00:00:00 2001 From: smitdol Date: Fri, 28 Aug 2020 12:15:20 +0200 Subject: [PATCH 11/67] updated README.mkd --- README.mkd | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/README.mkd b/README.mkd index a6d6404..dcc0967 100644 --- a/README.mkd +++ b/README.mkd @@ -23,12 +23,19 @@ How does it work ? - At the end of each block, we write gathered MP3 data into an external file - Now we can enjoy downloaded music :) +How to build it +--------------- + +use make to build +artefact is in build folder +see Makefile + How to run it ------------- Here are two examples : - ./shoutr -u http://88.190.24.47:80 + ./shoutr -u http://88.190.24.47:80 -f ./%w-%H- -d 3580 or @@ -45,7 +52,19 @@ without these additional commandline options specified no proxy is used (note: libcurl respects the proxy environment variables named http_proxy, ftp_proxy, sftp_proxy etc., see CURLOPT_PROXY) basename will be radio###.mp3 (where ### is incrementing number) duration will be infinite (see CURLOPT_TIMEOUT) - + base name can contain timestamp directives (see strftime) + base name will be appended with name of downloaded music using metadata (if available) + +cron example : + +SHELL=/bin/bash +log=/HDD/log/crontab. +dt=date +%Y%m%d +dow=date +%u + +stream=http://88.190.24.47:80 +0 10 * * * cd /HDD; ./shoutr -u $stream -f ./$($dow)-10- -d 3580 >> $log$($dt).log 2>&1 + TODO ---- @@ -56,7 +75,6 @@ Some interesting features to add : - add a big shoucast radio list with lots of radios - add shoutr_start and shoutr_stop functions. - add id3tags -- add option to name downloaded music using metadata LICENSE ------- @@ -66,5 +84,4 @@ See the file COPYING for details. Contact ------- - Yoann Sculo - From fc620572cd3c8674c615c64419c8d3512efbfd0e Mon Sep 17 00:00:00 2001 From: smitdol Date: Sun, 30 Aug 2020 10:20:59 +0200 Subject: [PATCH 12/67] retry if connection closed prematurely --- src/curl.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/curl.c b/src/curl.c index d6dad68..e7d5501 100755 --- a/src/curl.c +++ b/src/curl.c @@ -1,5 +1,6 @@ #include #include +#include #include "types.h" #include "parsing.h" @@ -31,7 +32,6 @@ int read_stream(Stream *stream) curl_easy_setopt(curl, CURLOPT_URL, stream->url); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_PROXY, stream->proxy); - curl_easy_setopt(curl, CURLOPT_TIMEOUT, stream->duration); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, parse_header); curl_easy_setopt(curl, CURLOPT_HEADERDATA, stream); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, parse_data); @@ -41,11 +41,19 @@ int read_stream(Stream *stream) curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - curl_res = curl_easy_perform(curl); - if (curl_res != CURLE_OK && curl_res != CURLE_OPERATION_TIMEDOUT) { - printf("ERROR %2d: %s\n", curl_res, curl_easy_strerror(curl_res)); - ret = -1; - goto err; + time_t start_t, end_t; + time(&start_t); + uint seconds_elapsed = 0; + while(seconds_elapsed <= stream->duration) { + curl_easy_setopt(curl, CURLOPT_TIMEOUT, stream->duration-seconds_elapsed); + curl_res = curl_easy_perform(curl); + if (curl_res != CURLE_OK && curl_res != CURLE_OPERATION_TIMEDOUT) { + printf("ERROR %2d: %s\n", curl_res, curl_easy_strerror(curl_res)); + ret = -1; + goto err; + } + time(&end_t); + seconds_elapsed=(uint)difftime(end_t, start_t); } err: From 750dc91f781c08cd8877c06d8b2267296c4c1c71 Mon Sep 17 00:00:00 2001 From: smitdol Date: Sun, 30 Aug 2020 10:48:17 +0200 Subject: [PATCH 13/67] update README --- README.mkd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.mkd b/README.mkd index dcc0967..46022b9 100644 --- a/README.mkd +++ b/README.mkd @@ -10,6 +10,9 @@ Dependencies ------------ - libcurl + sudo apt-get install libcurl-dev + sudo apt-get install libcurl4-openssl-dev + How does it work ? ------------------ From ceaf2f57165da6672eb3285bd437b444b9cf39eb Mon Sep 17 00:00:00 2001 From: smitdol Date: Sun, 30 Aug 2020 17:11:45 +0200 Subject: [PATCH 14/67] added repeat functionality --- include/curl.h | 8 ++ include/shoutcast.h | 2 +- include/types.h | 1 + src/curl.c | 188 ++++++++++++++++++++++++++++++++------------ src/main.c | 9 ++- src/stream.c | 10 +-- 6 files changed, 159 insertions(+), 59 deletions(-) mode change 100644 => 100755 include/curl.h diff --git a/include/curl.h b/include/curl.h old mode 100644 new mode 100755 index 7f56f36..a1dd6a5 --- a/include/curl.h +++ b/include/curl.h @@ -1,6 +1,14 @@ #ifndef __CURL_H_ #define __CURL_H_ +void SwapOfs(void *p); int read_stream(Stream *stream); +#if LIBCURL_VERSION_NUM >= 0x072000 +int xferinfo(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); +#else +int older_progress(void *p, double dltotal, double dlnow, double ultotal, double ulnow); +#endif + + #endif // __CURL_H_ diff --git a/include/shoutcast.h b/include/shoutcast.h index 5090d9c..2922669 100644 --- a/include/shoutcast.h +++ b/include/shoutcast.h @@ -3,7 +3,7 @@ #include "types.h" -int load_stream(Stream *stream, const char *url, const char *proxy, const char *basefilename, const char* duration); +int load_stream(Stream *stream, const char *url, const char *proxy, const char *basefilename, const char* duration, const char* repeat); void global_listener(Stream *stream, char *buffer); int write_data(Stream *stream); diff --git a/include/types.h b/include/types.h index bc533ef..59737b3 100644 --- a/include/types.h +++ b/include/types.h @@ -51,6 +51,7 @@ typedef struct char proxy[255]; // Network proxy char basefilename[255]; // basefilename of output mp3 file unsigned int duration; // max recording duration + unsigned int repeat; // max recording repeats FILE *output_stream; // Output MP3 file char stream_title[500]; // Current title diff --git a/src/curl.c b/src/curl.c index e7d5501..4fc2ff0 100755 --- a/src/curl.c +++ b/src/curl.c @@ -1,64 +1,150 @@ #include #include #include - #include "types.h" #include "parsing.h" -int read_stream(Stream *stream) -{ - CURL *curl; - CURLcode curl_res; - struct curl_slist *headers = NULL; - int ret = 0; - - if (stream->url == NULL) { - printf("Error : stream->url null\n"); - ret = -1; - goto early_err; - } - - printf("stream->url [%s]\n", stream->url); - printf("stream->proxy [%s]\n", stream->proxy); - - if ((curl = curl_easy_init()) == NULL) { - printf("Error : curl_easy_init\n"); - ret = -1; - goto early_err; - } +#if LIBCURL_VERSION_NUM >= 0x073d00 +#define TIME_IN_US 1 +#define TIMETYPE curl_off_t +#define TIMEOPT CURLINFO_TOTAL_TIME_T +#define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL 3000000 +#else +#define TIMETYPE double +#define TIMEOPT CURLINFO_TOTAL_TIME +#define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL 3 +#endif - headers = curl_slist_append(headers, "Icy-MetaData:1"); // On force la récupération des metadata +struct myprogress { + TIMETYPE lastruntime; /* type depends on version, see above */ + CURL *curl; + long duration; + Stream *stream; + void (*thread) (void *); +}; - curl_easy_setopt(curl, CURLOPT_URL, stream->url); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(curl, CURLOPT_PROXY, stream->proxy); - curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, parse_header); - curl_easy_setopt(curl, CURLOPT_HEADERDATA, stream); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, parse_data); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, stream); - curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); - curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 60L); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); +void SwapOfs(void *p) { + struct myprogress *myp = (struct myprogress *)p; + CURL *curl = myp->curl; +// char filename[255] = ""; + long duration = myp->duration; + Stream *stream = myp->stream; +#ifdef TIME_IN_US + duration*=1000000; +#endif + TIMETYPE curtime = 0; + curl_easy_getinfo(curl, TIMEOPT, &curtime); + /* under certain circumstances it may be desirable for certain functionality + to only run every N seconds, in order to do this the transaction time can + be used */ + if((curtime - myp->lastruntime) >= duration) { + myp->lastruntime = curtime; + stream->metadata_count++; + char new_filename[255] = ""; + snprintf(new_filename,255,"%s%03d-%s.mp3", stream->basefilename, stream->metadata_count, stream->stream_title); + new_filename[254]='\0'; + fclose(stream->output_stream); + stream->output_stream = fopen(new_filename, "wb"); + } +} - time_t start_t, end_t; - time(&start_t); - uint seconds_elapsed = 0; - while(seconds_elapsed <= stream->duration) { - curl_easy_setopt(curl, CURLOPT_TIMEOUT, stream->duration-seconds_elapsed); - curl_res = curl_easy_perform(curl); - if (curl_res != CURLE_OK && curl_res != CURLE_OPERATION_TIMEDOUT) { - printf("ERROR %2d: %s\n", curl_res, curl_easy_strerror(curl_res)); - ret = -1; - goto err; - } - time(&end_t); - seconds_elapsed=(uint)difftime(end_t, start_t); - } +#if LIBCURL_VERSION_NUM >= 0x072000 +int xferinfo(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) +{ + struct myprogress *myp = (struct myprogress *)p; + myp->thread(p); + return 0; +} +#else +/* for libcurl older than 7.32.0 (CURLOPT_PROGRESSFUNCTION) */ +int older_progress(void *p, double dltotal, double dlnow, double ultotal, double ulnow) +{ + struct myprogress *myp = (struct myprogress *)p; + myp->thread(p); + return 0; +} +#endif +int read_stream(Stream *stream) +{ + struct myprogress prog; + time_t now; + struct tm *info; + char buffer[80]; + CURL *curl; + CURLcode curl_res; + struct curl_slist *headers = NULL; + int ret = 0; + if (stream->url == NULL) { + time(&now); + info = localtime( &now ); + strftime(buffer,80,"%Y-%m-%d %H:%M:%S Error : stream->url null\n", info); + printf(buffer); + ret = -1; + goto early_err; + } + time(&now); + info = localtime( &now ); + strftime(buffer,80, "%Y-%m-%d %H:%M:%S", info); + printf("%s stream->url [%s]\n", buffer, stream->url); + printf("%s stream->proxy [%s]\n", buffer, stream->proxy); + printf(buffer); + if ((curl = curl_easy_init()) == NULL) { + time(&now); + info = localtime( &now ); + strftime(buffer,80,"%Y-%m-%d %H:%M:%S Error : curl_easy_init\n", info); + printf(buffer); + ret = -1; + goto early_err; + } + prog.curl = curl; + prog.stream = stream; + prog.thread = &SwapOfs; + prog.lastruntime = 0; + prog.duration = stream->duration; + headers = curl_slist_append(headers, "Icy-MetaData:1"); // On force la récupération des metadata + curl_easy_setopt(curl, CURLOPT_URL, stream->url); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl, CURLOPT_PROXY, stream->proxy); + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, parse_header); + curl_easy_setopt(curl, CURLOPT_HEADERDATA, stream); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, parse_data); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, stream); + curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); + curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 60L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); +#if LIBCURL_VERSION_NUM >= 0x072000 + curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo); + /* pass the struct pointer into the xferinfo function, note that this is an alias to CURLOPT_PROGRESSDATA */ + curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog); +#else + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, older_progress); + /* pass the struct pointer into the progress function */ + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &prog); +#endif + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); + time_t start_t, end_t; + time(&start_t); + uint seconds_elapsed = 0; + uint duration=stream->duration*(1+stream->repeat); + do { + curl_easy_setopt(curl, CURLOPT_TIMEOUT, duration-seconds_elapsed); + curl_res = curl_easy_perform(curl); + if (curl_res != CURLE_OK && curl_res != CURLE_OPERATION_TIMEDOUT) { + time(&now); + info = localtime( &now ); + strftime(buffer,80,"%Y-%m-%d %H:%M:%S", info); + printf("%s ERROR %2d: %s\n", buffer, curl_res, curl_easy_strerror(curl_res)); + ret = -1; + goto err; + } + time(&end_t); + seconds_elapsed=(uint)difftime(end_t, start_t); + } while(seconds_elapsed < duration); err: - curl_slist_free_all(headers); - curl_easy_cleanup(curl); + curl_slist_free_all(headers); + curl_easy_cleanup(curl); early_err: - return ret; + return ret; } diff --git a/src/main.c b/src/main.c index 09f8a7e..830fabb 100755 --- a/src/main.c +++ b/src/main.c @@ -27,6 +27,7 @@ void usage(void) printf(" -x\t: proxy (default no proxy)\n"); printf(" -f\t: basefilename (default radio)\n"); printf(" -d\t: recording duration (in seconds, default 0 = unlimited)\n"); + printf(" -r\t: recording repeats (default 0 = none)\n"); } int main(int argc, char *argv[]) @@ -38,11 +39,12 @@ int main(int argc, char *argv[]) char *cvalue = NULL; char *proxy = NULL; char *duration = "0"; + char *repeat = "0"; char* basefilename = (char*) malloc(255*sizeof(char)); sprintf(basefilename, "radio"); - while ((c = getopt(argc, argv, "p:u:h:x:f:d:")) != -1) { + while ((c = getopt(argc, argv, "p:u:h:x:f:d:r:")) != -1) { switch(c) { // playlist case 'p': @@ -66,6 +68,9 @@ int main(int argc, char *argv[]) case 'd': duration = optarg; break; + case 'r': + repeat = optarg; + break; case 'h': default: usage(); @@ -94,7 +99,7 @@ int main(int argc, char *argv[]) if (uflag) { Stream stream; - load_stream(&stream, cvalue, proxy, basefilename, duration); + load_stream(&stream, cvalue, proxy, basefilename, duration, repeat); if ((ret = read_stream(&stream)) < 0) { printf("Error : Couldn't read Shoutcast stream\n"); diff --git a/src/stream.c b/src/stream.c index 8ec240a..1c3107d 100755 --- a/src/stream.c +++ b/src/stream.c @@ -9,7 +9,7 @@ #include "pls.h" #include "curl.h" -int load_stream(Stream *stream, const char *url, const char *proxy, const char *basefilename, const char* duration) +int load_stream(Stream *stream, const char *url, const char *proxy, const char *basefilename, const char* duration, const char* repeat) { int success = TRUE; char filename[255] = ""; @@ -40,12 +40,12 @@ int load_stream(Stream *stream, const char *url, const char *proxy, const char * stream->bytes_count_total = 0; stream->blocks_count = 0; stream->metadata_count = 0; - stream->stream_title[0] = '*';//force create new file - stream->stream_title[1] = '\0'; + stream->stream_title[0] = '\0'; stream->status = E_STATUS_HEADER; stream->duration = atoi(duration); + stream->repeat = atoi(repeat); memset(stream->proxy, 0, 255); memset(stream->url, 0, 255); @@ -63,7 +63,7 @@ int load_stream(Stream *stream, const char *url, const char *proxy, const char * success = success && ((strncpy(stream->url, url, 254) != NULL) && (0 != strftime(stream->basefilename,254,basefilename,timeinfo))); if (success) { - sprintf(filename, "%s%03d.mp3", stream->basefilename, stream->metadata_count); + snprintf(filename,255,"%s%03d-%s.mp3", stream->basefilename, stream->metadata_count, stream->stream_title); stream->output_stream = fopen(filename, "wb"); return 0; } @@ -91,7 +91,7 @@ int load_stream_from_playlist(char *filename, const char *proxy, const char *bas goto early_err; } - if ((ret = load_stream(&stream, pls.entries->file, proxy, basefilename, duration)) < 0) { + if ((ret = load_stream(&stream, pls.entries->file, proxy, basefilename, duration, "0")) < 0) { printf("Error : Couldn't load Shoutcast stream\n"); goto err; } From bef2c29306a813e325cdbcff698b6261c66a5bb7 Mon Sep 17 00:00:00 2001 From: smitdol Date: Mon, 31 Aug 2020 18:58:15 +0200 Subject: [PATCH 15/67] update documentation --- README.mkd | 70 ++++++++++++++++++++++++++++++++++++++++++++++-------- src/curl.c | 8 +++---- src/main.c | 13 +++++----- 3 files changed, 70 insertions(+), 21 deletions(-) diff --git a/README.mkd b/README.mkd index 46022b9..368364a 100644 --- a/README.mkd +++ b/README.mkd @@ -49,35 +49,85 @@ Additional commandline options -x proxy defines proxy to use, (see CURLOPT_PROXY) -f hotmusic defines the base name of the mp3 file(s) created -d duration defines the recording length in seconds (see CURLOPT_TIMEOUT) + -r repeat repeat the recording specified number of times without these additional commandline options specified - no proxy is used (note: libcurl respects the proxy environment variables named http_proxy, ftp_proxy, sftp_proxy etc., see CURLOPT_PROXY) - basename will be radio###.mp3 (where ### is incrementing number) + no proxy is used + libcurl respects the proxy environment variables named http_proxy, ftp_proxy, sftp_proxy etc., see CURLOPT_PROXY + basename will be radio###.mp3 + ### is incrementing number + incrementing number can be used for sorting. + as metadata is never changing exacty on the moment the song changes, + a fluent playback is only possible in recording order (hence incrementing number) + incrementing number will increment when + metadata streamtitle changes + repeat > 0 and duration passes + basename can handle timestamp directives (see strftime) + basename will be appended with name of downloaded music using metadata (if available) duration will be infinite (see CURLOPT_TIMEOUT) - base name can contain timestamp directives (see strftime) - base name will be appended with name of downloaded music using metadata (if available) + repeat will be 0 (no repeat) + repeat will + reuse/continue the recording using the existing connection + avoid establishing new connection (preventing new connection pub) + change incrementing number + create a separate recording file for each repeat + not change basename (weekday nor Hour nor any supplied timestamp directive) + N.B. a repeat set to 2 will produce 3 recordings (0, 1=1st repeat, 2=2nd repeat) + (of the same stream and of the same duration) + cron example : +` SHELL=/bin/bash log=/HDD/log/crontab. dt=date +%Y%m%d dow=date +%u stream=http://88.190.24.47:80 -0 10 * * * cd /HDD; ./shoutr -u $stream -f ./$($dow)-10- -d 3580 >> $log$($dt).log 2>&1 +0 10 * * * cd /HDD; ./shoutr -u $stream -f ./$($dow)-10- -d 3580 -r 1 >> $log$($dt).log 2>&1 +` + +copy recordings in recording order : + +` +#!/bin/bash +SECONDS=0 +TEST= +IFS=$'\n' +DRIVE="$(dirname "$0")" +DST="${DRIVE}/.." +LOG="${DRIVE}/copyit.LOG" +echo "" > $LOG + +function cpit { +$TEST mkdir -pv "${DST}/${CWD}" | tee -a $LOG +for i in $( find "${SRC}${CWD}" -type f -mtime -6 | sort ) +do + $TEST rsync --min-size=1mb -avh --no-p --no-g --chmod=ugo=rwX --modify-window=2 "$i" "${DST}/${CWD}" | tee -a $LOG +done +} + +SRC=/mnt/nfs/HDD/ +for G in "CD01" "CD02" "CD04" +do + CWD=$G + echo $CWD $DST + cpit +done +echo "Script finished in $SECONDS seconds=> $(($SECONDS/60)) min $(($SECONDS%60)) sec" | tee -a $LOG +` TODO ---- Some interesting features to add : -- add option --quiet -- add option --ncurses -- add a big shoucast radio list with lots of radios -- add shoutr_start and shoutr_stop functions. -- add id3tags +- add id3tags (taglib) + +- for a big shoucast radio list with lots of radios see www.radio-browser.info + LICENSE ------- diff --git a/src/curl.c b/src/curl.c index 4fc2ff0..d97a50b 100755 --- a/src/curl.c +++ b/src/curl.c @@ -78,21 +78,21 @@ int read_stream(Stream *stream) if (stream->url == NULL) { time(&now); info = localtime( &now ); - strftime(buffer,80,"%Y-%m-%d %H:%M:%S Error : stream->url null\n", info); + strftime(buffer,80,"%T Error : stream->url null\n", info); printf(buffer); ret = -1; goto early_err; } time(&now); info = localtime( &now ); - strftime(buffer,80, "%Y-%m-%d %H:%M:%S", info); + strftime(buffer,80, "%T", info); printf("%s stream->url [%s]\n", buffer, stream->url); printf("%s stream->proxy [%s]\n", buffer, stream->proxy); printf(buffer); if ((curl = curl_easy_init()) == NULL) { time(&now); info = localtime( &now ); - strftime(buffer,80,"%Y-%m-%d %H:%M:%S Error : curl_easy_init\n", info); + strftime(buffer,80,"%T Error : curl_easy_init\n", info); printf(buffer); ret = -1; goto early_err; @@ -134,7 +134,7 @@ int read_stream(Stream *stream) if (curl_res != CURLE_OK && curl_res != CURLE_OPERATION_TIMEDOUT) { time(&now); info = localtime( &now ); - strftime(buffer,80,"%Y-%m-%d %H:%M:%S", info); + strftime(buffer,80,"%T", info); printf("%s ERROR %2d: %s\n", buffer, curl_res, curl_easy_strerror(curl_res)); ret = -1; goto err; diff --git a/src/main.c b/src/main.c index 830fabb..7dd743e 100755 --- a/src/main.c +++ b/src/main.c @@ -21,13 +21,12 @@ int load_stream_from_playlist(char *filename); void usage(void) { - printf("Usage: shoutr [OPTIONS]\n"); - printf(" -p\t: playlist file\n"); - printf(" -u\t: stream url\n"); - printf(" -x\t: proxy (default no proxy)\n"); - printf(" -f\t: basefilename (default radio)\n"); - printf(" -d\t: recording duration (in seconds, default 0 = unlimited)\n"); - printf(" -r\t: recording repeats (default 0 = none)\n"); + printf("Usage: shoutr [-p |-u ] [OPTIONS]\n"); + printf("options:\n"); + printf("\t-x\t: proxy (default no proxy)\n"); + printf("\t-f\t: basefilename (default radio)\n"); + printf("\t-d\t: recording duration (in seconds, default 0 = unlimited)\n"); + printf("\t-r\t: recording repeats (default 0 = none)\n"); } int main(int argc, char *argv[]) From 8e6b1b7865aa027adb27cbbb8cc2c3c9c682696e Mon Sep 17 00:00:00 2001 From: smitdol Date: Tue, 1 Sep 2020 18:20:41 +0200 Subject: [PATCH 16/67] added taglib for id3tag --- Makefile | 2 +- README.mkd | 8 +++++--- include/types.h | 1 + src/curl.c | 2 +- src/metadata.c | 28 ++++++++++++++++++++++------ src/shoutcast.c | 3 +++ src/stream.c | 4 ++++ 7 files changed, 37 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 8f65604..eeb55d5 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ INCLUDES = -Iinclude \ -I/usr/include CFLAGS = -W -Wall -g -LDFLAGS = -L/usr/lib -lcurl +LDFLAGS = -L/usr/lib -lcurl -L/usr/lib/arm-linux-gnueabihf/libtag.so -L/usr/lib/arm-linux-gnueabihf/libtag_c.so -ltag_c all: prepare $(EXEC) diff --git a/README.mkd b/README.mkd index 368364a..5f8328b 100644 --- a/README.mkd +++ b/README.mkd @@ -12,6 +12,9 @@ Dependencies - libcurl sudo apt-get install libcurl-dev sudo apt-get install libcurl4-openssl-dev +- taglib + sudo apt-get install libtag1-dev + sudo apt-get install libtagc0-dev How does it work ? @@ -124,9 +127,8 @@ TODO Some interesting features to add : -- add id3tags (taglib) - -- for a big shoucast radio list with lots of radios see www.radio-browser.info +- more id3tags (taglib) (artist and title depends on station) +- see www.radio-browser.info for a big shoucast radio list LICENSE diff --git a/include/types.h b/include/types.h index 59737b3..e2f1589 100644 --- a/include/types.h +++ b/include/types.h @@ -50,6 +50,7 @@ typedef struct char url[255]; // Stream url char proxy[255]; // Network proxy char basefilename[255]; // basefilename of output mp3 file + char filename[255]; // current filename of output mp3 file unsigned int duration; // max recording duration unsigned int repeat; // max recording repeats FILE *output_stream; // Output MP3 file diff --git a/src/curl.c b/src/curl.c index d97a50b..951f705 100755 --- a/src/curl.c +++ b/src/curl.c @@ -26,7 +26,6 @@ struct myprogress { void SwapOfs(void *p) { struct myprogress *myp = (struct myprogress *)p; CURL *curl = myp->curl; -// char filename[255] = ""; long duration = myp->duration; Stream *stream = myp->stream; #ifdef TIME_IN_US @@ -45,6 +44,7 @@ void SwapOfs(void *p) { new_filename[254]='\0'; fclose(stream->output_stream); stream->output_stream = fopen(new_filename, "wb"); + strncpy(stream->filename, new_filename, 254); } } diff --git a/src/metadata.c b/src/metadata.c index 5559cab..e13e88c 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -1,10 +1,12 @@ #include #include #include +#include #include "types.h" #include "metadata.h" #include "icy-string.h" +#include #include "log.h" @@ -45,9 +47,9 @@ int metadata_body_handler(Stream *stream, char *buffer) MetaData *metadata = &stream->metadata; *metadata->ptr = *buffer; if ((unsigned)(metadata->ptr - metadata->buffer) == (metadata->size-1)) { - char metadata_content[500]; - char stream_title[500]; - strncpy(metadata_content, metadata->buffer, metadata->size); + char metadata_content[500]=""; + char stream_title[500]=""; + strncpy(metadata_content, metadata->buffer, MIN(metadata->size,500)); get_metadata_field(metadata_content, "StreamTitle", stream_title); stream_title[499]='\0'; metadata_content[499]='\0'; @@ -64,16 +66,30 @@ int metadata_body_handler(Stream *stream, char *buffer) if (stream_title[i]=='/') { stream_title[i]='_'; continue; } if (stream_title[i]=='\0') { break;} //done } - printf("%s\n", stream_title); + printf("stream_title: %s\n", stream_title); if (0 != strncmp(stream->stream_title, stream_title, 500)) { - strncpy(stream->stream_title,stream_title, 500); stream->metadata_count++; char new_filename[255] = ""; - snprintf(new_filename,255,"%s%03d-%s.mp3", stream->basefilename, stream->metadata_count, stream->stream_title); + snprintf(new_filename,255,"%s%03d-%s.mp3", stream->basefilename, stream->metadata_count, stream_title); new_filename[254]='\0'; fclose(stream->output_stream); stream->output_stream = fopen(new_filename, "wb"); + + taglib_set_strings_unicode(FALSE); + TagLib_File *media_file = taglib_file_new(stream->filename); + if (media_file != NULL) { + TagLib_Tag *tag = taglib_file_tag(media_file); + if (tag != NULL) { + taglib_tag_set_comment(tag, stream->stream_title); + taglib_file_save(media_file); + } + taglib_tag_free_strings(); + taglib_file_free(media_file); + } + + strncpy(stream->filename,new_filename, 254); + strncpy(stream->stream_title,stream_title, 500); } snprintf(stream_title,500, "%s\n", stream->stream_title); slog_prog(stream_title); diff --git a/src/shoutcast.c b/src/shoutcast.c index c295a65..77b33fa 100644 --- a/src/shoutcast.c +++ b/src/shoutcast.c @@ -23,6 +23,9 @@ void global_listener(Stream *stream, char *buffer) int write_data(Stream *stream) { + if (stream->output_stream == NULL) { + return 0; + } int written = fwrite(stream->mp3data.buffer, sizeof(char), stream->mp3data.size, (FILE *)stream->output_stream); diff --git a/src/stream.c b/src/stream.c index 1c3107d..f94df1d 100755 --- a/src/stream.c +++ b/src/stream.c @@ -41,6 +41,7 @@ int load_stream(Stream *stream, const char *url, const char *proxy, const char * stream->blocks_count = 0; stream->metadata_count = 0; stream->stream_title[0] = '\0'; + stream->output_stream = NULL; stream->status = E_STATUS_HEADER; @@ -51,6 +52,7 @@ int load_stream(Stream *stream, const char *url, const char *proxy, const char * memset(stream->url, 0, 255); memset(stream->basefilename, 0, 255); memset(filename, 0, 255); + memset(stream->filename, 0, 255); if (proxy != NULL) { success = strncpy(stream->proxy, proxy, 254) != NULL; @@ -64,6 +66,8 @@ int load_stream(Stream *stream, const char *url, const char *proxy, const char * if (success) { snprintf(filename,255,"%s%03d-%s.mp3", stream->basefilename, stream->metadata_count, stream->stream_title); + filename[254]='\0'; + strncpy(stream->filename, filename, 254); stream->output_stream = fopen(filename, "wb"); return 0; } From 34a697ffc2848a5af283ff18bbb9b87466ca9930 Mon Sep 17 00:00:00 2001 From: smitdol Date: Wed, 2 Sep 2020 20:58:52 +0200 Subject: [PATCH 17/67] split stream_title in title and artist and add id3tag --- include/types.h | 2 +- src/curl.c | 1 + src/main.c | 8 +++++++- src/metadata.c | 18 ++++++++++++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/include/types.h b/include/types.h index e2f1589..8cc11a6 100644 --- a/include/types.h +++ b/include/types.h @@ -55,7 +55,7 @@ typedef struct unsigned int repeat; // max recording repeats FILE *output_stream; // Output MP3 file char stream_title[500]; // Current title - + int TA; // title = - <Artist> else <Artist> - <Title> parsing_status status; ICYHeader header; // Stream header (won't change after being set) diff --git a/src/curl.c b/src/curl.c index 951f705..967d459 100755 --- a/src/curl.c +++ b/src/curl.c @@ -1,6 +1,7 @@ #include <curl/curl.h> #include <curl/easy.h> #include <time.h> +#include <string.h> #include "types.h" #include "parsing.h" diff --git a/src/main.c b/src/main.c index 7dd743e..be059ae 100755 --- a/src/main.c +++ b/src/main.c @@ -27,6 +27,7 @@ void usage(void) printf("\t-f\t: basefilename (default radio)\n"); printf("\t-d\t: recording duration (in seconds, default 0 = unlimited)\n"); printf("\t-r\t: recording repeats (default 0 = none)\n"); + printf("\t-i\t: title - artist (0, default) or artist - title (1)\n"); } int main(int argc, char *argv[]) @@ -39,11 +40,12 @@ int main(int argc, char *argv[]) char *proxy = NULL; char *duration = "0"; char *repeat = "0"; + char *ta = "0"; char* basefilename = (char*) malloc(255*sizeof(char)); sprintf(basefilename, "radio"); - while ((c = getopt(argc, argv, "p:u:h:x:f:d:r:")) != -1) { + while ((c = getopt(argc, argv, "p:u:h:x:f:d:r:i:")) != -1) { switch(c) { // playlist case 'p': @@ -70,6 +72,9 @@ int main(int argc, char *argv[]) case 'r': repeat = optarg; break; + case 'i': + ta = optarg; + break; case 'h': default: usage(); @@ -98,6 +103,7 @@ int main(int argc, char *argv[]) if (uflag) { Stream stream; + stream.TA=atoi(ta); load_stream(&stream, cvalue, proxy, basefilename, duration, repeat); if ((ret = read_stream(&stream)) < 0) { diff --git a/src/metadata.c b/src/metadata.c index e13e88c..3daf6f5 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -82,6 +82,24 @@ int metadata_body_handler(Stream *stream, char *buffer) TagLib_Tag *tag = taglib_file_tag(media_file); if (tag != NULL) { taglib_tag_set_comment(tag, stream->stream_title); + char* token=strtok(stream->stream_title,"-"); + if (stream->TA == 0) { + if (token) { + taglib_tag_set_title(tag,token); + token=strtok(NULL,"-"); + } + if (token) { + taglib_tag_set_artist(tag,token); + } + } else { + if (token) { + taglib_tag_set_artist(tag,token); + token=strtok(NULL,"-"); + } + if (token) { + taglib_tag_set_title(tag,token); + } + } taglib_file_save(media_file); } taglib_tag_free_strings(); From a5f2ed5083a8ea1c9ab785029fec6074df4ab013 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Wed, 2 Sep 2020 21:46:42 +0200 Subject: [PATCH 18/67] cleanup Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index eeb55d5..7d03136 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ INCLUDES = -Iinclude \ -I/usr/include CFLAGS = -W -Wall -g -LDFLAGS = -L/usr/lib -lcurl -L/usr/lib/arm-linux-gnueabihf/libtag.so -L/usr/lib/arm-linux-gnueabihf/libtag_c.so -ltag_c +LDFLAGS = -L/usr/lib -lcurl -ltag_c all: prepare $(EXEC) From 89fbfebc90bb9e2f333cc0fbf5895bf56409690b Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Mon, 14 Sep 2020 19:14:55 +0200 Subject: [PATCH 19/67] filename using dot separation instead of dash --- README.mkd | 7 ++++--- src/curl.c | 6 +++++- src/metadata.c | 6 +++++- src/stream.c | 6 +++++- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/README.mkd b/README.mkd index 5f8328b..265c3fe 100644 --- a/README.mkd +++ b/README.mkd @@ -41,7 +41,7 @@ How to run it Here are two examples : - ./shoutr -u http://88.190.24.47:80 -f ./%w-%H- -d 3580 + ./shoutr -u http://88.190.24.47:80 -f ./%w-%H -d 3580 or @@ -53,6 +53,7 @@ Additional commandline options -f hotmusic defines the base name of the mp3 file(s) created -d duration defines the recording length in seconds (see CURLOPT_TIMEOUT) -r repeat repeat the recording specified number of times + -i id3tags split stream_title (on '-') into artist - title (default, 0) or title - artist (1) without these additional commandline options specified @@ -78,10 +79,10 @@ without these additional commandline options specified not change basename (weekday nor Hour nor any supplied timestamp directive) N.B. a repeat set to 2 will produce 3 recordings (0, 1=1st repeat, 2=2nd repeat) (of the same stream and of the same duration) + non-empty stream_title will be used for id3tag assuming artist - title cron example : - ` SHELL=/bin/bash log=/HDD/log/crontab. @@ -89,7 +90,7 @@ dt=date +%Y%m%d dow=date +%u stream=http://88.190.24.47:80 -0 10 * * * cd /HDD; ./shoutr -u $stream -f ./$($dow)-10- -d 3580 -r 1 >> $log$($dt).log 2>&1 +0 10 * * * cd /HDD; ./shoutr -u $stream -f ./$($dow)-10 -d 3580 -r 1 >> $log$($dt).log 2>&1 ` copy recordings in recording order : diff --git a/src/curl.c b/src/curl.c index 967d459..0d3a643 100755 --- a/src/curl.c +++ b/src/curl.c @@ -41,7 +41,11 @@ void SwapOfs(void *p) { myp->lastruntime = curtime; stream->metadata_count++; char new_filename[255] = ""; - snprintf(new_filename,255,"%s%03d-%s.mp3", stream->basefilename, stream->metadata_count, stream->stream_title); + if (strlen(stream->stream_title)==0) { + snprintf(new_filename,255,"%s.%03d.mp3", stream->basefilename, stream->metadata_count); + } else { + snprintf(new_filename,255,"%s.%03d.%s.mp3", stream->basefilename, stream->metadata_count, stream->stream_title); + } new_filename[254]='\0'; fclose(stream->output_stream); stream->output_stream = fopen(new_filename, "wb"); diff --git a/src/metadata.c b/src/metadata.c index 3daf6f5..608bdc0 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -71,7 +71,11 @@ int metadata_body_handler(Stream *stream, char *buffer) { stream->metadata_count++; char new_filename[255] = ""; - snprintf(new_filename,255,"%s%03d-%s.mp3", stream->basefilename, stream->metadata_count, stream_title); + if (strlen(stream_title)==0){ + snprintf(new_filename,255,"%s.%03d.mp3", stream->basefilename, stream->metadata_count); + } else { + snprintf(new_filename,255,"%s.%03d.%s.mp3", stream->basefilename, stream->metadata_count, stream_title); + } new_filename[254]='\0'; fclose(stream->output_stream); stream->output_stream = fopen(new_filename, "wb"); diff --git a/src/stream.c b/src/stream.c index f94df1d..8a2b52e 100755 --- a/src/stream.c +++ b/src/stream.c @@ -65,7 +65,11 @@ int load_stream(Stream *stream, const char *url, const char *proxy, const char * success = success && ((strncpy(stream->url, url, 254) != NULL) && (0 != strftime(stream->basefilename,254,basefilename,timeinfo))); if (success) { - snprintf(filename,255,"%s%03d-%s.mp3", stream->basefilename, stream->metadata_count, stream->stream_title); + if (strlen(stream->stream_title)==0){ + snprintf(filename,255,"%s.%03d.mp3", stream->basefilename, stream->metadata_count); + } else { + snprintf(filename,255,"%s.%03d.%s.mp3", stream->basefilename, stream->metadata_count, stream->stream_title); + } filename[254]='\0'; strncpy(stream->filename, filename, 254); stream->output_stream = fopen(filename, "wb"); From 4a257e025a0142e9a86f4276d152293f46826274 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Mon, 14 Sep 2020 20:16:26 +0200 Subject: [PATCH 20/67] newfilename function added, proglog removed --- include/types.h | 2 ++ src/curl.c | 7 +------ src/log.c | 16 ---------------- src/metadata.c | 10 +--------- src/stream.c | 18 ++++++++++++------ 5 files changed, 16 insertions(+), 37 deletions(-) diff --git a/include/types.h b/include/types.h index 8cc11a6..da4d6d9 100644 --- a/include/types.h +++ b/include/types.h @@ -68,4 +68,6 @@ typedef struct unsigned int metadata_count; // Number of metadata blocks received since beginning } Stream; +void newfilename(const Stream *stream, char* filename, unsigned int size, char* title); + #endif // __TYPES_H_ diff --git a/src/curl.c b/src/curl.c index 0d3a643..b0a4174 100755 --- a/src/curl.c +++ b/src/curl.c @@ -41,12 +41,7 @@ void SwapOfs(void *p) { myp->lastruntime = curtime; stream->metadata_count++; char new_filename[255] = ""; - if (strlen(stream->stream_title)==0) { - snprintf(new_filename,255,"%s.%03d.mp3", stream->basefilename, stream->metadata_count); - } else { - snprintf(new_filename,255,"%s.%03d.%s.mp3", stream->basefilename, stream->metadata_count, stream->stream_title); - } - new_filename[254]='\0'; + newfilename(stream, new_filename, 255, stream->stream_title); fclose(stream->output_stream); stream->output_stream = fopen(new_filename, "wb"); strncpy(stream->filename, new_filename, 254); diff --git a/src/log.c b/src/log.c index e9571d1..72978b5 100644 --- a/src/log.c +++ b/src/log.c @@ -4,7 +4,6 @@ #include "log.h" static FILE *fp_log; -static FILE *fp_prog; static char current_time[20]; static char current_date[20]; static char tempfile[255]; @@ -62,13 +61,6 @@ int log_open_files(void) return -1; } - snprintf(tempfile,255,"prog.%s.log",current_date); - fp_prog = fopen(tempfile,"a"); - if (fp_prog == NULL) { - printf("Couldn't open prog.log file\n"); - return -1; - } - return 0; } @@ -77,9 +69,6 @@ int log_close_files(void) if (fclose(fp_log) == EOF) return EOF; - if (fclose(fp_prog) == EOF) - return EOF; - return 0; } @@ -109,8 +98,3 @@ void slog(char *line) printf("Coudln't write shoutr log\n"); } -void slog_prog(char *line) -{ - if (log_append(fp_prog, line) < 0) - printf("Coudln't write prog log\n"); -} diff --git a/src/metadata.c b/src/metadata.c index 608bdc0..ebc8928 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -71,12 +71,7 @@ int metadata_body_handler(Stream *stream, char *buffer) { stream->metadata_count++; char new_filename[255] = ""; - if (strlen(stream_title)==0){ - snprintf(new_filename,255,"%s.%03d.mp3", stream->basefilename, stream->metadata_count); - } else { - snprintf(new_filename,255,"%s.%03d.%s.mp3", stream->basefilename, stream->metadata_count, stream_title); - } - new_filename[254]='\0'; + newfilename(stream, new_filename, 255, stream_title); fclose(stream->output_stream); stream->output_stream = fopen(new_filename, "wb"); @@ -113,9 +108,6 @@ int metadata_body_handler(Stream *stream, char *buffer) strncpy(stream->filename,new_filename, 254); strncpy(stream->stream_title,stream_title, 500); } - snprintf(stream_title,500, "%s\n", stream->stream_title); - slog_prog(stream_title); - // slog metadata_content snprintf(stream_title,500, "%s\n", metadata_content); slog(stream_title); diff --git a/src/stream.c b/src/stream.c index 8a2b52e..8ea9cf1 100755 --- a/src/stream.c +++ b/src/stream.c @@ -65,12 +65,7 @@ int load_stream(Stream *stream, const char *url, const char *proxy, const char * success = success && ((strncpy(stream->url, url, 254) != NULL) && (0 != strftime(stream->basefilename,254,basefilename,timeinfo))); if (success) { - if (strlen(stream->stream_title)==0){ - snprintf(filename,255,"%s.%03d.mp3", stream->basefilename, stream->metadata_count); - } else { - snprintf(filename,255,"%s.%03d.%s.mp3", stream->basefilename, stream->metadata_count, stream->stream_title); - } - filename[254]='\0'; + newfilename(stream, filename, 255, stream->stream_title); strncpy(stream->filename, filename, 254); stream->output_stream = fopen(filename, "wb"); return 0; @@ -115,3 +110,14 @@ int load_stream_from_playlist(char *filename, const char *proxy, const char *bas return ret; } + +void newfilename(const Stream *stream, char* filename, unsigned int size, char* title) +{ + if (strlen(title)==0) { + snprintf(filename,size,"%s.%03d.mp3", stream->basefilename, stream->metadata_count); + } else { + snprintf(filename,size,"%s.%03d.%s.mp3", stream->basefilename, stream->metadata_count, title); + } + filename[size-1]='\0'; +} + From 43c0007f7e4093b49c02b21a16bce91257ee44af Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Mon, 14 Sep 2020 21:44:20 +0200 Subject: [PATCH 21/67] fix playlist handling --- radios/frequence3.pls | 8 ++++---- src/main.c | 20 ++++++++++---------- src/pls.c | 7 ++++--- src/stream.c | 10 ++-------- 4 files changed, 20 insertions(+), 25 deletions(-) diff --git a/radios/frequence3.pls b/radios/frequence3.pls index e551663..1036dc5 100644 --- a/radios/frequence3.pls +++ b/radios/frequence3.pls @@ -1,9 +1,9 @@ [playlist] NumberOfEntries=2 -File1=http://stream-hautdebit.frequence3.net:8000/ -Title1=[Serveur Generique] - Frequence3 - Une Rafale de Tubes ! [HautDebit] +File1=http://ice.stream.frequence3.net/frequence3-128.mp3 +Title1=[Serveur Generique] - Frequence3 - Une Rafale de Tubes ! Length1=-1 -File2=http://stream-hautdebit.frequence3.net:8000/ -Title2=[Serveur Generique] - Frequence3 - Une Rafale de Tubes ! [HautDebit] +File2=http://ice.stream.frequence3.net/frequence3-32.mp3 +Title2=[Serveur Generique] - Frequence3 - Une Rafale de Tubes ! Length2=-1 Version=2 diff --git a/src/main.c b/src/main.c index be059ae..94c631a 100755 --- a/src/main.c +++ b/src/main.c @@ -17,7 +17,7 @@ #include "curl.h" #include "log.h" -int load_stream_from_playlist(char *filename); +int load_stream_from_playlist(Stream *stream, char *filename, const char *proxy, const char *basefilename, const char *duration, const char *repeat); void usage(void) { @@ -94,25 +94,25 @@ int main(int argc, char *argv[]) goto err_early; } + Stream stream; + stream.TA=atoi(ta); + if (pflag) { - if ((ret = load_stream_from_playlist(cvalue)) < 0) { + if ((ret = load_stream_from_playlist(&stream, cvalue, proxy, basefilename, duration, repeat)) < 0) { printf("Couldn't load stream from playlist\n"); goto err; } } if (uflag) { - Stream stream; - stream.TA=atoi(ta); - load_stream(&stream, cvalue, proxy, basefilename, duration, repeat); + load_stream(&stream, cvalue, proxy, basefilename, duration, repeat); - if ((ret = read_stream(&stream)) < 0) { - printf("Error : Couldn't read Shoutcast stream\n"); - goto err; - } } - // res = load_stream(&stream, "http://88.190.24.47:80"); + if ((ret = read_stream(&stream)) < 0) { + printf("Error : Couldn't read Shoutcast stream\n"); + goto err; + } err: log_close_files(); err_early: diff --git a/src/pls.c b/src/pls.c index e8d39f7..16889f0 100755 --- a/src/pls.c +++ b/src/pls.c @@ -76,7 +76,7 @@ static int pls_get_field(char *buffer, char *value) ptr_begin = strstr(buffer, "=")+1; ptr_end = strstr(buffer, "\n")-1; - strncpy(value, ptr_begin, (int)(ptr_end - ptr_begin)); + strncpy(value, ptr_begin, (int)(ptr_end - ptr_begin + 1)); return 0; } @@ -88,13 +88,14 @@ static int pls_get_entries(FILE *fp, PlsFile *pls) PlsEntry *entry = pls->entries; fseek(fp, 0 ,SEEK_SET); - fgets(buffer, MAX_LINE_LENGTH, fp); - for (i=0;i<pls->number_entries;i++) { + i=0; + while (i<pls->number_entries) { fgets(buffer, MAX_LINE_LENGTH, fp); if (strstr(buffer, "File") != NULL) { pls_get_field(buffer, entry->file); entry++; + i++; } } return 0; // TODO : use a better return value diff --git a/src/stream.c b/src/stream.c index 8ea9cf1..a6dac24 100755 --- a/src/stream.c +++ b/src/stream.c @@ -73,9 +73,8 @@ int load_stream(Stream *stream, const char *url, const char *proxy, const char * return 1; } -int load_stream_from_playlist(char *filename, const char *proxy, const char *basefilename, const char *duration) +int load_stream_from_playlist(Stream *stream, char *filename, const char *proxy, const char *basefilename, const char *duration, const char *repeat) { - Stream stream; PlsFile pls; int ret = 0; @@ -94,16 +93,11 @@ int load_stream_from_playlist(char *filename, const char *proxy, const char *bas goto early_err; } - if ((ret = load_stream(&stream, pls.entries->file, proxy, basefilename, duration, "0")) < 0) { + if ((ret = load_stream(stream, pls.entries->file, proxy, basefilename, duration, repeat)) < 0) { printf("Error : Couldn't load Shoutcast stream\n"); goto err; } - if ((ret = read_stream(&stream)) < 0) { - printf("Error : Couldn't read Shoutcast stream\n"); - goto err; - } - err: free(pls.entries); early_err: From ceea33c58f667db13b6bd56da05f730106cd75d2 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sat, 24 Oct 2020 22:11:07 +0200 Subject: [PATCH 22/67] handling special non-ascii cahracters --- src/metadata.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/metadata.c b/src/metadata.c index ebc8928..05cee24 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -41,6 +41,12 @@ int metadata_header_handler(Stream *stream, char *buffer) return 0; } +void removechar( char str[], unsigned int i ) +{ + for (unsigned int j=i; j<strlen(str)-2; j++) + str[j]=str[j+1]; + str[strlen(str)-1]='\0'; +} int metadata_body_handler(Stream *stream, char *buffer) { @@ -54,7 +60,7 @@ int metadata_body_handler(Stream *stream, char *buffer) stream_title[499]='\0'; metadata_content[499]='\0'; // filter problematic characters from StreamTitle - for (int i =0; i < 499; i++) { + for (unsigned int i =0; i < 496; i++) { if (stream_title[i]=='*') { stream_title[i]='_'; continue; } if (stream_title[i]=='?') { stream_title[i]='_'; continue; } if (stream_title[i]=='>') { stream_title[i]='_'; continue; } @@ -64,6 +70,33 @@ int metadata_body_handler(Stream *stream, char *buffer) if (stream_title[i]=='\"') { stream_title[i]='_'; continue; } if (stream_title[i]==':') { stream_title[i]='_'; continue; } if (stream_title[i]=='/') { stream_title[i]='_'; continue; } + if ((stream_title[i]==0xE9)&&(stream_title[i+1]==0x8B)) { //Ë E9 B + stream_title[i]=0xD3; + removechar(stream_title,i+1); + continue; + } else { + if ((stream_title[i]==0xE9)&&(stream_title[i+1]==0xA1)) { // á + stream_title[i]=0xE1; + removechar(stream_title,i+1); + continue; + } else { + if (stream_title[i]==0xE9) { // é + stream_title[i]=0xE9; + continue; + } + } + } + if ( (stream_title[i]==0xC3)&& + (stream_title[i+1]==0x83)&& + (stream_title[i+2]==0x83)&& + (stream_title[i+3]==0xC2)) + { + stream_title[i]=0xE9; //é C3 83 C2 A9 + removechar(stream_title,i+1); + removechar(stream_title,i+2); + removechar(stream_title,i+3); + continue; + } if (stream_title[i]=='\0') { break;} //done } printf("stream_title: %s\n", stream_title); From a032105bbda2d4af82090fe2183b80461e0e3527 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 25 Oct 2020 11:49:03 +0100 Subject: [PATCH 23/67] option to add file extension; fix SwapOfs when duration == 0 --- include/types.h | 5 +++-- src/curl.c | 15 +++++++-------- src/main.c | 17 +++++++++++++---- src/metadata.c | 2 +- src/stream.c | 4 ++-- 5 files changed, 26 insertions(+), 17 deletions(-) diff --git a/include/types.h b/include/types.h index da4d6d9..8f6f382 100644 --- a/include/types.h +++ b/include/types.h @@ -49,8 +49,9 @@ typedef struct { char url[255]; // Stream url char proxy[255]; // Network proxy - char basefilename[255]; // basefilename of output mp3 file - char filename[255]; // current filename of output mp3 file + char basefilename[255]; // basefilename of output file + char filename[255]; // current filename of output file + char ext[255]; // current extension of output file unsigned int duration; // max recording duration unsigned int repeat; // max recording repeats FILE *output_stream; // Output MP3 file diff --git a/src/curl.c b/src/curl.c index b0a4174..2e0ca72 100755 --- a/src/curl.c +++ b/src/curl.c @@ -9,17 +9,17 @@ #define TIME_IN_US 1 #define TIMETYPE curl_off_t #define TIMEOPT CURLINFO_TOTAL_TIME_T -#define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL 3000000 +#define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL 1000000 #else #define TIMETYPE double #define TIMEOPT CURLINFO_TOTAL_TIME -#define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL 3 +#define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL 1 #endif struct myprogress { TIMETYPE lastruntime; /* type depends on version, see above */ CURL *curl; - long duration; + TIMETYPE duration; Stream *stream; void (*thread) (void *); }; @@ -27,17 +27,15 @@ struct myprogress { void SwapOfs(void *p) { struct myprogress *myp = (struct myprogress *)p; CURL *curl = myp->curl; - long duration = myp->duration; + TIMETYPE duration = myp->duration; Stream *stream = myp->stream; -#ifdef TIME_IN_US - duration*=1000000; -#endif + duration*=MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL; TIMETYPE curtime = 0; curl_easy_getinfo(curl, TIMEOPT, &curtime); /* under certain circumstances it may be desirable for certain functionality to only run every N seconds, in order to do this the transaction time can be used */ - if((curtime - myp->lastruntime) >= duration) { + if(duration > 0 && (curtime - myp->lastruntime) >= duration) { myp->lastruntime = curtime; stream->metadata_count++; char new_filename[255] = ""; @@ -97,6 +95,7 @@ int read_stream(Stream *stream) ret = -1; goto early_err; } + printf(" %x\n", LIBCURL_VERSION_NUM); prog.curl = curl; prog.stream = stream; prog.thread = &SwapOfs; diff --git a/src/main.c b/src/main.c index 94c631a..8a3e18c 100755 --- a/src/main.c +++ b/src/main.c @@ -23,11 +23,12 @@ void usage(void) { printf("Usage: shoutr [-p <playlist>|-u <stream_url>] [OPTIONS]\n"); printf("options:\n"); - printf("\t-x\t: proxy (default no proxy)\n"); - printf("\t-f\t: basefilename (default radio)\n"); printf("\t-d\t: recording duration (in seconds, default 0 = unlimited)\n"); - printf("\t-r\t: recording repeats (default 0 = none)\n"); + printf("\t-e\t: fileextension (default mp3)\n"); + printf("\t-f\t: basefilename (default radio)\n"); printf("\t-i\t: title - artist (0, default) or artist - title (1)\n"); + printf("\t-r\t: recording repeats (default 0 = none)\n"); + printf("\t-x\t: proxy (default no proxy)\n"); } int main(int argc, char *argv[]) @@ -45,7 +46,10 @@ int main(int argc, char *argv[]) char* basefilename = (char*) malloc(255*sizeof(char)); sprintf(basefilename, "radio"); - while ((c = getopt(argc, argv, "p:u:h:x:f:d:r:i:")) != -1) { + char* fileext = (char*) malloc(255*sizeof(char)); + sprintf(fileext, "mp3"); + + while ((c = getopt(argc, argv, "p:u:h:x:f:e:d:r:i:")) != -1) { switch(c) { // playlist case 'p': @@ -61,6 +65,10 @@ int main(int argc, char *argv[]) case 'x': proxy = optarg; break; + // fileextension + case 'e': + fileext = optarg; + break; // basefilename case 'f': basefilename = optarg; @@ -96,6 +104,7 @@ int main(int argc, char *argv[]) Stream stream; stream.TA=atoi(ta); + snprintf(stream.ext, 255, "%s", fileext); if (pflag) { if ((ret = load_stream_from_playlist(&stream, cvalue, proxy, basefilename, duration, repeat)) < 0) { diff --git a/src/metadata.c b/src/metadata.c index 05cee24..74e662b 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -142,7 +142,7 @@ int metadata_body_handler(Stream *stream, char *buffer) strncpy(stream->stream_title,stream_title, 500); } // slog metadata_content - snprintf(stream_title,500, "%s\n", metadata_content); + snprintf(stream_title, 501, "%s\n", metadata_content); slog(stream_title); stream->bytes_count = 0; diff --git a/src/stream.c b/src/stream.c index a6dac24..9cd2b83 100755 --- a/src/stream.c +++ b/src/stream.c @@ -108,9 +108,9 @@ int load_stream_from_playlist(Stream *stream, char *filename, const char *proxy, void newfilename(const Stream *stream, char* filename, unsigned int size, char* title) { if (strlen(title)==0) { - snprintf(filename,size,"%s.%03d.mp3", stream->basefilename, stream->metadata_count); + snprintf(filename,size,"%s.%03d.%s", stream->basefilename, stream->metadata_count, stream->ext); } else { - snprintf(filename,size,"%s.%03d.%s.mp3", stream->basefilename, stream->metadata_count, title); + snprintf(filename,size,"%s.%03d.%s.%s", stream->basefilename, stream->metadata_count, title, stream->ext); } filename[size-1]='\0'; } From 81f4cee25ad1cda3cd14265a567d0446be7d47af Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 25 Oct 2020 19:16:42 +0100 Subject: [PATCH 24/67] refactor load_stream, parameters to stream type --- include/shoutcast.h | 2 +- src/main.c | 20 +++++++++++++++++--- src/stream.c | 35 ++++++++--------------------------- 3 files changed, 26 insertions(+), 31 deletions(-) diff --git a/include/shoutcast.h b/include/shoutcast.h index 2922669..a014bc5 100644 --- a/include/shoutcast.h +++ b/include/shoutcast.h @@ -3,7 +3,7 @@ #include "types.h" -int load_stream(Stream *stream, const char *url, const char *proxy, const char *basefilename, const char* duration, const char* repeat); +int load_stream(Stream *stream, const char *url); void global_listener(Stream *stream, char *buffer); int write_data(Stream *stream); diff --git a/src/main.c b/src/main.c index 8a3e18c..1d4e905 100755 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,7 @@ #include <stdio.h> #include <string.h> #include <math.h> +#include <time.h> #ifdef _WIN32 #include <io.h> @@ -17,7 +18,7 @@ #include "curl.h" #include "log.h" -int load_stream_from_playlist(Stream *stream, char *filename, const char *proxy, const char *basefilename, const char *duration, const char *repeat); +int load_stream_from_playlist(Stream *stream, char *filename); void usage(void) { @@ -104,17 +105,30 @@ int main(int argc, char *argv[]) Stream stream; stream.TA=atoi(ta); + + time_t rawtime; + struct tm * timeinfo; + time (&rawtime); + timeinfo = localtime(&rawtime); + strftime(stream.basefilename,254,basefilename,timeinfo); + snprintf(stream.ext, 255, "%s", fileext); + stream.duration=atoi(duration); + stream.repeat=atoi(repeat); + memset(stream.proxy, 0, 255); + if (proxy != NULL) { + strncpy(stream.proxy, proxy, 254); + } if (pflag) { - if ((ret = load_stream_from_playlist(&stream, cvalue, proxy, basefilename, duration, repeat)) < 0) { + if ((ret = load_stream_from_playlist(&stream, cvalue)) < 0) { printf("Couldn't load stream from playlist\n"); goto err; } } if (uflag) { - load_stream(&stream, cvalue, proxy, basefilename, duration, repeat); + load_stream(&stream, cvalue); } diff --git a/src/stream.c b/src/stream.c index 9cd2b83..42866cf 100755 --- a/src/stream.c +++ b/src/stream.c @@ -1,7 +1,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <time.h> #include "types.h" #include "stream.h" @@ -9,9 +8,8 @@ #include "pls.h" #include "curl.h" -int load_stream(Stream *stream, const char *url, const char *proxy, const char *basefilename, const char* duration, const char* repeat) +int load_stream(Stream *stream, const char *url) { - int success = TRUE; char filename[255] = ""; ICYHeader *header = &stream->header; @@ -45,35 +43,18 @@ int load_stream(Stream *stream, const char *url, const char *proxy, const char * stream->status = E_STATUS_HEADER; - stream->duration = atoi(duration); - stream->repeat = atoi(repeat); - - memset(stream->proxy, 0, 255); memset(stream->url, 0, 255); - memset(stream->basefilename, 0, 255); + strncpy(stream->url, url, 254); memset(filename, 0, 255); memset(stream->filename, 0, 255); - if (proxy != NULL) { - success = strncpy(stream->proxy, proxy, 254) != NULL; - } - - time_t rawtime; - struct tm * timeinfo; - time (&rawtime); - timeinfo = localtime(&rawtime); - success = success && ((strncpy(stream->url, url, 254) != NULL) && (0 != strftime(stream->basefilename,254,basefilename,timeinfo))); - if (success) - { - newfilename(stream, filename, 255, stream->stream_title); - strncpy(stream->filename, filename, 254); - stream->output_stream = fopen(filename, "wb"); - return 0; - } - return 1; + newfilename(stream, filename, 255, stream->stream_title); + strncpy(stream->filename, filename, 254); + stream->output_stream = fopen(filename, "wb"); + return 0; } -int load_stream_from_playlist(Stream *stream, char *filename, const char *proxy, const char *basefilename, const char *duration, const char *repeat) +int load_stream_from_playlist(Stream *stream, char *filename) { PlsFile pls; int ret = 0; @@ -93,7 +74,7 @@ int load_stream_from_playlist(Stream *stream, char *filename, const char *proxy, goto early_err; } - if ((ret = load_stream(stream, pls.entries->file, proxy, basefilename, duration, repeat)) < 0) { + if ((ret = load_stream(stream, pls.entries->file)) < 0) { printf("Error : Couldn't load Shoutcast stream\n"); goto err; } From f904f0caf36e1ca33cea14534d749d6ad27abe86 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 1 Nov 2020 16:56:17 +0100 Subject: [PATCH 25/67] aac metadata --- src/main.c | 5 ++++- src/metadata.c | 33 ++++++++++++++++++++++++++++----- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/main.c b/src/main.c index 1d4e905..8f382eb 100755 --- a/src/main.c +++ b/src/main.c @@ -112,9 +112,12 @@ int main(int argc, char *argv[]) timeinfo = localtime(&rawtime); strftime(stream.basefilename,254,basefilename,timeinfo); - snprintf(stream.ext, 255, "%s", fileext); + memset(stream.ext, 0, 255); + strncpy(stream.ext, fileext, 254); + stream.duration=atoi(duration); stream.repeat=atoi(repeat); + memset(stream.proxy, 0, 255); if (proxy != NULL) { strncpy(stream.proxy, proxy, 254); diff --git a/src/metadata.c b/src/metadata.c index 74e662b..5ca915e 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -1,5 +1,7 @@ #include <stdio.h> #include <stdlib.h> +#include <time.h> +#include <sys/time.h> #include <string.h> #include <sys/param.h> @@ -99,9 +101,22 @@ int metadata_body_handler(Stream *stream, char *buffer) } if (stream_title[i]=='\0') { break;} //done } - printf("stream_title: %s\n", stream_title); + +struct timeval curTime; +gettimeofday(&curTime, NULL); +int milli = curTime.tv_usec / 1000; + +char buffr [80]; +strftime(buffr, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); + +char currentTime[84] = ""; +sprintf(currentTime, "%s.%03d", buffr, milli); + + printf("%s stream_title: %s\n", currentTime, stream_title); if (0 != strncmp(stream->stream_title, stream_title, 500)) { + char ext[3]; + strncpy(ext, stream->ext, 3); stream->metadata_count++; char new_filename[255] = ""; newfilename(stream, new_filename, 255, stream_title); @@ -109,10 +124,19 @@ int metadata_body_handler(Stream *stream, char *buffer) stream->output_stream = fopen(new_filename, "wb"); taglib_set_strings_unicode(FALSE); - TagLib_File *media_file = taglib_file_new(stream->filename); - if (media_file != NULL) { + TagLib_File *media_file; + + if (strncmp(ext,"aac",3) == 0) + { + media_file = taglib_file_new_type(stream->filename, TagLib_File_MP4); + } else { + media_file = taglib_file_new(stream->filename); + } + if (media_file != NULL) + { TagLib_Tag *tag = taglib_file_tag(media_file); - if (tag != NULL) { + if (tag != NULL) + { taglib_tag_set_comment(tag, stream->stream_title); char* token=strtok(stream->stream_title,"-"); if (stream->TA == 0) { @@ -137,7 +161,6 @@ int metadata_body_handler(Stream *stream, char *buffer) taglib_tag_free_strings(); taglib_file_free(media_file); } - strncpy(stream->filename,new_filename, 254); strncpy(stream->stream_title,stream_title, 500); } From fc3a5d191b5adaf35171b38bb1551575d4c6d458 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 8 Nov 2020 14:39:26 +0100 Subject: [PATCH 26/67] refactoring while looking for segfault, seems cookie related...? --- include/types.h | 2 +- src/curl.c | 13 ++-- src/header.c | 16 +++- src/icy-string.c | 7 +- src/log.c | 3 + src/metadata.c | 190 ++++++++++++++++++++++++----------------------- src/stream.c | 30 +++++--- 7 files changed, 141 insertions(+), 120 deletions(-) diff --git a/include/types.h b/include/types.h index 8f6f382..d8b23e8 100644 --- a/include/types.h +++ b/include/types.h @@ -69,6 +69,6 @@ typedef struct unsigned int metadata_count; // Number of metadata blocks received since beginning } Stream; -void newfilename(const Stream *stream, char* filename, unsigned int size, char* title); +void newfilename(Stream* stream,const char* title); #endif // __TYPES_H_ diff --git a/src/curl.c b/src/curl.c index 2e0ca72..2a08423 100755 --- a/src/curl.c +++ b/src/curl.c @@ -36,13 +36,9 @@ void SwapOfs(void *p) { to only run every N seconds, in order to do this the transaction time can be used */ if(duration > 0 && (curtime - myp->lastruntime) >= duration) { + printf("SwapOfs duration %lld curtime %lld lastruntime %lld\n", duration, curtime, myp->lastruntime); myp->lastruntime = curtime; - stream->metadata_count++; - char new_filename[255] = ""; - newfilename(stream, new_filename, 255, stream->stream_title); - fclose(stream->output_stream); - stream->output_stream = fopen(new_filename, "wb"); - strncpy(stream->filename, new_filename, 254); + newfilename(stream, stream->stream_title); } } @@ -112,7 +108,7 @@ int read_stream(Stream *stream) curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 60L); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); +// curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); #if LIBCURL_VERSION_NUM >= 0x072000 curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo); /* pass the struct pointer into the xferinfo function, note that this is an alias to CURLOPT_PROGRESSDATA */ @@ -123,6 +119,9 @@ int read_stream(Stream *stream) curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &prog); #endif curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); + curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ""); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:82.0) Gecko/20100101 Firefox/82.0"); time_t start_t, end_t; time(&start_t); uint seconds_elapsed = 0; diff --git a/src/header.c b/src/header.c index 7e777c7..8b8f1f4 100644 --- a/src/header.c +++ b/src/header.c @@ -29,11 +29,17 @@ int header_listener(Stream *stream, char *buffer) if (header->metaint == 0) { printf("Error : Couldn't find metaint information\n"); + } else { + print_header(header); } - print_header(header); - // TODO init_for_mp3data(stream) ? + stream->blocks_count = 0; + stream->metadata_count = 0; + stream->stream_title[0] = '\0'; + stream->output_stream = NULL; + stream->filename[0] = '\0'; + stream->bytes_count = 0; stream->bytes_count_total = 0; // TODO : Commenter stream->mp3data.size = 0; @@ -47,10 +53,12 @@ int header_listener(Stream *stream, char *buffer) int is_header(Stream *stream) { - if (stream->status == E_STATUS_HEADER) + if (stream->status == E_STATUS_HEADER){ return TRUE; - else + + } else { return FALSE; + } } int print_header(ICYHeader *header) diff --git a/src/icy-string.c b/src/icy-string.c index fd2ad3b..65f2d07 100644 --- a/src/icy-string.c +++ b/src/icy-string.c @@ -14,8 +14,11 @@ int extract_header_fields(ICYHeader *header) get_http_header_field(header->buffer, "icy-genre", header->icy_genre); get_http_header_field(header->buffer, "icy-pub", header->icy_pub); get_http_header_field(header->buffer, "icy-br", header->icy_br); - get_http_header_field(header->buffer, "icy-metaint", metaint); - header->metaint = atoi(metaint); + if(0==get_http_header_field(header->buffer, "icy-metaint", metaint)){ + header->metaint = atoi(metaint); + } else { + header->metaint = 0; + } return 0; } diff --git a/src/log.c b/src/log.c index 72978b5..67adfb5 100644 --- a/src/log.c +++ b/src/log.c @@ -86,6 +86,9 @@ static int log_append(FILE *fp, char *line) if (fputs(line, fp) == EOF) return EOF; + if (fputc('\n', fp) == EOF) + return EOF; + if (fflush(fp) == EOF) return EOF; else diff --git a/src/metadata.c b/src/metadata.c index 5ca915e..970a27a 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -58,115 +58,115 @@ int metadata_body_handler(Stream *stream, char *buffer) char metadata_content[500]=""; char stream_title[500]=""; strncpy(metadata_content, metadata->buffer, MIN(metadata->size,500)); - get_metadata_field(metadata_content, "StreamTitle", stream_title); - stream_title[499]='\0'; - metadata_content[499]='\0'; - // filter problematic characters from StreamTitle - for (unsigned int i =0; i < 496; i++) { - if (stream_title[i]=='*') { stream_title[i]='_'; continue; } - if (stream_title[i]=='?') { stream_title[i]='_'; continue; } - if (stream_title[i]=='>') { stream_title[i]='_'; continue; } - if (stream_title[i]=='<') { stream_title[i]='_'; continue; } - if (stream_title[i]=='\\') { stream_title[i]='_'; continue; } - if (stream_title[i]=='|') { stream_title[i]='_'; continue; } - if (stream_title[i]=='\"') { stream_title[i]='_'; continue; } - if (stream_title[i]==':') { stream_title[i]='_'; continue; } - if (stream_title[i]=='/') { stream_title[i]='_'; continue; } - if ((stream_title[i]==0xE9)&&(stream_title[i+1]==0x8B)) { //Ë E9 B - stream_title[i]=0xD3; - removechar(stream_title,i+1); - continue; - } else { - if ((stream_title[i]==0xE9)&&(stream_title[i+1]==0xA1)) { // á - stream_title[i]=0xE1; + if(0==get_metadata_field(metadata_content, "StreamTitle", stream_title)) + { + stream_title[499]='\0'; + metadata_content[499]='\0'; + // filter problematic characters from StreamTitle + for (unsigned int i =0; i < MIN(metadata->size,496); i++) { + if (stream_title[i]=='\0') { break;} //done + if (stream_title[i]=='*') { stream_title[i]='_'; continue; } + if (stream_title[i]=='?') { stream_title[i]='_'; continue; } + if (stream_title[i]=='>') { stream_title[i]='_'; continue; } + if (stream_title[i]=='<') { stream_title[i]='_'; continue; } + if (stream_title[i]=='\\') { stream_title[i]='_'; continue; } + if (stream_title[i]=='|') { stream_title[i]='_'; continue; } + if (stream_title[i]=='\"') { stream_title[i]='_'; continue; } + if (stream_title[i]==':') { stream_title[i]='_'; continue; } + if (stream_title[i]=='/') { stream_title[i]='_'; continue; } + if ((stream_title[i]==0xE9)&&(stream_title[i+1]==0x8B)) { //Ë E9 B + stream_title[i]=0xD3; removechar(stream_title,i+1); continue; } else { - if (stream_title[i]==0xE9) { // é - stream_title[i]=0xE9; + if ((stream_title[i]==0xE9)&&(stream_title[i+1]==0xA1)) { // á + stream_title[i]=0xE1; + removechar(stream_title,i+1); continue; + } else { + if (stream_title[i]==0xE9) { // é + stream_title[i]=0xE9; + continue; + } } } + if ( (stream_title[i]==0xC3)&& + (stream_title[i+1]==0x83)&& + (stream_title[i+2]==0x83)&& + (stream_title[i+3]==0xC2)) + { + stream_title[i]=0xE9; //é C3 83 C2 A9 + removechar(stream_title,i+1); + removechar(stream_title,i+2); + removechar(stream_title,i+3); + continue; + } } - if ( (stream_title[i]==0xC3)&& - (stream_title[i+1]==0x83)&& - (stream_title[i+2]==0x83)&& - (stream_title[i+3]==0xC2)) - { - stream_title[i]=0xE9; //é C3 83 C2 A9 - removechar(stream_title,i+1); - removechar(stream_title,i+2); - removechar(stream_title,i+3); - continue; - } - if (stream_title[i]=='\0') { break;} //done - } -struct timeval curTime; -gettimeofday(&curTime, NULL); -int milli = curTime.tv_usec / 1000; + struct timeval curTime; + gettimeofday(&curTime, NULL); + int milli = curTime.tv_usec / 1000; -char buffr [80]; -strftime(buffr, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); + char buffr [80]; + strftime(buffr, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); -char currentTime[84] = ""; -sprintf(currentTime, "%s.%03d", buffr, milli); + char currentTime[84] = ""; + sprintf(currentTime, "%s.%03d", buffr, milli); - printf("%s stream_title: %s\n", currentTime, stream_title); - if (0 != strncmp(stream->stream_title, stream_title, 500)) - { - char ext[3]; - strncpy(ext, stream->ext, 3); - stream->metadata_count++; - char new_filename[255] = ""; - newfilename(stream, new_filename, 255, stream_title); - fclose(stream->output_stream); - stream->output_stream = fopen(new_filename, "wb"); - - taglib_set_strings_unicode(FALSE); - TagLib_File *media_file; - - if (strncmp(ext,"aac",3) == 0) + printf("%s stream_title: %s\n", currentTime, stream_title); + if (0 != strncmp(stream->stream_title, stream_title, 500)) { - media_file = taglib_file_new_type(stream->filename, TagLib_File_MP4); - } else { - media_file = taglib_file_new(stream->filename); - } - if (media_file != NULL) - { - TagLib_Tag *tag = taglib_file_tag(media_file); - if (tag != NULL) + char ext[3]; + strncpy(ext, stream->ext, 3); + char oldfilename[255]; + char oldtitle[500]; + strncpy(oldfilename,stream->filename, 255); + strncpy(oldtitle,stream->stream_title, 500); + + newfilename(stream, stream_title); + + taglib_set_strings_unicode(FALSE); + TagLib_File *media_file; + + if (strncmp(ext,"aac",3) == 0) { - taglib_tag_set_comment(tag, stream->stream_title); - char* token=strtok(stream->stream_title,"-"); - if (stream->TA == 0) { - if (token) { - taglib_tag_set_title(tag,token); - token=strtok(NULL,"-"); - } - if (token) { - taglib_tag_set_artist(tag,token); - } - } else { - if (token) { - taglib_tag_set_artist(tag,token); - token=strtok(NULL,"-"); - } - if (token) { - taglib_tag_set_title(tag,token); + media_file = taglib_file_new_type(oldfilename, TagLib_File_MP4); + } else { + media_file = taglib_file_new(oldfilename); + } + if (media_file != NULL) + { + TagLib_Tag *tag = taglib_file_tag(media_file); + if (tag != NULL) + { + taglib_tag_set_comment(tag, oldtitle); + char* token=strtok(oldtitle,"-"); + if (stream->TA == 0) { + if (token) { + taglib_tag_set_title(tag,token); + token=strtok(NULL,"-"); + } + if (token) { + taglib_tag_set_artist(tag,token); + } + } else { + if (token) { + taglib_tag_set_artist(tag,token); + token=strtok(NULL,"-"); + } + if (token) { + taglib_tag_set_title(tag,token); + } } + taglib_file_save(media_file); } - taglib_file_save(media_file); + taglib_tag_free_strings(); + taglib_file_free(media_file); } - taglib_tag_free_strings(); - taglib_file_free(media_file); } - strncpy(stream->filename,new_filename, 254); - strncpy(stream->stream_title,stream_title, 500); } // slog metadata_content - snprintf(stream_title, 501, "%s\n", metadata_content); - slog(stream_title); + slog(metadata_content); stream->bytes_count = 0; stream->status = E_STATUS_MP3DATA; @@ -186,16 +186,18 @@ int is_metadata(Stream *stream) int is_metadata_body(Stream *stream) { - if (stream->status == E_STATUS_METADATA_BODY) + if (stream->status == E_STATUS_METADATA_BODY){ return TRUE; - else + } else { return FALSE; + } } int is_metadata_header(Stream *stream) { - if (stream->status == E_STATUS_METADATA_HEADER) + if (stream->status == E_STATUS_METADATA_HEADER){ return TRUE; - else + } else { return FALSE; + } } diff --git a/src/stream.c b/src/stream.c index 42866cf..fc6178f 100755 --- a/src/stream.c +++ b/src/stream.c @@ -10,8 +10,6 @@ int load_stream(Stream *stream, const char *url) { - char filename[255] = ""; - ICYHeader *header = &stream->header; MetaData *metadata = &stream->metadata; Mp3Data *mp3data = &stream->mp3data; @@ -40,17 +38,13 @@ int load_stream(Stream *stream, const char *url) stream->metadata_count = 0; stream->stream_title[0] = '\0'; stream->output_stream = NULL; + stream->filename[0] = '\0'; stream->status = E_STATUS_HEADER; - memset(stream->url, 0, 255); - strncpy(stream->url, url, 254); - memset(filename, 0, 255); - memset(stream->filename, 0, 255); + strncpy(stream->url, url, 255); - newfilename(stream, filename, 255, stream->stream_title); - strncpy(stream->filename, filename, 254); - stream->output_stream = fopen(filename, "wb"); + newfilename(stream, stream->stream_title); return 0; } @@ -86,13 +80,25 @@ int load_stream_from_playlist(Stream *stream, char *filename) } -void newfilename(const Stream *stream, char* filename, unsigned int size, char* title) +void newfilename(Stream *stream, const char* title) { - if (strlen(title)==0) { + const int size=255+1+3+1+500+1+255; + char filename[size]; + if (title==NULL||strlen(title)==0) { snprintf(filename,size,"%s.%03d.%s", stream->basefilename, stream->metadata_count, stream->ext); } else { snprintf(filename,size,"%s.%03d.%s.%s", stream->basefilename, stream->metadata_count, title, stream->ext); } - filename[size-1]='\0'; + filename[254]='\0'; + printf("filename %s\n", filename); + if (stream->output_stream != NULL) fclose(stream->output_stream); + stream->output_stream = fopen(filename, "wb"); + strncpy(stream->filename, filename, 255); + if (title==NULL||strlen(title)==0) { + stream->stream_title[0]='\0'; + } else { + strncpy(stream->stream_title, title, 500); + } + stream->metadata_count++; } From 6f2ae767b38a2c3581240a09b71ccfe225cb2abb Mon Sep 17 00:00:00 2001 From: sofie <sofie@msi.home> Date: Sun, 8 Nov 2020 19:52:23 +0100 Subject: [PATCH 27/67] fix memleak --- src/header.c | 6 ------ src/main.c | 2 ++ src/stream.c | 1 - 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/header.c b/src/header.c index 8b8f1f4..4afcde4 100644 --- a/src/header.c +++ b/src/header.c @@ -34,12 +34,6 @@ int header_listener(Stream *stream, char *buffer) } // TODO init_for_mp3data(stream) ? - stream->blocks_count = 0; - stream->metadata_count = 0; - stream->stream_title[0] = '\0'; - stream->output_stream = NULL; - stream->filename[0] = '\0'; - stream->bytes_count = 0; stream->bytes_count_total = 0; // TODO : Commenter stream->mp3data.size = 0; diff --git a/src/main.c b/src/main.c index 8f382eb..9b8a906 100755 --- a/src/main.c +++ b/src/main.c @@ -142,6 +142,8 @@ int main(int argc, char *argv[]) err: log_close_files(); err_early: + free(basefilename); + free(fileext); return ret; } diff --git a/src/stream.c b/src/stream.c index fc6178f..4bd88fc 100755 --- a/src/stream.c +++ b/src/stream.c @@ -90,7 +90,6 @@ void newfilename(Stream *stream, const char* title) snprintf(filename,size,"%s.%03d.%s.%s", stream->basefilename, stream->metadata_count, title, stream->ext); } filename[254]='\0'; - printf("filename %s\n", filename); if (stream->output_stream != NULL) fclose(stream->output_stream); stream->output_stream = fopen(filename, "wb"); strncpy(stream->filename, filename, 255); From 7825d321e38dd7583142a9dd7236162e3228b9a4 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Thu, 12 Nov 2020 20:06:50 +0100 Subject: [PATCH 28/67] option to specify log folder; handle extended ascii --- include/log.h | 2 +- src/log.c | 6 ++-- src/main.c | 11 ++++-- src/metadata.c | 91 +++++++++++++++++++++++++++++++++++--------------- 4 files changed, 77 insertions(+), 33 deletions(-) diff --git a/include/log.h b/include/log.h index 507bc44..c3c3d60 100644 --- a/include/log.h +++ b/include/log.h @@ -1,7 +1,7 @@ #ifndef __LOG_H_ #define __LOG_H_ -int log_open_files(void); +int log_open_files(char* folder); int log_close_files(void); void slog(char *line); void slog_prog(char *line); diff --git a/src/log.c b/src/log.c index 67adfb5..1c76a5e 100644 --- a/src/log.c +++ b/src/log.c @@ -6,7 +6,7 @@ static FILE *fp_log; static char current_time[20]; static char current_date[20]; -static char tempfile[255]; +static char tempfile[270]; static int get_time(char *string) { @@ -45,7 +45,7 @@ static int get_date(char *string) return 0; } -int log_open_files(void) +int log_open_files(char* folder) { if (fp_log != NULL) return -1; @@ -54,7 +54,7 @@ int log_open_files(void) printf("Couldn't get date"); return -1; } - snprintf(tempfile,255,"shoutr.%s.log",current_date); + snprintf(tempfile,270,"%s/shoutr.%s.log",folder,current_date); fp_log = fopen(tempfile,"a"); if (fp_log == NULL) { printf("Couldn't open shoutr.log file\n"); diff --git a/src/main.c b/src/main.c index 9b8a906..2f1ab37 100755 --- a/src/main.c +++ b/src/main.c @@ -28,6 +28,7 @@ void usage(void) printf("\t-e\t: fileextension (default mp3)\n"); printf("\t-f\t: basefilename (default radio)\n"); printf("\t-i\t: title - artist (0, default) or artist - title (1)\n"); + printf("\t-l\t: logfolder (default current folder)\n"); printf("\t-r\t: recording repeats (default 0 = none)\n"); printf("\t-x\t: proxy (default no proxy)\n"); } @@ -50,7 +51,10 @@ int main(int argc, char *argv[]) char* fileext = (char*) malloc(255*sizeof(char)); sprintf(fileext, "mp3"); - while ((c = getopt(argc, argv, "p:u:h:x:f:e:d:r:i:")) != -1) { + char* log = (char*) malloc(255*sizeof(char)); + sprintf(log, "."); + + while ((c = getopt(argc, argv, "p:u:h:x:f:e:d:r:i:l:")) != -1) { switch(c) { // playlist case 'p': @@ -84,6 +88,9 @@ int main(int argc, char *argv[]) case 'i': ta = optarg; break; + case 'l': + log = optarg; + break; case 'h': default: usage(); @@ -98,7 +105,7 @@ int main(int argc, char *argv[]) goto err_early; } - if ((ret = log_open_files()) < 0) { + if ((ret = log_open_files(log)) < 0) { printf("Couldn't open log files.\n"); goto err_early; } diff --git a/src/metadata.c b/src/metadata.c index 970a27a..5a67d0b 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -74,33 +74,70 @@ int metadata_body_handler(Stream *stream, char *buffer) if (stream_title[i]=='\"') { stream_title[i]='_'; continue; } if (stream_title[i]==':') { stream_title[i]='_'; continue; } if (stream_title[i]=='/') { stream_title[i]='_'; continue; } - if ((stream_title[i]==0xE9)&&(stream_title[i+1]==0x8B)) { //Ë E9 B - stream_title[i]=0xD3; - removechar(stream_title,i+1); - continue; - } else { - if ((stream_title[i]==0xE9)&&(stream_title[i+1]==0xA1)) { // á - stream_title[i]=0xE1; - removechar(stream_title,i+1); - continue; - } else { - if (stream_title[i]==0xE9) { // é - stream_title[i]=0xE9; - continue; - } - } - } - if ( (stream_title[i]==0xC3)&& - (stream_title[i+1]==0x83)&& - (stream_title[i+2]==0x83)&& - (stream_title[i+3]==0xC2)) - { - stream_title[i]=0xE9; //é C3 83 C2 A9 - removechar(stream_title,i+1); - removechar(stream_title,i+2); - removechar(stream_title,i+3); - continue; - } + if (stream_title[i]==0xC0) { stream_title[i]='A'; continue; } + if (stream_title[i]==0xC1) { stream_title[i]='A'; continue; } + if (stream_title[i]==0xC2) { stream_title[i]='A'; continue; } + if (stream_title[i]==0xC3) { stream_title[i]='A'; continue; } + if (stream_title[i]==0xC4) { stream_title[i]='A'; continue; } + if (stream_title[i]==0xC5) { stream_title[i]='A'; continue; } + if (stream_title[i]==0xC6) { stream_title[i]='E'; continue; } + if (stream_title[i]==0xC7) { stream_title[i]='C'; continue; } + if (stream_title[i]==0xC8) { stream_title[i]='E'; continue; } + if (stream_title[i]==0xC9) { stream_title[i]='E'; continue; } + if (stream_title[i]==0xCA) { stream_title[i]='E'; continue; } + if (stream_title[i]==0xCB) { stream_title[i]='E'; continue; } + if (stream_title[i]==0xCC) { stream_title[i]='I'; continue; } + if (stream_title[i]==0xCD) { stream_title[i]='I'; continue; } + if (stream_title[i]==0xCE) { stream_title[i]='I'; continue; } + if (stream_title[i]==0xCF) { stream_title[i]='I'; continue; } + if (stream_title[i]==0xD0) { stream_title[i]='D'; continue; } + if (stream_title[i]==0xD1) { stream_title[i]='N'; continue; } + if (stream_title[i]==0xD2) { stream_title[i]='O'; continue; } + if (stream_title[i]==0xD3) { stream_title[i]='O'; continue; } + if (stream_title[i]==0xD4) { stream_title[i]='O'; continue; } + if (stream_title[i]==0xD5) { stream_title[i]='O'; continue; } + if (stream_title[i]==0xD6) { stream_title[i]='O'; continue; } + if (stream_title[i]==0xD7) { stream_title[i]='x'; continue; } + if (stream_title[i]==0xD8) { stream_title[i]='O'; continue; } + if (stream_title[i]==0xD9) { stream_title[i]='U'; continue; } + if (stream_title[i]==0xDA) { stream_title[i]='U'; continue; } + if (stream_title[i]==0xDB) { stream_title[i]='U'; continue; } + if (stream_title[i]==0xDC) { stream_title[i]='U'; continue; } + if (stream_title[i]==0xDD) { stream_title[i]='Y'; continue; } + if (stream_title[i]==0xDE) { stream_title[i]='p'; continue; } + if (stream_title[i]==0xDF) { stream_title[i]='B'; continue; } + if (stream_title[i]==0xE0) { stream_title[i]='a'; continue; } + if (stream_title[i]==0xE1) { stream_title[i]='a'; continue; } + if (stream_title[i]==0xE2) { stream_title[i]='a'; continue; } + if (stream_title[i]==0xE3) { stream_title[i]='a'; continue; } + if (stream_title[i]==0xE4) { stream_title[i]='a'; continue; } + if (stream_title[i]==0xE5) { stream_title[i]='a'; continue; } + if (stream_title[i]==0xE6) { stream_title[i]='a'; continue; } + if (stream_title[i]==0xE7) { stream_title[i]='c'; continue; } + if (stream_title[i]==0xE8) { stream_title[i]='e'; continue; } + if (stream_title[i]==0xE9) { stream_title[i]='e'; continue; } + if (stream_title[i]==0xEA) { stream_title[i]='e'; continue; } + if (stream_title[i]==0xEB) { stream_title[i]='e'; continue; } + if (stream_title[i]==0xEC) { stream_title[i]='i'; continue; } + if (stream_title[i]==0xED) { stream_title[i]='i'; continue; } + if (stream_title[i]==0xEE) { stream_title[i]='i'; continue; } + if (stream_title[i]==0xEF) { stream_title[i]='i'; continue; } + if (stream_title[i]==0xF0) { stream_title[i]='o'; continue; } + if (stream_title[i]==0xF1) { stream_title[i]='o'; continue; } + if (stream_title[i]==0xF2) { stream_title[i]='o'; continue; } + if (stream_title[i]==0xF3) { stream_title[i]='o'; continue; } + if (stream_title[i]==0xF4) { stream_title[i]='o'; continue; } + if (stream_title[i]==0xF5) { stream_title[i]='o'; continue; } + if (stream_title[i]==0xF6) { stream_title[i]='o'; continue; } + if (stream_title[i]==0xF7) { stream_title[i]='+'; continue; } + if (stream_title[i]==0xF8) { stream_title[i]='o'; continue; } + if (stream_title[i]==0xF9) { stream_title[i]='u'; continue; } + if (stream_title[i]==0xFA) { stream_title[i]='u'; continue; } + if (stream_title[i]==0xFB) { stream_title[i]='u'; continue; } + if (stream_title[i]==0xFC) { stream_title[i]='u'; continue; } + if (stream_title[i]==0xFD) { stream_title[i]='y'; continue; } + if (stream_title[i]==0xFE) { stream_title[i]='p'; continue; } + if (stream_title[i]==0xFF) { stream_title[i]='y'; continue; } } struct timeval curTime; From 309464e3a8f9e2c8249d15f784f70e9a4ea135f9 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Thu, 12 Nov 2020 21:26:09 +0100 Subject: [PATCH 29/67] ascii_table --- src/metadata.c | 94 +++++++++++--------------------------------------- 1 file changed, 20 insertions(+), 74 deletions(-) diff --git a/src/metadata.c b/src/metadata.c index 5a67d0b..1ca0b01 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -12,6 +12,24 @@ #include "log.h" +static char ascii[256]={'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_', +'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_', +' ','!','_','#','$','%','&','\'','(',')','_','+',',','-','.','_', +'0','1','2','3','4','5','6','7','8','9','_',';','_','=','_','_', +'@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O', +'P','Q','R','S','T','U','V','W','X','Y','Z','[','_',']','^','_', +'`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o', +'p','q','r','s','t','u','v','w','x','y','z','{','_','}','~',' ', +'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_', +'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_', +'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_', +'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_', +'A','A','A','A','A','A','E','C','E','E','E','E','I','I','I','I', +'D','N','O','O','O','O','O','x','O','U','U','U','U','Y','p','B', +'a','a','a','a','a','a','a','c','e','e','e','e','i','i','i','i', +'o','o','o','o','o','o','o','+','o','u','u','u','u','y','p','y'}; + + int metadata_listener(Stream *stream, char *buffer) { if (!is_metadata(stream)) @@ -63,81 +81,9 @@ int metadata_body_handler(Stream *stream, char *buffer) stream_title[499]='\0'; metadata_content[499]='\0'; // filter problematic characters from StreamTitle - for (unsigned int i =0; i < MIN(metadata->size,496); i++) { + for (unsigned int i =0; i < MIN(metadata->size,500); i++) { if (stream_title[i]=='\0') { break;} //done - if (stream_title[i]=='*') { stream_title[i]='_'; continue; } - if (stream_title[i]=='?') { stream_title[i]='_'; continue; } - if (stream_title[i]=='>') { stream_title[i]='_'; continue; } - if (stream_title[i]=='<') { stream_title[i]='_'; continue; } - if (stream_title[i]=='\\') { stream_title[i]='_'; continue; } - if (stream_title[i]=='|') { stream_title[i]='_'; continue; } - if (stream_title[i]=='\"') { stream_title[i]='_'; continue; } - if (stream_title[i]==':') { stream_title[i]='_'; continue; } - if (stream_title[i]=='/') { stream_title[i]='_'; continue; } - if (stream_title[i]==0xC0) { stream_title[i]='A'; continue; } - if (stream_title[i]==0xC1) { stream_title[i]='A'; continue; } - if (stream_title[i]==0xC2) { stream_title[i]='A'; continue; } - if (stream_title[i]==0xC3) { stream_title[i]='A'; continue; } - if (stream_title[i]==0xC4) { stream_title[i]='A'; continue; } - if (stream_title[i]==0xC5) { stream_title[i]='A'; continue; } - if (stream_title[i]==0xC6) { stream_title[i]='E'; continue; } - if (stream_title[i]==0xC7) { stream_title[i]='C'; continue; } - if (stream_title[i]==0xC8) { stream_title[i]='E'; continue; } - if (stream_title[i]==0xC9) { stream_title[i]='E'; continue; } - if (stream_title[i]==0xCA) { stream_title[i]='E'; continue; } - if (stream_title[i]==0xCB) { stream_title[i]='E'; continue; } - if (stream_title[i]==0xCC) { stream_title[i]='I'; continue; } - if (stream_title[i]==0xCD) { stream_title[i]='I'; continue; } - if (stream_title[i]==0xCE) { stream_title[i]='I'; continue; } - if (stream_title[i]==0xCF) { stream_title[i]='I'; continue; } - if (stream_title[i]==0xD0) { stream_title[i]='D'; continue; } - if (stream_title[i]==0xD1) { stream_title[i]='N'; continue; } - if (stream_title[i]==0xD2) { stream_title[i]='O'; continue; } - if (stream_title[i]==0xD3) { stream_title[i]='O'; continue; } - if (stream_title[i]==0xD4) { stream_title[i]='O'; continue; } - if (stream_title[i]==0xD5) { stream_title[i]='O'; continue; } - if (stream_title[i]==0xD6) { stream_title[i]='O'; continue; } - if (stream_title[i]==0xD7) { stream_title[i]='x'; continue; } - if (stream_title[i]==0xD8) { stream_title[i]='O'; continue; } - if (stream_title[i]==0xD9) { stream_title[i]='U'; continue; } - if (stream_title[i]==0xDA) { stream_title[i]='U'; continue; } - if (stream_title[i]==0xDB) { stream_title[i]='U'; continue; } - if (stream_title[i]==0xDC) { stream_title[i]='U'; continue; } - if (stream_title[i]==0xDD) { stream_title[i]='Y'; continue; } - if (stream_title[i]==0xDE) { stream_title[i]='p'; continue; } - if (stream_title[i]==0xDF) { stream_title[i]='B'; continue; } - if (stream_title[i]==0xE0) { stream_title[i]='a'; continue; } - if (stream_title[i]==0xE1) { stream_title[i]='a'; continue; } - if (stream_title[i]==0xE2) { stream_title[i]='a'; continue; } - if (stream_title[i]==0xE3) { stream_title[i]='a'; continue; } - if (stream_title[i]==0xE4) { stream_title[i]='a'; continue; } - if (stream_title[i]==0xE5) { stream_title[i]='a'; continue; } - if (stream_title[i]==0xE6) { stream_title[i]='a'; continue; } - if (stream_title[i]==0xE7) { stream_title[i]='c'; continue; } - if (stream_title[i]==0xE8) { stream_title[i]='e'; continue; } - if (stream_title[i]==0xE9) { stream_title[i]='e'; continue; } - if (stream_title[i]==0xEA) { stream_title[i]='e'; continue; } - if (stream_title[i]==0xEB) { stream_title[i]='e'; continue; } - if (stream_title[i]==0xEC) { stream_title[i]='i'; continue; } - if (stream_title[i]==0xED) { stream_title[i]='i'; continue; } - if (stream_title[i]==0xEE) { stream_title[i]='i'; continue; } - if (stream_title[i]==0xEF) { stream_title[i]='i'; continue; } - if (stream_title[i]==0xF0) { stream_title[i]='o'; continue; } - if (stream_title[i]==0xF1) { stream_title[i]='o'; continue; } - if (stream_title[i]==0xF2) { stream_title[i]='o'; continue; } - if (stream_title[i]==0xF3) { stream_title[i]='o'; continue; } - if (stream_title[i]==0xF4) { stream_title[i]='o'; continue; } - if (stream_title[i]==0xF5) { stream_title[i]='o'; continue; } - if (stream_title[i]==0xF6) { stream_title[i]='o'; continue; } - if (stream_title[i]==0xF7) { stream_title[i]='+'; continue; } - if (stream_title[i]==0xF8) { stream_title[i]='o'; continue; } - if (stream_title[i]==0xF9) { stream_title[i]='u'; continue; } - if (stream_title[i]==0xFA) { stream_title[i]='u'; continue; } - if (stream_title[i]==0xFB) { stream_title[i]='u'; continue; } - if (stream_title[i]==0xFC) { stream_title[i]='u'; continue; } - if (stream_title[i]==0xFD) { stream_title[i]='y'; continue; } - if (stream_title[i]==0xFE) { stream_title[i]='p'; continue; } - if (stream_title[i]==0xFF) { stream_title[i]='y'; continue; } + stream_title[i]=ascii[(int)stream_title[i]]; } struct timeval curTime; From b23d75d8b96b6639c6a818a1f860036706dbcafb Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Fri, 13 Nov 2020 18:50:57 +0100 Subject: [PATCH 30/67] create logfolder if not exist --- src/log.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/log.c b/src/log.c index 1c76a5e..c05599d 100644 --- a/src/log.c +++ b/src/log.c @@ -1,5 +1,7 @@ #include <stdio.h> #include <time.h> +#include <sys/types.h> +#include <sys/stat.h> #include "log.h" @@ -54,6 +56,11 @@ int log_open_files(char* folder) printf("Couldn't get date"); return -1; } + struct stat st; + if (stat(folder, &st) != 0) + { + mkdir(folder, 0777); + } snprintf(tempfile,270,"%s/shoutr.%s.log",folder,current_date); fp_log = fopen(tempfile,"a"); if (fp_log == NULL) { From bbc58997f53c8123652b30ff51a7efa7e1e7495a Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Wed, 2 Dec 2020 17:22:57 +0100 Subject: [PATCH 31/67] work around curl_easy_getinfo TIMEOPT max_int limitation --- src/curl.c | 18 ++++++++++++------ src/log.c | 2 +- src/main.c | 6 ++++-- src/stream.c | 2 +- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/curl.c b/src/curl.c index 2a08423..93f652c 100755 --- a/src/curl.c +++ b/src/curl.c @@ -1,6 +1,7 @@ #include <curl/curl.h> #include <curl/easy.h> #include <time.h> +#include <stdlib.h> #include <string.h> #include "types.h" #include "parsing.h" @@ -21,24 +22,28 @@ struct myprogress { CURL *curl; TIMETYPE duration; Stream *stream; + time_t last; void (*thread) (void *); }; void SwapOfs(void *p) { struct myprogress *myp = (struct myprogress *)p; CURL *curl = myp->curl; - TIMETYPE duration = myp->duration; Stream *stream = myp->stream; + TIMETYPE duration = stream->duration; duration*=MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL; + time_t now; + time(&now); TIMETYPE curtime = 0; curl_easy_getinfo(curl, TIMEOPT, &curtime); /* under certain circumstances it may be desirable for certain functionality to only run every N seconds, in order to do this the transaction time can be used */ - if(duration > 0 && (curtime - myp->lastruntime) >= duration) { - printf("SwapOfs duration %lld curtime %lld lastruntime %lld\n", duration, curtime, myp->lastruntime); - myp->lastruntime = curtime; + if( (curtime - myp->lastruntime) >= duration || difftime(now,myp->last)>= stream->duration) { newfilename(stream, stream->stream_title); + printf("SwapOfs\t%lld\t%lld\t%lld\t%ld\t%ld\t%s\n", duration, curtime, myp->lastruntime,now, myp->last, stream->filename); + myp->lastruntime = curtime; + myp->last=now; } } @@ -91,12 +96,13 @@ int read_stream(Stream *stream) ret = -1; goto early_err; } - printf(" %x\n", LIBCURL_VERSION_NUM); + printf("libcurlversion %x\n", LIBCURL_VERSION_NUM); + printf("curl_off_t_fmt %s\n", CURL_FORMAT_CURL_OFF_T); prog.curl = curl; prog.stream = stream; prog.thread = &SwapOfs; prog.lastruntime = 0; - prog.duration = stream->duration; + time(&prog.last); headers = curl_slist_append(headers, "Icy-MetaData:1"); // On force la récupération des metadata curl_easy_setopt(curl, CURLOPT_URL, stream->url); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); diff --git a/src/log.c b/src/log.c index c05599d..addd2d3 100644 --- a/src/log.c +++ b/src/log.c @@ -42,7 +42,7 @@ static int get_date(char *string) time (&rawtime); timeinfo = localtime(&rawtime); - sprintf(string, "%d%02d%02d", 1900+timeinfo->tm_year, timeinfo->tm_mon+1, timeinfo->tm_mday); + sprintf(string, "%d", timeinfo->tm_wday); return 0; } diff --git a/src/main.c b/src/main.c index 2f1ab37..0b48b46 100755 --- a/src/main.c +++ b/src/main.c @@ -35,6 +35,10 @@ void usage(void) int main(int argc, char *argv[]) { + if (argc == 1) { + usage(); + return -1; + } int ret = -1; int pflag = 0; int uflag = 0; @@ -149,8 +153,6 @@ int main(int argc, char *argv[]) err: log_close_files(); err_early: - free(basefilename); - free(fileext); return ret; } diff --git a/src/stream.c b/src/stream.c index 4bd88fc..17a449e 100755 --- a/src/stream.c +++ b/src/stream.c @@ -80,7 +80,7 @@ int load_stream_from_playlist(Stream *stream, char *filename) } -void newfilename(Stream *stream, const char* title) +void newfilename(Stream* stream, const char* title) { const int size=255+1+3+1+500+1+255; char filename[size]; From 291d03fc80a065db9a8b64ba4f62caec0a7b42f4 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sat, 5 Dec 2020 17:07:30 +0100 Subject: [PATCH 32/67] additional logging --- src/curl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/curl.c b/src/curl.c index 93f652c..adb26df 100755 --- a/src/curl.c +++ b/src/curl.c @@ -41,7 +41,7 @@ void SwapOfs(void *p) { be used */ if( (curtime - myp->lastruntime) >= duration || difftime(now,myp->last)>= stream->duration) { newfilename(stream, stream->stream_title); - printf("SwapOfs\t%lld\t%lld\t%lld\t%ld\t%ld\t%s\n", duration, curtime, myp->lastruntime,now, myp->last, stream->filename); + printf("SwapOfs\t%lld\t%lld\t%08lld\t%ld\t%ld\t%s\n", duration, curtime, myp->lastruntime,now, myp->last, stream->filename); myp->lastruntime = curtime; myp->last=now; } @@ -96,8 +96,9 @@ int read_stream(Stream *stream) ret = -1; goto early_err; } - printf("libcurlversion %x\n", LIBCURL_VERSION_NUM); + printf("libcurlversion %s\n", LIBCURL_VERSION); printf("curl_off_t_fmt %s\n", CURL_FORMAT_CURL_OFF_T); + printf("sizeof(curl_typeof_curl_off_t) %d\n", sizeof(CURL_TYPEOF_CURL_OFF_T)); prog.curl = curl; prog.stream = stream; prog.thread = &SwapOfs; From 58a06d5aa862819e1b5aa85f25fd75648b8998c9 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 6 Dec 2020 18:46:47 +0100 Subject: [PATCH 33/67] record specific title --- include/types.h | 1 + src/curl.c | 14 ++++++++++---- src/main.c | 13 ++++++++++++- src/stream.c | 39 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/include/types.h b/include/types.h index d8b23e8..d7bccec 100644 --- a/include/types.h +++ b/include/types.h @@ -52,6 +52,7 @@ typedef struct char basefilename[255]; // basefilename of output file char filename[255]; // current filename of output file char ext[255]; // current extension of output file + char onlytitle[255]; // record only if title contains onlytitle unsigned int duration; // max recording duration unsigned int repeat; // max recording repeats FILE *output_stream; // Output MP3 file diff --git a/src/curl.c b/src/curl.c index adb26df..45e1604 100755 --- a/src/curl.c +++ b/src/curl.c @@ -41,7 +41,7 @@ void SwapOfs(void *p) { be used */ if( (curtime - myp->lastruntime) >= duration || difftime(now,myp->last)>= stream->duration) { newfilename(stream, stream->stream_title); - printf("SwapOfs\t%lld\t%lld\t%08lld\t%ld\t%ld\t%s\n", duration, curtime, myp->lastruntime,now, myp->last, stream->filename); + printf("SwapOfs %lld %lld-%08lld=%lld %ld-%ld=%ld %s\n", duration, curtime, myp->lastruntime,curtime-myp->lastruntime, now, myp->last, now-myp->last,stream->filename); myp->lastruntime = curtime; myp->last=now; } @@ -115,7 +115,14 @@ int read_stream(Stream *stream) curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 60L); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); -// curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + + curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, 102400L); + curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 30000L); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/7.64.0"); + curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS); + curl_easy_setopt(curl, CURLOPT_HTTP09_ALLOWED, 1L); + #if LIBCURL_VERSION_NUM >= 0x072000 curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo); /* pass the struct pointer into the xferinfo function, note that this is an alias to CURLOPT_PROGRESSDATA */ @@ -128,7 +135,6 @@ int read_stream(Stream *stream) curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ""); - curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:82.0) Gecko/20100101 Firefox/82.0"); time_t start_t, end_t; time(&start_t); uint seconds_elapsed = 0; @@ -136,7 +142,7 @@ int read_stream(Stream *stream) do { curl_easy_setopt(curl, CURLOPT_TIMEOUT, duration-seconds_elapsed); curl_res = curl_easy_perform(curl); - if (curl_res != CURLE_OK && curl_res != CURLE_OPERATION_TIMEDOUT) { + if (curl_res != CURLE_OK && curl_res != CURLE_OPERATION_TIMEDOUT && curl_res != CURLE_RECV_ERROR) { time(&now); info = localtime( &now ); strftime(buffer,80,"%T", info); diff --git a/src/main.c b/src/main.c index 0b48b46..06f347f 100755 --- a/src/main.c +++ b/src/main.c @@ -30,6 +30,7 @@ void usage(void) printf("\t-i\t: title - artist (0, default) or artist - title (1)\n"); printf("\t-l\t: logfolder (default current folder)\n"); printf("\t-r\t: recording repeats (default 0 = none)\n"); + printf("\t-t\t: title to record (default any)\n"); printf("\t-x\t: proxy (default no proxy)\n"); } @@ -58,7 +59,9 @@ int main(int argc, char *argv[]) char* log = (char*) malloc(255*sizeof(char)); sprintf(log, "."); - while ((c = getopt(argc, argv, "p:u:h:x:f:e:d:r:i:l:")) != -1) { + char* title = NULL; + + while ((c = getopt(argc, argv, "p:u:h:x:f:e:d:r:i:l:t:")) != -1) { switch(c) { // playlist case 'p': @@ -95,6 +98,9 @@ int main(int argc, char *argv[]) case 'l': log = optarg; break; + case 't': + title = optarg; + break; case 'h': default: usage(); @@ -134,6 +140,11 @@ int main(int argc, char *argv[]) strncpy(stream.proxy, proxy, 254); } + memset(stream.onlytitle, 0, 255); + if (title != NULL) { + strncpy(stream.onlytitle, title, 254); + } + if (pflag) { if ((ret = load_stream_from_playlist(&stream, cvalue)) < 0) { printf("Couldn't load stream from playlist\n"); diff --git a/src/stream.c b/src/stream.c index 17a449e..bea3100 100755 --- a/src/stream.c +++ b/src/stream.c @@ -80,6 +80,40 @@ int load_stream_from_playlist(Stream *stream, char *filename) } +static char tolower[256]={ +'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_', +'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_', +' ','!','_','#','$','%','&','\'','(',')','_','+',',','-','.','_', +'0','1','2','3','4','5','6','7','8','9','_',';','_','=','_','_', +'@','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o', +'p','q','r','s','t','u','v','w','x','y','z','[','_',']','^',' ', +'`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o', +'p','q','r','s','t','u','v','w','x','y','z','{','_','}','~',' ', +'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_', +'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_', +'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_', +'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_', +'a','a','a','a','a','a','a','c','e','e','e','e','i','i','i','i', +'o','n','o','o','o','o','o','x','o','u','u','u','u','y','p','b', +'a','a','a','a','a','a','a','c','e','e','e','e','i','i','i','i', +'o','o','o','o','o','o','o','+','o','u','u','u','u','y','p','y'}; + +char* stristr(const char* haystack, const char* needle) { + do { + const char* h = haystack; + const char* n = needle; + while (tolower[(int)(*h)] == tolower[(int)(*n)] && *n) { + h++; + n++; + } + if (*n == 0) { + return (char *) haystack; + } + } while (*haystack++); + return 0; +} + + void newfilename(Stream* stream, const char* title) { const int size=255+1+3+1+500+1+255; @@ -89,6 +123,11 @@ void newfilename(Stream* stream, const char* title) } else { snprintf(filename,size,"%s.%03d.%s.%s", stream->basefilename, stream->metadata_count, title, stream->ext); } + if (stream->onlytitle!=NULL&&strlen(stream->onlytitle)!=0) { + if (stristr(title, stream->onlytitle)==NULL) { + snprintf(filename,size,"%s","/dev/null"); + } + } filename[254]='\0'; if (stream->output_stream != NULL) fclose(stream->output_stream); stream->output_stream = fopen(filename, "wb"); From 387531883495992602ca17ba9fbe35190a2626f3 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 13 Dec 2020 18:55:19 +0100 Subject: [PATCH 34/67] increment metadata_count only when creating new output file --- src/curl.c | 2 -- src/stream.c | 7 +++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/curl.c b/src/curl.c index 45e1604..fb6bd4c 100755 --- a/src/curl.c +++ b/src/curl.c @@ -97,8 +97,6 @@ int read_stream(Stream *stream) goto early_err; } printf("libcurlversion %s\n", LIBCURL_VERSION); - printf("curl_off_t_fmt %s\n", CURL_FORMAT_CURL_OFF_T); - printf("sizeof(curl_typeof_curl_off_t) %d\n", sizeof(CURL_TYPEOF_CURL_OFF_T)); prog.curl = curl; prog.stream = stream; prog.thread = &SwapOfs; diff --git a/src/stream.c b/src/stream.c index bea3100..959abbe 100755 --- a/src/stream.c +++ b/src/stream.c @@ -123,10 +123,10 @@ void newfilename(Stream* stream, const char* title) } else { snprintf(filename,size,"%s.%03d.%s.%s", stream->basefilename, stream->metadata_count, title, stream->ext); } - if (stream->onlytitle!=NULL&&strlen(stream->onlytitle)!=0) { - if (stristr(title, stream->onlytitle)==NULL) { + if (stream->onlytitle!=NULL&&strlen(stream->onlytitle)!=0&&stristr(title, stream->onlytitle)==NULL) { snprintf(filename,size,"%s","/dev/null"); - } + } else { + stream->metadata_count++; } filename[254]='\0'; if (stream->output_stream != NULL) fclose(stream->output_stream); @@ -137,6 +137,5 @@ void newfilename(Stream* stream, const char* title) } else { strncpy(stream->stream_title, title, 500); } - stream->metadata_count++; } From cc47932b55c37ebd333d68f9523e23d4baed1026 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 27 Dec 2020 11:12:09 +0100 Subject: [PATCH 35/67] only log streamTitle changes --- src/metadata.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/metadata.c b/src/metadata.c index 1ca0b01..e6bb19c 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -86,19 +86,18 @@ int metadata_body_handler(Stream *stream, char *buffer) stream_title[i]=ascii[(int)stream_title[i]]; } - struct timeval curTime; - gettimeofday(&curTime, NULL); - int milli = curTime.tv_usec / 1000; - - char buffr [80]; - strftime(buffr, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); - - char currentTime[84] = ""; - sprintf(currentTime, "%s.%03d", buffr, milli); - - printf("%s stream_title: %s\n", currentTime, stream_title); if (0 != strncmp(stream->stream_title, stream_title, 500)) { + struct timeval curTime; + gettimeofday(&curTime, NULL); + int milli = curTime.tv_usec / 1000; + + char buffr [80]; + strftime(buffr, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); + char currentTime[84] = ""; + sprintf(currentTime, "%s.%03d", buffr, milli); + printf("%s stream_title: %s\n", currentTime, stream_title); + char ext[3]; strncpy(ext, stream->ext, 3); char oldfilename[255]; From f5018147bc29d0af30efdaeb496c5f9298d138cf Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Mon, 8 Feb 2021 19:59:17 +0100 Subject: [PATCH 36/67] added timestamp to SwapOfs logline --- src/curl.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/curl.c b/src/curl.c index fb6bd4c..a21c342 100755 --- a/src/curl.c +++ b/src/curl.c @@ -41,7 +41,17 @@ void SwapOfs(void *p) { be used */ if( (curtime - myp->lastruntime) >= duration || difftime(now,myp->last)>= stream->duration) { newfilename(stream, stream->stream_title); - printf("SwapOfs %lld %lld-%08lld=%lld %ld-%ld=%ld %s\n", duration, curtime, myp->lastruntime,curtime-myp->lastruntime, now, myp->last, now-myp->last,stream->filename); + + struct timeval curTime; + gettimeofday(&curTime, NULL); + int milli = curTime.tv_usec / 1000; + + char buffr [80]; + strftime(buffr, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); + char currentTime[84] = ""; + sprintf(currentTime, "%s.%03d", buffr, milli); + + printf("%s SwapOfs %lld %lld-%08lld=%lld %ld-%ld=%ld %s\n", currentTime, duration, curtime, myp->lastruntime,curtime-myp->lastruntime, now, myp->last, now-myp->last,stream->filename); myp->lastruntime = curtime; myp->last=now; } From bb4ce5dcf001db0d5dbb080312db0e58b87236ae Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 18 Apr 2021 08:44:27 +0200 Subject: [PATCH 37/67] added stationname option --- src/curl.c | 5 +++-- src/main.c | 15 +++++++++++++-- src/metadata.c | 2 +- src/stream.c | 12 ++++++++++-- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/curl.c b/src/curl.c index a21c342..73111f6 100755 --- a/src/curl.c +++ b/src/curl.c @@ -48,6 +48,7 @@ void SwapOfs(void *p) { char buffr [80]; strftime(buffr, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); + char currentTime[84] = ""; sprintf(currentTime, "%s.%03d", buffr, milli); @@ -97,7 +98,6 @@ int read_stream(Stream *stream) strftime(buffer,80, "%T", info); printf("%s stream->url [%s]\n", buffer, stream->url); printf("%s stream->proxy [%s]\n", buffer, stream->proxy); - printf(buffer); if ((curl = curl_easy_init()) == NULL) { time(&now); info = localtime( &now ); @@ -106,7 +106,7 @@ int read_stream(Stream *stream) ret = -1; goto early_err; } - printf("libcurlversion %s\n", LIBCURL_VERSION); + printf("%s libcurlversion %s\n", buffer, LIBCURL_VERSION); prog.curl = curl; prog.stream = stream; prog.thread = &SwapOfs; @@ -143,6 +143,7 @@ int read_stream(Stream *stream) curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ""); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); time_t start_t, end_t; time(&start_t); uint seconds_elapsed = 0; diff --git a/src/main.c b/src/main.c index 06f347f..9f6eb1c 100755 --- a/src/main.c +++ b/src/main.c @@ -24,11 +24,12 @@ void usage(void) { printf("Usage: shoutr [-p <playlist>|-u <stream_url>] [OPTIONS]\n"); printf("options:\n"); - printf("\t-d\t: recording duration (in seconds, default 0 = unlimited)\n"); + printf("\t-d\t: recording duration (in seconds)\n"); printf("\t-e\t: fileextension (default mp3)\n"); printf("\t-f\t: basefilename (default radio)\n"); printf("\t-i\t: title - artist (0, default) or artist - title (1)\n"); printf("\t-l\t: logfolder (default current folder)\n"); + printf("\t-n\t: name of station (default radio)\n"); printf("\t-r\t: recording repeats (default 0 = none)\n"); printf("\t-t\t: title to record (default any)\n"); printf("\t-x\t: proxy (default no proxy)\n"); @@ -53,6 +54,8 @@ int main(int argc, char *argv[]) char* basefilename = (char*) malloc(255*sizeof(char)); sprintf(basefilename, "radio"); + char* stationname = NULL; + char* fileext = (char*) malloc(255*sizeof(char)); sprintf(fileext, "mp3"); @@ -61,7 +64,7 @@ int main(int argc, char *argv[]) char* title = NULL; - while ((c = getopt(argc, argv, "p:u:h:x:f:e:d:r:i:l:t:")) != -1) { + while ((c = getopt(argc, argv, "p:u:h:x:f:e:d:r:i:l:n:t:")) != -1) { switch(c) { // playlist case 'p': @@ -98,6 +101,9 @@ int main(int argc, char *argv[]) case 'l': log = optarg; break; + case 'n': + stationname = optarg; + break; case 't': title = optarg; break; @@ -132,6 +138,11 @@ int main(int argc, char *argv[]) memset(stream.ext, 0, 255); strncpy(stream.ext, fileext, 254); + memset(stream.stream_title, 0, 255); + if (stationname != NULL) { + strncpy(stream.stream_title, stationname, 254); + } + stream.duration=atoi(duration); stream.repeat=atoi(repeat); diff --git a/src/metadata.c b/src/metadata.c index e6bb19c..f51915f 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -96,7 +96,7 @@ int metadata_body_handler(Stream *stream, char *buffer) strftime(buffr, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); char currentTime[84] = ""; sprintf(currentTime, "%s.%03d", buffr, milli); - printf("%s stream_title: %s\n", currentTime, stream_title); + printf("%s stream_title: [%s]\n", currentTime, stream_title); char ext[3]; strncpy(ext, stream->ext, 3); diff --git a/src/stream.c b/src/stream.c index 959abbe..8ab4164 100755 --- a/src/stream.c +++ b/src/stream.c @@ -1,6 +1,8 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> +#include <sys/time.h> #include "types.h" #include "stream.h" @@ -36,14 +38,12 @@ int load_stream(Stream *stream, const char *url) stream->bytes_count_total = 0; stream->blocks_count = 0; stream->metadata_count = 0; - stream->stream_title[0] = '\0'; stream->output_stream = NULL; stream->filename[0] = '\0'; stream->status = E_STATUS_HEADER; strncpy(stream->url, url, 255); - newfilename(stream, stream->stream_title); return 0; } @@ -137,5 +137,13 @@ void newfilename(Stream* stream, const char* title) } else { strncpy(stream->stream_title, title, 500); } + struct timeval curTime; + gettimeofday(&curTime, NULL); + int milli = curTime.tv_usec / 1000; + char buffr[20]; + strftime(buffr, 20, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); + char currentTime[30] = ""; + sprintf(currentTime, "%s.%03d", buffr, milli); + printf("%s newfilename: %s\n", currentTime, filename); } From 2ee8983886fd464152ea0da3d34bd92e6a5a2b4f Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sat, 24 Apr 2021 12:18:45 +0200 Subject: [PATCH 38/67] support comma separated list of titles to record --- src/log.c | 2 +- src/metadata.c | 12 +++++++++++- src/stream.c | 20 +++++++++++++++++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/log.c b/src/log.c index addd2d3..c81a997 100644 --- a/src/log.c +++ b/src/log.c @@ -42,7 +42,7 @@ static int get_date(char *string) time (&rawtime); timeinfo = localtime(&rawtime); - sprintf(string, "%d", timeinfo->tm_wday); + sprintf(string, "%d", timeinfo->tm_mday); return 0; } diff --git a/src/metadata.c b/src/metadata.c index f51915f..206ebfd 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -68,6 +68,16 @@ void removechar( char str[], unsigned int i ) str[strlen(str)-1]='\0'; } +void rtrim(char *str) +{ + const char *seps = "\t\n\v\f\r "; + int i = strlen(str) - 1; + while (i >= 0 && strchr(seps, str[i]) != NULL) { + str[i] = '\0'; + i--; + } +} + int metadata_body_handler(Stream *stream, char *buffer) { MetaData *metadata = &stream->metadata; @@ -85,7 +95,7 @@ int metadata_body_handler(Stream *stream, char *buffer) if (stream_title[i]=='\0') { break;} //done stream_title[i]=ascii[(int)stream_title[i]]; } - + rtrim(stream_title); if (0 != strncmp(stream->stream_title, stream_title, 500)) { struct timeval curTime; diff --git a/src/stream.c b/src/stream.c index 8ab4164..c522657 100755 --- a/src/stream.c +++ b/src/stream.c @@ -123,8 +123,26 @@ void newfilename(Stream* stream, const char* title) } else { snprintf(filename,size,"%s.%03d.%s.%s", stream->basefilename, stream->metadata_count, title, stream->ext); } - if (stream->onlytitle!=NULL&&strlen(stream->onlytitle)!=0&&stristr(title, stream->onlytitle)==NULL) { + if (stream->onlytitle!=NULL&&strlen(stream->onlytitle)!=0) { + char* token=strtok(stream->onlytitle,","); + int title_found = 0; + if (token) { + while (token) { + if(stristr(title, token)!=NULL) { + title_found = 1; + } + token=strtok(NULL,","); + } + } else { + if(stristr(title, stream->onlytitle)!=NULL) { + title_found = 1; + } + } + if (title_found == 0) { snprintf(filename,size,"%s","/dev/null"); + } else { + stream->metadata_count++; + } } else { stream->metadata_count++; } From c5651143fb20109afaefe0dacda1b60bf534a461 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sat, 24 Apr 2021 16:11:41 +0200 Subject: [PATCH 39/67] preserve string for tokenizer --- src/stream.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/stream.c b/src/stream.c index c522657..c3c029f 100755 --- a/src/stream.c +++ b/src/stream.c @@ -124,8 +124,10 @@ void newfilename(Stream* stream, const char* title) snprintf(filename,size,"%s.%03d.%s.%s", stream->basefilename, stream->metadata_count, title, stream->ext); } if (stream->onlytitle!=NULL&&strlen(stream->onlytitle)!=0) { - char* token=strtok(stream->onlytitle,","); + char str[255]; + strncpy(str, stream->onlytitle, 255); int title_found = 0; + char* token=strtok(str,","); if (token) { while (token) { if(stristr(title, token)!=NULL) { From bdf099dc86aa24ad60973635145325b275c75554 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sat, 1 May 2021 17:32:59 +0200 Subject: [PATCH 40/67] refactor into plog --- include/log.h | 1 + src/curl.c | 13 ++----------- src/log.c | 20 +++++++++++++++++++- src/metadata.c | 15 +++------------ src/stream.c | 12 ++---------- 5 files changed, 27 insertions(+), 34 deletions(-) diff --git a/include/log.h b/include/log.h index c3c3d60..8660a89 100644 --- a/include/log.h +++ b/include/log.h @@ -5,5 +5,6 @@ int log_open_files(char* folder); int log_close_files(void); void slog(char *line); void slog_prog(char *line); +void plog(char *fmt, ...); #endif diff --git a/src/curl.c b/src/curl.c index 73111f6..0b4cf2f 100755 --- a/src/curl.c +++ b/src/curl.c @@ -5,6 +5,7 @@ #include <string.h> #include "types.h" #include "parsing.h" +#include "log.h" #if LIBCURL_VERSION_NUM >= 0x073d00 #define TIME_IN_US 1 @@ -42,17 +43,7 @@ void SwapOfs(void *p) { if( (curtime - myp->lastruntime) >= duration || difftime(now,myp->last)>= stream->duration) { newfilename(stream, stream->stream_title); - struct timeval curTime; - gettimeofday(&curTime, NULL); - int milli = curTime.tv_usec / 1000; - - char buffr [80]; - strftime(buffr, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); - - char currentTime[84] = ""; - sprintf(currentTime, "%s.%03d", buffr, milli); - - printf("%s SwapOfs %lld %lld-%08lld=%lld %ld-%ld=%ld %s\n", currentTime, duration, curtime, myp->lastruntime,curtime-myp->lastruntime, now, myp->last, now-myp->last,stream->filename); + plog("SwapOfs %lld %lld-%08lld=%lld %ld-%ld=%ld %s\n", duration, curtime, myp->lastruntime,curtime-myp->lastruntime, now, myp->last, now-myp->last,stream->filename); myp->lastruntime = curtime; myp->last=now; } diff --git a/src/log.c b/src/log.c index c81a997..1e0c726 100644 --- a/src/log.c +++ b/src/log.c @@ -1,7 +1,9 @@ #include <stdio.h> #include <time.h> +#include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> +#include <stdarg.h> #include "log.h" @@ -42,7 +44,7 @@ static int get_date(char *string) time (&rawtime); timeinfo = localtime(&rawtime); - sprintf(string, "%d", timeinfo->tm_mday); + sprintf(string, "%02d", timeinfo->tm_mday); return 0; } @@ -108,3 +110,19 @@ void slog(char *line) printf("Coudln't write shoutr log\n"); } +void printCurrentTime() { + struct timeval curTime; + gettimeofday(&curTime, NULL); + int milli = curTime.tv_usec / 1000; + char buffr [80]; + strftime(buffr, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); + printf("%s.%03d ", buffr, milli); +} + +void plog(char *fmt, ...) { + printCurrentTime(); + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} diff --git a/src/metadata.c b/src/metadata.c index 206ebfd..05426a1 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -1,7 +1,5 @@ #include <stdio.h> #include <stdlib.h> -#include <time.h> -#include <sys/time.h> #include <string.h> #include <sys/param.h> @@ -68,7 +66,7 @@ void removechar( char str[], unsigned int i ) str[strlen(str)-1]='\0'; } -void rtrim(char *str) +void rtrim(char str[]) { const char *seps = "\t\n\v\f\r "; int i = strlen(str) - 1; @@ -98,15 +96,8 @@ int metadata_body_handler(Stream *stream, char *buffer) rtrim(stream_title); if (0 != strncmp(stream->stream_title, stream_title, 500)) { - struct timeval curTime; - gettimeofday(&curTime, NULL); - int milli = curTime.tv_usec / 1000; - - char buffr [80]; - strftime(buffr, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); - char currentTime[84] = ""; - sprintf(currentTime, "%s.%03d", buffr, milli); - printf("%s stream_title: [%s]\n", currentTime, stream_title); + plog("stream_title: [%s]\n", stream_title); + char ext[3]; strncpy(ext, stream->ext, 3); diff --git a/src/stream.c b/src/stream.c index c3c029f..43de9e2 100755 --- a/src/stream.c +++ b/src/stream.c @@ -1,14 +1,13 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <time.h> -#include <sys/time.h> #include "types.h" #include "stream.h" #include "files.h" #include "pls.h" #include "curl.h" +#include "log.h" int load_stream(Stream *stream, const char *url) { @@ -157,13 +156,6 @@ void newfilename(Stream* stream, const char* title) } else { strncpy(stream->stream_title, title, 500); } - struct timeval curTime; - gettimeofday(&curTime, NULL); - int milli = curTime.tv_usec / 1000; - char buffr[20]; - strftime(buffr, 20, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); - char currentTime[30] = ""; - sprintf(currentTime, "%s.%03d", buffr, milli); - printf("%s newfilename: %s\n", currentTime, filename); + plog("newfilename: %s\n", filename); } From 6e1be2e7b964839c71856874b527bcc39c6e5ac9 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sat, 1 May 2021 17:58:20 +0200 Subject: [PATCH 41/67] update README --- README.mkd | 76 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/README.mkd b/README.mkd index 265c3fe..f74d4e3 100644 --- a/README.mkd +++ b/README.mkd @@ -10,11 +10,11 @@ Dependencies ------------ - libcurl - sudo apt-get install libcurl-dev - sudo apt-get install libcurl4-openssl-dev + - sudo apt-get install libcurl-dev + - sudo apt-get install libcurl4-openssl-dev - taglib - sudo apt-get install libtag1-dev - sudo apt-get install libtagc0-dev + - sudo apt-get install libtag1-dev + - sudo apt-get install libtagc0-dev How does it work ? @@ -32,54 +32,58 @@ How does it work ? How to build it --------------- -use make to build -artefact is in build folder -see Makefile +- use make to build +- artefact is in build folder +- see Makefile How to run it ------------- -Here are two examples : +Usage: shoutr [-p <playlist>|-u <stream_url>] [OPTIONS] - ./shoutr -u http://88.190.24.47:80 -f ./%w-%H -d 3580 +Examples : -or + ./shoutr -u http://88.190.24.47:80 -f ./%w-%H -d 3580 - ./shoutr -p frequence3.pls + ./shoutr -p frequence3.pls ./log -Additional commandline options +OPTIONS: - -x proxy defines proxy to use, (see CURLOPT_PROXY) - -f hotmusic defines the base name of the mp3 file(s) created -d duration defines the recording length in seconds (see CURLOPT_TIMEOUT) + -e extension fileextension (default: mp3) + -f basefilename defines the base name of the mp3 file(s) created (default: radio) + -i id3tags split stream_title (on '-') into artist - title (default, 0) or title - artist (1) + -l logfolder (rel/abs) path to folder for log (default: current folder) + -n name name of station (default radio) -r repeat repeat the recording specified number of times - -i id3tags split stream_title (on '-') into artist - title (default, 0) or title - artist (1) - + -t title (part of) title to record (default any) (tip: use '-' to record only music) + -x proxy defines proxy to use (see CURLOPT_PROXY) + without these additional commandline options specified no proxy is used - libcurl respects the proxy environment variables named http_proxy, ftp_proxy, sftp_proxy etc., see CURLOPT_PROXY + libcurl respects the proxy environment variables named http_proxy, ftp_proxy, sftp_proxy etc., see CURLOPT_PROXY basename will be radio###.mp3 - ### is incrementing number - incrementing number can be used for sorting. - as metadata is never changing exacty on the moment the song changes, - a fluent playback is only possible in recording order (hence incrementing number) - incrementing number will increment when - metadata streamtitle changes - repeat > 0 and duration passes - basename can handle timestamp directives (see strftime) - basename will be appended with name of downloaded music using metadata (if available) + ### is incrementing number + incrementing number can be used for sorting. + as metadata is never changing exacty on the moment the song changes, + a fluent playback is only possible in recording order (hence incrementing number) + incrementing number will increment when + metadata streamtitle changes + repeat > 0 and duration passes + basename can handle timestamp directives (see strftime) + basename will be appended with name of station (if provided with -n) and downloaded music using metadata (if available) duration will be infinite (see CURLOPT_TIMEOUT) - repeat will be 0 (no repeat) - repeat will - reuse/continue the recording using the existing connection - avoid establishing new connection (preventing new connection pub) - change incrementing number - create a separate recording file for each repeat - not change basename (weekday nor Hour nor any supplied timestamp directive) - N.B. a repeat set to 2 will produce 3 recordings (0, 1=1st repeat, 2=2nd repeat) - (of the same stream and of the same duration) - non-empty stream_title will be used for id3tag assuming artist - title + repeat will be 0 (no repeat) + repeat will + reuse/continue the recording using the existing connection + avoid establishing new connection (preventing new connection pub) + change incrementing number + create a separate recording file for each repeat + not change basename (weekday nor hour nor any supplied timestamp directive) + N.B. a repeat set to 2 will produce 3 recordings (0, 1=1st repeat, 2=2nd repeat) + (of the same stream and of the same duration) + non-empty stream_title will be used for id3tag assuming artist - title cron example : From 5e0f27179d1b0cb9a156bdf90df978527dd4481e Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sat, 1 May 2021 18:08:25 +0200 Subject: [PATCH 42/67] markdown fixes --- README.mkd | 61 +++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/README.mkd b/README.mkd index f74d4e3..f3291d8 100644 --- a/README.mkd +++ b/README.mkd @@ -39,13 +39,15 @@ How to build it How to run it ------------- -Usage: shoutr [-p <playlist>|-u <stream_url>] [OPTIONS] +Usage: + + ./shoutr [-p <playlist>|-u <stream_url>] [OPTIONS] Examples : ./shoutr -u http://88.190.24.47:80 -f ./%w-%H -d 3580 - ./shoutr -p frequence3.pls ./log + ./shoutr -p frequence3.pls -l ./log OPTIONS: @@ -99,34 +101,33 @@ stream=http://88.190.24.47:80 copy recordings in recording order : -` -#!/bin/bash -SECONDS=0 -TEST= -IFS=$'\n' -DRIVE="$(dirname "$0")" -DST="${DRIVE}/.." -LOG="${DRIVE}/copyit.LOG" -echo "" > $LOG - -function cpit { -$TEST mkdir -pv "${DST}/${CWD}" | tee -a $LOG -for i in $( find "${SRC}${CWD}" -type f -mtime -6 | sort ) -do - $TEST rsync --min-size=1mb -avh --no-p --no-g --chmod=ugo=rwX --modify-window=2 "$i" "${DST}/${CWD}" | tee -a $LOG -done -} - -SRC=/mnt/nfs/HDD/ -for G in "CD01" "CD02" "CD04" -do - CWD=$G - echo $CWD $DST - cpit -done -echo "Script finished in $SECONDS seconds=> $(($SECONDS/60)) min $(($SECONDS%60)) sec" | tee -a $LOG -` - + + #!/bin/bash + SECONDS=0 + TEST= + IFS=$'\n' + DRIVE="$(dirname "$0")" + DST="${DRIVE}/.." + LOG="${DRIVE}/copyit.LOG" + echo "" > $LOG + + function cpit { + $TEST mkdir -pv "${DST}/${CWD}" | tee -a $LOG + for i in $( find "${SRC}${CWD}" -type f -mtime -6 | sort ) + do + $TEST rsync --min-size=1mb -avh --no-p --no-g --chmod=ugo=rwX --modify-window=2 "$i" "${DST}/${CWD}" | tee -a $LOG + done + } + + SRC=/mnt/nfs/HDD/ + for G in "CD01" "CD02" "CD04" + do + CWD=$G + echo $CWD $DST + cpit + done + echo "Script finished in $SECONDS seconds=> $(($SECONDS/60)) min $(($SECONDS%60)) sec" | tee -a $LOG + TODO ---- From ca4e507d43b4c7aa729903f7fc54d8adadf65396 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 6 Jun 2021 11:53:14 +0200 Subject: [PATCH 43/67] fix segmentation fault --- README.mkd | 40 ++++++++++++++++++++-------------------- include/shoutcast.h | 1 + src/header.c | 1 - src/main.c | 6 +++++- src/stream.c | 6 ++++++ 5 files changed, 32 insertions(+), 22 deletions(-) diff --git a/README.mkd b/README.mkd index f3291d8..e7c95b5 100644 --- a/README.mkd +++ b/README.mkd @@ -1,10 +1,7 @@ SHOUTcast Recorder ================== -SHOUTcast Recorder is able to record and store SHOUTcast stream automatically -into separate mp3 files. This software was initially conceived to understand -the SHOUTcast protocol, not really to record web radios ;) The fun part is to -play with the protocol ! +SHOUTcast Recorder is able to record and store SHOUTcast stream automatically into separate mp3 files. This software was initially conceived to understand the SHOUTcast protocol, not really to record web radios ;) The fun part is to play with the protocol ! Dependencies ------------ @@ -51,15 +48,15 @@ Examples : OPTIONS: - -d duration defines the recording length in seconds (see CURLOPT_TIMEOUT) - -e extension fileextension (default: mp3) + -d duration defines the recording length in seconds (see CURLOPT_TIMEOUT) + -e extension fileextension (default: mp3) -f basefilename defines the base name of the mp3 file(s) created (default: radio) - -i id3tags split stream_title (on '-') into artist - title (default, 0) or title - artist (1) - -l logfolder (rel/abs) path to folder for log (default: current folder) - -n name name of station (default radio) - -r repeat repeat the recording specified number of times - -t title (part of) title to record (default any) (tip: use '-' to record only music) - -x proxy defines proxy to use (see CURLOPT_PROXY) + -i id3tags split stream_title (on '-') into artist - title (default, 0) or title - artist (1) + -l logfolder (rel/abs) path to folder for log (default: current folder) + -n name name of station (default radio) + -r repeat repeat the recording specified number of times + -t title (part of) title to record (default any) (tip: use '-' to record only music) + -x proxy defines proxy to use (see CURLOPT_PROXY) without these additional commandline options specified @@ -89,15 +86,15 @@ without these additional commandline options specified cron example : -` -SHELL=/bin/bash -log=/HDD/log/crontab. -dt=date +%Y%m%d -dow=date +%u -stream=http://88.190.24.47:80 -0 10 * * * cd /HDD; ./shoutr -u $stream -f ./$($dow)-10 -d 3580 -r 1 >> $log$($dt).log 2>&1 -` + SHELL=/bin/bash + log=/HDD/log/crontab. + dt=date +%Y%m%d + dow=date +%u + + stream=http://88.190.24.47:80 + 0 10 * * * cd /HDD; ./shoutr -u $stream -f ./$($dow)-10 -d 3580 -r 1 >> $log$($dt).log 2>&1 + copy recordings in recording order : @@ -146,3 +143,6 @@ See the file COPYING for details. Contact ------- Yoann Sculo - <yoann.sculo@gmail.com> + +------ +markdown by http://remarkableapp.github.io/ diff --git a/include/shoutcast.h b/include/shoutcast.h index a014bc5..21f9a97 100644 --- a/include/shoutcast.h +++ b/include/shoutcast.h @@ -3,6 +3,7 @@ #include "types.h" +int free_stream(Stream *stream); int load_stream(Stream *stream, const char *url); void global_listener(Stream *stream, char *buffer); int write_data(Stream *stream); diff --git a/src/header.c b/src/header.c index 4afcde4..aa4247b 100644 --- a/src/header.c +++ b/src/header.c @@ -25,7 +25,6 @@ int header_listener(Stream *stream, char *buffer) if (is_end_of_http_header(header)) { extract_header_fields(header); - free(header->buffer); if (header->metaint == 0) { printf("Error : Couldn't find metaint information\n"); diff --git a/src/main.c b/src/main.c index 9f6eb1c..288e2c9 100755 --- a/src/main.c +++ b/src/main.c @@ -175,6 +175,10 @@ int main(int argc, char *argv[]) err: log_close_files(); err_early: + free_stream(&stream); + free(basefilename); + free(fileext); + free(log); return ret; } @@ -186,7 +190,7 @@ size_t parse_header(void *ptr, size_t size, size_t nmemb, void *userdata) size_t numbytes = size * nmemb; //stream->header.buffer; - //copy *ptr to neader.buffer starting at header.ptr position + //copy *ptr to header.buffer starting at header.ptr position void* dest = stream->header.ptr; memcpy(dest, ptr, numbytes); diff --git a/src/stream.c b/src/stream.c index 43de9e2..d47fe33 100755 --- a/src/stream.c +++ b/src/stream.c @@ -9,6 +9,12 @@ #include "curl.h" #include "log.h" +void free_stream(Stream *stream) +{ + ICYHeader *header = &stream->header; + free(header->buffer); + header->ptr= NULL; +} int load_stream(Stream *stream, const char *url) { ICYHeader *header = &stream->header; From 1cb6ebfffc8e5dcce1cd386d379fbbe5837fe6a5 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 20 Jun 2021 08:31:42 +0200 Subject: [PATCH 44/67] handle timeinfo in newfilename and check for file existence --- README.mkd | 3 +-- src/main.c | 11 ++--------- src/stream.c | 31 ++++++++++++++++++++++++++++--- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/README.mkd b/README.mkd index e7c95b5..da3712b 100644 --- a/README.mkd +++ b/README.mkd @@ -90,10 +90,9 @@ cron example : SHELL=/bin/bash log=/HDD/log/crontab. dt=date +%Y%m%d - dow=date +%u stream=http://88.190.24.47:80 - 0 10 * * * cd /HDD; ./shoutr -u $stream -f ./$($dow)-10 -d 3580 -r 1 >> $log$($dt).log 2>&1 + 0 10 * * * cd /HDD; ./shoutr -u $stream -f ./\%u-10 -d 3580 -r 1 >> $log$($dt).log 2>&1 copy recordings in recording order : diff --git a/src/main.c b/src/main.c index 288e2c9..cf0fa96 100755 --- a/src/main.c +++ b/src/main.c @@ -129,11 +129,8 @@ int main(int argc, char *argv[]) Stream stream; stream.TA=atoi(ta); - time_t rawtime; - struct tm * timeinfo; - time (&rawtime); - timeinfo = localtime(&rawtime); - strftime(stream.basefilename,254,basefilename,timeinfo); + memset(stream.basefilename, 0, 255); + strncpy(stream.basefilename,basefilename,254); memset(stream.ext, 0, 255); strncpy(stream.ext, fileext, 254); @@ -175,10 +172,6 @@ int main(int argc, char *argv[]) err: log_close_files(); err_early: - free_stream(&stream); - free(basefilename); - free(fileext); - free(log); return ret; } diff --git a/src/stream.c b/src/stream.c index d47fe33..e06bf70 100755 --- a/src/stream.c +++ b/src/stream.c @@ -1,7 +1,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> - +#include <time.h> #include "types.h" #include "stream.h" #include "files.h" @@ -11,6 +11,7 @@ void free_stream(Stream *stream) { + plog("free_stream\n"); ICYHeader *header = &stream->header; free(header->buffer); header->ptr= NULL; @@ -118,15 +119,39 @@ char* stristr(const char* haystack, const char* needle) { return 0; } +int exists(const char *fname) +{ + FILE *file; + if ((file = fopen(fname, "r"))) + { + fclose(file); + return 1; + } + return 0; +} void newfilename(Stream* stream, const char* title) { const int size=255+1+3+1+500+1+255; char filename[size]; + time_t rawtime; + struct tm * timeinfo; + time (&rawtime); + timeinfo = localtime(&rawtime); + char basefilename[255]; + strftime(basefilename,254,stream->basefilename,timeinfo); if (title==NULL||strlen(title)==0) { - snprintf(filename,size,"%s.%03d.%s", stream->basefilename, stream->metadata_count, stream->ext); + snprintf(filename,size,"%s.%03d.%s", basefilename, stream->metadata_count, stream->ext); + while (1 == exists(filename)) { + stream->metadata_count++; + snprintf(filename,size,"%s.%03d.%s", basefilename, stream->metadata_count, stream->ext); + } } else { - snprintf(filename,size,"%s.%03d.%s.%s", stream->basefilename, stream->metadata_count, title, stream->ext); + snprintf(filename,size,"%s.%03d.%s.%s", basefilename, stream->metadata_count, title, stream->ext); + while (1 == exists(filename)) { + stream->metadata_count++; + snprintf(filename,size,"%s.%03d.%s.%s", basefilename, stream->metadata_count, title, stream->ext); + } } if (stream->onlytitle!=NULL&&strlen(stream->onlytitle)!=0) { char str[255]; From 9cdee55e3d32136af27fdb3bdd845861e69f11aa Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 17 Oct 2021 08:56:21 +0200 Subject: [PATCH 45/67] fix log date --- src/log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/log.c b/src/log.c index 1e0c726..9673de3 100644 --- a/src/log.c +++ b/src/log.c @@ -44,7 +44,7 @@ static int get_date(char *string) time (&rawtime); timeinfo = localtime(&rawtime); - sprintf(string, "%02d", timeinfo->tm_mday); + sprintf(string, "%03d", timeinfo->tm_yday+1); return 0; } From 3070d836cbac0a0c13fe70e47946093a0d2a6a5e Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 17 Oct 2021 09:51:47 +0200 Subject: [PATCH 46/67] handle no title to match --- src/stream.c | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/stream.c b/src/stream.c index e06bf70..aae1535 100755 --- a/src/stream.c +++ b/src/stream.c @@ -153,31 +153,35 @@ void newfilename(Stream* stream, const char* title) snprintf(filename,size,"%s.%03d.%s.%s", basefilename, stream->metadata_count, title, stream->ext); } } - if (stream->onlytitle!=NULL&&strlen(stream->onlytitle)!=0) { - char str[255]; - strncpy(str, stream->onlytitle, 255); - int title_found = 0; - char* token=strtok(str,","); - if (token) { - while (token) { - if(stristr(title, token)!=NULL) { - title_found = 1; + if (title==NULL||strlen(title)==0) { + // don't search for title match if no title to match + } else { + if (stream->onlytitle!=NULL&&strlen(stream->onlytitle)!=0) { + char str[255]; + strncpy(str, stream->onlytitle, 255); + int title_found = 0; + char* token=strtok(str,","); + if (token) { + while (token) { + if(stristr(title, token)!=NULL) { + title_found = 1; + } + token=strtok(NULL,","); } - token=strtok(NULL,","); + } else { + if(stristr(title, stream->onlytitle)!=NULL) { + title_found = 1; + } } - } else { - if(stristr(title, stream->onlytitle)!=NULL) { - title_found = 1; - } - } - if (title_found == 0) { + if (title_found == 0) { snprintf(filename,size,"%s","/dev/null"); - } else { - stream->metadata_count++; + } else { + stream->metadata_count++; + } + } else { + stream->metadata_count++; } - } else { - stream->metadata_count++; - } +} filename[254]='\0'; if (stream->output_stream != NULL) fclose(stream->output_stream); stream->output_stream = fopen(filename, "wb"); From 4a3b96c6fc1131a0aa470f895feb7ac9cee326e0 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Fri, 17 Dec 2021 18:31:16 +0100 Subject: [PATCH 47/67] fix metaint not found result in disfunction --- Makefile | 2 +- src/curl.c | 2 +- src/header.c | 4 ++-- src/icy-string.c | 5 ++--- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 7d03136..2894362 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ OBJ = $(SRC:src/%.c=$(BUILD_PATH)/%.o) INCLUDES = -Iinclude \ -I/usr/include -CFLAGS = -W -Wall -g +CFLAGS = -W -Wall -g -D_GNU_SOURCE LDFLAGS = -L/usr/lib -lcurl -ltag_c all: prepare $(EXEC) diff --git a/src/curl.c b/src/curl.c index 0b4cf2f..7b7ce58 100755 --- a/src/curl.c +++ b/src/curl.c @@ -115,7 +115,7 @@ int read_stream(Stream *stream) curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 60L); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, 102400L); + curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, CURL_MAX_READ_SIZE); curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 30000L); curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/7.64.0"); curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L); diff --git a/src/header.c b/src/header.c index aa4247b..d68722f 100644 --- a/src/header.c +++ b/src/header.c @@ -29,14 +29,14 @@ int header_listener(Stream *stream, char *buffer) if (header->metaint == 0) { printf("Error : Couldn't find metaint information\n"); } else { - print_header(header); + stream->status = E_STATUS_MP3DATA; } + print_header(header); // TODO init_for_mp3data(stream) ? stream->bytes_count = 0; stream->bytes_count_total = 0; // TODO : Commenter stream->mp3data.size = 0; - stream->status = E_STATUS_MP3DATA; } else { header->ptr++; diff --git a/src/icy-string.c b/src/icy-string.c index 65f2d07..1a5bc65 100644 --- a/src/icy-string.c +++ b/src/icy-string.c @@ -2,7 +2,6 @@ #include <stdlib.h> #include <string.h> #include "types.h" - #include "icy-string.h" int extract_header_fields(ICYHeader *header) @@ -28,7 +27,7 @@ int get_http_header_field(char *header, const char* field, char* value) char *occurrence = NULL; int content_pos = 0; - occurrence = strstr(header, field); + occurrence = strcasestr(header, field); content_pos = strlen(field)+1; if (occurrence != NULL) { for (i=content_pos; occurrence[i] != '\0';i++) { @@ -52,7 +51,7 @@ int get_metadata_field(char *metadata, const char* field, char* value) char *occurrence = NULL; split = strtok (metadata,";"); while (split != NULL) { - occurrence = strstr(split, field); + occurrence = strcasestr(split, field); if (occurrence != NULL) { unsigned int content_pos = strlen(field)+2; unsigned int content_size = strlen(split)-content_pos-1; From 2790b33cdf33004ee986a2ca05c0638ec1dba1f7 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Mon, 18 Apr 2022 13:44:04 +0200 Subject: [PATCH 48/67] use strstr iso strtok and add album tag --- src/metadata.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/metadata.c b/src/metadata.c index 05426a1..80da878 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -123,24 +123,22 @@ int metadata_body_handler(Stream *stream, char *buffer) if (tag != NULL) { taglib_tag_set_comment(tag, oldtitle); - char* token=strtok(oldtitle,"-"); - if (stream->TA == 0) { - if (token) { - taglib_tag_set_title(tag,token); - token=strtok(NULL,"-"); - } - if (token) { - taglib_tag_set_artist(tag,token); - } - } else { - if (token) { - taglib_tag_set_artist(tag,token); - token=strtok(NULL,"-"); - } - if (token) { - taglib_tag_set_title(tag,token); - } - } + char * const sep_at = strstr(oldtitle, " - "); + if (sep_at != NULL) { + *sep_at='\0'; + char* title; + char* artist; + if (stream->TA == 0) { + title = oldtitle; + artist = sep_at+3; + } else { + artist = oldtitle; + title = sep_at+3; + } + taglib_tag_set_title(tag,title); + taglib_tag_set_album(tag,title); + taglib_tag_set_artist(tag,artist); + } taglib_file_save(media_file); } taglib_tag_free_strings(); From 04d2fab09788a5210d677e6e444435dafa2a7ca1 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Mon, 18 Apr 2022 14:03:41 +0200 Subject: [PATCH 49/67] spaces to tabs --- src/metadata.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/metadata.c b/src/metadata.c index 80da878..a3329bc 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -61,19 +61,19 @@ int metadata_header_handler(Stream *stream, char *buffer) void removechar( char str[], unsigned int i ) { - for (unsigned int j=i; j<strlen(str)-2; j++) - str[j]=str[j+1]; - str[strlen(str)-1]='\0'; + for (unsigned int j=i; j<strlen(str)-2; j++) + str[j]=str[j+1]; + str[strlen(str)-1]='\0'; } void rtrim(char str[]) { - const char *seps = "\t\n\v\f\r "; - int i = strlen(str) - 1; - while (i >= 0 && strchr(seps, str[i]) != NULL) { - str[i] = '\0'; - i--; - } + const char *seps = "\t\n\v\f\r "; + int i = strlen(str) - 1; + while (i >= 0 && strchr(seps, str[i]) != NULL) { + str[i] = '\0'; + i--; + } } int metadata_body_handler(Stream *stream, char *buffer) @@ -89,11 +89,11 @@ int metadata_body_handler(Stream *stream, char *buffer) stream_title[499]='\0'; metadata_content[499]='\0'; // filter problematic characters from StreamTitle - for (unsigned int i =0; i < MIN(metadata->size,500); i++) { + for (unsigned int i =0; i < MIN(metadata->size,500); i++) { if (stream_title[i]=='\0') { break;} //done stream_title[i]=ascii[(int)stream_title[i]]; } - rtrim(stream_title); + rtrim(stream_title); if (0 != strncmp(stream->stream_title, stream_title, 500)) { plog("stream_title: [%s]\n", stream_title); @@ -124,21 +124,21 @@ int metadata_body_handler(Stream *stream, char *buffer) { taglib_tag_set_comment(tag, oldtitle); char * const sep_at = strstr(oldtitle, " - "); - if (sep_at != NULL) { - *sep_at='\0'; - char* title; - char* artist; - if (stream->TA == 0) { - title = oldtitle; - artist = sep_at+3; - } else { - artist = oldtitle; - title = sep_at+3; - } - taglib_tag_set_title(tag,title); + if (sep_at != NULL) { + *sep_at='\0'; + char* title; + char* artist; + if (stream->TA == 0) { + title = oldtitle; + artist = sep_at+3; + } else { + artist = oldtitle; + title = sep_at+3; + } + taglib_tag_set_title(tag,title); taglib_tag_set_album(tag,title); taglib_tag_set_artist(tag,artist); - } + } taglib_file_save(media_file); } taglib_tag_free_strings(); From aa6f38b2241761eb42dcc2e19e85041480644cdf Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 1 May 2022 21:30:52 +0200 Subject: [PATCH 50/67] metadata update with newfilename --- src/metadata.c | 47 -------------- src/stream.c | 163 +++++++++++++++++++++++++++++++------------------ 2 files changed, 103 insertions(+), 107 deletions(-) diff --git a/src/metadata.c b/src/metadata.c index a3329bc..9e54769 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -6,7 +6,6 @@ #include "types.h" #include "metadata.h" #include "icy-string.h" -#include <taglib/tag_c.h> #include "log.h" @@ -97,53 +96,7 @@ int metadata_body_handler(Stream *stream, char *buffer) if (0 != strncmp(stream->stream_title, stream_title, 500)) { plog("stream_title: [%s]\n", stream_title); - - - char ext[3]; - strncpy(ext, stream->ext, 3); - char oldfilename[255]; - char oldtitle[500]; - strncpy(oldfilename,stream->filename, 255); - strncpy(oldtitle,stream->stream_title, 500); - newfilename(stream, stream_title); - - taglib_set_strings_unicode(FALSE); - TagLib_File *media_file; - - if (strncmp(ext,"aac",3) == 0) - { - media_file = taglib_file_new_type(oldfilename, TagLib_File_MP4); - } else { - media_file = taglib_file_new(oldfilename); - } - if (media_file != NULL) - { - TagLib_Tag *tag = taglib_file_tag(media_file); - if (tag != NULL) - { - taglib_tag_set_comment(tag, oldtitle); - char * const sep_at = strstr(oldtitle, " - "); - if (sep_at != NULL) { - *sep_at='\0'; - char* title; - char* artist; - if (stream->TA == 0) { - title = oldtitle; - artist = sep_at+3; - } else { - artist = oldtitle; - title = sep_at+3; - } - taglib_tag_set_title(tag,title); - taglib_tag_set_album(tag,title); - taglib_tag_set_artist(tag,artist); - } - taglib_file_save(media_file); - } - taglib_tag_free_strings(); - taglib_file_free(media_file); - } } } // slog metadata_content diff --git a/src/stream.c b/src/stream.c index aae1535..6a03479 100755 --- a/src/stream.c +++ b/src/stream.c @@ -8,6 +8,7 @@ #include "pls.h" #include "curl.h" #include "log.h" +#include <taglib/tag_c.h> void free_stream(Stream *stream) { @@ -132,65 +133,107 @@ int exists(const char *fname) void newfilename(Stream* stream, const char* title) { - const int size=255+1+3+1+500+1+255; - char filename[size]; - time_t rawtime; - struct tm * timeinfo; - time (&rawtime); - timeinfo = localtime(&rawtime); - char basefilename[255]; - strftime(basefilename,254,stream->basefilename,timeinfo); - if (title==NULL||strlen(title)==0) { - snprintf(filename,size,"%s.%03d.%s", basefilename, stream->metadata_count, stream->ext); - while (1 == exists(filename)) { - stream->metadata_count++; - snprintf(filename,size,"%s.%03d.%s", basefilename, stream->metadata_count, stream->ext); - } - } else { - snprintf(filename,size,"%s.%03d.%s.%s", basefilename, stream->metadata_count, title, stream->ext); - while (1 == exists(filename)) { - stream->metadata_count++; - snprintf(filename,size,"%s.%03d.%s.%s", basefilename, stream->metadata_count, title, stream->ext); - } - } - if (title==NULL||strlen(title)==0) { - // don't search for title match if no title to match - } else { - if (stream->onlytitle!=NULL&&strlen(stream->onlytitle)!=0) { - char str[255]; - strncpy(str, stream->onlytitle, 255); - int title_found = 0; - char* token=strtok(str,","); - if (token) { - while (token) { - if(stristr(title, token)!=NULL) { - title_found = 1; - } - token=strtok(NULL,","); - } - } else { - if(stristr(title, stream->onlytitle)!=NULL) { - title_found = 1; - } - } - if (title_found == 0) { - snprintf(filename,size,"%s","/dev/null"); - } else { - stream->metadata_count++; - } - } else { - stream->metadata_count++; - } -} - filename[254]='\0'; - if (stream->output_stream != NULL) fclose(stream->output_stream); - stream->output_stream = fopen(filename, "wb"); - strncpy(stream->filename, filename, 255); - if (title==NULL||strlen(title)==0) { - stream->stream_title[0]='\0'; - } else { - strncpy(stream->stream_title, title, 500); - } - plog("newfilename: %s\n", filename); + const int size=255+1+3+1+500+1+255; + char filename[size]; + time_t rawtime; + struct tm * timeinfo; + time (&rawtime); + timeinfo = localtime(&rawtime); + char basefilename[255]; + strftime(basefilename,254,stream->basefilename,timeinfo); + if (title==NULL||strlen(title)==0) { + snprintf(filename,size,"%s.%03d.%s", basefilename, stream->metadata_count, stream->ext); + while (1 == exists(filename)) { + stream->metadata_count++; + snprintf(filename,size,"%s.%03d.%s", basefilename, stream->metadata_count, stream->ext); + } + } else { + snprintf(filename,size,"%s.%03d.%s.%s", basefilename, stream->metadata_count, title, stream->ext); + while (1 == exists(filename)) { + stream->metadata_count++; + snprintf(filename,size,"%s.%03d.%s.%s", basefilename, stream->metadata_count, title, stream->ext); + } + } + if (title==NULL||strlen(title)==0) { + // don't search for title match if no title to match + } else { + if (stream->onlytitle!=NULL&&strlen(stream->onlytitle)!=0) { + char str[255]; + strncpy(str, stream->onlytitle, 255); + int title_found = 0; + char* token=strtok(str,","); + if (token) { + while (token) { + if(stristr(title, token)!=NULL) { + title_found = 1; + } + token=strtok(NULL,","); + } + } else { + if(stristr(title, stream->onlytitle)!=NULL) { + title_found = 1; + } + } + if (title_found == 0) { + snprintf(filename,size,"%s","/dev/null"); + } else { + stream->metadata_count++; + } + } else { + stream->metadata_count++; + } + } + filename[254]='\0'; + + char ext[3]; + strncpy(ext, stream->ext, 3); + char oldfilename[255]; + char oldtitle[500]; + strncpy(oldfilename,stream->filename, 255); + strncpy(oldtitle,stream->stream_title, 500); + + if (stream->output_stream != NULL) fclose(stream->output_stream); + stream->output_stream = fopen(filename, "wb"); + strncpy(stream->filename, filename, 255); + if (title==NULL||strlen(title)==0) { + stream->stream_title[0]='\0'; + } else { + strncpy(stream->stream_title, title, 500); + } + + taglib_set_strings_unicode(FALSE); + TagLib_File *media_file; + if (strncmp(ext,"aac",3) == 0) { + media_file = taglib_file_new_type(oldfilename, TagLib_File_MP4); + } else { + media_file = taglib_file_new(oldfilename); + } + if (media_file != NULL) { + TagLib_Tag *tag = taglib_file_tag(media_file); + if (tag != NULL) { + taglib_tag_set_comment(tag, oldtitle); + char * const sep_at = strstr(oldtitle, " - "); + if (sep_at != NULL) { + *sep_at='\0'; + char* title; + char* artist; + if (stream->TA == 0) { + title = oldtitle; + artist = sep_at+3; + } else { + artist = oldtitle; + title = sep_at+3; + } + taglib_tag_set_title(tag,title); + taglib_tag_set_album(tag,title); + taglib_tag_set_artist(tag,artist); + } + taglib_file_save(media_file); + } + taglib_tag_free_strings(); + taglib_file_free(media_file); + } + + plog("newfilename: %s\n", filename); } From e4e7e303e63233d75020ca110c7204fa4a8a1e02 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 8 May 2022 10:06:18 +0200 Subject: [PATCH 51/67] change default artist - title --- src/curl.c | 2 +- src/main.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/curl.c b/src/curl.c index 7b7ce58..3b6920d 100755 --- a/src/curl.c +++ b/src/curl.c @@ -138,7 +138,7 @@ int read_stream(Stream *stream) time_t start_t, end_t; time(&start_t); uint seconds_elapsed = 0; - uint duration=stream->duration*(1+stream->repeat); + uint duration=5+stream->duration*(1+stream->repeat);// add 5 seconds to enforce newfile before timeout do { curl_easy_setopt(curl, CURLOPT_TIMEOUT, duration-seconds_elapsed); curl_res = curl_easy_perform(curl); diff --git a/src/main.c b/src/main.c index cf0fa96..b4bd8fc 100755 --- a/src/main.c +++ b/src/main.c @@ -27,7 +27,7 @@ void usage(void) printf("\t-d\t: recording duration (in seconds)\n"); printf("\t-e\t: fileextension (default mp3)\n"); printf("\t-f\t: basefilename (default radio)\n"); - printf("\t-i\t: title - artist (0, default) or artist - title (1)\n"); + printf("\t-i\t: title - artist (0) or artist - title (1, default)\n"); printf("\t-l\t: logfolder (default current folder)\n"); printf("\t-n\t: name of station (default radio)\n"); printf("\t-r\t: recording repeats (default 0 = none)\n"); @@ -49,7 +49,7 @@ int main(int argc, char *argv[]) char *proxy = NULL; char *duration = "0"; char *repeat = "0"; - char *ta = "0"; + char *ta = "1"; char* basefilename = (char*) malloc(255*sizeof(char)); sprintf(basefilename, "radio"); From a0f3d586f19a62c1e09c96e25f90a5fef07aade0 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 8 May 2022 10:09:07 +0200 Subject: [PATCH 52/67] update readme --- README.mkd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.mkd b/README.mkd index da3712b..c8994ee 100644 --- a/README.mkd +++ b/README.mkd @@ -51,7 +51,7 @@ OPTIONS: -d duration defines the recording length in seconds (see CURLOPT_TIMEOUT) -e extension fileextension (default: mp3) -f basefilename defines the base name of the mp3 file(s) created (default: radio) - -i id3tags split stream_title (on '-') into artist - title (default, 0) or title - artist (1) + -i id3tags split stream_title (on ' - ') into artist - title (0) or title - artist (1, default) -l logfolder (rel/abs) path to folder for log (default: current folder) -n name name of station (default radio) -r repeat repeat the recording specified number of times From af33895e20b6725a8cea0d0cc63fb0e2b14f8c27 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Thu, 21 Jul 2022 20:53:35 +0200 Subject: [PATCH 53/67] prevent duplicate prefixes --- src/curl.c | 13 +- src/files.c | 36 ++--- src/header.c | 82 ++++++------ src/icy-string.c | 126 +++++++++--------- src/log.c | 152 ++++++++++----------- src/main.c | 334 +++++++++++++++++++++++------------------------ src/metadata.c | 144 ++++++++++---------- src/mp3data.c | 34 ++--- src/pls.c | 194 +++++++++++++-------------- src/shoutcast.c | 28 ++-- src/stream.c | 327 ++++++++++++++++++++++++---------------------- 11 files changed, 744 insertions(+), 726 deletions(-) diff --git a/src/curl.c b/src/curl.c index 3b6920d..79e52d1 100755 --- a/src/curl.c +++ b/src/curl.c @@ -3,6 +3,7 @@ #include <time.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "types.h" #include "parsing.h" #include "log.h" @@ -138,22 +139,26 @@ int read_stream(Stream *stream) time_t start_t, end_t; time(&start_t); uint seconds_elapsed = 0; - uint duration=5+stream->duration*(1+stream->repeat);// add 5 seconds to enforce newfile before timeout + uint duration=1+stream->duration*(1+stream->repeat);// add 1 second to enforce newfile before timeout do { curl_easy_setopt(curl, CURLOPT_TIMEOUT, duration-seconds_elapsed); curl_res = curl_easy_perform(curl); - if (curl_res != CURLE_OK && curl_res != CURLE_OPERATION_TIMEDOUT && curl_res != CURLE_RECV_ERROR) { + if (curl_res == CURLE_OK || curl_res == CURLE_OPERATION_TIMEDOUT || curl_res == CURLE_RECV_ERROR) { + // expected curl_res + } else { + // unexpected curl_res time(&now); info = localtime( &now ); strftime(buffer,80,"%T", info); printf("%s ERROR %2d: %s\n", buffer, curl_res, curl_easy_strerror(curl_res)); ret = -1; - goto err; +// goto err; // not error out in such a case? + sleep(60); // one minute } time(&end_t); seconds_elapsed=(uint)difftime(end_t, start_t); } while(seconds_elapsed < duration); -err: +//err: curl_slist_free_all(headers); curl_easy_cleanup(curl); early_err: diff --git a/src/files.c b/src/files.c index 3aa0bf3..d4d4a64 100644 --- a/src/files.c +++ b/src/files.c @@ -6,34 +6,34 @@ int get_extension(char *extension, char *string) { - char *pstr = NULL; + char *pstr = NULL; - if (string == NULL) - return -1; + if (string == NULL) + return -1; - pstr = strrchr(string, '.'); - if (pstr == NULL) { - strcpy(extension, ""); - return -1; - } + pstr = strrchr(string, '.'); + if (pstr == NULL) { + strcpy(extension, ""); + return -1; + } - strcpy(extension, pstr+1); + strcpy(extension, pstr+1); - return 0; + return 0; } int is_pls_extension(char *string) { - char extension[10]; + char extension[10]; - if (string == NULL) - return FALSE; + if (string == NULL) + return FALSE; - get_extension(extension, string); + get_extension(extension, string); - if (!strcmp(extension, "pls")) - return TRUE; - else - return FALSE; + if (!strcmp(extension, "pls")) + return TRUE; + else + return FALSE; } diff --git a/src/header.c b/src/header.c index d68722f..0e5c151 100644 --- a/src/header.c +++ b/src/header.c @@ -10,60 +10,60 @@ int header_listener(Stream *stream, char *buffer) { - ICYHeader *header; - if (!is_header(stream)) - return 1; + ICYHeader *header; + if (!is_header(stream)) + return 1; - header = &stream->header; + header = &stream->header; - if (stream->bytes_count_total >= HEADER_MAX) { - printf("Error : couldn't retrieve server information.\n"); - exit(-1); - } + if (stream->bytes_count_total >= HEADER_MAX) { + printf("Error : couldn't retrieve server information.\n"); + exit(-1); + } - *header->ptr = *buffer; + *header->ptr = *buffer; - if (is_end_of_http_header(header)) { - extract_header_fields(header); + if (is_end_of_http_header(header)) { + extract_header_fields(header); - if (header->metaint == 0) { - printf("Error : Couldn't find metaint information\n"); - } else { - stream->status = E_STATUS_MP3DATA; - } - print_header(header); + if (header->metaint == 0) { + printf("Error : Couldn't find metaint information\n"); + } else { + stream->status = E_STATUS_MP3DATA; + } + print_header(header); - // TODO init_for_mp3data(stream) ? - stream->bytes_count = 0; - stream->bytes_count_total = 0; // TODO : Commenter - stream->mp3data.size = 0; - } - else { - header->ptr++; - } - return 0; + // TODO init_for_mp3data(stream) ? + stream->bytes_count = 0; + stream->bytes_count_total = 0; // TODO : Commenter + stream->mp3data.size = 0; + } + else { + header->ptr++; + } + return 0; } int is_header(Stream *stream) { - if (stream->status == E_STATUS_HEADER){ - return TRUE; + if (stream->status == E_STATUS_HEADER){ + return TRUE; - } else { - return FALSE; - } + } else { + return FALSE; + } } int print_header(ICYHeader *header) { - printf("##################################\n"); - printf("Name\t: %s\n", header->icy_name); - printf("icy-notice1\t: %s\n", header->icy_notice1); - printf("icy-notice2\t: %s\n", header->icy_notice2); - printf("Genre\t: %s\n", header->icy_genre); - //printf("Public\t: %s\n", (header->icy_pub?"yes":"no")); - printf("Bitrate : %s kbit/s\n", header->icy_br); - printf("metaint\t: %d\n", header->metaint); - printf("##################################\n"); - return 0; + printf("##################################\n"); + printf("Name\t: %s\n", header->icy_name); + printf("icy-notice1\t: %s\n", header->icy_notice1); + printf("icy-notice2\t: %s\n", header->icy_notice2); + printf("Genre\t: %s\n", header->icy_genre); + //printf("Public\t: %s\n", (header->icy_pub?"yes":"no")); + printf("Bitrate : %s kbit/s\n", header->icy_br); + printf("metaint\t: %d\n", header->metaint); + printf("##################################\n"); + return 0; } diff --git a/src/icy-string.c b/src/icy-string.c index 1a5bc65..c2242b3 100644 --- a/src/icy-string.c +++ b/src/icy-string.c @@ -6,87 +6,87 @@ int extract_header_fields(ICYHeader *header) { - char metaint[20]; - get_http_header_field(header->buffer, "icy-name", header->icy_name); - get_http_header_field(header->buffer, "icy-notice1", header->icy_notice1); - get_http_header_field(header->buffer, "icy-notice2", header->icy_notice2); - get_http_header_field(header->buffer, "icy-genre", header->icy_genre); - get_http_header_field(header->buffer, "icy-pub", header->icy_pub); - get_http_header_field(header->buffer, "icy-br", header->icy_br); - if(0==get_http_header_field(header->buffer, "icy-metaint", metaint)){ - header->metaint = atoi(metaint); - } else { - header->metaint = 0; - } - return 0; + char metaint[20]; + get_http_header_field(header->buffer, "icy-name", header->icy_name); + get_http_header_field(header->buffer, "icy-notice1", header->icy_notice1); + get_http_header_field(header->buffer, "icy-notice2", header->icy_notice2); + get_http_header_field(header->buffer, "icy-genre", header->icy_genre); + get_http_header_field(header->buffer, "icy-pub", header->icy_pub); + get_http_header_field(header->buffer, "icy-br", header->icy_br); + if(0==get_http_header_field(header->buffer, "icy-metaint", metaint)){ + header->metaint = atoi(metaint); + } else { + header->metaint = 0; + } + return 0; } int get_http_header_field(char *header, const char* field, char* value) { - int i; - char *occurrence = NULL; - int content_pos = 0; + int i; + char *occurrence = NULL; + int content_pos = 0; - occurrence = strcasestr(header, field); - content_pos = strlen(field)+1; - if (occurrence != NULL) { - for (i=content_pos; occurrence[i] != '\0';i++) { - if (is_cr_present(occurrence, i)) { - // "<field>:" is deleted - strncpy(value, occurrence+content_pos, i-content_pos); - value[i-content_pos-1] = '\0'; - return 0; - } - } - } - // Value hasn't been found - value[0] = '\0'; - return 1; + occurrence = strcasestr(header, field); + content_pos = strlen(field)+1; + if (occurrence != NULL) { + for (i=content_pos; occurrence[i] != '\0';i++) { + if (is_cr_present(occurrence, i)) { + // "<field>:" is deleted + strncpy(value, occurrence+content_pos, i-content_pos); + value[i-content_pos-1] = '\0'; + return 0; + } + } + } + // Value hasn't been found + value[0] = '\0'; + return 1; } int get_metadata_field(char *metadata, const char* field, char* value) { - char *split; - char *occurrence = NULL; - split = strtok (metadata,";"); - while (split != NULL) { - occurrence = strcasestr(split, field); - if (occurrence != NULL) { - unsigned int content_pos = strlen(field)+2; - unsigned int content_size = strlen(split)-content_pos-1; - strncpy(value, occurrence+content_pos, content_size); - value[content_size] = '\0'; - return 0; - } - split = strtok (NULL,";"); - } - // Value hasn't been found - value[0]='\0'; - return 1; + char *split; + char *occurrence = NULL; + split = strtok (metadata,";"); + while (split != NULL) { + occurrence = strcasestr(split, field); + if (occurrence != NULL) { + unsigned int content_pos = strlen(field)+2; + unsigned int content_size = strlen(split)-content_pos-1; + strncpy(value, occurrence+content_pos, content_size); + value[content_size] = '\0'; + return 0; + } + split = strtok (NULL,";"); + } + // Value hasn't been found + value[0]='\0'; + return 1; } int is_cr_present(char *str, int pos) { - if (str[pos-1] == '\r' && str[pos] == '\n') - return TRUE; - else - return FALSE; + if (str[pos-1] == '\r' && str[pos] == '\n') + return TRUE; + else + return FALSE; } int is_end_of_http_header(ICYHeader *header) { - unsigned int buffer_size = 0; - buffer_size = header->ptr - header->buffer + 1; + unsigned int buffer_size = 0; + buffer_size = header->ptr - header->buffer + 1; - if (buffer_size < 4) - return FALSE; + if (buffer_size < 4) + return FALSE; - if (*(header->ptr-3) == '\r' && - *(header->ptr-2) == '\n' && - *(header->ptr-1) == '\r' && - *(header->ptr) == '\n') - return TRUE; - else - return FALSE; + if (*(header->ptr-3) == '\r' && + *(header->ptr-2) == '\n' && + *(header->ptr-1) == '\r' && + *(header->ptr) == '\n') + return TRUE; + else + return FALSE; } diff --git a/src/log.c b/src/log.c index 9673de3..eb4fda6 100644 --- a/src/log.c +++ b/src/log.c @@ -14,115 +14,115 @@ static char tempfile[270]; static int get_time(char *string) { - time_t rawtime; - struct tm *timeinfo; - - if (string == NULL) - return -1; - - time (&rawtime); - timeinfo = localtime(&rawtime); - - sprintf(string, "%d:%02d:%02d-%02d:%02d:%02d ", 1900+timeinfo->tm_year, - timeinfo->tm_mon+1, - timeinfo->tm_mday, - timeinfo->tm_hour, - timeinfo->tm_min, - timeinfo->tm_sec); - - return 0; + time_t rawtime; + struct tm *timeinfo; + + if (string == NULL) + return -1; + + time (&rawtime); + timeinfo = localtime(&rawtime); + + sprintf(string, "%d:%02d:%02d-%02d:%02d:%02d ", 1900+timeinfo->tm_year, + timeinfo->tm_mon+1, + timeinfo->tm_mday, + timeinfo->tm_hour, + timeinfo->tm_min, + timeinfo->tm_sec); + + return 0; } static int get_date(char *string) { - time_t rawtime; - struct tm *timeinfo; - - if (string == NULL) - return -1; + time_t rawtime; + struct tm *timeinfo; + + if (string == NULL) + return -1; - time (&rawtime); - timeinfo = localtime(&rawtime); + time (&rawtime); + timeinfo = localtime(&rawtime); - sprintf(string, "%03d", timeinfo->tm_yday+1); + sprintf(string, "%03d", timeinfo->tm_yday+1); - return 0; + return 0; } int log_open_files(char* folder) { - if (fp_log != NULL) - return -1; - - if( get_date(current_date) <0) { - printf("Couldn't get date"); - return -1; - } - struct stat st; - if (stat(folder, &st) != 0) - { - mkdir(folder, 0777); - } - snprintf(tempfile,270,"%s/shoutr.%s.log",folder,current_date); - fp_log = fopen(tempfile,"a"); - if (fp_log == NULL) { - printf("Couldn't open shoutr.log file\n"); - return -1; - } - - return 0; + if (fp_log != NULL) + return -1; + + if( get_date(current_date) <0) { + printf("Couldn't get date"); + return -1; + } + struct stat st; + if (stat(folder, &st) != 0) + { + mkdir(folder, 0777); + } + snprintf(tempfile,270,"%s/shoutr.%s.log",folder,current_date); + fp_log = fopen(tempfile,"a"); + if (fp_log == NULL) { + printf("Couldn't open shoutr.log file\n"); + return -1; + } + + return 0; } int log_close_files(void) { - if (fclose(fp_log) == EOF) - return EOF; + if (fclose(fp_log) == EOF) + return EOF; - return 0; + return 0; } static int log_append(FILE *fp, char *line) { - if (fp == NULL || line == NULL) - return -1; + if (fp == NULL || line == NULL) + return -1; - if (get_time(current_time) < 0) - return -1; + if (get_time(current_time) < 0) + return -1; - if (fputs(current_time, fp) == EOF) - return EOF; + if (fputs(current_time, fp) == EOF) + return EOF; - if (fputs(line, fp) == EOF) - return EOF; + if (fputs(line, fp) == EOF) + return EOF; - if (fputc('\n', fp) == EOF) - return EOF; + if (fputc('\n', fp) == EOF) + return EOF; - if (fflush(fp) == EOF) - return EOF; - else - return 0; + if (fflush(fp) == EOF) + return EOF; + else + return 0; } void slog(char *line) { - if (log_append(fp_log, line) < 0) - printf("Coudln't write shoutr log\n"); + if (log_append(fp_log, line) < 0) + printf("Coudln't write shoutr log\n"); } void printCurrentTime() { - struct timeval curTime; - gettimeofday(&curTime, NULL); - int milli = curTime.tv_usec / 1000; - char buffr [80]; - strftime(buffr, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); - printf("%s.%03d ", buffr, milli); + struct timeval curTime; + gettimeofday(&curTime, NULL); + int milli = curTime.tv_usec / 1000; + char buffr [80]; + strftime(buffr, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); + printf("%s.%03d ", buffr, milli); } void plog(char *fmt, ...) { - printCurrentTime(); - va_list ap; - va_start(ap, fmt); - vprintf(fmt, ap); - va_end(ap); + printCurrentTime(); + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); } diff --git a/src/main.c b/src/main.c index b4bd8fc..91a0d22 100755 --- a/src/main.c +++ b/src/main.c @@ -22,202 +22,202 @@ int load_stream_from_playlist(Stream *stream, char *filename); void usage(void) { - printf("Usage: shoutr [-p <playlist>|-u <stream_url>] [OPTIONS]\n"); - printf("options:\n"); - printf("\t-d\t: recording duration (in seconds)\n"); - printf("\t-e\t: fileextension (default mp3)\n"); - printf("\t-f\t: basefilename (default radio)\n"); - printf("\t-i\t: title - artist (0) or artist - title (1, default)\n"); - printf("\t-l\t: logfolder (default current folder)\n"); - printf("\t-n\t: name of station (default radio)\n"); - printf("\t-r\t: recording repeats (default 0 = none)\n"); - printf("\t-t\t: title to record (default any)\n"); - printf("\t-x\t: proxy (default no proxy)\n"); + printf("Usage: shoutr [-p <playlist>|-u <stream_url>] [OPTIONS]\n"); + printf("options:\n"); + printf("\t-d\t: recording duration (in seconds)\n"); + printf("\t-e\t: fileextension (default mp3)\n"); + printf("\t-f\t: basefilename (default radio)\n"); + printf("\t-i\t: title - artist (0) or artist - title (1, default)\n"); + printf("\t-l\t: logfolder (default current folder)\n"); + printf("\t-n\t: name of station (default radio)\n"); + printf("\t-r\t: recording repeats (default 0 = none)\n"); + printf("\t-t\t: title to record (default any)\n"); + printf("\t-x\t: proxy (default no proxy)\n"); } int main(int argc, char *argv[]) { - if (argc == 1) { - usage(); - return -1; - } - int ret = -1; - int pflag = 0; - int uflag = 0; - int c; - char *cvalue = NULL; - char *proxy = NULL; - char *duration = "0"; - char *repeat = "0"; - char *ta = "1"; - - char* basefilename = (char*) malloc(255*sizeof(char)); - sprintf(basefilename, "radio"); - - char* stationname = NULL; - - char* fileext = (char*) malloc(255*sizeof(char)); - sprintf(fileext, "mp3"); - - char* log = (char*) malloc(255*sizeof(char)); - sprintf(log, "."); - - char* title = NULL; - - while ((c = getopt(argc, argv, "p:u:h:x:f:e:d:r:i:l:n:t:")) != -1) { - switch(c) { - // playlist - case 'p': - pflag = 1; - cvalue = optarg; - break; - // stream url - case 'u': - uflag = 1; - cvalue = optarg; - break; - // proxy - case 'x': - proxy = optarg; - break; - // fileextension - case 'e': - fileext = optarg; - break; - // basefilename - case 'f': - basefilename = optarg; - break; - // duration - case 'd': - duration = optarg; - break; - case 'r': - repeat = optarg; - break; - case 'i': - ta = optarg; - break; - case 'l': - log = optarg; - break; - case 'n': - stationname = optarg; - break; - case 't': - title = optarg; - break; - case 'h': - default: - usage(); - goto err_early; - break; - } - } - - - if (pflag && uflag) { - usage(); - goto err_early; - } - - if ((ret = log_open_files(log)) < 0) { - printf("Couldn't open log files.\n"); - goto err_early; - } - - Stream stream; - stream.TA=atoi(ta); - - memset(stream.basefilename, 0, 255); - strncpy(stream.basefilename,basefilename,254); - - memset(stream.ext, 0, 255); - strncpy(stream.ext, fileext, 254); - - memset(stream.stream_title, 0, 255); - if (stationname != NULL) { - strncpy(stream.stream_title, stationname, 254); - } + if (argc == 1) { + usage(); + return -1; + } + int ret = -1; + int pflag = 0; + int uflag = 0; + int c; + char *cvalue = NULL; + char *proxy = NULL; + char *duration = "0"; + char *repeat = "0"; + char *ta = "1"; + + char* basefilename = (char*) malloc(255*sizeof(char)); + sprintf(basefilename, "radio"); + + char* stationname = NULL; + + char* fileext = (char*) malloc(255*sizeof(char)); + sprintf(fileext, "mp3"); + + char* log = (char*) malloc(255*sizeof(char)); + sprintf(log, "."); + + char* title = NULL; + + while ((c = getopt(argc, argv, "p:u:h:x:f:e:d:r:i:l:n:t:")) != -1) { + switch(c) { + // playlist + case 'p': + pflag = 1; + cvalue = optarg; + break; + // stream url + case 'u': + uflag = 1; + cvalue = optarg; + break; + // proxy + case 'x': + proxy = optarg; + break; + // fileextension + case 'e': + fileext = optarg; + break; + // basefilename + case 'f': + basefilename = optarg; + break; + // duration + case 'd': + duration = optarg; + break; + case 'r': + repeat = optarg; + break; + case 'i': + ta = optarg; + break; + case 'l': + log = optarg; + break; + case 'n': + stationname = optarg; + break; + case 't': + title = optarg; + break; + case 'h': + default: + usage(); + goto err_early; + break; + } + } + + + if (pflag && uflag) { + usage(); + goto err_early; + } + + if ((ret = log_open_files(log)) < 0) { + printf("Couldn't open log files.\n"); + goto err_early; + } + + Stream stream; + stream.TA=atoi(ta); + + memset(stream.basefilename, 0, 255); + strncpy(stream.basefilename,basefilename,254); + + memset(stream.ext, 0, 255); + strncpy(stream.ext, fileext, 254); + + memset(stream.stream_title, 0, 255); + if (stationname != NULL) { + strncpy(stream.stream_title, stationname, 254); + } stream.duration=atoi(duration); stream.repeat=atoi(repeat); - memset(stream.proxy, 0, 255); + memset(stream.proxy, 0, 255); if (proxy != NULL) { - strncpy(stream.proxy, proxy, 254); - } + strncpy(stream.proxy, proxy, 254); + } - memset(stream.onlytitle, 0, 255); + memset(stream.onlytitle, 0, 255); if (title != NULL) { - strncpy(stream.onlytitle, title, 254); - } + strncpy(stream.onlytitle, title, 254); + } - if (pflag) { - if ((ret = load_stream_from_playlist(&stream, cvalue)) < 0) { - printf("Couldn't load stream from playlist\n"); - goto err; - } - } + if (pflag) { + if ((ret = load_stream_from_playlist(&stream, cvalue)) < 0) { + printf("Couldn't load stream from playlist\n"); + goto err; + } + } - if (uflag) { - load_stream(&stream, cvalue); + if (uflag) { + load_stream(&stream, cvalue); - } + } - if ((ret = read_stream(&stream)) < 0) { - printf("Error : Couldn't read Shoutcast stream\n"); - goto err; - } + if ((ret = read_stream(&stream)) < 0) { + printf("Error : Couldn't read Shoutcast stream\n"); + goto err; + } err: - log_close_files(); + log_close_files(); err_early: - return ret; + return ret; } size_t parse_header(void *ptr, size_t size, size_t nmemb, void *userdata) { - unsigned int i; - char buffer; - Stream *stream = (Stream *)userdata; - size_t numbytes = size * nmemb; - - //stream->header.buffer; - //copy *ptr to header.buffer starting at header.ptr position - void* dest = stream->header.ptr; - memcpy(dest, ptr, numbytes); - - for (i=0;i<numbytes;i++) { - buffer = ((char*)ptr)[i]; - global_listener(stream, &buffer); - stream->bytes_count_total++; - } - - printf("%.*s", (int) numbytes, (char*)ptr); + unsigned int i; + char buffer; + Stream *stream = (Stream *)userdata; + size_t numbytes = size * nmemb; + + //stream->header.buffer; + //copy *ptr to header.buffer starting at header.ptr position + void* dest = stream->header.ptr; + memcpy(dest, ptr, numbytes); + + for (i=0;i<numbytes;i++) { + buffer = ((char*)ptr)[i]; + global_listener(stream, &buffer); + stream->bytes_count_total++; + } + + printf("%.*s", (int) numbytes, (char*)ptr); return numbytes; } size_t parse_data(void *ptr, size_t size, size_t nmemb, void *userdata) { - unsigned int i; - char buffer; - Stream *stream = (Stream *)userdata; - size_t numbytes = size * nmemb; + unsigned int i; + char buffer; + Stream *stream = (Stream *)userdata; + size_t numbytes = size * nmemb; - stream->mp3data.buffer = (char*) malloc(numbytes); - stream->mp3data.ptr = stream->mp3data.buffer; + stream->mp3data.buffer = (char*) malloc(numbytes); + stream->mp3data.ptr = stream->mp3data.buffer; - for (i=0;i<numbytes;i++) { - buffer = ((char*)ptr)[i]; - global_listener(stream, &buffer); - stream->bytes_count_total++; - } + for (i=0;i<numbytes;i++) { + buffer = ((char*)ptr)[i]; + global_listener(stream, &buffer); + stream->bytes_count_total++; + } - write_data(stream); - free(stream->mp3data.buffer); - stream->mp3data.size = 0; + write_data(stream); + free(stream->mp3data.buffer); + stream->mp3data.size = 0; - stream->blocks_count++; + stream->blocks_count++; - return numbytes; + return numbytes; } diff --git a/src/metadata.c b/src/metadata.c index 9e54769..f19b290 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -29,109 +29,109 @@ static char ascii[256]={'_','_','_','_','_','_','_','_','_','_','_','_','_','_', int metadata_listener(Stream *stream, char *buffer) { - if (!is_metadata(stream)) - return -1; + if (!is_metadata(stream)) + return -1; - if (is_metadata_header(stream)) - return metadata_header_handler(stream, buffer); - else if (is_metadata_body(stream)) - return metadata_body_handler(stream, buffer); + if (is_metadata_header(stream)) + return metadata_header_handler(stream, buffer); + else if (is_metadata_body(stream)) + return metadata_body_handler(stream, buffer); - return 0; + return 0; } int metadata_header_handler(Stream *stream, char *buffer) { - MetaData *metadata = &stream->metadata; + MetaData *metadata = &stream->metadata; - metadata->ptr = metadata->buffer; // Rewind - metadata->size = abs((int)*buffer) * 16; + metadata->ptr = metadata->buffer; // Rewind + metadata->size = abs((int)*buffer) * 16; - if (metadata->size == 0) { - stream->bytes_count = 0; - stream->status = E_STATUS_MP3DATA; - } - else { - stream->status = E_STATUS_METADATA_BODY; - } + if (metadata->size == 0) { + stream->bytes_count = 0; + stream->status = E_STATUS_MP3DATA; + } + else { + stream->status = E_STATUS_METADATA_BODY; + } - return 0; + return 0; } void removechar( char str[], unsigned int i ) { - for (unsigned int j=i; j<strlen(str)-2; j++) - str[j]=str[j+1]; - str[strlen(str)-1]='\0'; + for (unsigned int j=i; j<strlen(str)-2; j++) + str[j]=str[j+1]; + str[strlen(str)-1]='\0'; } void rtrim(char str[]) { - const char *seps = "\t\n\v\f\r "; - int i = strlen(str) - 1; - while (i >= 0 && strchr(seps, str[i]) != NULL) { - str[i] = '\0'; - i--; - } + const char *seps = "\t\n\v\f\r "; + int i = strlen(str) - 1; + while (i >= 0 && strchr(seps, str[i]) != NULL) { + str[i] = '\0'; + i--; + } } int metadata_body_handler(Stream *stream, char *buffer) { - MetaData *metadata = &stream->metadata; - *metadata->ptr = *buffer; - if ((unsigned)(metadata->ptr - metadata->buffer) == (metadata->size-1)) { - char metadata_content[500]=""; - char stream_title[500]=""; - strncpy(metadata_content, metadata->buffer, MIN(metadata->size,500)); - if(0==get_metadata_field(metadata_content, "StreamTitle", stream_title)) - { - stream_title[499]='\0'; - metadata_content[499]='\0'; - // filter problematic characters from StreamTitle - for (unsigned int i =0; i < MIN(metadata->size,500); i++) { - if (stream_title[i]=='\0') { break;} //done - stream_title[i]=ascii[(int)stream_title[i]]; - } - rtrim(stream_title); - if (0 != strncmp(stream->stream_title, stream_title, 500)) - { - plog("stream_title: [%s]\n", stream_title); - newfilename(stream, stream_title); - } - } - // slog metadata_content - slog(metadata_content); - - stream->bytes_count = 0; - stream->status = E_STATUS_MP3DATA; - } else { - metadata->ptr++; - } - return 0; + MetaData *metadata = &stream->metadata; + *metadata->ptr = *buffer; + if ((unsigned)(metadata->ptr - metadata->buffer) == (metadata->size-1)) { + char metadata_content[500]=""; + char stream_title[500]=""; + strncpy(metadata_content, metadata->buffer, MIN(metadata->size,500)); + if(0==get_metadata_field(metadata_content, "StreamTitle", stream_title)) + { + stream_title[499]='\0'; + metadata_content[499]='\0'; + // filter problematic characters from StreamTitle + for (unsigned int i =0; i < MIN(metadata->size,500); i++) { + if (stream_title[i]=='\0') { break;} //done + stream_title[i]=ascii[(int)stream_title[i]]; + } + rtrim(stream_title); + if (0 != strncmp(stream->stream_title, stream_title, 500)) + { + plog("stream_title: [%s]\n", stream_title); + newfilename(stream, stream_title); + } + } + // slog metadata_content + slog(metadata_content); + + stream->bytes_count = 0; + stream->status = E_STATUS_MP3DATA; + } else { + metadata->ptr++; + } + return 0; } int is_metadata(Stream *stream) { - if (is_metadata_body(stream) || is_metadata_header(stream)) - return TRUE; - else - return FALSE; + if (is_metadata_body(stream) || is_metadata_header(stream)) + return TRUE; + else + return FALSE; } int is_metadata_body(Stream *stream) { - if (stream->status == E_STATUS_METADATA_BODY){ - return TRUE; - } else { - return FALSE; - } + if (stream->status == E_STATUS_METADATA_BODY){ + return TRUE; + } else { + return FALSE; + } } int is_metadata_header(Stream *stream) { - if (stream->status == E_STATUS_METADATA_HEADER){ - return TRUE; - } else { - return FALSE; - } + if (stream->status == E_STATUS_METADATA_HEADER){ + return TRUE; + } else { + return FALSE; + } } diff --git a/src/mp3data.c b/src/mp3data.c index d2fbdce..7e1dbfc 100644 --- a/src/mp3data.c +++ b/src/mp3data.c @@ -8,29 +8,29 @@ int mp3data_listener(Stream *stream, char *buffer) { - Mp3Data *mp3data; - if (!is_mp3data(stream)) - return -1; + Mp3Data *mp3data; + if (!is_mp3data(stream)) + return -1; - mp3data = &stream->mp3data; + mp3data = &stream->mp3data; - if (mp3data->ptr == NULL) - return 0; - *mp3data->ptr = *buffer; - mp3data->size++; - mp3data->ptr++; - stream->bytes_count++; + if (mp3data->ptr == NULL) + return 0; + *mp3data->ptr = *buffer; + mp3data->size++; + mp3data->ptr++; + stream->bytes_count++; - if (stream->header.metaint > 0 && stream->bytes_count == stream->header.metaint) - stream->status = E_STATUS_METADATA_HEADER; + if (stream->header.metaint > 0 && stream->bytes_count == stream->header.metaint) + stream->status = E_STATUS_METADATA_HEADER; - return 0; + return 0; } int is_mp3data(Stream *stream) { - if (stream->status == E_STATUS_MP3DATA) - return TRUE; - else - return FALSE; + if (stream->status == E_STATUS_MP3DATA) + return TRUE; + else + return FALSE; } diff --git a/src/pls.c b/src/pls.c index 16889f0..49b525d 100755 --- a/src/pls.c +++ b/src/pls.c @@ -11,135 +11,135 @@ static int pls_get_entries(FILE *fp, PlsFile *pls); void print_pls(PlsFile *pls) { - unsigned int i; - PlsEntry *entry = pls->entries; - for (i=0;i<pls->number_entries;i++) { - printf("%2d %s\n", i, entry->file); - entry++; - } + unsigned int i; + PlsEntry *entry = pls->entries; + for (i=0;i<pls->number_entries;i++) { + printf("%2d %s\n", i, entry->file); + entry++; + } } int pls_load_file(char *filename, PlsFile *pls) { - unsigned int number_entries = 0; - //int res = 0; - FILE *fp; + unsigned int number_entries = 0; + //int res = 0; + FILE *fp; - fp = fopen(filename, "r"); + fp = fopen(filename, "r"); - if (fp == NULL) { - printf("fopen(%s) failed\n", filename); - return -1; + if (fp == NULL) { + printf("fopen(%s) failed\n", filename); + return -1; } - if (!is_pls_file(fp)) { - printf("%s is not a pls file\n", filename); - return -1; - } + if (!is_pls_file(fp)) { + printf("%s is not a pls file\n", filename); + return -1; + } - number_entries = pls_get_number_entries(fp); - init_pls_struct(pls, number_entries); - pls_get_entries(fp, pls); + number_entries = pls_get_number_entries(fp); + init_pls_struct(pls, number_entries); + pls_get_entries(fp, pls); - printf("number_entries = %d\n", number_entries); + printf("number_entries = %d\n", number_entries); - print_pls(pls); - fclose(fp); + print_pls(pls); + fclose(fp); - return 0; + return 0; } int init_pls_struct(PlsFile *pls, unsigned int number_entries) { - pls->number_entries = number_entries; - pls->entries = malloc(number_entries*sizeof(PlsEntry)); - pls->version = 0; - if (pls->entries == NULL) { - printf("no entries\n"); - return -1; - } else { - unsigned int i; - PlsEntry *entry = pls->entries; - for (i=0;i<pls->number_entries;i++) { - memset(entry->file, 0, sizeof entry->file); - memset(entry->title, 0, sizeof entry->file); - entry++; - } - return 0; - } + pls->number_entries = number_entries; + pls->entries = malloc(number_entries*sizeof(PlsEntry)); + pls->version = 0; + if (pls->entries == NULL) { + printf("no entries\n"); + return -1; + } else { + unsigned int i; + PlsEntry *entry = pls->entries; + for (i=0;i<pls->number_entries;i++) { + memset(entry->file, 0, sizeof entry->file); + memset(entry->title, 0, sizeof entry->file); + entry++; + } + return 0; + } } static int pls_get_field(char *buffer, char *value) { - char *ptr_begin; - char *ptr_end; + char *ptr_begin; + char *ptr_end; - ptr_begin = strstr(buffer, "=")+1; - ptr_end = strstr(buffer, "\n")-1; - strncpy(value, ptr_begin, (int)(ptr_end - ptr_begin + 1)); + ptr_begin = strstr(buffer, "=")+1; + ptr_end = strstr(buffer, "\n")-1; + strncpy(value, ptr_begin, (int)(ptr_end - ptr_begin + 1)); - return 0; + return 0; } static int pls_get_entries(FILE *fp, PlsFile *pls) { - unsigned int i; - char buffer[MAX_LINE_LENGTH]; - PlsEntry *entry = pls->entries; - - fseek(fp, 0 ,SEEK_SET); - - i=0; - while (i<pls->number_entries) { - fgets(buffer, MAX_LINE_LENGTH, fp); - if (strstr(buffer, "File") != NULL) { - pls_get_field(buffer, entry->file); - entry++; - i++; - } - } - return 0; // TODO : use a better return value + unsigned int i; + char buffer[MAX_LINE_LENGTH]; + PlsEntry *entry = pls->entries; + + fseek(fp, 0 ,SEEK_SET); + + i=0; + while (i<pls->number_entries) { + fgets(buffer, MAX_LINE_LENGTH, fp); + if (strstr(buffer, "File") != NULL) { + pls_get_field(buffer, entry->file); + entry++; + i++; + } + } + return 0; // TODO : use a better return value } int is_pls_file(FILE *fp) { - char buffer[MAX_LINE_LENGTH]; - fseek(fp, 0 ,SEEK_SET); - fgets(buffer, MAX_LINE_LENGTH, fp); - - if (strncmp(buffer, "[playlist]", 10) != 0) { - fseek(fp, 0 ,SEEK_SET); - printf("no [playlist] in %s\n", buffer); - return FALSE; - } - - // TODO : Check NumberOfEntries - // TODO : Check goup of 3 entries - - while (!feof (fp)) { - fgets(buffer, MAX_LINE_LENGTH, fp); - } - if (strstr(buffer, "Version=") != NULL) { - fseek(fp, 0, SEEK_SET); - return TRUE; - } - printf("no [Version=]\n"); - return FALSE; + char buffer[MAX_LINE_LENGTH]; + fseek(fp, 0 ,SEEK_SET); + fgets(buffer, MAX_LINE_LENGTH, fp); + + if (strncmp(buffer, "[playlist]", 10) != 0) { + fseek(fp, 0 ,SEEK_SET); + printf("no [playlist] in %s\n", buffer); + return FALSE; + } + + // TODO : Check NumberOfEntries + // TODO : Check goup of 3 entries + + while (!feof (fp)) { + fgets(buffer, MAX_LINE_LENGTH, fp); + } + if (strstr(buffer, "Version=") != NULL) { + fseek(fp, 0, SEEK_SET); + return TRUE; + } + printf("no [Version=]\n"); + return FALSE; } static unsigned int pls_get_number_entries(FILE *fp) { - char buffer[MAX_LINE_LENGTH]; - char number_entries_str[3]; - - fseek(fp, 0, SEEK_SET); - fgets(buffer, MAX_LINE_LENGTH, fp); - while (!feof (fp)) { - fgets(buffer, MAX_LINE_LENGTH, fp); - if (strstr(buffer, "NumberOfEntries=") != NULL) { - sprintf(number_entries_str, "%c%c", buffer[16], buffer[17]); - return (unsigned int)atoi(number_entries_str); - } - } - return 0; + char buffer[MAX_LINE_LENGTH]; + char number_entries_str[3]; + + fseek(fp, 0, SEEK_SET); + fgets(buffer, MAX_LINE_LENGTH, fp); + while (!feof (fp)) { + fgets(buffer, MAX_LINE_LENGTH, fp); + if (strstr(buffer, "NumberOfEntries=") != NULL) { + sprintf(number_entries_str, "%c%c", buffer[16], buffer[17]); + return (unsigned int)atoi(number_entries_str); + } + } + return 0; } diff --git a/src/shoutcast.c b/src/shoutcast.c index 77b33fa..cfae69c 100644 --- a/src/shoutcast.c +++ b/src/shoutcast.c @@ -11,23 +11,23 @@ void global_listener(Stream *stream, char *buffer) { - // http_code_listener(stream, buffer); + // http_code_listener(stream, buffer); - if (is_header(stream)) - header_listener(stream, buffer); - else if (is_metadata(stream)) - metadata_listener(stream, buffer); - else if (is_mp3data(stream)) - mp3data_listener(stream, buffer); + if (is_header(stream)) + header_listener(stream, buffer); + else if (is_metadata(stream)) + metadata_listener(stream, buffer); + else if (is_mp3data(stream)) + mp3data_listener(stream, buffer); } int write_data(Stream *stream) { - if (stream->output_stream == NULL) { - return 0; - } - int written = fwrite(stream->mp3data.buffer, sizeof(char), - stream->mp3data.size, - (FILE *)stream->output_stream); - return written; + if (stream->output_stream == NULL) { + return 0; + } + int written = fwrite(stream->mp3data.buffer, sizeof(char), + stream->mp3data.size, + (FILE *)stream->output_stream); + return written; } diff --git a/src/stream.c b/src/stream.c index 6a03479..f752c3c 100755 --- a/src/stream.c +++ b/src/stream.c @@ -9,81 +9,83 @@ #include "curl.h" #include "log.h" #include <taglib/tag_c.h> +#include <glob.h> +#include <regex.h> void free_stream(Stream *stream) { - plog("free_stream\n"); - ICYHeader *header = &stream->header; - free(header->buffer); - header->ptr= NULL; + plog("free_stream\n"); + ICYHeader *header = &stream->header; + free(header->buffer); + header->ptr= NULL; } int load_stream(Stream *stream, const char *url) { - ICYHeader *header = &stream->header; - MetaData *metadata = &stream->metadata; - Mp3Data *mp3data = &stream->mp3data; - - // Setting header - header->icy_name[0] = '\0'; - header->icy_notice1[0] = '\0'; - header->icy_notice2[0] = '\0'; - header->icy_genre[0] = '\0'; - header->icy_pub[0] = '\0'; - header->icy_br[0] = '\0'; - header->is_set = 0; - header->buffer = malloc(4000*sizeof(char)); - header->ptr = header->buffer; - header->metaint = 0; - - metadata->ptr = NULL; - metadata->size = 0; - - mp3data->ptr = NULL; - - // Setting Stream information - stream->bytes_count = 0; - stream->bytes_count_total = 0; - stream->blocks_count = 0; - stream->metadata_count = 0; - stream->output_stream = NULL; + ICYHeader *header = &stream->header; + MetaData *metadata = &stream->metadata; + Mp3Data *mp3data = &stream->mp3data; + + // Setting header + header->icy_name[0] = '\0'; + header->icy_notice1[0] = '\0'; + header->icy_notice2[0] = '\0'; + header->icy_genre[0] = '\0'; + header->icy_pub[0] = '\0'; + header->icy_br[0] = '\0'; + header->is_set = 0; + header->buffer = malloc(4000*sizeof(char)); + header->ptr = header->buffer; + header->metaint = 0; + + metadata->ptr = NULL; + metadata->size = 0; + + mp3data->ptr = NULL; + + // Setting Stream information + stream->bytes_count = 0; + stream->bytes_count_total = 0; + stream->blocks_count = 0; + stream->metadata_count = 0; + stream->output_stream = NULL; stream->filename[0] = '\0'; - stream->status = E_STATUS_HEADER; + stream->status = E_STATUS_HEADER; - strncpy(stream->url, url, 255); - newfilename(stream, stream->stream_title); - return 0; + strncpy(stream->url, url, 255); + newfilename(stream, stream->stream_title); + return 0; } int load_stream_from_playlist(Stream *stream, char *filename) { - PlsFile pls; - int ret = 0; + PlsFile pls; + int ret = 0; - if (filename == NULL) { - ret = -1; - goto early_err; - } + if (filename == NULL) { + ret = -1; + goto early_err; + } - if (!is_pls_extension(filename)) { - ret = -1; - goto early_err; - } + if (!is_pls_extension(filename)) { + ret = -1; + goto early_err; + } - if ((ret = pls_load_file(filename, &pls)) < 0) { - printf("Error : Couldn't load pls file\n"); - goto early_err; - } + if ((ret = pls_load_file(filename, &pls)) < 0) { + printf("Error : Couldn't load pls file\n"); + goto early_err; + } - if ((ret = load_stream(stream, pls.entries->file)) < 0) { - printf("Error : Couldn't load Shoutcast stream\n"); - goto err; - } + if ((ret = load_stream(stream, pls.entries->file)) < 0) { + printf("Error : Couldn't load Shoutcast stream\n"); + goto err; + } err: - free(pls.entries); + free(pls.entries); early_err: - return ret; + return ret; } @@ -131,109 +133,120 @@ int exists(const char *fname) return 0; } +int exists_partially(char * fname) { + glob_t result; + int exists = 0; + const int ok = glob( fname, /*flags:*/ 0, /*errfunc:*/ NULL, &result ); + if( 0 == ok ) { + exists = result.gl_pathc; + } + else { + // error + } + return exists; +} + void newfilename(Stream* stream, const char* title) { - const int size=255+1+3+1+500+1+255; - char filename[size]; - time_t rawtime; - struct tm * timeinfo; - time (&rawtime); - timeinfo = localtime(&rawtime); - char basefilename[255]; - strftime(basefilename,254,stream->basefilename,timeinfo); - if (title==NULL||strlen(title)==0) { - snprintf(filename,size,"%s.%03d.%s", basefilename, stream->metadata_count, stream->ext); - while (1 == exists(filename)) { - stream->metadata_count++; - snprintf(filename,size,"%s.%03d.%s", basefilename, stream->metadata_count, stream->ext); - } - } else { - snprintf(filename,size,"%s.%03d.%s.%s", basefilename, stream->metadata_count, title, stream->ext); - while (1 == exists(filename)) { - stream->metadata_count++; - snprintf(filename,size,"%s.%03d.%s.%s", basefilename, stream->metadata_count, title, stream->ext); - } - } - if (title==NULL||strlen(title)==0) { - // don't search for title match if no title to match - } else { - if (stream->onlytitle!=NULL&&strlen(stream->onlytitle)!=0) { - char str[255]; - strncpy(str, stream->onlytitle, 255); - int title_found = 0; - char* token=strtok(str,","); - if (token) { - while (token) { - if(stristr(title, token)!=NULL) { - title_found = 1; - } - token=strtok(NULL,","); - } - } else { - if(stristr(title, stream->onlytitle)!=NULL) { - title_found = 1; - } - } - if (title_found == 0) { - snprintf(filename,size,"%s","/dev/null"); - } else { - stream->metadata_count++; - } - } else { - stream->metadata_count++; - } - } - filename[254]='\0'; - - char ext[3]; - strncpy(ext, stream->ext, 3); - char oldfilename[255]; - char oldtitle[500]; - strncpy(oldfilename,stream->filename, 255); - strncpy(oldtitle,stream->stream_title, 500); - - if (stream->output_stream != NULL) fclose(stream->output_stream); - stream->output_stream = fopen(filename, "wb"); - strncpy(stream->filename, filename, 255); - if (title==NULL||strlen(title)==0) { - stream->stream_title[0]='\0'; - } else { - strncpy(stream->stream_title, title, 500); - } - - taglib_set_strings_unicode(FALSE); - TagLib_File *media_file; - if (strncmp(ext,"aac",3) == 0) { - media_file = taglib_file_new_type(oldfilename, TagLib_File_MP4); - } else { - media_file = taglib_file_new(oldfilename); - } - if (media_file != NULL) { - TagLib_Tag *tag = taglib_file_tag(media_file); - if (tag != NULL) { - taglib_tag_set_comment(tag, oldtitle); - char * const sep_at = strstr(oldtitle, " - "); - if (sep_at != NULL) { - *sep_at='\0'; - char* title; - char* artist; - if (stream->TA == 0) { - title = oldtitle; - artist = sep_at+3; - } else { - artist = oldtitle; - title = sep_at+3; - } - taglib_tag_set_title(tag,title); - taglib_tag_set_album(tag,title); - taglib_tag_set_artist(tag,artist); - } - taglib_file_save(media_file); - } - taglib_tag_free_strings(); - taglib_file_free(media_file); - } - - plog("newfilename: %s\n", filename); + const int size=255+1+3+1+500+1+255; + char filename[size]; + time_t rawtime; + struct tm * timeinfo; + time (&rawtime); + timeinfo = localtime(&rawtime); + char basefilename[255]; + strftime(basefilename,254,stream->basefilename,timeinfo); + + snprintf(filename,size,"%s.%03d*", basefilename, stream->metadata_count); + while (0 != exists_partially(filename)) { + stream->metadata_count++; + snprintf(filename,size,"%s.%03d*", basefilename, stream->metadata_count); + } + if (title==NULL||strlen(title)==0) { + snprintf(filename,size,"%s.%03d.%s", basefilename, stream->metadata_count, stream->ext); + } else { + snprintf(filename,size,"%s.%03d.%s.%s", basefilename, stream->metadata_count, title, stream->ext); + } + if (title==NULL||strlen(title)==0) { + // don't search for title match if no title to match + } else { + if (stream->onlytitle!=NULL&&strlen(stream->onlytitle)!=0) { + char str[255]; + strncpy(str, stream->onlytitle, 255); + int title_found = 0; + char* token=strtok(str,","); + if (token) { + while (token) { + if(stristr(title, token)!=NULL) { + title_found = 1; + } + token=strtok(NULL,","); + } + } else { + if(stristr(title, stream->onlytitle)!=NULL) { + title_found = 1; + } + } + if (title_found == 0) { + snprintf(filename,size,"%s","/dev/null"); + } else { + stream->metadata_count++; + } + } else { + stream->metadata_count++; + } + } + filename[254]='\0'; + + char ext[3]; + strncpy(ext, stream->ext, 3); + char oldfilename[255]; + char oldtitle[500]; + strncpy(oldfilename,stream->filename, 255); + strncpy(oldtitle,stream->stream_title, 500); + + if (stream->output_stream != NULL) fclose(stream->output_stream); + stream->output_stream = fopen(filename, "wb"); + strncpy(stream->filename, filename, 255); + if (title==NULL||strlen(title)==0) { + stream->stream_title[0]='\0'; + } else { + strncpy(stream->stream_title, title, 500); + } + + taglib_set_strings_unicode(FALSE); + TagLib_File *media_file; + if (strncmp(ext,"aac",3) == 0) { + media_file = taglib_file_new_type(oldfilename, TagLib_File_MP4); + } else { + media_file = taglib_file_new(oldfilename); + } + if (media_file != NULL) { + TagLib_Tag *tag = taglib_file_tag(media_file); + if (tag != NULL) { + taglib_tag_set_comment(tag, oldtitle); + char * const sep_at = strstr(oldtitle, " - "); + if (sep_at != NULL) { + *sep_at='\0'; + char* title; + char* artist; + if (stream->TA == 0) { + title = oldtitle; + artist = sep_at+3; + } else { + artist = oldtitle; + title = sep_at+3; + } + taglib_tag_set_title(tag,title); + taglib_tag_set_album(tag,title); + taglib_tag_set_artist(tag,artist); + } + taglib_file_save(media_file); + } + taglib_tag_free_strings(); + taglib_file_free(media_file); + } + + plog("newfilename: %s\n", filename); } From 315a38ef21b0b8dcd91e6200a61d8a4d0434833a Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 29 Jan 2023 10:38:26 +0100 Subject: [PATCH 54/67] convert streamtitle to pascal casing --- src/log.c | 2 +- src/metadata.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/log.c b/src/log.c index eb4fda6..31b86f7 100644 --- a/src/log.c +++ b/src/log.c @@ -44,7 +44,7 @@ static int get_date(char *string) time (&rawtime); timeinfo = localtime(&rawtime); - sprintf(string, "%03d", timeinfo->tm_yday+1); + sprintf(string, "%03d.%02d%02d%02d", timeinfo->tm_yday+1, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); return 0; } diff --git a/src/metadata.c b/src/metadata.c index f19b290..752385c 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -2,6 +2,7 @@ #include <stdlib.h> #include <string.h> #include <sys/param.h> +#include <ctype.h> #include "types.h" #include "metadata.h" @@ -88,9 +89,20 @@ int metadata_body_handler(Stream *stream, char *buffer) stream_title[499]='\0'; metadata_content[499]='\0'; // filter problematic characters from StreamTitle - for (unsigned int i =0; i < MIN(metadata->size,500); i++) { + // and make PascalCase + int toUpperCase = 1; //first character toUpperCase + for (unsigned int i=0; i < MIN(metadata->size,500); i++) { if (stream_title[i]=='\0') { break;} //done - stream_title[i]=ascii[(int)stream_title[i]]; + char c=ascii[(int)stream_title[i]]; + if (toUpperCase==1) { + stream_title[i]=toupper(c); + toUpperCase=0; + } else { + stream_title[i]=tolower(c); + } + if (' '==stream_title[i]) { + toUpperCase=1; //next character toUpperCase + } } rtrim(stream_title); if (0 != strncmp(stream->stream_title, stream_title, 500)) From 1ec9ede8431be49d83fe09915c636954d10255a8 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Wed, 1 Mar 2023 20:22:26 +0100 Subject: [PATCH 55/67] also log to stdout and 2 iso 3 digits for filename sequence number --- src/log.c | 4 ++++ src/stream.c | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/log.c b/src/log.c index 31b86f7..0046d23 100644 --- a/src/log.c +++ b/src/log.c @@ -11,6 +11,7 @@ static FILE *fp_log; static char current_time[20]; static char current_date[20]; static char tempfile[270]; +static FILE* fout = NULL; static int get_time(char *string) { @@ -108,6 +109,9 @@ void slog(char *line) { if (log_append(fp_log, line) < 0) printf("Coudln't write shoutr log\n"); + if (!fout) + fout = stdout; + log_append(fout, line); } void printCurrentTime() { diff --git a/src/stream.c b/src/stream.c index f752c3c..0573ccc 100755 --- a/src/stream.c +++ b/src/stream.c @@ -157,15 +157,15 @@ void newfilename(Stream* stream, const char* title) char basefilename[255]; strftime(basefilename,254,stream->basefilename,timeinfo); - snprintf(filename,size,"%s.%03d*", basefilename, stream->metadata_count); + snprintf(filename,size,"%s.%02d*", basefilename, stream->metadata_count); while (0 != exists_partially(filename)) { stream->metadata_count++; - snprintf(filename,size,"%s.%03d*", basefilename, stream->metadata_count); + snprintf(filename,size,"%s.%02d*", basefilename, stream->metadata_count); } if (title==NULL||strlen(title)==0) { - snprintf(filename,size,"%s.%03d.%s", basefilename, stream->metadata_count, stream->ext); + snprintf(filename,size,"%s.%02d.%s", basefilename, stream->metadata_count, stream->ext); } else { - snprintf(filename,size,"%s.%03d.%s.%s", basefilename, stream->metadata_count, title, stream->ext); + snprintf(filename,size,"%s.%02d.%s.%s", basefilename, stream->metadata_count, title, stream->ext); } if (title==NULL||strlen(title)==0) { // don't search for title match if no title to match From f59b780e670a7b3735dc834fd20c556cbcde9a55 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Wed, 29 Mar 2023 17:52:22 +0200 Subject: [PATCH 56/67] added station to stream --- include/types.h | 17 +++++++++-------- src/main.c | 12 +++++++----- src/metadata.c | 3 +++ 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/include/types.h b/include/types.h index d7bccec..9b5339c 100644 --- a/include/types.h +++ b/include/types.h @@ -48,21 +48,22 @@ typedef struct typedef struct { char url[255]; // Stream url - char proxy[255]; // Network proxy + char proxy[255]; // Network proxy char basefilename[255]; // basefilename of output file - char filename[255]; // current filename of output file - char ext[255]; // current extension of output file - char onlytitle[255]; // record only if title contains onlytitle + char filename[255]; // current filename of output file + char ext[255]; // current extension of output file + char onlytitle[255]; // record only if title contains onlytitle unsigned int duration; // max recording duration - unsigned int repeat; // max recording repeats + unsigned int repeat; // max recording repeats FILE *output_stream; // Output MP3 file char stream_title[500]; // Current title + char station[255]; // station int TA; // title = <Title> - <Artist> else <Artist> - <Title> parsing_status status; - ICYHeader header; // Stream header (won't change after being set) - MetaData metadata; // Stream metadata (will change during session) - Mp3Data mp3data; // MP3 raw data + ICYHeader header; // Stream header (won't change after being set) + MetaData metadata; // Stream metadata (will change during session) + Mp3Data mp3data; // MP3 raw data unsigned int bytes_count; // Number of bytes received since last metadata block unsigned int bytes_count_total; // Number of bytes received since beginning diff --git a/src/main.c b/src/main.c index 91a0d22..f4a5ab2 100755 --- a/src/main.c +++ b/src/main.c @@ -135,21 +135,23 @@ int main(int argc, char *argv[]) memset(stream.ext, 0, 255); strncpy(stream.ext, fileext, 254); - memset(stream.stream_title, 0, 255); + memset(stream.stream_title, 0, 500); + memset(stream.station, 0, 255); if (stationname != NULL) { strncpy(stream.stream_title, stationname, 254); + strncpy(stream.station, stationname, 254); } - stream.duration=atoi(duration); - stream.repeat=atoi(repeat); + stream.duration=atoi(duration); + stream.repeat=atoi(repeat); memset(stream.proxy, 0, 255); - if (proxy != NULL) { + if (proxy != NULL) { strncpy(stream.proxy, proxy, 254); } memset(stream.onlytitle, 0, 255); - if (title != NULL) { + if (title != NULL) { strncpy(stream.onlytitle, title, 254); } diff --git a/src/metadata.c b/src/metadata.c index 752385c..adf7714 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -105,6 +105,9 @@ int metadata_body_handler(Stream *stream, char *buffer) } } rtrim(stream_title); + if (stream_title==NULL||strlen(stream_title)==0) { + strncpy(stream->stream_title, stream->station, 255); + } if (0 != strncmp(stream->stream_title, stream_title, 500)) { plog("stream_title: [%s]\n", stream_title); From 0776e7f14d6bd0232a5ecccb6022c4e8942f42d5 Mon Sep 17 00:00:00 2001 From: sofie <sofie@msi.home> Date: Wed, 29 Mar 2023 18:37:02 +0200 Subject: [PATCH 57/67] TITLE_SIZE --- include/pls.h | 4 ++-- include/types.h | 3 ++- src/curl.c | 6 ++++++ src/main.c | 4 ++-- src/metadata.c | 30 ++++++++++++++++++++---------- src/stream.c | 8 ++++---- 6 files changed, 36 insertions(+), 19 deletions(-) diff --git a/include/pls.h b/include/pls.h index d84d600..0e44621 100644 --- a/include/pls.h +++ b/include/pls.h @@ -4,8 +4,8 @@ #define MAX_LINE_LENGTH 500 typedef struct { - char file[500]; - char title[500]; + char file[MAX_LINE_LENGTH]; + char title[MAX_LINE_LENGTH]; int length; } PlsEntry; diff --git a/include/types.h b/include/types.h index 9b5339c..18b12b7 100644 --- a/include/types.h +++ b/include/types.h @@ -3,6 +3,7 @@ #define TRUE 1 #define FALSE 0 +#define TITLE_SIZE 255 typedef enum { E_STATUS_NONE, @@ -56,7 +57,7 @@ typedef struct unsigned int duration; // max recording duration unsigned int repeat; // max recording repeats FILE *output_stream; // Output MP3 file - char stream_title[500]; // Current title + char stream_title[TITLE_SIZE]; // Current title char station[255]; // station int TA; // title = <Title> - <Artist> else <Artist> - <Title> parsing_status status; diff --git a/src/curl.c b/src/curl.c index 79e52d1..623dce4 100755 --- a/src/curl.c +++ b/src/curl.c @@ -19,6 +19,10 @@ #define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL 1 #endif +#ifndef CURL_MAX_READ_SIZE +#define CURL_MAX_READ_SIZE 10000000L +#endif + struct myprogress { TIMETYPE lastruntime; /* type depends on version, see above */ CURL *curl; @@ -121,7 +125,9 @@ int read_stream(Stream *stream) curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/7.64.0"); curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L); curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS); +#ifdef CURLOPT_HTTP09_ALLOWED curl_easy_setopt(curl, CURLOPT_HTTP09_ALLOWED, 1L); +#endif #if LIBCURL_VERSION_NUM >= 0x072000 curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo); diff --git a/src/main.c b/src/main.c index f4a5ab2..38b890b 100755 --- a/src/main.c +++ b/src/main.c @@ -135,10 +135,10 @@ int main(int argc, char *argv[]) memset(stream.ext, 0, 255); strncpy(stream.ext, fileext, 254); - memset(stream.stream_title, 0, 500); + memset(stream.stream_title, 0, TITLE_SIZE); memset(stream.station, 0, 255); if (stationname != NULL) { - strncpy(stream.stream_title, stationname, 254); + strncpy(stream.stream_title, stationname, TITLE_SIZE-1); strncpy(stream.station, stationname, 254); } diff --git a/src/metadata.c b/src/metadata.c index adf7714..2bd7ba5 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -66,7 +66,7 @@ void removechar( char str[], unsigned int i ) str[strlen(str)-1]='\0'; } -void rtrim(char str[]) +void rtrim(char *str) { const char *seps = "\t\n\v\f\r "; int i = strlen(str) - 1; @@ -76,22 +76,32 @@ void rtrim(char str[]) } } +void trim(char *str) +{ + const char *seps = "\t\n\v\f\r "; + int i = 0; + while (strchr(seps, str[i]) != NULL) { + str++; + } + rtrim(str); +} + int metadata_body_handler(Stream *stream, char *buffer) { MetaData *metadata = &stream->metadata; *metadata->ptr = *buffer; if ((unsigned)(metadata->ptr - metadata->buffer) == (metadata->size-1)) { - char metadata_content[500]=""; - char stream_title[500]=""; - strncpy(metadata_content, metadata->buffer, MIN(metadata->size,500)); + char metadata_content[TITLE_SIZE]=""; + char stream_title[TITLE_SIZE]=""; + strncpy(metadata_content, metadata->buffer, MIN(metadata->size,TITLE_SIZE)); if(0==get_metadata_field(metadata_content, "StreamTitle", stream_title)) { - stream_title[499]='\0'; - metadata_content[499]='\0'; + stream_title[TITLE_SIZE-1]='\0'; + metadata_content[TITLE_SIZE-1]='\0'; // filter problematic characters from StreamTitle // and make PascalCase int toUpperCase = 1; //first character toUpperCase - for (unsigned int i=0; i < MIN(metadata->size,500); i++) { + for (unsigned int i=0; i < MIN(metadata->size,TITLE_SIZE); i++) { if (stream_title[i]=='\0') { break;} //done char c=ascii[(int)stream_title[i]]; if (toUpperCase==1) { @@ -104,13 +114,13 @@ int metadata_body_handler(Stream *stream, char *buffer) toUpperCase=1; //next character toUpperCase } } - rtrim(stream_title); + trim(stream_title); if (stream_title==NULL||strlen(stream_title)==0) { strncpy(stream->stream_title, stream->station, 255); } - if (0 != strncmp(stream->stream_title, stream_title, 500)) + if (0 != strncmp(stream->stream_title, stream_title, TITLE_SIZE)) { - plog("stream_title: [%s]\n", stream_title); + plog("stream_title: [%s] [%s]\n", stream_title, stream->stream_title); newfilename(stream, stream_title); } } diff --git a/src/stream.c b/src/stream.c index 0573ccc..1d9dbdd 100755 --- a/src/stream.c +++ b/src/stream.c @@ -148,7 +148,7 @@ int exists_partially(char * fname) { void newfilename(Stream* stream, const char* title) { - const int size=255+1+3+1+500+1+255; + const int size=255+1+3+1+TITLE_SIZE+1+255; char filename[size]; time_t rawtime; struct tm * timeinfo; @@ -201,9 +201,9 @@ void newfilename(Stream* stream, const char* title) char ext[3]; strncpy(ext, stream->ext, 3); char oldfilename[255]; - char oldtitle[500]; + char oldtitle[TITLE_SIZE]; strncpy(oldfilename,stream->filename, 255); - strncpy(oldtitle,stream->stream_title, 500); + strncpy(oldtitle,stream->stream_title, TITLE_SIZE); if (stream->output_stream != NULL) fclose(stream->output_stream); stream->output_stream = fopen(filename, "wb"); @@ -211,7 +211,7 @@ void newfilename(Stream* stream, const char* title) if (title==NULL||strlen(title)==0) { stream->stream_title[0]='\0'; } else { - strncpy(stream->stream_title, title, 500); + strncpy(stream->stream_title, title, TITLE_SIZE); } taglib_set_strings_unicode(FALSE); From e6102ebae61426a37e031988ca8cd90f6058346c Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Wed, 29 Mar 2023 18:52:31 +0200 Subject: [PATCH 58/67] clean buffers --- src/metadata.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/metadata.c b/src/metadata.c index 2bd7ba5..2d9b371 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -91,8 +91,10 @@ int metadata_body_handler(Stream *stream, char *buffer) MetaData *metadata = &stream->metadata; *metadata->ptr = *buffer; if ((unsigned)(metadata->ptr - metadata->buffer) == (metadata->size-1)) { - char metadata_content[TITLE_SIZE]=""; - char stream_title[TITLE_SIZE]=""; + char metadata_content[TITLE_SIZE]; + memset(metadata_content, 0, TITLE_SIZE); + char stream_title[TITLE_SIZE]; + memset(stream_title, 0, TITLE_SIZE); strncpy(metadata_content, metadata->buffer, MIN(metadata->size,TITLE_SIZE)); if(0==get_metadata_field(metadata_content, "StreamTitle", stream_title)) { From 3d141c5efaf0918d75dc63ba7834c83012563ff2 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 2 Apr 2023 10:32:42 +0200 Subject: [PATCH 59/67] fix empty title (not) becoming station name --- src/metadata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/metadata.c b/src/metadata.c index 2d9b371..b63d694 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -118,7 +118,7 @@ int metadata_body_handler(Stream *stream, char *buffer) } trim(stream_title); if (stream_title==NULL||strlen(stream_title)==0) { - strncpy(stream->stream_title, stream->station, 255); + strncpy(stream_title, stream->station, 255); } if (0 != strncmp(stream->stream_title, stream_title, TITLE_SIZE)) { From dec33c96516ba8302540fa593ad2bb968aa5341f Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Wed, 19 Apr 2023 20:13:47 +0200 Subject: [PATCH 60/67] fix CamelCase --- src/metadata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/metadata.c b/src/metadata.c index b63d694..5ac97fc 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -112,7 +112,7 @@ int metadata_body_handler(Stream *stream, char *buffer) } else { stream_title[i]=tolower(c); } - if (' '==stream_title[i]) { + if ((' '==stream_title[i])||('.'==stream_title[i])){ toUpperCase=1; //next character toUpperCase } } From ed4ee5cf2c53a51dc1561a8146b7f150c21e329f Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Fri, 21 Apr 2023 22:06:15 +0200 Subject: [PATCH 61/67] use strftime for log --- src/log.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/src/log.c b/src/log.c index 0046d23..0da8db4 100644 --- a/src/log.c +++ b/src/log.c @@ -15,38 +15,21 @@ static FILE* fout = NULL; static int get_time(char *string) { - time_t rawtime; - struct tm *timeinfo; - + struct timeval curTime; if (string == NULL) return -1; - - time (&rawtime); - timeinfo = localtime(&rawtime); - - sprintf(string, "%d:%02d:%02d-%02d:%02d:%02d ", 1900+timeinfo->tm_year, - timeinfo->tm_mon+1, - timeinfo->tm_mday, - timeinfo->tm_hour, - timeinfo->tm_min, - timeinfo->tm_sec); - + gettimeofday(&curTime, NULL); + strftime(string, 20, "%Y%m%d-%H%M%S", localtime(&curTime.tv_sec)); return 0; } static int get_date(char *string) { - time_t rawtime; - struct tm *timeinfo; - + struct timeval curTime; if (string == NULL) return -1; - - time (&rawtime); - timeinfo = localtime(&rawtime); - - sprintf(string, "%03d.%02d%02d%02d", timeinfo->tm_yday+1, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); - + gettimeofday(&curTime, NULL); + strftime(string, 20, "%a.%Y%m%d.%H%M%S", localtime(&curTime.tv_sec)); return 0; } From 0b80f0e2a47aba166a25ee42b68bfaf2f13c6d1f Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Wed, 26 Apr 2023 20:18:25 +0200 Subject: [PATCH 62/67] fix mising space after timestamp and refactor log --- src/log.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/log.c b/src/log.c index 0da8db4..b6d7ea2 100644 --- a/src/log.c +++ b/src/log.c @@ -8,10 +8,11 @@ #include "log.h" static FILE *fp_log; -static char current_time[20]; +static char current_time[25]; static char current_date[20]; static char tempfile[270]; static FILE* fout = NULL; +static char buffr[20]; static int get_time(char *string) { @@ -19,7 +20,9 @@ static int get_time(char *string) if (string == NULL) return -1; gettimeofday(&curTime, NULL); - strftime(string, 20, "%Y%m%d-%H%M%S", localtime(&curTime.tv_sec)); + int milli = curTime.tv_usec / 1000; + strftime(buffr, 20, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); + snprintf(string, 25, "%s.%03d ", buffr, milli); return 0; } @@ -98,12 +101,9 @@ void slog(char *line) } void printCurrentTime() { - struct timeval curTime; - gettimeofday(&curTime, NULL); - int milli = curTime.tv_usec / 1000; - char buffr [80]; - strftime(buffr, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec)); - printf("%s.%03d ", buffr, milli); + if (get_time(current_time) < 0) + return; + printf("%s", current_time); } void plog(char *fmt, ...) { From f9e95e1f550a0c674edecbe6556cfd6f38e8f34b Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Fri, 12 May 2023 17:12:08 +0200 Subject: [PATCH 63/67] another camel-case --- src/log.c | 4 ++-- src/metadata.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/log.c b/src/log.c index b6d7ea2..dde8c66 100644 --- a/src/log.c +++ b/src/log.c @@ -53,7 +53,7 @@ int log_open_files(char* folder) snprintf(tempfile,270,"%s/shoutr.%s.log",folder,current_date); fp_log = fopen(tempfile,"a"); if (fp_log == NULL) { - printf("Couldn't open shoutr.log file\n"); + printf("Couldn't open %s file\n", tempfile); return -1; } @@ -103,7 +103,7 @@ void slog(char *line) void printCurrentTime() { if (get_time(current_time) < 0) return; - printf("%s", current_time); + fwrite(current_time, sizeof(char), sizeof(current_time)-1, stdout); } void plog(char *fmt, ...) { diff --git a/src/metadata.c b/src/metadata.c index 5ac97fc..779e0b9 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -112,7 +112,7 @@ int metadata_body_handler(Stream *stream, char *buffer) } else { stream_title[i]=tolower(c); } - if ((' '==stream_title[i])||('.'==stream_title[i])){ + if ((' '==stream_title[i])||('.'==stream_title[i])||('('==stream_title[i])){ toUpperCase=1; //next character toUpperCase } } From 03a4f33e9cde8bde3f13422b2ea9c1880c798829 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Tue, 31 Oct 2023 22:07:52 +0100 Subject: [PATCH 64/67] added option to ignore a stream_title change --- README.mkd | 19 +++++----- include/types.h | 19 +++++----- src/main.c | 96 +++++++++++++++++-------------------------------- src/metadata.c | 5 +-- src/stream.c | 20 +++++------ 5 files changed, 66 insertions(+), 93 deletions(-) diff --git a/README.mkd b/README.mkd index c8994ee..1e47069 100644 --- a/README.mkd +++ b/README.mkd @@ -48,15 +48,16 @@ Examples : OPTIONS: - -d duration defines the recording length in seconds (see CURLOPT_TIMEOUT) - -e extension fileextension (default: mp3) - -f basefilename defines the base name of the mp3 file(s) created (default: radio) - -i id3tags split stream_title (on ' - ') into artist - title (0) or title - artist (1, default) - -l logfolder (rel/abs) path to folder for log (default: current folder) - -n name name of station (default radio) - -r repeat repeat the recording specified number of times - -t title (part of) title to record (default any) (tip: use '-' to record only music) - -x proxy defines proxy to use (see CURLOPT_PROXY) + -d duration defines the recording length in seconds (see CURLOPT_TIMEOUT) + -e extension fileextension (default: mp3) + -f basefilename defines the base name of the mp3 file(s) created (default: radio) + -i ignore stream_title (change) to ignore (do not create a new file) + -l logfolder (rel/abs) path to folder for log (default: current folder) + -n name name of station (default radio) + -r repeat repeat the recording specified number of times + -s id3tags split stream_title (on ' - ') into artist - title (0) or title - artist (1, default) + -t title (part of) title to record (default any) (tip: use '-' to record only music) + -x proxy defines proxy to use (see CURLOPT_PROXY) without these additional commandline options specified diff --git a/include/types.h b/include/types.h index 18b12b7..1b6b75e 100644 --- a/include/types.h +++ b/include/types.h @@ -3,7 +3,7 @@ #define TRUE 1 #define FALSE 0 -#define TITLE_SIZE 255 +#define TITLE_SIZE 160 typedef enum { E_STATUS_NONE, @@ -19,7 +19,7 @@ typedef struct char icy_name[500]; char icy_notice1[500]; char icy_notice2[500]; - char icy_genre[255]; + char icy_genre[TITLE_SIZE]; char icy_pub[10]; char icy_br[10]; // bitrate @@ -48,17 +48,18 @@ typedef struct typedef struct { - char url[255]; // Stream url - char proxy[255]; // Network proxy - char basefilename[255]; // basefilename of output file - char filename[255]; // current filename of output file - char ext[255]; // current extension of output file - char onlytitle[255]; // record only if title contains onlytitle + char url[TITLE_SIZE]; // Stream url + char proxy[TITLE_SIZE]; // Network proxy + char basefilename[TITLE_SIZE]; // basefilename of output file + char filename[TITLE_SIZE]; // current filename of output file + char ext[TITLE_SIZE]; // current extension of output file + char onlytitle[TITLE_SIZE]; // record only if title contains onlytitle + char to_ignore[TITLE_SIZE]; // ignore stream_title changes when including this string unsigned int duration; // max recording duration unsigned int repeat; // max recording repeats FILE *output_stream; // Output MP3 file char stream_title[TITLE_SIZE]; // Current title - char station[255]; // station + char station[TITLE_SIZE]; // station int TA; // title = <Title> - <Artist> else <Artist> - <Title> parsing_status status; diff --git a/src/main.c b/src/main.c index 38b890b..eee93d5 100755 --- a/src/main.c +++ b/src/main.c @@ -27,10 +27,10 @@ void usage(void) printf("\t-d\t: recording duration (in seconds)\n"); printf("\t-e\t: fileextension (default mp3)\n"); printf("\t-f\t: basefilename (default radio)\n"); - printf("\t-i\t: title - artist (0) or artist - title (1, default)\n"); printf("\t-l\t: logfolder (default current folder)\n"); printf("\t-n\t: name of station (default radio)\n"); printf("\t-r\t: recording repeats (default 0 = none)\n"); + printf("\t-s\t: split title - artist (0) or artist - title (1, default)\n"); printf("\t-t\t: title to record (default any)\n"); printf("\t-x\t: proxy (default no proxy)\n"); } @@ -46,25 +46,24 @@ int main(int argc, char *argv[]) int uflag = 0; int c; char *cvalue = NULL; - char *proxy = NULL; - char *duration = "0"; - char *repeat = "0"; - char *ta = "1"; - - char* basefilename = (char*) malloc(255*sizeof(char)); - sprintf(basefilename, "radio"); - - char* stationname = NULL; - - char* fileext = (char*) malloc(255*sizeof(char)); - sprintf(fileext, "mp3"); - - char* log = (char*) malloc(255*sizeof(char)); - sprintf(log, "."); - - char* title = NULL; + char *log = malloc(TITLE_SIZE*sizeof(char)); + memset(log, 0, TITLE_SIZE); + strncpy(log, ".", TITLE_SIZE-1); + Stream stream; + memset(stream.to_ignore, 0, TITLE_SIZE); + memset(stream.ext, 0, TITLE_SIZE); + strncpy(stream.ext, "mp3", TITLE_SIZE-1); + memset(stream.proxy, 0, TITLE_SIZE); + stream.duration=0; + stream.repeat=0; + stream.TA = 1; + memset(stream.basefilename, 0, TITLE_SIZE); + strncpy(stream.basefilename,"radio",TITLE_SIZE-1); + memset(stream.stream_title, 0, TITLE_SIZE); + memset(stream.station, 0, TITLE_SIZE); + memset(stream.onlytitle, 0, TITLE_SIZE); - while ((c = getopt(argc, argv, "p:u:h:x:f:e:d:r:i:l:n:t:")) != -1) { + while ((c = getopt(argc, argv, "p:u:h:x:f:e:d:r:i:l:n:t:s:")) != -1) { switch(c) { // playlist case 'p': @@ -78,34 +77,38 @@ int main(int argc, char *argv[]) break; // proxy case 'x': - proxy = optarg; + strncpy(stream.proxy, optarg, TITLE_SIZE-1); break; // fileextension case 'e': - fileext = optarg; + strncpy(stream.ext, optarg, TITLE_SIZE-1); break; // basefilename case 'f': - basefilename = optarg; + strncpy(stream.basefilename, optarg, TITLE_SIZE-1); break; // duration case 'd': - duration = optarg; + stream.duration = atoi(optarg); break; case 'r': - repeat = optarg; + stream.repeat=atoi(optarg); break; - case 'i': - ta = optarg; + case 's': + stream.TA = atoi(optarg); break; case 'l': - log = optarg; + strncpy(log, optarg, TITLE_SIZE-1); break; case 'n': - stationname = optarg; + strncpy(stream.stream_title, optarg, TITLE_SIZE-1); + strncpy(stream.station, optarg, TITLE_SIZE-1); break; case 't': - title = optarg; + strncpy(stream.onlytitle, optarg, TITLE_SIZE-1); + break; + case 'i': + strncpy(stream.to_ignore, optarg, TITLE_SIZE-1); break; case 'h': default: @@ -114,47 +117,14 @@ int main(int argc, char *argv[]) break; } } - - if (pflag && uflag) { usage(); goto err_early; } - if ((ret = log_open_files(log)) < 0) { printf("Couldn't open log files.\n"); goto err_early; } - - Stream stream; - stream.TA=atoi(ta); - - memset(stream.basefilename, 0, 255); - strncpy(stream.basefilename,basefilename,254); - - memset(stream.ext, 0, 255); - strncpy(stream.ext, fileext, 254); - - memset(stream.stream_title, 0, TITLE_SIZE); - memset(stream.station, 0, 255); - if (stationname != NULL) { - strncpy(stream.stream_title, stationname, TITLE_SIZE-1); - strncpy(stream.station, stationname, 254); - } - - stream.duration=atoi(duration); - stream.repeat=atoi(repeat); - - memset(stream.proxy, 0, 255); - if (proxy != NULL) { - strncpy(stream.proxy, proxy, 254); - } - - memset(stream.onlytitle, 0, 255); - if (title != NULL) { - strncpy(stream.onlytitle, title, 254); - } - if (pflag) { if ((ret = load_stream_from_playlist(&stream, cvalue)) < 0) { printf("Couldn't load stream from playlist\n"); @@ -164,7 +134,6 @@ int main(int argc, char *argv[]) if (uflag) { load_stream(&stream, cvalue); - } if ((ret = read_stream(&stream)) < 0) { @@ -174,6 +143,7 @@ int main(int argc, char *argv[]) err: log_close_files(); err_early: + free(log); return ret; } diff --git a/src/metadata.c b/src/metadata.c index 779e0b9..417ad8a 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -118,9 +118,10 @@ int metadata_body_handler(Stream *stream, char *buffer) } trim(stream_title); if (stream_title==NULL||strlen(stream_title)==0) { - strncpy(stream_title, stream->station, 255); + strncpy(stream_title, stream->station, TITLE_SIZE); } - if (0 != strncmp(stream->stream_title, stream_title, TITLE_SIZE)) + if (0 != strncmp(stream->stream_title, stream_title, TITLE_SIZE) + && NULL == strstr(stream_title, stream->to_ignore)) { plog("stream_title: [%s] [%s]\n", stream_title, stream->stream_title); newfilename(stream, stream_title); diff --git a/src/stream.c b/src/stream.c index 1d9dbdd..0e225bc 100755 --- a/src/stream.c +++ b/src/stream.c @@ -52,7 +52,7 @@ int load_stream(Stream *stream, const char *url) stream->status = E_STATUS_HEADER; - strncpy(stream->url, url, 255); + strncpy(stream->url, url, TITLE_SIZE); newfilename(stream, stream->stream_title); return 0; } @@ -148,14 +148,14 @@ int exists_partially(char * fname) { void newfilename(Stream* stream, const char* title) { - const int size=255+1+3+1+TITLE_SIZE+1+255; + const int size=TITLE_SIZE+1+3+1+TITLE_SIZE+1+TITLE_SIZE; char filename[size]; time_t rawtime; struct tm * timeinfo; time (&rawtime); timeinfo = localtime(&rawtime); - char basefilename[255]; - strftime(basefilename,254,stream->basefilename,timeinfo); + char basefilename[TITLE_SIZE]; + strftime(basefilename,TITLE_SIZE-1,stream->basefilename,timeinfo); snprintf(filename,size,"%s.%02d*", basefilename, stream->metadata_count); while (0 != exists_partially(filename)) { @@ -171,8 +171,8 @@ void newfilename(Stream* stream, const char* title) // don't search for title match if no title to match } else { if (stream->onlytitle!=NULL&&strlen(stream->onlytitle)!=0) { - char str[255]; - strncpy(str, stream->onlytitle, 255); + char str[TITLE_SIZE]; + strncpy(str, stream->onlytitle, TITLE_SIZE); int title_found = 0; char* token=strtok(str,","); if (token) { @@ -196,18 +196,18 @@ void newfilename(Stream* stream, const char* title) stream->metadata_count++; } } - filename[254]='\0'; + filename[TITLE_SIZE-1]='\0'; char ext[3]; strncpy(ext, stream->ext, 3); - char oldfilename[255]; + char oldfilename[TITLE_SIZE]; char oldtitle[TITLE_SIZE]; - strncpy(oldfilename,stream->filename, 255); + strncpy(oldfilename,stream->filename, TITLE_SIZE); strncpy(oldtitle,stream->stream_title, TITLE_SIZE); if (stream->output_stream != NULL) fclose(stream->output_stream); stream->output_stream = fopen(filename, "wb"); - strncpy(stream->filename, filename, 255); + strncpy(stream->filename, filename, TITLE_SIZE); if (title==NULL||strlen(title)==0) { stream->stream_title[0]='\0'; } else { From 3f89752cfeb4df2e51b776aebf868dec872876d0 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 5 Nov 2023 08:56:27 +0100 Subject: [PATCH 65/67] fix to_ignore + add more logging --- src/main.c | 12 ++++++++++++ src/metadata.c | 12 ++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/main.c b/src/main.c index eee93d5..c0d8312 100755 --- a/src/main.c +++ b/src/main.c @@ -69,46 +69,58 @@ int main(int argc, char *argv[]) case 'p': pflag = 1; cvalue = optarg; + printf("playlist: %s\n", optarg); break; // stream url case 'u': uflag = 1; cvalue = optarg; + printf("url: %s\n", optarg); break; // proxy case 'x': strncpy(stream.proxy, optarg, TITLE_SIZE-1); + printf("proxy: %s\n", optarg); break; // fileextension case 'e': strncpy(stream.ext, optarg, TITLE_SIZE-1); + printf("ext: %s\n", optarg); break; // basefilename case 'f': strncpy(stream.basefilename, optarg, TITLE_SIZE-1); + printf("basefilename: %s\n", optarg); break; // duration case 'd': stream.duration = atoi(optarg); + printf("duration: %s\n", optarg); break; case 'r': stream.repeat=atoi(optarg); + printf("repeat: %s\n", optarg); break; case 's': stream.TA = atoi(optarg); + printf("TA: %si\n", optarg); break; case 'l': strncpy(log, optarg, TITLE_SIZE-1); + printf("log: %s\n", optarg); break; case 'n': strncpy(stream.stream_title, optarg, TITLE_SIZE-1); strncpy(stream.station, optarg, TITLE_SIZE-1); + printf("station: %s\n", optarg); break; case 't': strncpy(stream.onlytitle, optarg, TITLE_SIZE-1); + printf("onlytitle: %s\n", optarg); break; case 'i': strncpy(stream.to_ignore, optarg, TITLE_SIZE-1); + printf("to_ignore: %s\n", optarg); break; case 'h': default: diff --git a/src/metadata.c b/src/metadata.c index 417ad8a..20f6bca 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -120,11 +120,15 @@ int metadata_body_handler(Stream *stream, char *buffer) if (stream_title==NULL||strlen(stream_title)==0) { strncpy(stream_title, stream->station, TITLE_SIZE); } - if (0 != strncmp(stream->stream_title, stream_title, TITLE_SIZE) - && NULL == strstr(stream_title, stream->to_ignore)) + if (0 != strncmp(stream->stream_title, stream_title, TITLE_SIZE)) { - plog("stream_title: [%s] [%s]\n", stream_title, stream->stream_title); - newfilename(stream, stream_title); + plog("stream_title: [%s] [%s] (%s)\n", stream_title, stream->stream_title,stream->to_ignore); + if ( (NULL!=stream->to_ignore)&&(strlen(stream->to_ignore)!=0) + &&(NULL!=strstr(stream_title, stream->to_ignore))){ + plog("no newfilename, ignore [%s] found in [%s]\n", stream->to_ignore, stream_title); + } else { + newfilename(stream, stream_title); + } } } // slog metadata_content From 5d92aee6e298000407d1718653464b3edc7ecd4c Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Sun, 25 May 2025 08:04:39 +0200 Subject: [PATCH 66/67] add ignore option for changes in title --- include/types.h | 1 + src/main.c | 1 + src/metadata.c | 14 ++++++++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/types.h b/include/types.h index 1b6b75e..eba0bb0 100644 --- a/include/types.h +++ b/include/types.h @@ -71,6 +71,7 @@ typedef struct unsigned int bytes_count_total; // Number of bytes received since beginning unsigned int blocks_count; // Number of HTTP blocks received unsigned int metadata_count; // Number of metadata blocks received since beginning + int ignoring; // ignoring title change } Stream; void newfilename(Stream* stream,const char* title); diff --git a/src/main.c b/src/main.c index c0d8312..98f240a 100755 --- a/src/main.c +++ b/src/main.c @@ -57,6 +57,7 @@ int main(int argc, char *argv[]) stream.duration=0; stream.repeat=0; stream.TA = 1; + stream.ignoring = FALSE; memset(stream.basefilename, 0, TITLE_SIZE); strncpy(stream.basefilename,"radio",TITLE_SIZE-1); memset(stream.stream_title, 0, TITLE_SIZE); diff --git a/src/metadata.c b/src/metadata.c index 20f6bca..a3e0625 100755 --- a/src/metadata.c +++ b/src/metadata.c @@ -120,12 +120,22 @@ int metadata_body_handler(Stream *stream, char *buffer) if (stream_title==NULL||strlen(stream_title)==0) { strncpy(stream_title, stream->station, TITLE_SIZE); } + plog("stream_title: [%s] [%s] (%s)\n", stream_title, stream->stream_title,stream->to_ignore); if (0 != strncmp(stream->stream_title, stream_title, TITLE_SIZE)) { - plog("stream_title: [%s] [%s] (%s)\n", stream_title, stream->stream_title,stream->to_ignore); if ( (NULL!=stream->to_ignore)&&(strlen(stream->to_ignore)!=0) - &&(NULL!=strstr(stream_title, stream->to_ignore))){ + &&(NULL!=strstr(stream_title, stream->to_ignore))) { plog("no newfilename, ignore [%s] found in [%s]\n", stream->to_ignore, stream_title); + stream->ignoring=TRUE; + } else { + newfilename(stream, stream_title); + } + } else { + if ( stream->ignoring == TRUE ) { + plog("no newfilename, ignore sequence [%s] active, keep same filename\n", stream->to_ignore); + stream->ignoring=FALSE; + } else if ((NULL!=stream->to_ignore) && (0 == strncmp("TRUE", stream->to_ignore, 4))) { + plog("no newfilename, ignore set to [%s]\n", stream->to_ignore); } else { newfilename(stream, stream_title); } From 676ca301c4ef8b99f7751b193574a58d93afa0f5 Mon Sep 17 00:00:00 2001 From: smitdol <smitdol@brade.nl> Date: Tue, 16 Sep 2025 17:28:06 +0200 Subject: [PATCH 67/67] adding -z option --- src/main.c | 19 ++++++++++++++++--- src/stream.c | 6 +++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/main.c b/src/main.c index 98f240a..eb3abbf 100755 --- a/src/main.c +++ b/src/main.c @@ -33,6 +33,7 @@ void usage(void) printf("\t-s\t: split title - artist (0) or artist - title (1, default)\n"); printf("\t-t\t: title to record (default any)\n"); printf("\t-x\t: proxy (default no proxy)\n"); + printf("\t-z\t: use only artist/title for filename\n"); } int main(int argc, char *argv[]) @@ -64,7 +65,7 @@ int main(int argc, char *argv[]) memset(stream.station, 0, TITLE_SIZE); memset(stream.onlytitle, 0, TITLE_SIZE); - while ((c = getopt(argc, argv, "p:u:h:x:f:e:d:r:i:l:n:t:s:")) != -1) { + while ((c = getopt(argc, argv, "p:u:h:x:f:e:d:r:i:l:n:t:s:z:")) != -1) { switch(c) { // playlist case 'p': @@ -103,8 +104,20 @@ int main(int argc, char *argv[]) printf("repeat: %s\n", optarg); break; case 's': - stream.TA = atoi(optarg); - printf("TA: %si\n", optarg); + if (atoi(optarg)> 0){ + stream.TA |= 1; + } else { + stream.TA &= ~1; + } + printf("TA: %s TA:%i\n", optarg, stream.TA); + break; + case 'z': + if (atoi(optarg)> 0){ + stream.TA |= 2; + } else { + stream.TA &= ~2; + } + printf("onlyta: %s TA:%i\n", optarg, stream.TA); break; case 'l': strncpy(log, optarg, TITLE_SIZE-1); diff --git a/src/stream.c b/src/stream.c index 0e225bc..1e3004d 100755 --- a/src/stream.c +++ b/src/stream.c @@ -165,7 +165,11 @@ void newfilename(Stream* stream, const char* title) if (title==NULL||strlen(title)==0) { snprintf(filename,size,"%s.%02d.%s", basefilename, stream->metadata_count, stream->ext); } else { - snprintf(filename,size,"%s.%02d.%s.%s", basefilename, stream->metadata_count, title, stream->ext); + if (stream->TA > 1) { + snprintf(filename,size,"%s%s.%s", basefilename, title, stream->ext); + } else { + snprintf(filename,size,"%s.%02d.%s.%s", basefilename, stream->metadata_count, title, stream->ext); + } } if (title==NULL||strlen(title)==0) { // don't search for title match if no title to match