Beispiel #1
0
obs_source_t obs_source_create(enum obs_source_type type, const char *id,
                               const char *name, const char *settings)
{
    struct obs_source *source;

    const struct source_info *info = get_source_info(type, id);
    if (!info) {
        blog(LOG_WARNING, "Source '%s' not found", id);
        return NULL;
    }

    source = bmalloc(sizeof(struct obs_source));
    memset(source, 0, sizeof(struct obs_source));

    if (!obs_source_init_handlers(source))
        goto fail;

    source->name = bstrdup(name);
    source->type = type;
    source->data = info->create(settings, source);
    if (!source->data)
        goto fail;

    if (!obs_source_init(source, settings, info))
        goto fail;

    obs_source_dosignal(source, "source-create");
    return source;

fail:
    blog(LOG_ERROR, "obs_source_create failed");
    obs_source_destroy(source);
    return NULL;
}
Beispiel #2
0
obs_source_t obs_source_create(enum obs_source_type type, const char *id,
		const char *name, obs_data_t settings)
{
	struct obs_source *source;

	const struct obs_source_info *info = get_source_info(type, id);
	if (!info) {
		blog(LOG_ERROR, "Source '%s' not found", id);
		return NULL;
	}

	source = bzalloc(sizeof(struct obs_source));

	if (!obs_source_init_context(source, settings, name))
		goto fail;

	if (info->defaults)
		info->defaults(source->context.settings);

	source->context.data = info->create(source->context.settings, source);
	if (!source->context.data)
		goto fail;

	if (!obs_source_init(source, info))
		goto fail;

	obs_source_dosignal(source, "source_create", NULL);
	return source;

fail:
	blog(LOG_ERROR, "obs_source_create failed");
	obs_source_destroy(source);
	return NULL;
}
Beispiel #3
0
obs_properties_t obs_source_properties(enum obs_source_type type,
		const char *id, const char *locale)
{
	const struct source_info *info = get_source_info(type, id);
	if (info && info->properties)
	       return info->properties(locale);
	return NULL;
}
Beispiel #4
0
obs_properties_t obs_get_source_properties(enum obs_source_type type,
		const char *id, const char *locale)
{
	const struct obs_source_info *info = get_source_info(type, id);
	if (info && info->properties) {
		obs_data_t       defaults = get_defaults(info);
		obs_properties_t properties;

		properties = info->properties(locale);
		obs_properties_apply_settings(properties, defaults);
		obs_data_release(defaults);
		return properties;
	}
	return NULL;
}
Beispiel #5
0
void CVmBifT3::get_stack_trace(VMG_ uint argc)
{
    int single_level = 0;
    int level;
    vm_val_t *fp;
    vm_val_t lst_val;
    CVmObjList *lst;
    const uchar *entry_addr;
    ulong method_ofs;
    vm_val_t stack_info_cls;
    int want_named_args = FALSE;
    int want_locals = FALSE;
    int want_frefs = FALSE;
    int flags = 0;
    const vm_rcdesc *rc;

    /* check arguments */
    check_argc_range(vmg_ argc, 0, 2);

    /* get the imported stack information class */
    stack_info_cls.set_obj(G_predef->stack_info_cls);
    if (stack_info_cls.val.obj == VM_INVALID_OBJ)
    {
        /* 
         *   there's no stack information class - we can't return any
         *   meaningful information, so just return nil 
         */
        retval_nil(vmg0_);
        return;
    }

    /* 
     *   look up T3StackInfo.construct() to determine how many arguments it
     *   wants 
     */
    {
        int min_args, opt_args, varargs;
        if (vm_objp(vmg_ stack_info_cls.val.obj)->get_prop_interface(
            vmg_ stack_info_cls.val.obj, G_predef->obj_construct,
            min_args, opt_args, varargs))
        {
            /* check to see how many extra arguments they want */
            want_named_args = (min_args + opt_args >= 7 || varargs);
            want_locals = (min_args + opt_args >= 8 || varargs);
            want_frefs = (min_args + opt_args >= 9 || varargs);
        }
    }

    /* check to see if we're fetching a single level or the full trace */
    if (argc >= 1)
    {
        /* 
         *   Get the single level, and adjust to a 0 base.  If the level is
         *   nil, we're still getting all levels. 
         */
        if (G_stk->get(0)->typ == VM_NIL)
        {
            /* it's nil - get all levels */
            G_stk->discard();
        }
        else
        {
            /* get the level number */
            single_level = pop_int_val(vmg0_);

            /* make sure it's in range */
            if (single_level <= 0)
                err_throw(VMERR_BAD_VAL_BIF);
            
            /* we won't need a return list */
            lst_val.set_obj_or_nil(VM_INVALID_OBJ);
            lst = 0;
        }
    }

    /* get the flags argument, if present */
    if (argc >= 2)
        flags = pop_int_val(vmg0_);

    /* if we're not doing a single level, we need a list for the result */
    if (!single_level)
    {
        /* 
         *   We're returning a full list, so we need to allocate the list for
         *   the return value.  First, count stack levels to see how big a
         *   list we'll need.  
         */
        fp = G_interpreter->get_frame_ptr();
        entry_addr = G_interpreter->get_entry_ptr();
        method_ofs = G_interpreter->get_method_ofs();
        for (level = 0 ; fp != 0 ;
             fp = G_interpreter->get_enclosing_frame_ptr(vmg_ fp), ++level)
        {
            /* add an extra level for each system call */
            if (method_ofs == 0 && entry_addr != 0)
                ++level;

            /* get the return address */
            entry_addr =
                G_interpreter->get_enclosing_entry_ptr_from_frame(vmg_ fp);
            method_ofs = G_interpreter->get_return_ofs_from_frame(vmg_ fp);
        }

        /* create the list */
        lst_val.set_obj(CVmObjList::create(vmg_ FALSE, level));
        lst = (CVmObjList *)vm_objp(vmg_ lst_val.val.obj);

        /* 
         *   we create other objects while building this list, so the gc
         *   could run - clear the list to ensure it contains valid data 
         */
        lst->cons_clear();
        
        /* protect the list from garbage collection while we work */
        G_stk->push(&lst_val);

        /* flag that we're doing the whole stack */
        single_level = -1;
    }
    else
    {
        /* adjust the level to a 0-based index */
        single_level -= 1;
    }

    /* set up at the current function */
    fp = G_interpreter->get_frame_ptr();
    entry_addr = G_interpreter->get_entry_ptr();
    method_ofs = G_interpreter->get_method_ofs();
    rc = 0;

    /* traverse the frames */
    for (level = 0 ; fp != 0 ; ++level)
    {
        int fr_argc;
        int i;
        vm_obj_id_t def_obj;
        vm_val_t info_self;
        vm_val_t info_func;
        vm_val_t info_obj;
        vm_val_t info_prop;
        vm_val_t info_args;
        vm_val_t info_locals;
        vm_val_t info_srcloc;
        vm_val_t info_frameref;
        CVmObjList *arglst;
        vm_val_t ele;
        CVmFuncPtr func_ptr;
        int gc_cnt = 0;
        int info_argc = 0;

        /* if we're looking for a single level, and this isn't it, skip it */
        if (single_level >= 0 && level != single_level)
            goto done_with_level;
       
        /* 
         *   start with the information values to nil - we'll set the
         *   appropriate ones when we find out what we have 
         */
        info_func.set_nil();
        info_obj.set_nil();
        info_prop.set_nil();
        info_self.set_nil();
        info_locals.set_nil();
        info_frameref.set_nil();

        /* get the number of arguments to the function in this frame */
        fr_argc = G_interpreter->get_argc_from_frame(vmg_ fp);

        /* set up a function pointer for the method's entry address */
        func_ptr.set(entry_addr);

        /* get the current frame's defining object */
        def_obj = G_interpreter->get_defining_obj_from_frame(vmg_ fp);

        /* check for special method offsets */
        switch (method_ofs)
        {
        case VMRUN_RET_OP:
            /* the real return address is one past the last argument */
            method_ofs = G_interpreter->get_param_from_frame(vmg_ fp, argc)
                         ->val.intval;
            break;

        case VMRUN_RET_OP_ASILCL:
            /* the real return address is two past the last argument */
            method_ofs = G_interpreter->get_param_from_frame(vmg_ fp, argc+1)
                         ->val.intval;
            break;
        }

        /* determine whether it's an object.prop or a function call */
        if (method_ofs == 0)
        {
            /* 
             *   A zero method offset indicates a recursive VM invocation
             *   from a native function.  Presume we have no information on
             *   the caller.  
             */
            info_self.set_nil();
            fr_argc = 0;

            /* check for a native caller context */
            if (rc != 0)
            {
                /* check which kind of native caller we have */
                if (rc->bifptr.typ != VM_NIL)
                {
                    /* we have a built-in function at this level */
                    info_func = rc->bifptr;
                }
                else if (rc->self.typ != VM_NIL)
                {
                    /* it's an intrinsic class method - get the 'self' */
                    info_obj = info_self = rc->self;

                    /* get the metaclass */
                    CVmMetaclass *mc;
                    switch (info_obj.typ)
                    {
                    case VM_OBJ:
                        /* get the metaclass from the object */
                        mc = vm_objp(vmg_ info_obj.val.obj)
                             ->get_metaclass_reg();
                        break;

                    case VM_LIST:
                        /* list constant - use the List metaclass */
                        mc = CVmObjList::metaclass_reg_;
                        break;

                    case VM_SSTRING:
                        /* string constant - use the String metaclass */
                        mc = CVmObjString::metaclass_reg_;
                        break;

                    default:
                        /* other types don't have metaclasses */
                        mc = 0;
                        break;
                    }

                    /* get the registration table entry */
                    vm_meta_entry_t *me =
                        mc == 0 ? 0 :
                        G_meta_table->get_entry_from_reg(mc->get_reg_idx());

                    /* get the metaclass and property from the entry */
                    if (me != 0)
                    {
                        /* set 'obj' to the IntrinsicClass object */
                        info_obj.set_obj(me->class_obj_);

                        /* get the property ID */
                        info_prop.set_propid(me->xlat_func(rc->method_idx));
                    }
                }
            }
        }
        else if (def_obj == VM_INVALID_OBJ)
        {
            /* there's no defining object, so this is a function call */
            func_ptr.get_fnptr(vmg_ &info_func);
        }
        else
        {
            /* it's an object.prop invocation */
            info_obj.set_obj(def_obj); // $$$ walk up to base modified obj?
            info_prop.set_propid(
                G_interpreter->get_target_prop_from_frame(vmg_ fp));

            /* get the 'self' in this frame */
            info_self.set_obj(G_interpreter->get_self_from_frame(vmg_ fp));
        }

        /* 
         *   build the argument list and source location, except for system
         *   routines 
         */
        if (method_ofs != 0 || rc != 0)
        {
            /* allocate a list object to store the argument list */
            int ac = (rc != 0 ? rc->argc : fr_argc);
            info_args.set_obj(CVmObjList::create(vmg_ FALSE, ac));
            arglst = (CVmObjList *)vm_objp(vmg_ info_args.val.obj);
            
            /* push the argument list for gc protection */
            G_stk->push(&info_args);
            ++gc_cnt;
            
            /* build the argument list */
            for (i = 0 ; i < ac ; ++i)
            {
                /* add this element to the argument list */
                const vm_val_t *v =
                    (rc != 0
                     ? rc->argp - i
                     : G_interpreter->get_param_from_frame(vmg_ fp, i));
                arglst->cons_set_element(i, v);
            }

            /* get the source location */
            get_source_info(vmg_ entry_addr, method_ofs, &info_srcloc);

            /* 
             *   if they want locals, and this isn't a recursive native
             *   caller, retrieve them 
             */
            if (rc == 0
                && (((flags & T3_GST_LOCALS) != 0 && want_locals)
                    || ((flags & T3_GST_FREFS) != 0 && want_frefs)))
            {
                /* get the locals */
                get_stack_locals(vmg_ fp, entry_addr, method_ofs,
                                 (flags & T3_GST_LOCALS) != 0 && want_locals
                                 ? &info_locals : 0,
                                 (flags & T3_GST_FREFS) != 0 && want_frefs
                                 ? &info_frameref : 0);

                /* 
                 *   that leaves the LookupTable and StackFrameDesc on the
                 *   stack, so note that we need to discard the stack level
                 *   when we're done with it 
                 */
                if (info_locals.typ == VM_OBJ)
                    ++gc_cnt;
                if (info_frameref.typ == VM_OBJ)
                    ++gc_cnt;
            }
        }
        else
        {
            /* 
             *   it's a system routine - no argument information is
             *   available, so return nil rather than an empty list to to
             *   indicate the absence 
             */
            info_args.set_nil();

            /* there's obviously no source location for system code */
            info_srcloc.set_nil();
        }

        /* 
         *   We have all of the information on this level now, so create the
         *   information object for the level.  This is an object of the
         *   exported stack-info class, which is a TadsObject type.  
         */

        /* start with the original complement of arguments */
        info_argc = 7;

        /* 
         *   if we have a modern T3StackInfo object, push the locals,
         *   named argument elements, and frame reference object
         */
        if (want_frefs)
        {
            G_stk->push(&info_frameref);
            ++info_argc;
        }
        if (want_named_args)
        {
            /* 
             *   the constructor has a slot for named arguments - push either
             *   a table or nil, depending...
             */
            vm_val_t *argp;
            const uchar *t = 0;

            /* if the flags request locals, retrieve the named arguments */
            if ((flags & T3_GST_LOCALS) != 0)
                t = CVmRun::get_named_args_from_frame(vmg_ fp, &argp);

            /* 
             *   if we do in fact have named arguments, build a lookup table
             *   copy and push it; otherwise just push nil 
             */
            if (t != 0)
            {
                /* get the number of table entries */
                int n = osrp2(t);
                t += 2;
                
                /* create a lookup table for the arguments */
                G_stk->push()->set_obj(CVmObjLookupTable::create(
                    vmg_ FALSE, n <= 8 ? 8 : n <= 32 ? 32 : 64, n));
                CVmObjLookupTable *lt = (CVmObjLookupTable *)vm_objp(
                    vmg_ G_stk->get(0)->val.obj);
                
                /* 
                 *   Populate the lookup table with the named arguments.  The
                 *   compiler builds the table in the order pushed, which is
                 *   right to left.  Lookup tables preserve the order in
                 *   which elements are added, and reflect this order in key
                 *   lists, so to that extent the order of building the
                 *   lookup table matters.  For readability of the generated
                 *   list, in case it's presented to the user, build the
                 *   table in left-to-right order, which is the reverse of
                 *   the table order in the bytecode table.  
                 */
                argp += n - 1;
                for (int i = (n-1)*2 ; i >= 0 ; i -= 2, --argp)
                {
                    /* get the name pointer and length from the index */
                    uint ofs = osrp2(t + i), nxtofs = osrp2(t + i + 2);
                    const char *name = (const char *)t + ofs;
                    size_t len = nxtofs - ofs;
                    
                    /* create a string from the name */
                    vm_val_t str;
                    str.set_obj(CVmObjString::create(vmg_ FALSE, name, len));
                    
                    /* add it to the table */
                    lt->add_entry(vmg_ &str, argp);
                }
            }
            else
            {
                /* there are no named arguments - push nil */
                G_stk->push()->set_nil();
            }

            /* count the argument */
            ++info_argc;
        }
        if (want_locals)
        {
            G_stk->push(&info_locals);
            ++info_argc;
        }

        /* push the rest of the arguments */
        G_stk->push(&info_srcloc);
        G_stk->push(&info_args);
        G_stk->push(&info_self);
        G_stk->push(&info_prop);
        G_stk->push(&info_obj);
        G_stk->push(&info_func);
        G_stk->push(&stack_info_cls);
        ele.set_obj(CVmObjTads::create_from_stack(vmg_ 0, info_argc));

        /* discard the gc protection items */
        G_stk->discard(gc_cnt);

        /* 
         *   if we're fetching a single level, this is it - return the new
         *   stack info object and we're done
         */
        if (single_level >= 0)
        {
            /* return the single level object */
            retval_obj(vmg_ ele.val.obj);

            /* we're done */
            return;
        }

        /* add the new element to our list */
        lst->cons_set_element(level, &ele);

    done_with_level:
        /*
         *   If this is a system call level, and we're not in debug mode,
         *   this recursive frame contains the entry address for the caller,
         *   but not the calling byte-code address.  Stay on the current
         *   level in this case.  
         */
        if (method_ofs == 0 && entry_addr != 0)
        {
            /* 
             *   This is a recursive caller, and we have a valid entry
             *   address for the prior frame.  Stay in the current frame, and
             *   retrieve the actual return address from the calling frame.  
             */
            if (rc != 0)
            {
                /* get the actual return address from the recursive context */
                method_ofs = rc->return_addr - entry_addr;

                /* 
                 *   we're now in the bytecode part of the frame, so forget
                 *   the recursive context 
                 */
                rc = 0;
            }
            else
            {
                /* no recursive context - use a fake return address */
                method_ofs = G_interpreter->get_funchdr_size();
            }
        }
        else
        {
            /* move up to the enclosing frame */
            entry_addr =
                G_interpreter->get_enclosing_entry_ptr_from_frame(vmg_ fp);
            method_ofs = G_interpreter->get_return_ofs_from_frame(vmg_ fp);
            rc = G_interpreter->get_rcdesc_from_frame(vmg_ fp);
            fp = G_interpreter->get_enclosing_frame_ptr(vmg_ fp);
        }
    }

    /* return the list */
    retval_obj(vmg_ lst_val.val.obj);

    /* discard our gc protection */
    G_stk->discard();
}
Beispiel #6
0
/*
 * mono_debug_symfile_get_line_numbers_full:
 *
 * On return, SOURCE_FILE_LIST will point to a GPtrArray of MonoDebugSourceFile
 * structures, and SOURCE_FILES will contain indexes into this array.
 * The MonoDebugSourceFile structures are owned by this module.
 */
void
mono_debug_symfile_get_line_numbers_full (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int *n_il_offsets, int **il_offsets, int **line_numbers, int **source_files)
{
    // FIXME: Unify this with mono_debug_symfile_lookup_location
    MonoSymbolFile *symfile;
    const unsigned char *ptr;
    StatementMachine stm;
    uint32_t i;
    GPtrArray *il_offset_array, *line_number_array, *source_file_array;

    if (source_file_list)
        *source_file_list = NULL;
    if (n_il_offsets)
        *n_il_offsets = 0;
    if (source_files)
        *source_files = NULL;
    if (source_file)
        *source_file = NULL;

    if ((symfile = minfo->handle->symfile) == NULL)
        return;

    il_offset_array = g_ptr_array_new ();
    line_number_array = g_ptr_array_new ();
    source_file_array = g_ptr_array_new ();

    stm.line_base = read32 (&symfile->offset_table->_line_number_table_line_base);
    stm.line_range = read32 (&symfile->offset_table->_line_number_table_line_range);
    stm.opcode_base = (uint8_t) read32 (&symfile->offset_table->_line_number_table_opcode_base);
    stm.max_address_incr = (255 - stm.opcode_base) / stm.line_range;

    mono_debugger_lock ();

    ptr = symfile->raw_contents + minfo->lnt_offset;

    stm.symfile = symfile;
    stm.offset = stm.last_offset = 0;
    stm.last_file = 0;
    stm.last_line = 0;
    stm.first_file = 0;
    stm.file = 1;
    stm.line = 1;
    stm.is_hidden = FALSE;

    while (TRUE) {
        uint8_t opcode = *ptr++;

        if (opcode == 0) {
            uint8_t size = *ptr++;
            const unsigned char *end_ptr = ptr + size;

            opcode = *ptr++;

            if (opcode == DW_LNE_end_sequence) {
                if (il_offset_array->len == 0)
                    /* Empty table */
                    break;
                add_line (&stm, il_offset_array, line_number_array, source_file_array);
                break;
            } else if (opcode == DW_LNE_MONO_negate_is_hidden) {
                stm.is_hidden = !stm.is_hidden;
            } else if ((opcode >= DW_LNE_MONO__extensions_start) &&
                       (opcode <= DW_LNE_MONO__extensions_end)) {
                ; // reserved for future extensions
            } else {
                g_warning ("Unknown extended opcode %x in LNT", opcode);
            }

            ptr = end_ptr;
            continue;
        } else if (opcode < stm.opcode_base) {
            switch (opcode) {
            case DW_LNS_copy:
                add_line (&stm, il_offset_array, line_number_array, source_file_array);
                break;
            case DW_LNS_advance_pc:
                stm.offset += read_leb128 (ptr, &ptr);
                break;
            case DW_LNS_advance_line:
                stm.line += read_leb128 (ptr, &ptr);
                break;
            case DW_LNS_set_file:
                stm.file = read_leb128 (ptr, &ptr);
                break;
            case DW_LNS_const_add_pc:
                stm.offset += stm.max_address_incr;
                break;
            default:
                g_warning ("Unknown standard opcode %x in LNT", opcode);
                g_assert_not_reached ();
            }
        } else {
            opcode -= stm.opcode_base;

            stm.offset += opcode / stm.line_range;
            stm.line += stm.line_base + (opcode % stm.line_range);

            add_line (&stm, il_offset_array, line_number_array, source_file_array);
        }
    }

    if (!stm.file && stm.first_file)
        stm.file = stm.first_file;

    if (stm.file && source_file) {
        int offset = read32(&(stm.symfile->offset_table->_source_table_offset)) +
                     (stm.file - 1) * sizeof (MonoSymbolFileSourceEntry);
        MonoSymbolFileSourceEntry *se = (MonoSymbolFileSourceEntry *)
                                        (stm.symfile->raw_contents + offset);

        if (source_file)
            *source_file = read_string (stm.symfile->raw_contents + read32(&(se->_data_offset)), NULL);
    }

    if (source_file_list) {
        int file, last_file = 0;

        *source_file_list = g_ptr_array_new ();
        if (source_files)
            *source_files = g_malloc (il_offset_array->len * sizeof (int));

        for (i = 0; i < il_offset_array->len; ++i) {
            file = GPOINTER_TO_UINT (g_ptr_array_index (source_file_array, i));
            if (file && file != last_file) {
                MonoDebugSourceInfo *info = get_source_info (symfile, file);

                g_ptr_array_add (*source_file_list, info);
            }
            last_file = file;
            if (source_files)
                (*source_files) [i] = (*source_file_list)->len - 1;
        }
        if ((*source_file_list)->len == 0 && stm.file) {
            MonoDebugSourceInfo *info = get_source_info (symfile, stm.file);

            g_ptr_array_add (*source_file_list, info);
        }
    }

    if (n_il_offsets)
        *n_il_offsets = il_offset_array->len;
    if (il_offsets && line_numbers) {
        *il_offsets = g_malloc (il_offset_array->len * sizeof (int));
        *line_numbers = g_malloc (il_offset_array->len * sizeof (int));
        for (i = 0; i < il_offset_array->len; ++i) {
            (*il_offsets) [i] = GPOINTER_TO_UINT (g_ptr_array_index (il_offset_array, i));
            (*line_numbers) [i] = GPOINTER_TO_UINT (g_ptr_array_index (line_number_array, i));
        }
    }
    g_ptr_array_free (il_offset_array, TRUE);
    g_ptr_array_free (line_number_array, TRUE);

    mono_debugger_unlock ();
    return;
}
void obs_register_source_s(const struct obs_source_info *info, size_t size)
{
	struct obs_source_info data = {0};
	struct darray *array = NULL;

	if (info->type == OBS_SOURCE_TYPE_INPUT) {
		array = &obs->input_types.da;
	} else if (info->type == OBS_SOURCE_TYPE_FILTER) {
		array = &obs->filter_types.da;
	} else if (info->type == OBS_SOURCE_TYPE_TRANSITION) {
		array = &obs->transition_types.da;
	} else if (info->type != OBS_SOURCE_TYPE_SCENE) {
		source_warn("Tried to register unknown source type: %u",
				info->type);
		goto error;
	}

	if (get_source_info(info->id)) {
		source_warn("Source '%s' already exists!  "
		                  "Duplicate library?", info->id);
		goto error;
	}

	memcpy(&data, info, size);

	/* mark audio-only filters as an async filter categorically */
	if (data.type == OBS_SOURCE_TYPE_FILTER) {
		if ((data.output_flags & OBS_SOURCE_VIDEO) == 0)
			data.output_flags |= OBS_SOURCE_ASYNC;
	}

	if (data.type == OBS_SOURCE_TYPE_TRANSITION) {
		if (data.get_width)
			source_warn("get_width ignored registering "
					"transition '%s'",
					data.id);
		if (data.get_height)
			source_warn("get_height ignored registering "
					"transition '%s'",
					data.id);
		data.output_flags |= OBS_SOURCE_COMPOSITE | OBS_SOURCE_VIDEO |
			OBS_SOURCE_CUSTOM_DRAW;
	}

	if ((data.output_flags & OBS_SOURCE_COMPOSITE) != 0) {
		if ((data.output_flags & OBS_SOURCE_AUDIO) != 0) {
			source_warn("Source '%s': Composite sources "
					"cannot be audio sources", info->id);
			goto error;
		}
		if ((data.output_flags & OBS_SOURCE_ASYNC) != 0) {
			source_warn("Source '%s': Composite sources "
					"cannot be async sources", info->id);
			goto error;
		}
	}

#define CHECK_REQUIRED_VAL_(info, val, func) \
	CHECK_REQUIRED_VAL(struct obs_source_info, info, val, func)
	CHECK_REQUIRED_VAL_(info, get_name, obs_register_source);
	CHECK_REQUIRED_VAL_(info, create,   obs_register_source);
	CHECK_REQUIRED_VAL_(info, destroy,  obs_register_source);

	if (info->type != OBS_SOURCE_TYPE_FILTER         &&
	    info->type != OBS_SOURCE_TYPE_TRANSITION     &&
	    (info->output_flags & OBS_SOURCE_VIDEO) != 0 &&
	    (info->output_flags & OBS_SOURCE_ASYNC) == 0) {
		CHECK_REQUIRED_VAL_(info, get_width,  obs_register_source);
		CHECK_REQUIRED_VAL_(info, get_height, obs_register_source);
	}

	if ((data.output_flags & OBS_SOURCE_COMPOSITE) != 0) {
		CHECK_REQUIRED_VAL_(info, audio_render, obs_register_source);
	}
#undef CHECK_REQUIRED_VAL_

	if (size > sizeof(data)) {
		source_warn("Tried to register obs_source_info with size "
				"%llu which is more than libobs currently "
				"supports (%llu)", (long long unsigned)size,
				(long long unsigned)sizeof(data));
		goto error;
	}

	if (array)
		darray_push_back(sizeof(struct obs_source_info), array, &data);
	da_push_back(obs->source_types, &data);
	return;

error:
	HANDLE_ERROR(size, obs_source_info, info);
}
Beispiel #8
0
/*
 * mono_debug_symfile_get_seq_points:
 *
 * On return, SOURCE_FILE_LIST will point to a GPtrArray of MonoDebugSourceFile
 * structures, and SOURCE_FILES will contain indexes into this array.
 * The MonoDebugSourceFile structures are owned by this module.
 */
void
mono_debug_symfile_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points)
{
	// FIXME: Unify this with mono_debug_symfile_lookup_location
	MonoSymbolFile *symfile;
	const unsigned char *ptr;
	StatementMachine stm;
	uint32_t i, j, n;
	LineNumberTableFlags flags;
	GPtrArray *il_offset_array, *line_number_array, *source_file_array, *hidden_array;
	gboolean has_column_info, has_end_info;
	MonoSymSeqPoint *sps;

	if (source_file_list)
		*source_file_list = NULL;
	if (seq_points)
		*seq_points = NULL;
	if (n_seq_points)
		*n_seq_points = 0;
	if (source_files)
		*source_files = NULL;
	if (source_file)
		*source_file = NULL;

	if ((symfile = minfo->handle->symfile) == NULL)
		return;

	flags = method_get_lnt_flags (minfo);
	has_column_info = (flags & LNT_FLAG_HAS_COLUMN_INFO) > 0;
	has_end_info = (flags & LNT_FLAG_HAS_END_INFO) > 0;

	il_offset_array = g_ptr_array_new ();
	line_number_array = g_ptr_array_new ();
	source_file_array = g_ptr_array_new ();
	hidden_array = g_ptr_array_new();

	stm.line_base = read32 (&symfile->offset_table->_line_number_table_line_base);
	stm.line_range = read32 (&symfile->offset_table->_line_number_table_line_range);
	stm.opcode_base = (uint8_t) read32 (&symfile->offset_table->_line_number_table_opcode_base);
	stm.max_address_incr = (255 - stm.opcode_base) / stm.line_range;

	mono_debugger_lock ();

	ptr = symfile->raw_contents + minfo->lnt_offset;

	stm.symfile = symfile;
	stm.offset = stm.last_offset = 0;
	stm.last_file = 0;
	stm.last_line = 0;
	stm.first_file = 0;
	stm.file = 1;
	stm.line = 1;
	stm.is_hidden = FALSE;

	while (TRUE) {
		uint8_t opcode = *ptr++;

		if (opcode == 0) {
			uint8_t size = *ptr++;
			const unsigned char *end_ptr = ptr + size;

			opcode = *ptr++;

			if (opcode == DW_LNE_end_sequence) {
				if (il_offset_array->len == 0)
					/* Empty table */
					break;
				break;
			} else if (opcode == DW_LNE_MONO_negate_is_hidden) {
				stm.is_hidden = !stm.is_hidden;
			} else if ((opcode >= DW_LNE_MONO__extensions_start) &&
				   (opcode <= DW_LNE_MONO__extensions_end)) {
				; // reserved for future extensions
			} else {
				g_warning ("Unknown extended opcode %x in LNT", opcode);
			}

			ptr = end_ptr;
			continue;
		} else if (opcode < stm.opcode_base) {
			switch (opcode) {
			case DW_LNS_copy:
				add_line (&stm, il_offset_array, line_number_array, source_file_array, hidden_array);
				break;
			case DW_LNS_advance_pc:
				stm.offset += read_leb128 (ptr, &ptr);
				break;
			case DW_LNS_advance_line:
				stm.line += read_leb128 (ptr, &ptr);
				break;
			case DW_LNS_set_file:
				stm.file = read_leb128 (ptr, &ptr);
				break;
			case DW_LNS_const_add_pc:
				stm.offset += stm.max_address_incr;
				break;
			default:
				g_warning ("Unknown standard opcode %x in LNT", opcode);
				g_assert_not_reached ();
			}
		} else {
			opcode -= stm.opcode_base;

			stm.offset += opcode / stm.line_range;
			stm.line += stm.line_base + (opcode % stm.line_range);

			add_line (&stm, il_offset_array, line_number_array, source_file_array, hidden_array);
		}
	}

	if (!stm.file && stm.first_file)
		stm.file = stm.first_file;

	if (stm.file && source_file) {
		int offset = read32(&(stm.symfile->offset_table->_source_table_offset)) +
			(stm.file - 1) * sizeof (MonoSymbolFileSourceEntry);
		MonoSymbolFileSourceEntry *se = (MonoSymbolFileSourceEntry *)
			(stm.symfile->raw_contents + offset);

		if (source_file)
			*source_file = read_string (stm.symfile->raw_contents + read32(&(se->_data_offset)), NULL);
	}

	if (source_file_list) {
		int file, last_file = 0;

		*source_file_list = g_ptr_array_new ();
		if (source_files)
			*source_files = (int *)g_malloc (il_offset_array->len * sizeof (int));

		for (i = 0; i < il_offset_array->len; ++i) {
			file = GPOINTER_TO_UINT (g_ptr_array_index (source_file_array, i));
			if (file && file != last_file) {
				MonoDebugSourceInfo *info = get_source_info (symfile, file);

				g_ptr_array_add (*source_file_list, info);
			}
			last_file = file;
			if (source_files)
				(*source_files) [i] = (*source_file_list)->len - 1;
		}
		if ((*source_file_list)->len == 0 && stm.file) {
			MonoDebugSourceInfo *info = get_source_info (symfile, stm.file);

			g_ptr_array_add (*source_file_list, info);
		}
	}				

	if (n_seq_points) {
		g_assert (seq_points);

		n = il_offset_array->len;
		for (i = 0; i < il_offset_array->len; i++) {
			if (GPOINTER_TO_UINT (g_ptr_array_index (hidden_array, i))) {
				n --;
			}
		}

		*n_seq_points = n;
		*seq_points = sps = g_new0 (MonoSymSeqPoint, n);
		j = 0;
		for (i = 0; i < il_offset_array->len; ++i) {
			MonoSymSeqPoint *sp = &(sps [j]);
			if (!GPOINTER_TO_UINT (g_ptr_array_index (hidden_array, i))) {
				sp->il_offset = GPOINTER_TO_UINT (g_ptr_array_index (il_offset_array, i));
				sp->line = GPOINTER_TO_UINT (g_ptr_array_index (line_number_array, i));
				sp->column = -1;
				sp->end_line = -1;
				sp->end_column = -1;
				j ++;
			}
		}

		if (has_column_info) {
			j = 0;
			for (i = 0; i < il_offset_array->len; ++i) {
				MonoSymSeqPoint *sp = &(sps [j]);
				int column = read_leb128 (ptr, &ptr);
				if (!GPOINTER_TO_UINT (g_ptr_array_index (hidden_array, i))) {
					sp->column = column;
					j++;
				}
			}
		}

		if (has_end_info) {
			j = 0;
			for (i = 0; i < il_offset_array->len; ++i) {
				MonoSymSeqPoint *sp = &(sps [j]);
				int end_row, end_column = -1;

				end_row = read_leb128 (ptr, &ptr);
				if (end_row != 0xffffff) {
					end_row += GPOINTER_TO_UINT (g_ptr_array_index (line_number_array, i));
					end_column = read_leb128 (ptr, &ptr);
					if (!GPOINTER_TO_UINT (g_ptr_array_index (hidden_array, i))) {
						sp->end_line = end_row;
						sp->end_column = end_column;
						j++;
					}
				}
			}
		}
	}

	g_ptr_array_free (il_offset_array, TRUE);
	g_ptr_array_free (line_number_array, TRUE);
	g_ptr_array_free (hidden_array, TRUE);

	mono_debugger_unlock ();
	return;
}
Beispiel #9
0
const char *obs_source_getdisplayname(enum obs_source_type type,
                                      const char *id, const char *locale)
{
    const struct source_info *info = get_source_info(type, id);
    return (info != NULL) ? info->getname(locale) : NULL;
}
Beispiel #10
0
obs_data_t obs_source_settings(enum obs_source_type type, const char *id)
{
	const struct obs_source_info *info = get_source_info(type, id);
	return (info) ? get_defaults(info) : NULL;
}