/* Some of this based on ao/src/ao_wav.c */ int write_prelim_header(OggVorbis_File *vf, FILE *out, ogg_int64_t knownlength) { unsigned int size = 0x7fffffff; int channels = ov_info(vf,0)->channels; int samplerate = ov_info(vf,0)->rate; int bytespersec = channels*samplerate*bits/8; int align = channels*bits/8; int samplesize = bits; if(knownlength && knownlength*bits/8*channels < size) size = (unsigned int)(knownlength*bits/8*channels+44) ; memcpy(headbuf, "RIFF", 4); WRITE_U32(headbuf+4, size-8); memcpy(headbuf+8, "WAVE", 4); memcpy(headbuf+12, "fmt ", 4); WRITE_U32(headbuf+16, 16); WRITE_U16(headbuf+20, 1); /* format */ WRITE_U16(headbuf+22, channels); WRITE_U32(headbuf+24, samplerate); WRITE_U32(headbuf+28, bytespersec); WRITE_U16(headbuf+32, align); WRITE_U16(headbuf+34, samplesize); memcpy(headbuf+36, "data", 4); WRITE_U32(headbuf+40, size - 44); if(fwrite(headbuf, 1, 44, out) != 44) { fprintf(stderr, _("ERROR: Failed to write Wave header: %s\n"), strerror(errno)); return 1; } return 0; }
bool build_handshake_packet(nabto_connect* con, uint8_t* buffer, size_t bufferLength, size_t* packetLength) { uint8_t* packetPtr; /* * type, 1 bytes * flags, 1 bytes * nsi cp, 4 bytes * nsi sp, 4 bytes * nsi co, 4 bytes * id, 20 bytes */ size_t nonceLength = 38; uint8_t nonce[38]; uint8_t* noncePtr = nonce; packetPtr = insert_header(buffer, con->cpnsi, con->spnsi, NP_PACKET_HDR_TYPE_GW_CONN_U, false, 0, 0, con->consi); //NOTE: These type and flags must match the connection attributes set //in the unabto_tcp_fallback_connect_thread when a connection is //established. WRITE_U8(noncePtr, NP_GW_CONN_U_TYPE_TCP); noncePtr+=1; WRITE_U8(noncePtr, NP_GW_CONN_U_FLAG_RELIABLE); noncePtr+=1; WRITE_U32(noncePtr, con->cpnsi); noncePtr+=4; WRITE_U32(noncePtr, con->spnsi); noncePtr+=4; memcpy(noncePtr, con->consi, 8); noncePtr+=8; memcpy(noncePtr, con->gatewayId, 20); packetPtr = insert_payload(packetPtr, NP_PAYLOAD_TYPE_NONCE, nonce, nonceLength); *packetLength = packetPtr - buffer; insert_length(buffer, *packetLength); return true; }
/** * Build U_CONNECT response to GSP * @param buf the destination buffer * @param seq the sequence number * @param notif the result notification * @param nsi the nsi value of the connection * @param cpnsi the nsi of the clientpeer to put into the packet. * @param spnsi the nsi of the serverpeer to put into the packet. * @param isLocalConnectRsp true if a capabilities packet * @return the size of the response */ static size_t mk_gsp_connect_rsp(uint8_t* buf, uint16_t seq, uint32_t notif, uint32_t nsi, uint32_t cpnsi, uint32_t spnsi, bool isLocalConnectRsp) { uint8_t* ptr = insert_header(buf, cpnsi, spnsi, U_CONNECT, true, seq, 0, 0); ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_NOTIFY, 0, 8); WRITE_U32(ptr, notif); ptr += 4; WRITE_U32(ptr, nsi); ptr += 4; if (isLocalConnectRsp) { ptr = insert_capabilities(ptr, 1 /*unenc*/); } insert_length(buf, ptr - buf); return ptr - buf; }
static VC_CONTAINER_STATUS_T avi_finish_data_chunk( VC_CONTAINER_T *p_ctx, uint32_t chunk_size ) { VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; if (chunk_size) { /* Rewrite the chunk size, this won't be efficient if it happens often */ if (STREAM_SEEKABLE(p_ctx)) { SEEK(p_ctx, STREAM_POSITION(p_ctx) - chunk_size - 4); WRITE_U32(p_ctx, chunk_size, "Chunk Size"); SKIP_BYTES(p_ctx, chunk_size); } else { LOG_DEBUG(p_ctx, "warning, can't rewrite chunk size, data will be malformed"); status = VC_CONTAINER_ERROR_FAILED; } } AVI_END_CHUNK(p_ctx); if (status != VC_CONTAINER_SUCCESS) status = STREAM_STATUS(p_ctx); return status; }
static int ao_au_close(ao_device *device) { ao_au_internal *internal = (ao_au_internal *) device->internal; off_t size; unsigned char buf[4]; /* Try to find the total file length, including header */ size = ftell(device->file); /* It's not a problem if the lseek() fails; the AU * format does not require a file length. This is * useful for writing to non-seekable files (e.g. * pipes). */ if (size > 0) { internal->au.data_size = size - AU_HEADER_LEN; /* Rewind the file */ if (fseek(device->file, 8 /* offset of data_size */, SEEK_SET) < 0) { return 1; /* Seek failed; that's okay */ } /* Fill in the file length */ WRITE_U32 (buf, internal->au.data_size); if (fwrite(buf, sizeof(char), 4, device->file) < 4) { return 1; /* Header write failed; that's okay */ } } return 1; }
ssize_t microchip_udp_read(UDP_SOCKET socket, uint8_t* buf, size_t len, uint32_t* addr, uint16_t* port) { ssize_t rlen; #if NABTO_LOG_CHECK(NABTO_LOG_SEVERITY_TRACE) UDP_SOCKET_INFO* debug; uint32_t sourceIp; #endif if (UDPIsGetReady(socket)) { #if NABTO_LOG_CHECK(NABTO_LOG_SEVERITY_TRACE) debug = &UDPSocketInfo[socket]; READ_U32(sourceIp, &debug->remote.remoteNode.IPAddr.Val); #endif unabto_microchip_arp_add_resolved(&(UDPSocketInfo[socket].remote.remoteNode)); // *addr = ntohl(UDPSocketInfo[socket].remote.remoteNode.IPAddr.Val); WRITE_U32(addr, UDPSocketInfo[socket].remote.remoteNode.IPAddr.Val); *port = UDPSocketInfo[socket].remotePort; rlen = (ssize_t) UDPGetArray(buf, len); NABTO_LOG_TRACE(("UDP read length: %i, %" PRIu16 " <- " PRIip ":%" PRIu16, rlen, debug->localPort, MAKE_IP_PRINTABLE(sourceIp), debug->remotePort)); NABTO_LOG_BUFFER(NABTO_LOG_SEVERITY_TRACE, ("UDP in datagram"), buf, rlen); return rlen; } return 0; }
int rewrite_header(FILE *out, unsigned int written) { unsigned int length = written; length += 44; WRITE_U32(headbuf+4, length-8); WRITE_U32(headbuf+40, length-44); if(fseek(out, 0, SEEK_SET) != 0) return 1; if(fwrite(headbuf, 1, 44, out) != 44) { fprintf(stderr, _("ERROR: Failed to write Wave header: %s\n"), strerror(errno)); return 1; } return 0; }
/* Reconstruct nabto header with crypto payload header. */ uint8_t* reconstruct_header(uint8_t* buf, const nabto_packet_header * hdr) { uint8_t* ptr; // insert copy of request header (Length will be inserted later) ptr = buf; /* Write fixed part of packet header */ WRITE_U32(ptr, hdr->nsi_cp); ptr += 4; WRITE_U32(ptr, hdr->nsi_sp); ptr += 4; WRITE_U8(ptr, hdr->type); ptr += 1; WRITE_U8(ptr, hdr->version); ptr += 1; WRITE_U8(ptr, hdr->rsvd); ptr += 1; WRITE_U8(ptr, hdr->flags | NP_PACKET_HDR_FLAG_RESPONSE); ptr += 1; WRITE_U16(ptr, hdr->seq); ptr += 2; /*WRITE_U16(ptr, len);*/ ptr += 2; /* Length to be packed later */ /* Write NSI.co to packet header (optional) */ if (hdr->flags & NP_PACKET_HDR_FLAG_NSI_CO) { memcpy(ptr, (const void*) hdr->nsi_co, 8); ptr += 8; } /* Write tag to packet header (optional) */ if (hdr->flags & NP_PACKET_HDR_FLAG_TAG) { WRITE_U16(ptr, hdr->tag); ptr += 2; } { ptrdiff_t diff = ptr - buf; if (hdr->hlen != (uint16_t)(diff)) { NABTO_LOG_ERROR(("header length mismatch: %" PRIu16 " != %" PRIptrdiff " !!!!!!!!!!!!!!!!!!!", hdr->hlen, diff)); return NULL; } } // insert crypto header (len and code will be inserted later) WRITE_U8(ptr, NP_PAYLOAD_TYPE_CRYPTO); ptr += 1; WRITE_U8(ptr, NP_PAYLOAD_HDR_FLAG_NONE); /*ptr += 1; WRITE_U16(ptr, len); ptr += 2; WRITE_U16(ptr, code); ptr += 2;*/ /* len and code is patched by unabto_encrypt() */ ptr += 5; return ptr; /* return end of packet (so far) */ }
static int ao_wav_close(ao_device *device) { ao_wav_internal *internal = (ao_wav_internal *) device->internal; unsigned char buf[4]; /* For holding length values */ long size; /* Find how long our file is in total, including header */ size = ftell(device->file); if (size < 0) { return 0; /* Wav header corrupt */ } /* Go back and set correct length info */ internal->wave.riff.len = size - 8; internal->wave.data.len = size - WAV_HEADER_LEN; /* Rewind to riff len and write it */ if (fseek(device->file, 4, SEEK_SET) < 0) return 0; /* Wav header corrupt */ WRITE_U32(buf, internal->wave.riff.len); if (fwrite(buf, sizeof(char), 4, device->file) < 4) return 0; /* Wav header corrupt */ /* Rewind to data len and write it */ if (fseek(device->file, 64, SEEK_SET) < 0) return 0; /* Wav header corrupt */ WRITE_U32(buf, internal->wave.data.len); if (fwrite(buf, sizeof(char), 4, device->file) < 4) return 0; /* Wav header corrupt */ return 1; /* Wav header correct */ }
bool aes128_test(const uint8_t key[16], const uint8_t plaintext[16], const uint8_t result[16]) { uint32_t block[4]; AES_CTX ctx; int i; AES_set_key(&ctx, key, key, AES_MODE_128); for (i = 0; i < 4; i++) { WRITE_U32(&block[i], *(uint32_t*)(plaintext+(i*sizeof(uint32_t)))); } AES_encrypt(&ctx, block); for (i = 0; i < 4; i++) { WRITE_U32(plaintext+(i*sizeof(uint32_t)), block[i]); } return (memcmp((const uint8_t*)plaintext, result, 16) == 0); }
static VC_CONTAINER_STATUS_T avi_write_stream_header_chunk(VC_CONTAINER_T *p_ctx, VC_CONTAINER_TRACK_T *track) { VC_CONTAINER_FOURCC_T fourcc_type = 0, fourcc_handler = 0; uint32_t flags, scale = 0, rate = 0, div, start = 0, sample_size = 0; uint16_t left = 0, right = 0, top = 0, bottom = 0; uint32_t max_chunk_size, length = 0; WRITE_FOURCC(p_ctx, VC_FOURCC('s','t','r','h'), "Chunk ID"); WRITE_U32(p_ctx, 56, "Chunk Size"); if (!track->is_enabled) flags = 0; /* AVISF_DISABLED; FIXME: write_media should set this correctly! */ else flags = 0; if (track->format->es_type == VC_CONTAINER_ES_TYPE_VIDEO) { fourcc_type = VC_FOURCC('v','i','d','s'); sample_size = 0; scale = track->format->type->video.frame_rate_den; rate = track->format->type->video.frame_rate_num; if (rate == 0 || scale == 0) { LOG_DEBUG(p_ctx, "invalid video framerate (%d/%d)", rate, scale); LOG_DEBUG(p_ctx, "using 30/1 (playback timing will almost certainly be incorrect)"); scale = 1; rate = 30; } top = track->format->type->video.y_offset; left = track->format->type->video.x_offset; bottom = track->format->type->video.y_offset + track->format->type->video.visible_height; right = track->format->type->video.x_offset + track->format->type->video.visible_width; } else if (track->format->es_type == VC_CONTAINER_ES_TYPE_AUDIO) { fourcc_type = VC_FOURCC('a','u','d','s'); sample_size = track->format->type->audio.block_align; scale = 1; if (track->format->type->audio.block_align) rate = (track->format->bitrate / track->format->type->audio.block_align) >> 3; if (rate == 0) { rate = track->format->type->audio.sample_rate ? track->format->type->audio.sample_rate : 32000; LOG_DEBUG(p_ctx, "invalid audio rate, using %d (playback timing will almost certainly be incorrect)", rate); } }
static void send_rendezvous_socket(nabto_socket_t socket, nabto_connect* con, uint16_t seq, nabto_endpoint* dest, nabto_endpoint *myAddress) { uint8_t* ptr; uint8_t* buf = nabtoCommunicationBuffer; ptr = insert_header(buf, 0, con->spnsi, U_CONNECT, false, seq, 0, 0); ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_EP, 0, 6); WRITE_U32(ptr, dest->addr); ptr += 4; WRITE_U16(ptr, dest->port); ptr += 2; if (seq > 0) { if (!myAddress) { NABTO_LOG_ERROR(("Send rendezvous called with an invalid address")); return; } else { ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_EP, 0, 6); WRITE_U32(ptr, myAddress->addr); ptr += 4; WRITE_U16(ptr, myAddress->port); ptr += 2; } } { size_t len = ptr - buf; insert_length(buf, len); if (seq) { NABTO_LOG_DEBUG((PRInsi " RENDEZVOUS Send to " PRIep ": seq=%" PRIu16 " " PRIep, MAKE_NSI_PRINTABLE(0, con->spnsi, 0), MAKE_EP_PRINTABLE(*dest), seq, MAKE_EP_PRINTABLE(*myAddress))); } else { NABTO_LOG_DEBUG((PRInsi " RENDEZVOUS Send to " PRIep ": seq=0", MAKE_NSI_PRINTABLE(0, con->spnsi, 0), MAKE_EP_PRINTABLE(*dest))); } if (dest->addr != 0 && dest->port != 0) { nabto_write(socket, buf, len, dest->addr, dest->port); } else { NABTO_LOG_TRACE(("invalid rendezvous packet thrown away")); } } }
static int ao_au_open(ao_device *device, ao_sample_format *format) { ao_au_internal *internal = (ao_au_internal *) device->internal; unsigned char buf[AU_HEADER_LEN]; /* The AU format is big-endian */ device->driver_byte_format = AO_FMT_BIG; /* Fill out the header */ internal->au.magic = AUDIO_FILE_MAGIC; internal->au.channels = device->output_channels; if (format->bits == 8) internal->au.encoding = AUDIO_FILE_ENCODING_LINEAR_8; else if (format->bits == 16) internal->au.encoding = AUDIO_FILE_ENCODING_LINEAR_16; else { /* Only 8 and 16 bits are supported at present. */ return 0; } internal->au.sample_rate = format->rate; internal->au.hdr_size = AU_HEADER_LEN; /* From the AU specification: "When audio files are passed * through pipes, the 'data_size' field may not be known in * advance. In such cases, the 'data_size' should be set * to AUDIO_UNKNOWN_SIZE." */ internal->au.data_size = AUDIO_UNKNOWN_SIZE; /* strncpy(state->au.info, "OGG ", 4); */ /* Write the header in big-endian order */ WRITE_U32(buf, internal->au.magic); WRITE_U32(buf + 4, internal->au.hdr_size); WRITE_U32(buf + 8, internal->au.data_size); WRITE_U32(buf + 12, internal->au.encoding); WRITE_U32(buf + 16, internal->au.sample_rate); WRITE_U32(buf + 20, internal->au.channels); strncpy (buf + 24, internal->au.info, 4); if (fwrite(buf, sizeof(char), AU_HEADER_LEN, device->file) != AU_HEADER_LEN) { return 0; /* Error writing header */ } if(!device->inter_matrix){ /* set up matrix such that users are warned about > stereo playback */ if(device->output_channels<=2) device->inter_matrix=strdup("L,R"); //else no matrix, which results in a warning } return 1; }
ssize_t microchip_udp_write(UDP_SOCKET socket, const uint8_t* buf, size_t len, uint32_t addr, uint16_t port) { NODE_INFO remoteInfo; ssize_t size; uint32_t addrNetworkOrder; #if NABTO_LOG_CHECK(NABTO_LOG_SEVERITY_TRACE) UDP_SOCKET_INFO* debug; uint32_t sourceIp; #endif if (addr == 0 || port == 0) { return 0; } WRITE_U32(&addrNetworkOrder, addr); if (unabto_microchip_arp_resolve(addrNetworkOrder, &remoteInfo.MACAddr)) { remoteInfo.IPAddr.Val = addrNetworkOrder; memcpy((void*) &UDPSocketInfo[socket].remote.remoteNode, (void*) &remoteInfo, sizeof (NODE_INFO)); } else { if (UDPSocketInfo[socket].remote.remoteNode.IPAddr.Val != addrNetworkOrder) { return 0; } // the arp resolve is not finished but the socket already knows // a mac address, lets just use it. } if (UDPIsPutReady(socket) >= len) { #if NABTO_LOG_CHECK(NABTO_LOG_SEVERITY_TRACE) debug = &UDPSocketInfo[socket]; READ_U32(sourceIp, &debug->remote.remoteNode.IPAddr.Val); #endif UDPSocketInfo[socket].remotePort = port; size = (ssize_t) UDPPutArray((BYTE*) buf, len); UDPFlush(); NABTO_LOG_TRACE(("UDP write length: %i, %" PRIu16 " -> " PRIip ":%" PRIu16, size, debug->localPort, MAKE_IP_PRINTABLE(sourceIp), debug->remotePort)); NABTO_LOG_BUFFER(NABTO_LOG_SEVERITY_TRACE, ("UDP out datagram"), buf, len); return size; } else { NABTO_LOG_TRACE(("Socket was not put ready %i", socket)); } return 0; }
bool unabto_util_test(void) { uint8_t buf[] = {0x00,0x00,0x00,0x00,0x12, 0x34, 0x56, 0x78}; uint32_t* buf2 = (uint32_t*)buf; uint32_t testNr; uint16_t testu16; bool ret = true; READ_U32(testNr, buf+4); if (testNr != 305419896) { // 0x12345678 in host byte order NABTO_LOG_TRACE(("testNr: %i", testNr)); ret = false; } READ_U32(testNr, buf2+1); if (testNr != 0x12345678) { NABTO_LOG_TRACE(("testNr: %i", testNr)); ret = false; } READ_U16(testu16, buf+4); if (testu16 != 4660) { NABTO_LOG_TRACE(("testu16 read failed %i", testu16)); ret = false; } WRITE_U32(buf, 0x01020304); if (buf[0] != 0x01 || buf[1] != 0x02 || buf[2] != 0x03 || buf[3] != 0x04) { NABTO_LOG_TRACE(("WRITE u32 failed")); ret = false; } WRITE_U16(buf, 0x0506); if (buf[0] != 0x05 || buf[1] != 0x06) { NABTO_LOG_TRACE(("WRITE u16 failed")); ret = false; } return ret; }
static VC_CONTAINER_STATUS_T avi_write_stream_format_chunk(VC_CONTAINER_T *p_ctx, VC_CONTAINER_TRACK_T *track, uint32_t chunk_size) { VC_CONTAINER_STATUS_T status; WRITE_FOURCC(p_ctx, VC_FOURCC('s','t','r','f'), "Chunk ID"); WRITE_U32(p_ctx, chunk_size, "Chunk Size"); if ((status = STREAM_STATUS(p_ctx)) != VC_CONTAINER_SUCCESS) return status; if(track->format->es_type == VC_CONTAINER_ES_TYPE_VIDEO) status = vc_container_write_bitmapinfoheader(p_ctx, track->format); else if(track->format->es_type == VC_CONTAINER_ES_TYPE_AUDIO) status = vc_container_write_waveformatex(p_ctx, track->format); if (status != VC_CONTAINER_SUCCESS) return status; AVI_END_CHUNK(p_ctx); return STREAM_STATUS(p_ctx); }
bool sendPacket(unabto_api_stream_t stream, uint8_t* packet, size_t packetLength) { bool ret = true; uint8_t lengthBuffer[sizeof(uint32_t)]; WRITE_U32(lengthBuffer, packetLength); { xSemaphoreTake(sendLock, portMAX_DELAY); if (unabto_api_stream_write_all(stream, lengthBuffer, sizeof(uint32_t)) != UNABTO_API_OK) { NABTO_LOG_TRACE(("failed to send packet length")); ret = false; } else if (unabto_api_stream_write_all(stream, packet, packetLength) != UNABTO_API_OK) { NABTO_LOG_TRACE(("failed to send packet data")); ret = false; } xSemaphoreGive(sendLock); } return ret; }
void unabto_sha256_final(sha256_ctx* context,sha2_byte digest[]) { sha2_word32 *d = (sha2_word32*)digest; unsigned int usedspace; /* Sanity check: */ // assert(context != (sha256_ctx*)0); /* If no digest buffer is passed, we don't bother doing this: */ if (digest != (sha2_byte*)0) { usedspace = context->byteCount % SHA256_BLOCK_LENGTH; if (usedspace > 0) { /* Begin padding with a 1 bit: */ context->buffer[usedspace++] = 0x80; if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { /* Set-up for the last transform: */ MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace); } else { if (usedspace < SHA256_BLOCK_LENGTH) { MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace); } /* Do second-to-last transform: */ SHA256_Transform(context, (sha2_word32*)context->buffer); /* And set-up for the last transform: */ MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH); } } else { /* Set-up for the last transform: */ MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH); /* Begin padding with a 1 bit: */ *context->buffer = 0x80; } /* Set the bit count: */ /* Convert FROM host byte order */ { uint16_t tmp16; uint16_t tmp16_ = context->byteCount; tmp16_ <<= 3; READ_U16(tmp16, &tmp16_); memset(&context->buffer[SHA256_BLOCK_LENGTH - 8], 0, 6); *(uint16_t*)&context->buffer[SHA256_BLOCK_LENGTH - 2] = tmp16; } //print_sha256_ctx(context); /* Final transform: */ SHA256_Transform(context, (sha2_word32*)context->buffer); //print_sha256_ctx(context); { /* Convert TO host byte order */ uint8_t j; for (j = 0; j < 8; j++) { WRITE_U32(d, context->state[j]); d++; } } } /* Clean up state data: */ MEMSET_BZERO(context, sizeof(sha256_ctx)); usedspace = 0; }
static int ao_wav_open(ao_device *device, ao_sample_format *format) { ao_wav_internal *internal = (ao_wav_internal *) device->internal; unsigned char buf[WAV_HEADER_LEN]; int size = 0x7fffffff; /* Use a bogus size initially */ /* Store information */ internal->wave.common.wChannels = device->output_channels; internal->wave.common.wBitsPerSample = ((format->bits+7)>>3)<<3; internal->wave.common.wValidBitsPerSample = format->bits; internal->wave.common.dwSamplesPerSec = format->rate; memset(buf, 0, WAV_HEADER_LEN); /* Fill out our wav-header with some information. */ strncpy(internal->wave.riff.id, "RIFF",4); internal->wave.riff.len = size - 8; strncpy(internal->wave.riff.wave_id, "WAVE",4); strncpy(internal->wave.format.id, "fmt ",4); internal->wave.format.len = 40; internal->wave.common.wFormatTag = WAVE_FORMAT_EXTENSIBLE; internal->wave.common.dwAvgBytesPerSec = internal->wave.common.wChannels * internal->wave.common.dwSamplesPerSec * (internal->wave.common.wBitsPerSample >> 3); internal->wave.common.wBlockAlign = internal->wave.common.wChannels * (internal->wave.common.wBitsPerSample >> 3); internal->wave.common.cbSize = 22; internal->wave.common.subFormat = WAVE_FORMAT_PCM; internal->wave.common.dwChannelMask=device->output_mask; strncpy(internal->wave.data.id, "data",4); internal->wave.data.len = size - WAV_HEADER_LEN; strncpy(buf, internal->wave.riff.id, 4); WRITE_U32(buf+4, internal->wave.riff.len); strncpy(buf+8, internal->wave.riff.wave_id, 4); strncpy(buf+12, internal->wave.format.id,4); WRITE_U32(buf+16, internal->wave.format.len); WRITE_U16(buf+20, internal->wave.common.wFormatTag); WRITE_U16(buf+22, internal->wave.common.wChannels); WRITE_U32(buf+24, internal->wave.common.dwSamplesPerSec); WRITE_U32(buf+28, internal->wave.common.dwAvgBytesPerSec); WRITE_U16(buf+32, internal->wave.common.wBlockAlign); WRITE_U16(buf+34, internal->wave.common.wBitsPerSample); WRITE_U16(buf+36, internal->wave.common.cbSize); WRITE_U16(buf+38, internal->wave.common.wValidBitsPerSample); WRITE_U32(buf+40, internal->wave.common.dwChannelMask); WRITE_U16(buf+44, internal->wave.common.subFormat); memcpy(buf+46,"\x00\x00\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71",14); strncpy(buf+60, internal->wave.data.id, 4); WRITE_U32(buf+64, internal->wave.data.len); if (fwrite(buf, sizeof(char), WAV_HEADER_LEN, device->file) != WAV_HEADER_LEN) { return 0; /* Could not write wav header */ } device->driver_byte_format = AO_FMT_LITTLE; return 1; }
bool CXBTFWriter::UpdateHeader(const std::vector<unsigned int>& dupes) { if (m_file == NULL) { return false; } uint64_t offset = m_xbtf.GetHeaderSize(); WRITE_STR(XBTF_MAGIC, 4, m_file); WRITE_STR(XBTF_VERSION, 1, m_file); std::vector<CXBTFFile>& files = m_xbtf.GetFiles(); WRITE_U32(files.size(), m_file); for (size_t i = 0; i < files.size(); i++) { CXBTFFile& file = files[i]; // Convert path to lower case char* ch = file.GetPath(); while (*ch) { *ch = tolower(*ch); ch++; } WRITE_STR(file.GetPath(), 256, m_file); WRITE_U32(file.GetLoop(), m_file); std::vector<CXBTFFrame>& frames = file.GetFrames(); WRITE_U32(frames.size(), m_file); for (size_t j = 0; j < frames.size(); j++) { CXBTFFrame& frame = frames[j]; if (dupes[i] != i) frame.SetOffset(files[dupes[i]].GetFrames()[j].GetOffset()); else { frame.SetOffset(offset); offset += frame.GetPackedSize(); } WRITE_U32(frame.GetWidth(), m_file); WRITE_U32(frame.GetHeight(), m_file); WRITE_U32(frame.GetFormat(true), m_file); WRITE_U64(frame.GetPackedSize(), m_file); WRITE_U64(frame.GetUnpackedSize(), m_file); WRITE_U32(frame.GetDuration(), m_file); WRITE_U64(frame.GetOffset(), m_file); } } // Sanity check int64_t pos = ftell(m_file); if (pos != (int64_t)m_xbtf.GetHeaderSize()) { printf("Expected header size (%" PRId64 ") != actual size (%" PRId64 ")\n", m_xbtf.GetHeaderSize(), pos); return false; } return true; }