Assists music production by grouping standalone programs into sessions. Community version of "Non Session Manager".
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

328 lines
6.3KB

  1. /*******************************************************************************/
  2. /* Copyright (C) 2008 Jonathan Moore Liles */
  3. /* */
  4. /* This program is free software; you can redistribute it and/or modify it */
  5. /* under the terms of the GNU General Public License as published by the */
  6. /* Free Software Foundation; either version 2 of the License, or (at your */
  7. /* option) any later version. */
  8. /* */
  9. /* This program is distributed in the hope that it will be useful, but WITHOUT */
  10. /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
  11. /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
  12. /* more details. */
  13. /* */
  14. /* You should have received a copy of the GNU General Public License along */
  15. /* with This program; see the file COPYING. If not,write to the Free Software */
  16. /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  17. /*******************************************************************************/
  18. #define _LOGGABLE_C
  19. #include "Loggable.H"
  20. #undef _LOGABLE_C
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <stdarg.h>
  24. FILE *Loggable::_fp;
  25. int Loggable::_log_id = 0;
  26. int Loggable::_level = 0;
  27. int Loggable::_undo_index = 1;
  28. vector <Loggable *> Loggable::_loggables;
  29. bool
  30. Loggable::open ( const char *filename )
  31. {
  32. if ( ! ( Loggable::_fp = fopen( filename, "a+" ) ) )
  33. {
  34. printf( "Could not open log file for writing!" );
  35. return false;
  36. }
  37. return true;
  38. }
  39. /** sigh. parse a string of ":name value :name value" pairs into an array of strings, one per pair */
  40. static
  41. char **
  42. parse_alist( const char *s )
  43. {
  44. // FIXME: bogus over allocation...
  45. int tl = strlen( s );
  46. char **r = (char**)malloc( sizeof( char* ) * tl );
  47. const char *e = s + tl;
  48. const char *c = NULL;
  49. int i = 0;
  50. for ( ; ; s++ )
  51. {
  52. /* if ( *s == '\n' ) */
  53. /* break; */
  54. // if ( *s == ':' || s == e )
  55. if ( *s == ':' || *s == '\0' )
  56. {
  57. if ( c )
  58. {
  59. int l = s - c;
  60. char *pair = (char*)malloc( l + 1 );
  61. strncpy( pair, c, l );
  62. pair[ l ] = '\0';
  63. r[ i++ ] = pair;
  64. }
  65. c = s;
  66. if ( *s == '\0' )
  67. break;
  68. }
  69. }
  70. r[ i ] = NULL;
  71. return r;
  72. }
  73. void
  74. Loggable::undo ( void )
  75. {
  76. char *buf = new char[ BUFSIZ ];
  77. // fflush( _fp );
  78. fseek( _fp, 0, SEEK_END );
  79. size_t len = ftell( _fp );
  80. fseek( _fp, 0 - (BUFSIZ > len ? len : BUFSIZ), SEEK_END );
  81. len = fread( buf, 1, BUFSIZ, _fp );
  82. char *s = buf + len - 1;
  83. // FIXME: handle blocks
  84. int i = 1;
  85. /* move back _undo_index lines from the end */
  86. for ( int j = _undo_index; j-- ; )
  87. for ( --s; *s && s >= buf; --s, ++i )
  88. {
  89. if ( *s == '\n' )
  90. {
  91. // s++;
  92. break;
  93. }
  94. }
  95. s++;
  96. buf[ len ] = NULL;
  97. // fsync( fileno( _fp ) );
  98. /* pop the entry off the end */
  99. /* fseek( _fp, 0 - i, SEEK_END ); */
  100. /* ftruncate( fileno( _fp ), ftell( _fp ) ); */
  101. if ( ! strlen( s ) )
  102. {
  103. printf( "corrupt undo file or no undo entries.\n" );
  104. return;
  105. }
  106. printf( "undoing \"%s\"\n", s );
  107. int id;
  108. sscanf( s, "%*s %X ", &id );
  109. Loggable *l = find( id );
  110. assert( l );
  111. char command[40];
  112. char *arguments;
  113. sscanf( s, "%*s %*X %s %*[^\n<] << %a[^\n]", command, &arguments );
  114. if ( ! strcmp( command, "set" ) )
  115. {
  116. printf( "got set command.\n" );
  117. char **sa = parse_alist( arguments );
  118. l->set( sa );
  119. }
  120. ++_undo_index;
  121. delete buf;
  122. }
  123. void
  124. Loggable::log ( const char *fmt, ... )
  125. {
  126. va_list args;
  127. if ( fmt )
  128. {
  129. va_start( args, fmt );
  130. vfprintf( _fp, fmt, args );
  131. va_end( args );
  132. }
  133. fflush( _fp );
  134. }
  135. static
  136. void free_sa ( char **sa )
  137. {
  138. char **a = sa;
  139. for ( ; *a; a++ )
  140. free( *a );
  141. free( sa );
  142. }
  143. void
  144. Loggable::log_print( char **o, char **n )
  145. {
  146. if ( n )
  147. for ( ; *n; n++ )
  148. log( "%s%s", *n, *(n + 1) ? " " : "" );
  149. if ( o && *o )
  150. {
  151. if ( n ) log( " << " );
  152. for ( ; *o; o++ )
  153. log( "%s%s", *o, *(o + 1) ? " " : "" );
  154. }
  155. log( "\n" );
  156. }
  157. /** compare elements of dumps s1 and s2, removing those elements
  158. of dst which are not changed from src */
  159. static
  160. bool
  161. log_diff ( char **sa1, char **sa2 )
  162. {
  163. if ( ! sa1 )
  164. return true;
  165. int w = 0;
  166. for ( int i = 0; sa1[ i ]; ++i )
  167. {
  168. if ( ! strcmp( sa1[ i ], sa2[ i ] ) )
  169. {
  170. free( sa2[ i ] );
  171. free( sa1[ i ] );
  172. }
  173. else
  174. {
  175. sa2[ w ] = sa2[ i ];
  176. sa1[ w ] = sa1[ i ];
  177. w++;
  178. }
  179. }
  180. sa1[ w ] = NULL;
  181. sa2[ w ] = NULL;
  182. return w == 0 ? false : true;
  183. }
  184. void
  185. Loggable::log_start ( void )
  186. {
  187. if ( ! _old_state )
  188. _old_state = log_dump();
  189. ++_nest;
  190. }
  191. void
  192. Loggable::log_end ( void )
  193. {
  194. if ( --_nest > 0 )
  195. return;
  196. // assert( _old_state );
  197. char **_new_state = log_dump();
  198. // if ( _old_state )
  199. if ( log_diff( _old_state, _new_state ) )
  200. {
  201. indent();
  202. log( "%s 0x%X set ", class_name(), _id );
  203. log_print( _old_state, _new_state );
  204. }
  205. if ( _new_state )
  206. free_sa( _new_state );
  207. if ( _old_state )
  208. free_sa( _old_state );
  209. _old_state = NULL;
  210. /* if ( _old_state ) */
  211. /* { */
  212. /* free_sa( _old_state ); */
  213. /* _old_state = NULL; */
  214. /* } */
  215. // _old_state = NULL;
  216. }
  217. void
  218. Loggable::log_create ( void )
  219. {
  220. indent();
  221. log( "%s 0x%X new ", class_name(), _id );
  222. char **sa = log_dump();
  223. if ( sa )
  224. {
  225. log_print( NULL, sa );
  226. free_sa( sa );
  227. }
  228. else
  229. log( "\n" );
  230. }
  231. void
  232. Loggable::log_destroy ( void )
  233. {
  234. indent();
  235. log( "%s 0x%X destroy ", class_name(), _id );
  236. char **sa = log_dump();
  237. log_print( sa, NULL );
  238. free_sa( sa );
  239. }