Fix audio load fclose crashes
This commit is contained in:
parent
3ff0968538
commit
ee3ad5c0e0
|
@ -12,22 +12,22 @@
|
||||||
function u32
|
function u32
|
||||||
AtomicAddU32AndReturnOriginal(u32 volatile *Value, u32 Addend)
|
AtomicAddU32AndReturnOriginal(u32 volatile *Value, u32 Addend)
|
||||||
{
|
{
|
||||||
// NOTE(casey): Returns the original value _prior_ to adding
|
// NOTE(casey): Returns the original value _prior_ to adding
|
||||||
u32 Result = _InterlockedExchangeAdd((long volatile*)Value, (long)Addend);
|
u32 Result = _InterlockedExchangeAdd((long volatile*)Value, (long)Addend);
|
||||||
return(Result);
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
def_audio_begin_ticket_mutex(Audio_System *Crunky)
|
def_audio_begin_ticket_mutex(Audio_System *Crunky)
|
||||||
{
|
{
|
||||||
u32 Ticket = AtomicAddU32AndReturnOriginal(&Crunky->ticket, 1);
|
u32 Ticket = AtomicAddU32AndReturnOriginal(&Crunky->ticket, 1);
|
||||||
while(Ticket != Crunky->serving) {_mm_pause();}
|
while(Ticket != Crunky->serving) {_mm_pause();}
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
def_audio_end_ticket_mutex(Audio_System *Crunky)
|
def_audio_end_ticket_mutex(Audio_System *Crunky)
|
||||||
{
|
{
|
||||||
AtomicAddU32AndReturnOriginal(&Crunky->serving, 1);
|
AtomicAddU32AndReturnOriginal(&Crunky->serving, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,131 +38,131 @@ global Audio_System def_audio_system = {};
|
||||||
|
|
||||||
function void
|
function void
|
||||||
def_audio_init(void){
|
def_audio_init(void){
|
||||||
block_zero_struct(&def_audio_system);
|
block_zero_struct(&def_audio_system);
|
||||||
system_set_source_mixer(&def_audio_system, def_audio_mix_sources);
|
system_set_source_mixer(&def_audio_system, def_audio_mix_sources);
|
||||||
system_set_destination_mixer(def_audio_mix_destination);
|
system_set_destination_mixer(def_audio_mix_destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
def_audio_play_clip(Audio_Clip clip, Audio_Control *control){
|
def_audio_play_clip(Audio_Clip clip, Audio_Control *control){
|
||||||
clip.control = control;
|
clip.control = control;
|
||||||
Audio_System *Crunky = &def_audio_system;
|
Audio_System *Crunky = &def_audio_system;
|
||||||
def_audio_begin_ticket_mutex(Crunky);
|
def_audio_begin_ticket_mutex(Crunky);
|
||||||
if (Crunky->pending_clip_count < ArrayCount(Crunky->pending_clips))
|
if (Crunky->pending_clip_count < ArrayCount(Crunky->pending_clips))
|
||||||
{
|
{
|
||||||
Crunky->pending_clips[Crunky->pending_clip_count++] = clip;
|
Crunky->pending_clips[Crunky->pending_clip_count++] = clip;
|
||||||
}
|
}
|
||||||
def_audio_end_ticket_mutex(Crunky);
|
def_audio_end_ticket_mutex(Crunky);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal b32
|
internal b32
|
||||||
def_audio_is_playing(Audio_Control *control){
|
def_audio_is_playing(Audio_Control *control){
|
||||||
Audio_System *Crunky = &def_audio_system;
|
Audio_System *Crunky = &def_audio_system;
|
||||||
b32 result = (Crunky->generation - control->generation < 2);
|
b32 result = (Crunky->generation - control->generation < 2);
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
def_audio_stop(Audio_Control *control){
|
def_audio_stop(Audio_Control *control){
|
||||||
Audio_System *Crunky = &def_audio_system;
|
Audio_System *Crunky = &def_audio_system;
|
||||||
def_audio_begin_ticket_mutex(Crunky);
|
def_audio_begin_ticket_mutex(Crunky);
|
||||||
|
|
||||||
Audio_Clip *clip = Crunky->playing_clips;
|
Audio_Clip *clip = Crunky->playing_clips;
|
||||||
for(u32 i = 0;
|
for(u32 i = 0;
|
||||||
i < ArrayCount(Crunky->playing_clips);
|
i < ArrayCount(Crunky->playing_clips);
|
||||||
i += 1, clip += 1){
|
i += 1, clip += 1){
|
||||||
if (clip->control == control){
|
if (clip->control == control){
|
||||||
clip->at_sample_index = clip->sample_count;
|
clip->at_sample_index = clip->sample_count;
|
||||||
clip->control = 0;
|
clip->control = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
control->loop = false;
|
control->loop = false;
|
||||||
|
|
||||||
def_audio_end_ticket_mutex(Crunky);
|
def_audio_end_ticket_mutex(Crunky);
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
def_audio_mix_sources(void *ctx, f32 *mix_buffer, u32 sample_count){
|
def_audio_mix_sources(void *ctx, f32 *mix_buffer, u32 sample_count){
|
||||||
Audio_System *Crunky = (Audio_System*)ctx;
|
Audio_System *Crunky = (Audio_System*)ctx;
|
||||||
def_audio_begin_ticket_mutex(Crunky);
|
def_audio_begin_ticket_mutex(Crunky);
|
||||||
// NOTE(casey): Move pending sounds into the playing list
|
// NOTE(casey): Move pending sounds into the playing list
|
||||||
{
|
{
|
||||||
Crunky->generation += 1;
|
Crunky->generation += 1;
|
||||||
u32 PendIndex = 0;
|
u32 PendIndex = 0;
|
||||||
Audio_Clip *clip = Crunky->playing_clips;
|
Audio_Clip *clip = Crunky->playing_clips;
|
||||||
for(u32 DestIndex = 0;
|
for(u32 DestIndex = 0;
|
||||||
(DestIndex < ArrayCount(Crunky->playing_clips)) && (PendIndex < Crunky->pending_clip_count);
|
(DestIndex < ArrayCount(Crunky->playing_clips)) && (PendIndex < Crunky->pending_clip_count);
|
||||||
DestIndex += 1, clip += 1)
|
DestIndex += 1, clip += 1)
|
||||||
{
|
{
|
||||||
if (clip->at_sample_index == clip->sample_count)
|
if (clip->at_sample_index == clip->sample_count)
|
||||||
{
|
{
|
||||||
Audio_Control *control = clip->control;
|
Audio_Control *control = clip->control;
|
||||||
if (control == 0 || !control->loop){
|
if (control == 0 || !control->loop){
|
||||||
*clip = Crunky->pending_clips[PendIndex++];
|
*clip = Crunky->pending_clips[PendIndex++];
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Crunky->pending_clip_count = 0;
|
|
||||||
}
|
}
|
||||||
def_audio_end_ticket_mutex(Crunky);
|
}
|
||||||
|
}
|
||||||
|
Crunky->pending_clip_count = 0;
|
||||||
|
}
|
||||||
|
def_audio_end_ticket_mutex(Crunky);
|
||||||
|
|
||||||
|
// NOTE(casey): Mix all sounds into the output buffer
|
||||||
|
{
|
||||||
|
Audio_Clip *clip = Crunky->playing_clips;
|
||||||
|
for(u32 SoundIndex = 0;
|
||||||
|
SoundIndex < ArrayCount(Crunky->playing_clips);
|
||||||
|
SoundIndex += 1, clip += 1)
|
||||||
|
{
|
||||||
|
// NOTE(allen): Determine starting point
|
||||||
|
Audio_Control *control = clip->control;
|
||||||
|
if (control != 0 && control->loop && clip->at_sample_index == clip->sample_count){
|
||||||
|
clip->at_sample_index = 0;
|
||||||
|
}
|
||||||
|
u32 base_sample_index = clip->at_sample_index;
|
||||||
|
|
||||||
|
// NOTE(casey): Determine how many samples are left to play in this
|
||||||
|
// sound (possible none)
|
||||||
|
u32 SamplesToMix = clamp_top((clip->sample_count - clip->at_sample_index), sample_count);
|
||||||
|
clip->at_sample_index += SamplesToMix;
|
||||||
|
|
||||||
|
// NOTE(casey): Load the volume out of the control if there is one,
|
||||||
|
// and if there is, update the generation and sample index so
|
||||||
|
// external controllers can take action
|
||||||
|
f32 LeftVol = clip->channel_volume[0];
|
||||||
|
f32 RightVol = clip->channel_volume[1];
|
||||||
|
if(SamplesToMix && control != 0)
|
||||||
|
{
|
||||||
|
LeftVol *= control->channel_volume[0];
|
||||||
|
RightVol *= control->channel_volume[1];
|
||||||
|
control->generation = Crunky->generation;
|
||||||
|
control->last_played_sample_index = clip->at_sample_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(casey): Mix samples
|
||||||
|
for(u32 SampleIndex = 0;
|
||||||
|
SampleIndex < SamplesToMix;
|
||||||
|
++SampleIndex)
|
||||||
|
{
|
||||||
|
u32 src_index = 2*(base_sample_index + SampleIndex);
|
||||||
|
f32 Left = LeftVol *(f32)clip->samples[src_index + 0];
|
||||||
|
f32 Right = RightVol*(f32)clip->samples[src_index + 1];
|
||||||
|
|
||||||
// NOTE(casey): Mix all sounds into the output buffer
|
u32 dst_index = 2*SampleIndex;
|
||||||
{
|
mix_buffer[dst_index + 0] += Left;
|
||||||
Audio_Clip *clip = Crunky->playing_clips;
|
mix_buffer[dst_index + 1] += Right;
|
||||||
for(u32 SoundIndex = 0;
|
}
|
||||||
SoundIndex < ArrayCount(Crunky->playing_clips);
|
}
|
||||||
SoundIndex += 1, clip += 1)
|
}
|
||||||
{
|
|
||||||
// NOTE(allen): Determine starting point
|
|
||||||
Audio_Control *control = clip->control;
|
|
||||||
if (control != 0 && control->loop && clip->at_sample_index == clip->sample_count){
|
|
||||||
clip->at_sample_index = 0;
|
|
||||||
}
|
|
||||||
u32 base_sample_index = clip->at_sample_index;
|
|
||||||
|
|
||||||
// NOTE(casey): Determine how many samples are left to play in this
|
|
||||||
// sound (possible none)
|
|
||||||
u32 SamplesToMix = clamp_top((clip->sample_count - clip->at_sample_index), sample_count);
|
|
||||||
clip->at_sample_index += SamplesToMix;
|
|
||||||
|
|
||||||
// NOTE(casey): Load the volume out of the control if there is one,
|
|
||||||
// and if there is, update the generation and sample index so
|
|
||||||
// external controllers can take action
|
|
||||||
f32 LeftVol = clip->channel_volume[0];
|
|
||||||
f32 RightVol = clip->channel_volume[1];
|
|
||||||
if(SamplesToMix && control != 0)
|
|
||||||
{
|
|
||||||
LeftVol *= control->channel_volume[0];
|
|
||||||
RightVol *= control->channel_volume[1];
|
|
||||||
control->generation = Crunky->generation;
|
|
||||||
control->last_played_sample_index = clip->at_sample_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE(casey): Mix samples
|
|
||||||
for(u32 SampleIndex = 0;
|
|
||||||
SampleIndex < SamplesToMix;
|
|
||||||
++SampleIndex)
|
|
||||||
{
|
|
||||||
u32 src_index = 2*(base_sample_index + SampleIndex);
|
|
||||||
f32 Left = LeftVol *(f32)clip->samples[src_index + 0];
|
|
||||||
f32 Right = RightVol*(f32)clip->samples[src_index + 1];
|
|
||||||
|
|
||||||
u32 dst_index = 2*SampleIndex;
|
|
||||||
mix_buffer[dst_index + 0] += Left;
|
|
||||||
mix_buffer[dst_index + 1] += Right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
def_audio_mix_destination(i16 *dst, f32 *src, u32 sample_count){
|
def_audio_mix_destination(i16 *dst, f32 *src, u32 sample_count){
|
||||||
u32 opl = sample_count*2;
|
u32 opl = sample_count*2;
|
||||||
for(u32 i = 0; i < opl; i += 1){
|
for(u32 i = 0; i < opl; i += 1){
|
||||||
f32 sample = src[i];
|
f32 sample = src[i];
|
||||||
f32 sat_sample = clamp(-32768.f, sample, 32767.f);
|
f32 sat_sample = clamp(-32768.f, sample, 32767.f);
|
||||||
dst[i] = (i16)sat_sample;
|
dst[i] = (i16)sat_sample;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -174,97 +174,100 @@ def_audio_mix_destination(i16 *dst, f32 *src, u32 sample_count){
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct wave_fmt_data
|
struct wave_fmt_data
|
||||||
{
|
{
|
||||||
u16 wFormatTag;
|
u16 wFormatTag;
|
||||||
u16 wChannels;
|
u16 wChannels;
|
||||||
u32 dwSamplesPerSec;
|
u32 dwSamplesPerSec;
|
||||||
u32 dwAvgBytesPerSec;
|
u32 dwAvgBytesPerSec;
|
||||||
u16 wBlockAlign;
|
u16 wBlockAlign;
|
||||||
u16 wBitsPerSample;
|
u16 wBitsPerSample;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct riff_header
|
struct riff_header
|
||||||
{
|
{
|
||||||
u32 ID;
|
u32 ID;
|
||||||
u32 DataSize;
|
u32 DataSize;
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
function Audio_Clip
|
function Audio_Clip
|
||||||
audio_clip_from_wav_data(String_Const_u8 data){
|
audio_clip_from_wav_data(String_Const_u8 data){
|
||||||
Audio_Clip Result = {};
|
Audio_Clip Result = {};
|
||||||
|
|
||||||
if (data.size >= 4 && *(u32 *)data.str == *(u32 *)"RIFF"){
|
if (data.size >= 4 && *(u32 *)data.str == *(u32 *)"RIFF"){
|
||||||
// NOTE(casey): This ROM is in WAV format
|
// NOTE(casey): This ROM is in WAV format
|
||||||
|
|
||||||
riff_header *RootHeader = (riff_header *)data.str;
|
riff_header *RootHeader = (riff_header *)data.str;
|
||||||
|
|
||||||
wave_fmt_data *Format = 0;
|
wave_fmt_data *Format = 0;
|
||||||
u32 SampleDataSize = 0;
|
u32 SampleDataSize = 0;
|
||||||
i16 *Samples = 0;
|
i16 *Samples = 0;
|
||||||
|
|
||||||
u32 At = sizeof(riff_header);
|
u32 At = sizeof(riff_header);
|
||||||
u32 LastAt = At + ((RootHeader->DataSize + 1) & ~1);
|
u32 LastAt = At + ((RootHeader->DataSize + 1) & ~1);
|
||||||
if ((*(u32 *)(data.str + At) == *(u32 *)"WAVE") &&
|
if ((*(u32 *)(data.str + At) == *(u32 *)"WAVE") &&
|
||||||
(LastAt <= data.size)){
|
(LastAt <= data.size)){
|
||||||
At += sizeof(u32);
|
At += sizeof(u32);
|
||||||
while (At < LastAt){
|
while (At < LastAt){
|
||||||
riff_header *Header = (riff_header *)(data.str + At);
|
riff_header *Header = (riff_header *)(data.str + At);
|
||||||
u32 DataAt = At + sizeof(riff_header);
|
u32 DataAt = At + sizeof(riff_header);
|
||||||
u32 EndAt = DataAt + ((Header->DataSize + 1) & ~1);
|
u32 EndAt = DataAt + ((Header->DataSize + 1) & ~1);
|
||||||
if(EndAt <= data.size)
|
if(EndAt <= data.size)
|
||||||
{
|
{
|
||||||
void *Data = (data.str + DataAt);
|
void *Data = (data.str + DataAt);
|
||||||
if(Header->ID == *(u32 *)"fmt ")
|
if(Header->ID == *(u32 *)"fmt ")
|
||||||
{
|
{
|
||||||
Format = (wave_fmt_data *)Data;
|
Format = (wave_fmt_data *)Data;
|
||||||
}
|
}
|
||||||
else if(Header->ID == *(u32 *)"data")
|
else if(Header->ID == *(u32 *)"data")
|
||||||
{
|
{
|
||||||
SampleDataSize = Header->DataSize;
|
SampleDataSize = Header->DataSize;
|
||||||
Samples = (i16 *)Data;
|
Samples = (i16 *)Data;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
At = EndAt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Format &&
|
|
||||||
Samples &&
|
|
||||||
(Format->wFormatTag == 1) &&
|
|
||||||
(Format->wChannels == 2) &&
|
|
||||||
(Format->wBitsPerSample == 16) &&
|
|
||||||
(Format->dwSamplesPerSec == 48000)){
|
|
||||||
for (u32 i = 0; i < 2; i += 1){
|
|
||||||
Result.channel_volume[i] = 1.f;
|
|
||||||
}
|
|
||||||
Result.sample_count = SampleDataSize / (Format->wChannels*Format->wBitsPerSample/8);
|
|
||||||
Result.samples = (i16 *)Samples;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
// TODO(casey): This is where you would output an error - to 4coder somehow?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
// TODO(casey): This is where you would output an error - to 4coder somehow?
|
|
||||||
}
|
|
||||||
|
|
||||||
return(Result);
|
At = EndAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Format &&
|
||||||
|
Samples &&
|
||||||
|
(Format->wFormatTag == 1) &&
|
||||||
|
(Format->wChannels == 2) &&
|
||||||
|
(Format->wBitsPerSample == 16) &&
|
||||||
|
(Format->dwSamplesPerSec == 48000)){
|
||||||
|
for (u32 i = 0; i < 2; i += 1){
|
||||||
|
Result.channel_volume[i] = 1.f;
|
||||||
|
}
|
||||||
|
Result.sample_count = SampleDataSize / (Format->wChannels*Format->wBitsPerSample/8);
|
||||||
|
Result.samples = (i16 *)Samples;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// TODO(casey): This is where you would output an error - to 4coder somehow?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// TODO(casey): This is where you would output an error - to 4coder somehow?
|
||||||
|
}
|
||||||
|
|
||||||
|
return(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Audio_Clip
|
function Audio_Clip
|
||||||
audio_clip_from_wav_FILE(Arena *arena, FILE *file){
|
audio_clip_from_wav_FILE(Arena *arena, FILE *file){
|
||||||
String_Const_u8 data = data_from_file(arena, file);
|
String_Const_u8 data = data_from_file(arena, file);
|
||||||
Audio_Clip result = audio_clip_from_wav_data(data);
|
Audio_Clip result = audio_clip_from_wav_data(data);
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Audio_Clip
|
function Audio_Clip
|
||||||
audio_clip_from_wav_file_name(Arena *arena, char *file_name){
|
audio_clip_from_wav_file_name(Arena *arena, char *file_name){
|
||||||
String_Const_u8 data = {};
|
Audio_Clip result = {};
|
||||||
FILE *file = fopen(file_name, "rb");
|
String_Const_u8 data = {};
|
||||||
Audio_Clip result = audio_clip_from_wav_FILE(arena, file);
|
FILE *file = fopen(file_name, "rb");
|
||||||
fclose(file);
|
if (file != 0){
|
||||||
return(result);
|
result = audio_clip_from_wav_FILE(arena, file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,18 +10,18 @@ customization writers.
|
||||||
CUSTOM_COMMAND_SIG(double_backspace)
|
CUSTOM_COMMAND_SIG(double_backspace)
|
||||||
CUSTOM_DOC("Example of history group helpers")
|
CUSTOM_DOC("Example of history group helpers")
|
||||||
{
|
{
|
||||||
/* History_Group is a wrapper around the history API that makes it easy to
|
/* History_Group is a wrapper around the history API that makes it easy to
|
||||||
group any series of edits into a single undo/redo record in the buffer's history.
|
group any series of edits into a single undo/redo record in the buffer's history.
|
||||||
Before any edits call history_group_begin and afterwards call history_group_end.
|
Before any edits call history_group_begin and afterwards call history_group_end.
|
||||||
After history_group_end all of the edits to the buffer supplied in history_group_begin
|
After history_group_end all of the edits to the buffer supplied in history_group_begin
|
||||||
will be merged, including all edits from function and command calls. */
|
will be merged, including all edits from function and command calls. */
|
||||||
|
|
||||||
View_ID view = get_active_view(app, Access_ReadWriteVisible);
|
View_ID view = get_active_view(app, Access_ReadWriteVisible);
|
||||||
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible);
|
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible);
|
||||||
History_Group group = history_group_begin(app, buffer);
|
History_Group group = history_group_begin(app, buffer);
|
||||||
backspace_char(app);
|
backspace_char(app);
|
||||||
backspace_char(app);
|
backspace_char(app);
|
||||||
history_group_end(group);
|
history_group_end(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
// tags: query; bar
|
// tags: query; bar
|
||||||
|
@ -29,8 +29,8 @@ will be merged, including all edits from function and command calls. */
|
||||||
CUSTOM_COMMAND_SIG(play_with_a_counter)
|
CUSTOM_COMMAND_SIG(play_with_a_counter)
|
||||||
CUSTOM_DOC("Example of query bar")
|
CUSTOM_DOC("Example of query bar")
|
||||||
{
|
{
|
||||||
/* Query bars make a quick lightweight display of a single line of text for interactive
|
/* Query bars make a quick lightweight display of a single line of text for interactive
|
||||||
commands, while still showing the buffer. Query bars are convenient because they don't
|
commands, while still showing the buffer. Query bars are convenient because they don't
|
||||||
require any complex UI setup, or extra rendering work inside your command.
|
require any complex UI setup, or extra rendering work inside your command.
|
||||||
|
|
||||||
First, constructing a Query_Bar_Group is a convenient way to make sure the query bar
|
First, constructing a Query_Bar_Group is a convenient way to make sure the query bar
|
||||||
|
@ -40,49 +40,49 @@ Second, we make our query bar and start showing it with start_query_bar. Until w
|
||||||
call end_query_bar on the same bar, or the group's destructor runs, the bar struct
|
call end_query_bar on the same bar, or the group's destructor runs, the bar struct
|
||||||
needs to remain in memory. The easy way to accomplish this is to just let the bar be
|
needs to remain in memory. The easy way to accomplish this is to just let the bar be
|
||||||
on the commands stack frame. */
|
on the commands stack frame. */
|
||||||
|
|
||||||
i32 counter = 0;
|
i32 counter = 0;
|
||||||
|
|
||||||
Query_Bar_Group group(app);
|
Query_Bar_Group group(app);
|
||||||
Query_Bar dumb_bar = {};
|
Query_Bar dumb_bar = {};
|
||||||
dumb_bar.prompt = SCu8("Goes away at >= 10");
|
dumb_bar.prompt = SCu8("Goes away at >= 10");
|
||||||
if (!start_query_bar(app, &dumb_bar, 0)){
|
if (!start_query_bar(app, &dumb_bar, 0)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Query_Bar bar = {};
|
Query_Bar bar = {};
|
||||||
bar.prompt = SCu8("Counter = ");
|
bar.prompt = SCu8("Counter = ");
|
||||||
bar.string = SCu8("");
|
bar.string = SCu8("");
|
||||||
if (!start_query_bar(app, &bar, 0)){
|
if (!start_query_bar(app, &bar, 0)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;){
|
for (;;){
|
||||||
/* Notice here, we set the string of the query bar BEFORE we call get_next_input.
|
/* Notice here, we set the string of the query bar BEFORE we call get_next_input.
|
||||||
get_next_input blocks this command until the next input is sent from the core. Whatever
|
get_next_input blocks this command until the next input is sent from the core. Whatever
|
||||||
string we put in the bar now will be shown and remain in the bar until an event wakes
|
string we put in the bar now will be shown and remain in the bar until an event wakes
|
||||||
up this command and we get a chance to modify the bar again. */
|
up this command and we get a chance to modify the bar again. */
|
||||||
Scratch_Block scratch(app);
|
Scratch_Block scratch(app);
|
||||||
bar.string = push_stringf(scratch, "%d", counter);
|
bar.string = push_stringf(scratch, "%d", counter);
|
||||||
if (counter >= 10){
|
if (counter >= 10){
|
||||||
end_query_bar(app, &dumb_bar, 0);
|
end_query_bar(app, &dumb_bar, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
User_Input in = get_next_input(app, EventPropertyGroup_Any, EventProperty_Escape);
|
User_Input in = get_next_input(app, EventPropertyGroup_Any, EventProperty_Escape);
|
||||||
if (in.abort){
|
if (in.abort){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match_key_code(&in.event, KeyCode_Up)){
|
if (match_key_code(&in.event, KeyCode_Up)){
|
||||||
counter += 1;
|
counter += 1;
|
||||||
}
|
}
|
||||||
else if (match_key_code(&in.event, KeyCode_Down)){
|
else if (match_key_code(&in.event, KeyCode_Down)){
|
||||||
counter -= 1;
|
counter -= 1;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
leave_current_input_unhandled(app);
|
leave_current_input_unhandled(app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// tags: input; loop
|
// tags: input; loop
|
||||||
|
@ -90,46 +90,46 @@ up this command and we get a chance to modify the bar again. */
|
||||||
CUSTOM_COMMAND_SIG(display_key_codes)
|
CUSTOM_COMMAND_SIG(display_key_codes)
|
||||||
CUSTOM_DOC("Example of input handling loop")
|
CUSTOM_DOC("Example of input handling loop")
|
||||||
{
|
{
|
||||||
/* In the 4coder custom layer, inputs are handled by a view context. A view context is a
|
/* In the 4coder custom layer, inputs are handled by a view context. A view context is a
|
||||||
thread that hands off control with the main thread of the 4coder core. When a command is
|
thread that hands off control with the main thread of the 4coder core. When a command is
|
||||||
running in a view context thread, it can wait for inputs from the core by calling
|
running in a view context thread, it can wait for inputs from the core by calling
|
||||||
get_next_input. If your command gets inputs from the core, then default input handling
|
get_next_input. If your command gets inputs from the core, then default input handling
|
||||||
isn't happening, so command bindings don't trigger unless you trigger them yourself. */
|
isn't happening, so command bindings don't trigger unless you trigger them yourself. */
|
||||||
|
|
||||||
Query_Bar_Group group(app);
|
Query_Bar_Group group(app);
|
||||||
Query_Bar bar = {};
|
Query_Bar bar = {};
|
||||||
bar.prompt = SCu8("KeyCode = ");
|
bar.prompt = SCu8("KeyCode = ");
|
||||||
if (!start_query_bar(app, &bar, 0)){
|
if (!start_query_bar(app, &bar, 0)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Key_Code code = 0;
|
Key_Code code = 0;
|
||||||
b32 is_dead_key = false;
|
b32 is_dead_key = false;
|
||||||
|
|
||||||
for (;;){
|
for (;;){
|
||||||
Scratch_Block scratch(app);
|
Scratch_Block scratch(app);
|
||||||
if (code == 0){
|
if (code == 0){
|
||||||
bar.string = SCu8("...");
|
bar.string = SCu8("...");
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
bar.string = push_stringf(scratch, "KeyCode_%s (%d)%s", key_code_name[code], code,
|
bar.string = push_stringf(scratch, "KeyCode_%s (%d)%s", key_code_name[code], code,
|
||||||
is_dead_key?" dead-key":"");
|
is_dead_key?" dead-key":"");
|
||||||
}
|
}
|
||||||
User_Input in = get_next_input(app, EventPropertyGroup_Any, EventProperty_Escape);
|
User_Input in = get_next_input(app, EventPropertyGroup_Any, EventProperty_Escape);
|
||||||
if (in.abort){
|
if (in.abort){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (in.event.kind == InputEventKind_KeyStroke){
|
if (in.event.kind == InputEventKind_KeyStroke){
|
||||||
code = in.event.key.code;
|
code = in.event.key.code;
|
||||||
is_dead_key = event_is_dead_key(&in.event);
|
is_dead_key = event_is_dead_key(&in.event);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
/* Marking inputs as handled lets the core determine if certain inputs should
|
/* Marking inputs as handled lets the core determine if certain inputs should
|
||||||
be passed to additional handlers. This is especially important for text input,
|
be passed to additional handlers. This is especially important for text input,
|
||||||
which is explained more in the example display_text_input. */
|
which is explained more in the example display_text_input. */
|
||||||
leave_current_input_unhandled(app);
|
leave_current_input_unhandled(app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// tags: text; input
|
// tags: text; input
|
||||||
|
@ -137,41 +137,41 @@ isn't happening, so command bindings don't trigger unless you trigger them yours
|
||||||
CUSTOM_COMMAND_SIG(display_text_input)
|
CUSTOM_COMMAND_SIG(display_text_input)
|
||||||
CUSTOM_DOC("Example of to_writable and leave_current_input_unhandled")
|
CUSTOM_DOC("Example of to_writable and leave_current_input_unhandled")
|
||||||
{
|
{
|
||||||
/* In the 4coder custom layer, inputs are handled by a view context. A view context is a
|
/* In the 4coder custom layer, inputs are handled by a view context. A view context is a
|
||||||
thread that hands off control with the main thread of the 4coder core. When a command is
|
thread that hands off control with the main thread of the 4coder core. When a command is
|
||||||
running in a view context thread, it can wait for inputs from the core by calling
|
running in a view context thread, it can wait for inputs from the core by calling
|
||||||
get_next_input. If your command gets inputs from the core, then default input handling
|
get_next_input. If your command gets inputs from the core, then default input handling
|
||||||
isn't happening, so command bindings don't trigger unless you trigger them yourself. */
|
isn't happening, so command bindings don't trigger unless you trigger them yourself. */
|
||||||
|
|
||||||
Query_Bar_Group group(app);
|
Query_Bar_Group group(app);
|
||||||
Query_Bar bar = {};
|
Query_Bar bar = {};
|
||||||
bar.prompt = SCu8("Weird String: ");
|
bar.prompt = SCu8("Weird String: ");
|
||||||
if (!start_query_bar(app, &bar, 0)){
|
if (!start_query_bar(app, &bar, 0)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 buffer[256];
|
u8 buffer[256];
|
||||||
u64 size = 0;
|
u64 size = 0;
|
||||||
|
|
||||||
for (;;){
|
for (;;){
|
||||||
User_Input in = get_next_input(app, EventPropertyGroup_Any, EventProperty_Escape);
|
User_Input in = get_next_input(app, EventPropertyGroup_Any, EventProperty_Escape);
|
||||||
if (in.abort){
|
if (in.abort){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
String_Const_u8 in_string = to_writable(&in);
|
String_Const_u8 in_string = to_writable(&in);
|
||||||
if (in_string.size > 0){
|
if (in_string.size > 0){
|
||||||
size = clamp_top(in_string.size, sizeof(buffer));
|
size = clamp_top(in_string.size, sizeof(buffer));
|
||||||
block_copy(buffer, in_string.str, size);
|
block_copy(buffer, in_string.str, size);
|
||||||
bar.string = SCu8(buffer, size);
|
bar.string = SCu8(buffer, size);
|
||||||
}
|
}
|
||||||
else if (in.event.kind == InputEventKind_KeyStroke){
|
else if (in.event.kind == InputEventKind_KeyStroke){
|
||||||
/* If we handle a key stroke then the core marks any text input generated from that
|
/* If we handle a key stroke then the core marks any text input generated from that
|
||||||
key stroke as handled too, and the text input is never passed. By marking key strokes
|
key stroke as handled too, and the text input is never passed. By marking key strokes
|
||||||
as unhandled, we ensure we get text input events. */
|
as unhandled, we ensure we get text input events. */
|
||||||
leave_current_input_unhandled(app);
|
leave_current_input_unhandled(app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// tags: string; number; query; user
|
// tags: string; number; query; user
|
||||||
|
@ -179,33 +179,33 @@ as unhandled, we ensure we get text input events. */
|
||||||
CUSTOM_COMMAND_SIG(string_repeat)
|
CUSTOM_COMMAND_SIG(string_repeat)
|
||||||
CUSTOM_DOC("Example of query_user_string and query_user_number")
|
CUSTOM_DOC("Example of query_user_string and query_user_number")
|
||||||
{
|
{
|
||||||
Query_Bar_Group group(app);
|
Query_Bar_Group group(app);
|
||||||
Query_Bar string_bar = {};
|
Query_Bar string_bar = {};
|
||||||
string_bar.prompt = SCu8("String: ");
|
string_bar.prompt = SCu8("String: ");
|
||||||
u8 string_buffer[KB(1)];
|
u8 string_buffer[KB(1)];
|
||||||
string_bar.string.str = string_buffer;
|
string_bar.string.str = string_buffer;
|
||||||
string_bar.string_capacity = sizeof(string_buffer);
|
string_bar.string_capacity = sizeof(string_buffer);
|
||||||
Query_Bar number_bar = {};
|
Query_Bar number_bar = {};
|
||||||
number_bar.prompt = SCu8("Repeat Count: ");
|
number_bar.prompt = SCu8("Repeat Count: ");
|
||||||
u8 number_buffer[KB(1)];
|
u8 number_buffer[KB(1)];
|
||||||
number_bar.string.str = number_buffer;
|
number_bar.string.str = number_buffer;
|
||||||
number_bar.string_capacity = sizeof(number_buffer);
|
number_bar.string_capacity = sizeof(number_buffer);
|
||||||
|
|
||||||
if (query_user_string(app, &string_bar)){
|
if (query_user_string(app, &string_bar)){
|
||||||
if (string_bar.string.size > 0){
|
if (string_bar.string.size > 0){
|
||||||
if (query_user_number(app, &number_bar)){
|
if (query_user_number(app, &number_bar)){
|
||||||
if (number_bar.string.size > 0){
|
if (number_bar.string.size > 0){
|
||||||
i32 repeats = (i32)string_to_integer(number_bar.string, 10);
|
i32 repeats = (i32)string_to_integer(number_bar.string, 10);
|
||||||
repeats = clamp_top(repeats, 1000);
|
repeats = clamp_top(repeats, 1000);
|
||||||
Scratch_Block scratch(app);
|
Scratch_Block scratch(app);
|
||||||
String_Const_u8 msg = push_stringf(scratch, "%.*s\n", string_expand(string_bar.string));
|
String_Const_u8 msg = push_stringf(scratch, "%.*s\n", string_expand(string_bar.string));
|
||||||
for (i32 i = 0; i < repeats; i += 1){
|
for (i32 i = 0; i < repeats; i += 1){
|
||||||
print_message(app, msg);
|
print_message(app, msg);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
global Audio_Control the_music_control = {};
|
global Audio_Control the_music_control = {};
|
||||||
|
@ -213,50 +213,54 @@ global Audio_Control the_music_control = {};
|
||||||
CUSTOM_COMMAND_SIG(music_start)
|
CUSTOM_COMMAND_SIG(music_start)
|
||||||
CUSTOM_DOC("Starts the music.")
|
CUSTOM_DOC("Starts the music.")
|
||||||
{
|
{
|
||||||
local_persist Audio_Clip the_music_clip = {};
|
local_persist Audio_Clip the_music_clip = {};
|
||||||
if (the_music_clip.sample_count == 0){
|
if (the_music_clip.sample_count == 0){
|
||||||
Scratch_Block scratch(app);
|
Scratch_Block scratch(app);
|
||||||
FILE *file = def_search_normal_fopen(scratch, "audio_test/chtulthu.wav", "rb");
|
FILE *file = def_search_normal_fopen(scratch, "audio_test/chtulthu.wav", "rb");
|
||||||
the_music_clip = audio_clip_from_wav_FILE(&global_permanent_arena, file);
|
if (file != 0){
|
||||||
fclose(file);
|
the_music_clip = audio_clip_from_wav_FILE(&global_permanent_arena, file);
|
||||||
}
|
fclose(file);
|
||||||
|
}
|
||||||
if (!def_audio_is_playing(&the_music_control)){
|
}
|
||||||
the_music_control.loop = true;
|
|
||||||
the_music_control.channel_volume[0] = 1.f;
|
if (!def_audio_is_playing(&the_music_control)){
|
||||||
the_music_control.channel_volume[1] = 1.f;
|
the_music_control.loop = true;
|
||||||
def_audio_play_clip(the_music_clip, &the_music_control);
|
the_music_control.channel_volume[0] = 1.f;
|
||||||
}
|
the_music_control.channel_volume[1] = 1.f;
|
||||||
|
def_audio_play_clip(the_music_clip, &the_music_control);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_COMMAND_SIG(music_stop)
|
CUSTOM_COMMAND_SIG(music_stop)
|
||||||
CUSTOM_DOC("Stops the music.")
|
CUSTOM_DOC("Stops the music.")
|
||||||
{
|
{
|
||||||
def_audio_stop(&the_music_control);
|
def_audio_stop(&the_music_control);
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_COMMAND_SIG(hit_sfx)
|
CUSTOM_COMMAND_SIG(hit_sfx)
|
||||||
CUSTOM_DOC("Play the hit sound effect")
|
CUSTOM_DOC("Play the hit sound effect")
|
||||||
{
|
{
|
||||||
local_persist Audio_Clip the_hit_clip = {};
|
local_persist Audio_Clip the_hit_clip = {};
|
||||||
if (the_hit_clip.sample_count == 0){
|
if (the_hit_clip.sample_count == 0){
|
||||||
Scratch_Block scratch(app);
|
Scratch_Block scratch(app);
|
||||||
FILE *file = def_search_normal_fopen(scratch, "audio_test/hit.wav", "rb");
|
FILE *file = def_search_normal_fopen(scratch, "audio_test/hit.wav", "rb");
|
||||||
the_hit_clip = audio_clip_from_wav_FILE(&global_permanent_arena, file);
|
if (file != 0){
|
||||||
fclose(file);
|
the_hit_clip = audio_clip_from_wav_FILE(&global_permanent_arena, file);
|
||||||
}
|
fclose(file);
|
||||||
|
}
|
||||||
local_persist u32 index = 0;
|
}
|
||||||
local_persist Audio_Control controls[8] = {};
|
|
||||||
|
local_persist u32 index = 0;
|
||||||
Audio_Control *control = &controls[index%8];
|
local_persist Audio_Control controls[8] = {};
|
||||||
if (!def_audio_is_playing(control)){
|
|
||||||
control->loop = false;
|
Audio_Control *control = &controls[index%8];
|
||||||
control->channel_volume[0] = 1.f;
|
if (!def_audio_is_playing(control)){
|
||||||
control->channel_volume[1] = 1.f;
|
control->loop = false;
|
||||||
def_audio_play_clip(the_hit_clip, control);
|
control->channel_volume[0] = 1.f;
|
||||||
index += 1;
|
control->channel_volume[1] = 1.f;
|
||||||
}
|
def_audio_play_clip(the_hit_clip, control);
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -340,7 +340,7 @@ static Command_Metadata fcoder_metacmd_table[252] = {
|
||||||
{ PROC_LINKS(goto_prev_jump_no_skips, 0), false, "goto_prev_jump_no_skips", 23, "If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, and does not skip sub jump locations.", 136, "../code/custom/4coder_jump_sticky.cpp", 37, 511 },
|
{ PROC_LINKS(goto_prev_jump_no_skips, 0), false, "goto_prev_jump_no_skips", 23, "If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, and does not skip sub jump locations.", 136, "../code/custom/4coder_jump_sticky.cpp", 37, 511 },
|
||||||
{ PROC_LINKS(hide_filebar, 0), false, "hide_filebar", 12, "Sets the current view to hide it's filebar.", 43, "../code/custom/4coder_base_commands.cpp", 39, 704 },
|
{ PROC_LINKS(hide_filebar, 0), false, "hide_filebar", 12, "Sets the current view to hide it's filebar.", 43, "../code/custom/4coder_base_commands.cpp", 39, 704 },
|
||||||
{ PROC_LINKS(hide_scrollbar, 0), false, "hide_scrollbar", 14, "Sets the current view to hide it's scrollbar.", 45, "../code/custom/4coder_base_commands.cpp", 39, 690 },
|
{ PROC_LINKS(hide_scrollbar, 0), false, "hide_scrollbar", 14, "Sets the current view to hide it's scrollbar.", 45, "../code/custom/4coder_base_commands.cpp", 39, 690 },
|
||||||
{ PROC_LINKS(hit_sfx, 0), false, "hit_sfx", 7, "Play the hit sound effect", 25, "../code/custom/4coder_examples.cpp", 34, 238 },
|
{ PROC_LINKS(hit_sfx, 0), false, "hit_sfx", 7, "Play the hit sound effect", 25, "../code/custom/4coder_examples.cpp", 34, 240 },
|
||||||
{ PROC_LINKS(hms_demo_tutorial, 0), false, "hms_demo_tutorial", 17, "Tutorial for built in 4coder bindings and features.", 51, "../code/custom/4coder_tutorial.cpp", 34, 869 },
|
{ PROC_LINKS(hms_demo_tutorial, 0), false, "hms_demo_tutorial", 17, "Tutorial for built in 4coder bindings and features.", 51, "../code/custom/4coder_tutorial.cpp", 34, 869 },
|
||||||
{ PROC_LINKS(if0_off, 0), false, "if0_off", 7, "Surround the range between the cursor and mark with an '#if 0' and an '#endif'", 78, "../code/custom/4coder_combined_write_commands.cpp", 49, 70 },
|
{ PROC_LINKS(if0_off, 0), false, "if0_off", 7, "Surround the range between the cursor and mark with an '#if 0' and an '#endif'", 78, "../code/custom/4coder_combined_write_commands.cpp", 49, 70 },
|
||||||
{ PROC_LINKS(if_read_only_goto_position, 0), false, "if_read_only_goto_position", 26, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "../code/custom/4coder_jump_sticky.cpp", 37, 564 },
|
{ PROC_LINKS(if_read_only_goto_position, 0), false, "if_read_only_goto_position", 26, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "../code/custom/4coder_jump_sticky.cpp", 37, 564 },
|
||||||
|
@ -416,7 +416,7 @@ static Command_Metadata fcoder_metacmd_table[252] = {
|
||||||
{ PROC_LINKS(multi_paste_interactive, 0), false, "multi_paste_interactive", 23, "Paste multiple lines from the clipboard history, controlled with arrow keys", 75, "../code/custom/4coder_clipboard.cpp", 35, 371 },
|
{ PROC_LINKS(multi_paste_interactive, 0), false, "multi_paste_interactive", 23, "Paste multiple lines from the clipboard history, controlled with arrow keys", 75, "../code/custom/4coder_clipboard.cpp", 35, 371 },
|
||||||
{ PROC_LINKS(multi_paste_interactive_quick, 0), false, "multi_paste_interactive_quick", 29, "Paste multiple lines from the clipboard history, controlled by inputing the number of lines to paste", 100, "../code/custom/4coder_clipboard.cpp", 35, 380 },
|
{ PROC_LINKS(multi_paste_interactive_quick, 0), false, "multi_paste_interactive_quick", 29, "Paste multiple lines from the clipboard history, controlled by inputing the number of lines to paste", 100, "../code/custom/4coder_clipboard.cpp", 35, 380 },
|
||||||
{ PROC_LINKS(music_start, 0), false, "music_start", 11, "Starts the music.", 17, "../code/custom/4coder_examples.cpp", 34, 213 },
|
{ PROC_LINKS(music_start, 0), false, "music_start", 11, "Starts the music.", 17, "../code/custom/4coder_examples.cpp", 34, 213 },
|
||||||
{ PROC_LINKS(music_stop, 0), false, "music_stop", 10, "Stops the music.", 16, "../code/custom/4coder_examples.cpp", 34, 232 },
|
{ PROC_LINKS(music_stop, 0), false, "music_stop", 10, "Stops the music.", 16, "../code/custom/4coder_examples.cpp", 34, 234 },
|
||||||
{ PROC_LINKS(open_all_code, 0), false, "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "../code/custom/4coder_project_commands.cpp", 42, 805 },
|
{ PROC_LINKS(open_all_code, 0), false, "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "../code/custom/4coder_project_commands.cpp", 42, 805 },
|
||||||
{ PROC_LINKS(open_all_code_recursive, 0), false, "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "../code/custom/4coder_project_commands.cpp", 42, 814 },
|
{ PROC_LINKS(open_all_code_recursive, 0), false, "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "../code/custom/4coder_project_commands.cpp", 42, 814 },
|
||||||
{ PROC_LINKS(open_file_in_quotes, 0), false, "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "../code/custom/4coder_base_commands.cpp", 39, 1576 },
|
{ PROC_LINKS(open_file_in_quotes, 0), false, "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "../code/custom/4coder_base_commands.cpp", 39, 1576 },
|
||||||
|
|
Binary file not shown.
|
@ -26,35 +26,39 @@ load_paths = {
|
||||||
|
|
||||||
commands = {
|
commands = {
|
||||||
.build_x64 = {
|
.build_x64 = {
|
||||||
.win = "echo build: x64 & bin\build.bat",
|
.win = "echo build: x64 & bin\\build.bat",
|
||||||
|
.linux = "echo build: x64 & bin/build-linux.sh",
|
||||||
.out = "*compilation*",
|
.out = "*compilation*",
|
||||||
.footer_panel = true,
|
.footer_panel = true,
|
||||||
.save_dirty_files = true,
|
.save_dirty_files = true,
|
||||||
.cursor_at_end = false,
|
.cursor_at_end = false,
|
||||||
},
|
},
|
||||||
.build_x86 = {
|
.build_x86 = {
|
||||||
.win = "echo build: x86 & bin\build.bat /DDEV_BUILD_X86",
|
.win = "echo build: x86 & bin\\build.bat /DDEV_BUILD_X86",
|
||||||
|
.linux = "echo build: x86 & bin/build-linux.sh /DDEV_BUILD_X86",
|
||||||
.out = "*compilation*",
|
.out = "*compilation*",
|
||||||
.footer_panel = true,
|
.footer_panel = true,
|
||||||
.save_dirty_files = true,
|
.save_dirty_files = true,
|
||||||
.cursor_at_end = false,
|
.cursor_at_end = false,
|
||||||
},
|
},
|
||||||
.package = {
|
.package = {
|
||||||
.win = "echo package & bin\package.bat",
|
.win = "echo package & bin\\package.bat",
|
||||||
|
.linux = "echo package & bin/package.sh",
|
||||||
.out = "*compilation*",
|
.out = "*compilation*",
|
||||||
.footer_panel = false,
|
.footer_panel = false,
|
||||||
.save_dirty_files = true,
|
.save_dirty_files = true,
|
||||||
.cursor_at_end = false,
|
.cursor_at_end = false,
|
||||||
},
|
},
|
||||||
.run_one_time = {
|
.run_one_time = {
|
||||||
.win = "pushd ..\build & one_time",
|
.win = "pushd ..\\build & one_time",
|
||||||
|
.linux = "pushd ../build & one_time",
|
||||||
.out = "*run*",
|
.out = "*run*",
|
||||||
.footer_panel = false,
|
.footer_panel = false,
|
||||||
.save_dirty_files = false,
|
.save_dirty_files = false,
|
||||||
.cursor_at_end = false,
|
.cursor_at_end = false,
|
||||||
},
|
},
|
||||||
.build_custom_api_docs = {
|
.build_custom_api_docs = {
|
||||||
.win = "custom\bin\build_one_time docs\4ed_doc_custom_api_main.cpp ..\build",
|
.win = "custom\\bin\\build_one_time docs\\4ed_doc_custom_api_main.cpp ..\\build",
|
||||||
.out = "*compilation*",
|
.out = "*compilation*",
|
||||||
.footer_panel = true,
|
.footer_panel = true,
|
||||||
.save_dirty_files = true,
|
.save_dirty_files = true,
|
||||||
|
|
Loading…
Reference in New Issue