RemixCount remix_seek (RemixEnv * env, RemixBase * base, RemixCount offset, int whence);
RemixCount remix_tell (RemixEnv * env, RemixBase * base);
int remix_flush (RemixEnv * env, RemixBase * base);
+int remix_reset (RemixEnv * env, RemixBase * base);
RemixCount remix_set_mixlength (RemixEnv * env, RemixCount mixlength);
RemixCount remix_get_mixlength (RemixEnv * env);
RemixStream * input,
RemixStream * output);
typedef int (*RemixFlushFunc) (RemixEnv * env, RemixBase * base);
+typedef int (*RemixResetFunc) (RemixEnv * env, RemixBase * base);
#define REMIX_FLAGS_NONE (0)
RemixLengthFunc length;
RemixSeekFunc seek;
RemixFlushFunc flush;
+ RemixResetFunc reset;
};
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
Name: libremix
Summary: An audio sequencing and mixing library.
-Version: 0.2.4+slp2+build02
+Version: 0.2.4+build14
Release: 1
Group: Libraries/Sound
License: LGPLv2.1
%install
if [ -d %{buildroot} ]; then rm -rf %{buildroot}; fi
make install DESTDIR=%{buildroot}
+mkdir -p %{buildroot}/usr/share/license
+cp %{_builddir}/%{buildsubdir}/COPYING %{buildroot}/usr/share/license/%{name}
%clean
if [ -d %{buildroot} ]; then rm -rf %{buildroot}; fi
%defattr(-,root,root,-)
%doc AUTHORS COPYING ChangeLog INSTALL NEWS README TODO doc
%{_libdir}/libremix.so.*
+%{_libdir}/libctxdata.so*
+%manifest %{name}.manifest
+/usr/share/license/%{name}
%files devel
%defattr(-,root,root,-)
CDList *
cd_list_remove (void * ctx, CDList * list, CDScalarType type, CDScalar data)
{
- CDList * l = cd_list_find (ctx, list, type, data);
+ CDList *ret_node, * l = cd_list_find (ctx, list, type, data);
if (l == NULL) return list;
if (l->prev) l->prev->next = l->next;
if (l->next) l->next->prev = l->prev;
- if (l == list) return list->next;
- else return list;
+ ret_node = (l != list) ? list : list->next;
+ //free the element here to avoid memory leak, otherwise reference is lost
+ //and a dangling pointer.
+ cd_free (l);
+
+ return ret_node;
}
CDList *
}
/*
+ * cd_list_call_destroy (ctx, list, destroy)
+ *
+ * Step through list 'list', calling AxDestroyFunc destroy function on each.
+ */
+CDList *
+cd_list_call_destroy (void * ctx, CDList * list, CDDestroyFunc destroy)
+{
+ CDList * l, * ln;
+
+ for (l = list; l; l = ln) {
+ ln = l->next;
+ destroy (ctx, l->data.s_pointer);
+ }
+
+ return NULL;
+}
+
+/*
* cd_list_free_all (ctx, list)
*
* Step through list 'list', freeing each item using cd_free(), and
{
RemixBase * base = remix_malloc (size);
_remix_context_copy (env, &base->context_limit);
- _remix_register_base (env, base);
+ //Don't register/unregister base unncessarily
+ //_remix_register_base (env, base);
return base;
}
return -1;
}
- _remix_unregister_base (env, base);
+ //Don't register/unregister base unncessarily
+ //_remix_unregister_base (env, base);
if (!base->methods || !base->methods->destroy) {
remix_set_error (env, REMIX_ERROR_INVALID);
return -1;
}
+
+ if (base && base->context_limit.channels) {
+ //free the cloned copy of channels to avoid memory leak.
+ cd_set_free(env, base->context_limit.channels);
+ }
+
return _remix_destroy (env, base);
}
return _remix_flush (env, base);
}
+int
+remix_reset (RemixEnv * env, RemixBase * base)
+{
+ if (!base) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+ if (!base->methods || !base->methods->reset) {
+ remix_set_error (env, REMIX_ERROR_INVALID);
+ return -1;
+ }
+ return _remix_reset (env, base);
+}
+
RemixMetaText *
remix_get_meta_text (RemixEnv * env, RemixBase * base)
{
world->refcount = 0;
world->plugins = cd_list_new (ctx);
- world->bases = cd_list_new (ctx);
+ //No need to record bases, as individual destroy will take care. Commenting to Fix Memory leak.
+ //world->bases = cd_list_new (ctx);
world->purging = FALSE;
ctx->mixlength = REMIX_DEFAULT_MIXLENGTH;
RemixEnv *
_remix_register_base (RemixEnv * env, RemixBase * base)
{
- RemixWorld * world = env->world;
- world->bases = cd_list_append (env, world->bases, CD_POINTER(base));
+ //As world->bases is not initialized and used, so should not add it to env
+ //RemixWorld * world = env->world;
+ //world->bases = cd_list_append (env, world->bases, CD_POINTER(base));
return env;
}
RemixWorld * world = env->world;
if (world->purging) return env;
- world->bases = cd_list_remove (env, world->bases, CD_TYPE_POINTER,
- CD_POINTER(base));
+ //As world->bases is not initialized and used, so should not remove it from env
+ //world->bases = cd_list_remove (env, world->bases, CD_TYPE_POINTER,
+ // CD_POINTER(base));
return env;
}
remix_deck_destroy (RemixEnv * env, RemixBase * base)
{
RemixDeck * deck = (RemixDeck *)base;
+
remix_destroy_list (env, deck->tracks);
remix_destroy (env, (RemixBase *)deck->_mixstream);
remix_free (deck);
remix_null_length, /* length */
NULL, /* seek */
NULL, /* flush */
+ NULL, /* reset */
};
static struct _RemixMethods _remix_deck_methods = {
remix_deck_length, /* length */
remix_deck_seek, /* seek */
remix_deck_flush, /* flush */
+ NULL, /* reset */
};
static struct _RemixMethods _remix_deck_onetrack_methods = {
remix_deck_length, /* length */
remix_deck_seek, /* seek */
remix_deck_flush, /* flush */
+ NULL, /* reset */
};
static struct _RemixMethods _remix_deck_twotrack_methods = {
remix_deck_length, /* length */
remix_deck_seek, /* seek */
remix_deck_flush, /* flush */
+ NULL, /* reset */
};
static RemixDeck *
remix_null_length,
remix_envelope_seek,
NULL, /* flush */
+ NULL, /* reset */
};
static struct _RemixMethods _remix_envelope_constant_methods = {
remix_envelope_length,
remix_envelope_seek,
NULL, /* flush */
+ NULL, /* reset */
};
static struct _RemixMethods _remix_envelope_linear_methods = {
remix_envelope_length,
remix_envelope_seek,
NULL, /* flush */
+ NULL, /* reset */
};
static struct _RemixMethods _remix_envelope_spline_methods = {
remix_envelope_length,
remix_envelope_seek,
NULL, /* flush */
+ NULL, /* reset */
};
static struct _RemixMethods _remix_envelope_methods = {
remix_envelope_length,
remix_envelope_seek,
NULL, /* flush */
+ NULL, /* reset */
};
static RemixEnvelope *
remix_layer_destroy (RemixEnv * env, RemixBase * base)
{
RemixLayer * layer = (RemixLayer *)base;
+
if (layer->track)
_remix_track_remove_layer (env, layer->track, layer);
- remix_destroy_list (env, layer->sounds);
+ //Just call destructor but dont delete item which is removed already.
+ //remix_destroy_list (env, layer->sounds);
+ cd_list_call_destroy(env, layer->sounds, (CDDestroyFunc)remix_destroy);
remix_free (layer);
return 0;
}
remix_layer_length, /* length */
remix_layer_seek, /* seek */
remix_layer_flush, /* flush */
+ NULL, /* reset */
};
static RemixLayer *
monitor->dev_dsp_fd = open (FILENAME, O_WRONLY, 0);
if (monitor->dev_dsp_fd == -1) {
- printf ("Couldn't open any output device.\n");
+ //printf ("Couldn't open any output device.\n");
remix_set_error (env, REMIX_ERROR_SYSTEM);
return RemixNone;
}
remix_monitor_length,
remix_monitor_seek,
remix_monitor_flush,
+ NULL, /* reset */
};
static RemixMonitor *
CDList * l;
RemixPluginInitFunc init;
- module = dlopen (path, RTLD_NOW);
+ module = dlopen (path, RTLD_LAZY);
if (!module) {
remix_dprintf ("[remix_plugin_init] Unable to open %s: %s\n", path,
(((RemixBase*)b)->methods->process ((a),((RemixBase*)b),(c),(i),(o)))
#define _remix_length(a,b) (((RemixBase*)b)->methods->length ((a), ((RemixBase*)b)))
#define _remix_flush(a,b) (((RemixBase*)b)->methods->flush ((a), ((RemixBase*)b)))
+#define _remix_reset(a,b) (((RemixBase*)b)->methods->reset ((a), ((RemixBase*)b)))
/* util */
return sf_seek (si->file, offset, SEEK_SET);
}
+static int
+remix_sndfile_reader_destroy (RemixEnv * env, RemixPlugin * plugin)
+{
+ cd_set_free (env, plugin->init_scheme);
+ return 0;
+}
+
+static int
+remix_sndfile_writer_destroy (RemixEnv * env, RemixPlugin * plugin)
+{
+ cd_set_free (env, plugin->init_scheme);
+ return 0;
+}
+
static struct _RemixMethods _remix_sndfile_reader_methods = {
remix_sndfile_clone,
remix_sndfile_destroy,
remix_sndfile_length,
remix_sndfile_seek,
NULL, /* flush */
+ NULL, /* reset */
};
static struct _RemixMethods _remix_sndfile_writer_methods = {
remix_sndfile_length,
remix_sndfile_seek,
NULL, /* flush */
+ NULL, /* reset */
};
static RemixBase *
CD_EMPTY_SET, /* process scheme */
NULL, /* suggests */
NULL, /* plugin data */
- NULL /* destroy */
+ remix_sndfile_reader_destroy /* destroy */
};
static struct _RemixPlugin sndfile_writer_plugin = {
CD_EMPTY_SET, /* process scheme */
NULL, /* suggests */
NULL, /* plugin data */
- NULL /* destroy */
+ remix_sndfile_writer_destroy /* destroy */
};
/* module init function */
remix_sound_length, /* length */
remix_sound_seek, /* seek */
remix_sound_flush, /* flush */
+ NULL, /* reset */
};
static RemixSound *
remix_squaretone_length,
remix_squaretone_seek,
NULL, /* flush */
+ NULL, /* reset */
};
static RemixSquareTone *
return -1;
}
- cd_set_destroy_with (env, stream->channels, (CDDestroyFunc)remix_destroy);
+ // RemixChannel doesnot inherit RemixBase, so register its own destructor explicitly.
+ cd_set_destroy_with (env, stream->channels, (CDDestroyFunc)remix_channel_destroy);
remix_free (stream);
return 0;
remix_stream_process,
remix_stream_length,
remix_stream_seek,
+ NULL, /* flush */
+ NULL, /* reset */
};
static RemixStream *
remix_track_destroy (RemixEnv * env, RemixBase * base)
{
RemixTrack * track = (RemixTrack *)base;
- remix_destroy_list (env, track->layers);
+ //Just call destructor but dont delete item which is removed already.
+ //remix_destroy_list (env, track->layers);
+ cd_list_call_destroy(env, track->layers, (CDDestroyFunc)remix_destroy);
+
+ if (track->_mixstream_a != RemixNone)
+ remix_destroy (env, (RemixBase *)track->_mixstream_a);
+ if (track->_mixstream_b != RemixNone)
+ remix_destroy (env, (RemixBase *)track->_mixstream_b);
remix_free (track);
return 0;
}
remix_null_length, /* length */
remix_null_seek, /* seek */
NULL, /* flush */
+ NULL, /* reset */
};
static struct _RemixMethods _remix_track_methods = {
remix_track_length, /* length */
remix_track_seek, /* seek */
remix_track_flush, /* flush */
+ NULL, /* reset */
};
static struct _RemixMethods _remix_track_onelayer_methods = {
remix_track_length, /* length */
remix_track_seek, /* seek */
remix_track_flush, /* flush */
+ NULL, /* reset */
};
static struct _RemixMethods _remix_track_twolayer_methods = {
remix_track_length, /* length */
remix_track_seek, /* seek */
remix_track_flush, /* flush */
+ NULL, /* reset */
};
static RemixTrack *
remix_ladspa_length,
NULL, /* seek */
NULL, /* flush */
+ NULL, /* reset */
};
static struct _RemixMethods _remix_ladspa_0_1_methods = {
remix_ladspa_length,
NULL, /* seek */
NULL, /* flush */
+ NULL, /* reset */
};
static struct _RemixMethods _remix_ladspa_1_1_methods = {
remix_ladspa_length,
NULL, /* seek */
NULL, /* flush */
+ NULL, /* reset */
};
remix_ladspa_length,
NULL, /* seek */
NULL, /* flush */
+ NULL, /* reset */
};
static RemixBase *
remix_noise_length,
NULL, /* seek */
NULL, /* flush */
+ NULL, /* reset */
};
static RemixBase *